mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-21 12:15:54 +00:00
@@ -1350,6 +1350,19 @@ parseTaker(boost::json::value const& taker)
|
||||
return Status{RippledError::rpcBAD_ISSUER, "invalidTakerAccount"};
|
||||
return *takerID;
|
||||
}
|
||||
|
||||
ripple::Issue
|
||||
parseIssue(boost::json::object const& issue)
|
||||
{
|
||||
Json::Value jv;
|
||||
if (issue.contains(JS(issuer)) && issue.at(JS(issuer)).is_string())
|
||||
jv["issuer"] = issue.at(JS(issuer)).as_string().c_str();
|
||||
if (issue.contains(JS(currency)) && issue.at(JS(currency)).is_string())
|
||||
jv["currency"] = issue.at(JS(currency)).as_string().c_str();
|
||||
|
||||
return ripple::issueFromJson(jv);
|
||||
}
|
||||
|
||||
bool
|
||||
specifiesCurrentOrClosedLedger(boost::json::object const& request)
|
||||
{
|
||||
|
||||
@@ -25,18 +25,55 @@
|
||||
*/
|
||||
|
||||
#include "data/BackendInterface.h"
|
||||
#include "data/Types.h"
|
||||
#include "rpc/Amendments.h"
|
||||
#include "rpc/Errors.h"
|
||||
#include "rpc/JS.h"
|
||||
#include "rpc/common/Types.h"
|
||||
#include "util/JsonUtils.h"
|
||||
#include "util/log/Logger.h"
|
||||
#include "web/Context.h"
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/regex/v5/regex_fwd.hpp>
|
||||
#include <boost/regex/v5/regex_match.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <ripple/basics/XRPAmount.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/protocol/AccountID.h>
|
||||
#include <ripple/protocol/Book.h>
|
||||
#include <ripple/protocol/Fees.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/Issue.h>
|
||||
#include <ripple/protocol/Keylet.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
#include <ripple/protocol/PublicKey.h>
|
||||
#include <ripple/protocol/Rate.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
#include <ripple/protocol/STBase.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
#include <ripple/protocol/STObject.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <ripple/protocol/SecretKey.h>
|
||||
#include <ripple/protocol/TxMeta.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
@@ -264,6 +301,16 @@ parseBook(boost::json::object const& request);
|
||||
std::variant<Status, ripple::AccountID>
|
||||
parseTaker(boost::json::value const& taker);
|
||||
|
||||
/**
|
||||
* @brief Parse the json object into a ripple::Issue object.
|
||||
* @param issue The json object to parse. The accepted format is { "currency" : "USD", "issuer" :
|
||||
* "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59" } or {"currency" : "XRP"}
|
||||
* @return The ripple::Issue object.
|
||||
* @exception raise Json::error exception if the json object is not in the accepted format.
|
||||
*/
|
||||
ripple::Issue
|
||||
parseIssue(boost::json::object const& issue);
|
||||
|
||||
bool
|
||||
specifiesCurrentOrClosedLedger(boost::json::object const& request);
|
||||
|
||||
|
||||
@@ -19,14 +19,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rpc/common/Concepts.h"
|
||||
#include "rpc/Errors.h"
|
||||
#include "rpc/common/Specs.h"
|
||||
#include "rpc/common/Types.h"
|
||||
#include "rpc/common/Validators.h"
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace rpc::meta {
|
||||
|
||||
@@ -180,6 +187,23 @@ public:
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Runs the stored validator and produces a custom error if the wrapped validator fails. This is an overload
|
||||
* for the requirement which can modify the value. Such as IfType.
|
||||
*
|
||||
* @param value The JSON value representing the outer object, this value can be modified by the requirement inside
|
||||
* @param key The key used to retrieve the element from the outer object
|
||||
* @return Possibly an error
|
||||
*/
|
||||
[[nodiscard]] MaybeError
|
||||
verify(boost::json::value& value, std::string_view key) const
|
||||
{
|
||||
if (auto const res = requirement.verify(value, key); not res)
|
||||
return Error{error};
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rpc::meta
|
||||
|
||||
@@ -217,19 +217,13 @@ CustomValidator SubscribeAccountsValidator =
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator AMMAssetValidator =
|
||||
CustomValidator CurrencyIssueValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (not value.is_object())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotObject"}};
|
||||
|
||||
Json::Value jvAsset;
|
||||
if (value.as_object().contains(JS(issuer)))
|
||||
jvAsset["issuer"] = value.at(JS(issuer)).as_string().c_str();
|
||||
if (value.as_object().contains(JS(currency)))
|
||||
jvAsset["currency"] = value.at(JS(currency)).as_string().c_str();
|
||||
// same as rippled
|
||||
try {
|
||||
ripple::issueFromJson(jvAsset);
|
||||
parseIssue(value.as_object());
|
||||
} catch (std::runtime_error const&) {
|
||||
return Error{Status{ClioError::rpcMALFORMED_REQUEST}};
|
||||
}
|
||||
|
||||
@@ -513,6 +513,6 @@ extern CustomValidator SubscribeAccountsValidator;
|
||||
*
|
||||
* Used by amm_info.
|
||||
*/
|
||||
extern CustomValidator AMMAssetValidator;
|
||||
extern CustomValidator CurrencyIssueValidator;
|
||||
|
||||
} // namespace rpc::validation
|
||||
|
||||
@@ -232,7 +232,7 @@ AMMInfoHandler::spec([[maybe_unused]] uint32_t apiVersion)
|
||||
},
|
||||
meta::IfType<std::string>{stringIssueValidator},
|
||||
meta::IfType<boost::json::object>{
|
||||
meta::WithCustomError{validation::AMMAssetValidator, Status(RippledError::rpcISSUE_MALFORMED)},
|
||||
meta::WithCustomError{validation::CurrencyIssueValidator, Status(RippledError::rpcISSUE_MALFORMED)},
|
||||
}},
|
||||
{JS(asset2),
|
||||
meta::WithCustomError{
|
||||
@@ -240,7 +240,7 @@ AMMInfoHandler::spec([[maybe_unused]] uint32_t apiVersion)
|
||||
},
|
||||
meta::IfType<std::string>{stringIssueValidator},
|
||||
meta::IfType<boost::json::object>{
|
||||
meta::WithCustomError{validation::AMMAssetValidator, Status(RippledError::rpcISSUE_MALFORMED)},
|
||||
meta::WithCustomError{validation::CurrencyIssueValidator, Status(RippledError::rpcISSUE_MALFORMED)},
|
||||
}},
|
||||
{JS(amm_account), meta::WithCustomError{validation::AccountValidator, Status(RippledError::rpcACT_MALFORMED)}},
|
||||
{JS(account), meta::WithCustomError{validation::AccountValidator, Status(RippledError::rpcACT_MALFORMED)}},
|
||||
@@ -297,24 +297,11 @@ tag_invoke(boost::json::value_to_tag<AMMInfoHandler::Input>, boost::json::value
|
||||
}
|
||||
}
|
||||
|
||||
auto getIssue = [](boost::json::value const& request) {
|
||||
if (request.is_string())
|
||||
return ripple::issueFromJson(request.as_string().c_str());
|
||||
|
||||
// Note: no checks needed as we already validated the input if we made it here
|
||||
auto const currency = ripple::to_currency(request.at(JS(currency)).as_string().c_str());
|
||||
if (ripple::isXRP(currency)) {
|
||||
return ripple::xrpIssue();
|
||||
}
|
||||
auto const issuer = ripple::parseBase58<ripple::AccountID>(request.at(JS(issuer)).as_string().c_str());
|
||||
return ripple::Issue{currency, *issuer};
|
||||
};
|
||||
|
||||
if (jsonObject.contains(JS(asset)))
|
||||
input.issue1 = getIssue(jsonObject.at(JS(asset)));
|
||||
input.issue1 = parseIssue(jsonObject.at(JS(asset)).as_object());
|
||||
|
||||
if (jsonObject.contains(JS(asset2)))
|
||||
input.issue2 = getIssue(jsonObject.at(JS(asset2)));
|
||||
input.issue2 = parseIssue(jsonObject.at(JS(asset2)).as_object());
|
||||
|
||||
if (jsonObject.contains(JS(account)))
|
||||
input.accountID = accountFromStringStrict(jsonObject.at(JS(account)).as_string().c_str());
|
||||
|
||||
@@ -30,13 +30,16 @@
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/basics/strHex.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/protocol/AccountID.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/Issue.h>
|
||||
#include <ripple/protocol/LedgerFormats.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
#include <ripple/protocol/SField.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
#include <ripple/protocol/STXChainBridge.h>
|
||||
#include <ripple/protocol/Serializer.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
#include <ripple/protocol/jss.h>
|
||||
@@ -111,6 +114,24 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
getIssuerFromJson(input.amm->at(JS(asset))), getIssuerFromJson(input.amm->at(JS(asset2)))
|
||||
)
|
||||
.key;
|
||||
} else if (input.bridge) {
|
||||
if (!input.bridgeAccount && !input.chainClaimId && !input.createAccountClaimId)
|
||||
return Error{Status{ClioError::rpcMALFORMED_REQUEST}};
|
||||
|
||||
if (input.bridgeAccount) {
|
||||
auto const bridgeAccount = ripple::parseBase58<ripple::AccountID>(*(input.bridgeAccount));
|
||||
auto const chainType = ripple::STXChainBridge::srcChain(bridgeAccount == input.bridge->lockingChainDoor());
|
||||
|
||||
if (bridgeAccount != input.bridge->door(chainType))
|
||||
return Error{Status{ClioError::rpcMALFORMED_REQUEST}};
|
||||
|
||||
key = ripple::keylet::bridge(input.bridge->value(), chainType).key;
|
||||
} else if (input.chainClaimId) {
|
||||
key = ripple::keylet::xChainClaimID(input.bridge->value(), input.chainClaimId.value()).key;
|
||||
} else {
|
||||
key = ripple::keylet::xChainCreateAccountClaimID(input.bridge->value(), input.createAccountClaimId.value())
|
||||
.key;
|
||||
}
|
||||
} else {
|
||||
// Must specify 1 of the following fields to indicate what type
|
||||
if (ctx.apiVersion == 1)
|
||||
@@ -225,7 +246,24 @@ tag_invoke(boost::json::value_to_tag<LedgerEntryHandler::Input>, boost::json::va
|
||||
{JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
|
||||
{JS(ticket), ripple::ltTICKET},
|
||||
{JS(nft_page), ripple::ltNFTOKEN_PAGE},
|
||||
{JS(amm), ripple::ltAMM}
|
||||
{JS(amm), ripple::ltAMM},
|
||||
{JS(xchain_owned_create_account_claim_id), ripple::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID},
|
||||
{JS(xchain_owned_claim_id), ripple::ltXCHAIN_OWNED_CLAIM_ID},
|
||||
};
|
||||
|
||||
auto const parseBridgeFromJson = [](boost::json::value const& bridgeJson) {
|
||||
auto const lockingDoor = *ripple::parseBase58<ripple::AccountID>(
|
||||
bridgeJson.at(ripple::sfLockingChainDoor.getJsonName().c_str()).as_string().c_str()
|
||||
);
|
||||
auto const issuingDoor = *ripple::parseBase58<ripple::AccountID>(
|
||||
bridgeJson.at(ripple::sfIssuingChainDoor.getJsonName().c_str()).as_string().c_str()
|
||||
);
|
||||
auto const lockingIssue =
|
||||
parseIssue(bridgeJson.at(ripple::sfLockingChainIssue.getJsonName().c_str()).as_object());
|
||||
auto const issuingIssue =
|
||||
parseIssue(bridgeJson.at(ripple::sfIssuingChainIssue.getJsonName().c_str()).as_object());
|
||||
|
||||
return ripple::STXChainBridge{lockingDoor, lockingIssue, issuingDoor, issuingIssue};
|
||||
};
|
||||
|
||||
auto const indexFieldType =
|
||||
@@ -259,6 +297,19 @@ tag_invoke(boost::json::value_to_tag<LedgerEntryHandler::Input>, boost::json::va
|
||||
input.ticket = jv.at(JS(ticket)).as_object();
|
||||
} else if (jsonObject.contains(JS(amm))) {
|
||||
input.amm = jv.at(JS(amm)).as_object();
|
||||
} else if (jsonObject.contains(JS(bridge))) {
|
||||
input.bridge.emplace(parseBridgeFromJson(jv.at(JS(bridge))));
|
||||
if (jsonObject.contains(JS(bridge_account)))
|
||||
input.bridgeAccount = jv.at(JS(bridge_account)).as_string().c_str();
|
||||
} else if (jsonObject.contains(JS(xchain_owned_claim_id))) {
|
||||
input.bridge.emplace(parseBridgeFromJson(jv.at(JS(xchain_owned_claim_id))));
|
||||
input.chainClaimId =
|
||||
boost::json::value_to<std::int32_t>(jv.at(JS(xchain_owned_claim_id)).at(JS(xchain_owned_claim_id)));
|
||||
} else if (jsonObject.contains(JS(xchain_owned_create_account_claim_id))) {
|
||||
input.bridge.emplace(parseBridgeFromJson(jv.at(JS(xchain_owned_create_account_claim_id))));
|
||||
input.createAccountClaimId = boost::json::value_to<std::int32_t>(
|
||||
jv.at(JS(xchain_owned_create_account_claim_id)).at(JS(xchain_owned_create_account_claim_id))
|
||||
);
|
||||
}
|
||||
|
||||
return input;
|
||||
|
||||
@@ -20,11 +20,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "data/BackendInterface.h"
|
||||
#include "rpc/RPCHelpers.h"
|
||||
#include "rpc/Errors.h"
|
||||
#include "rpc/JS.h"
|
||||
#include "rpc/common/MetaProcessors.h"
|
||||
#include "rpc/common/Types.h"
|
||||
#include "rpc/common/Validators.h"
|
||||
|
||||
#include <boost/json/conversion.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/protocol/AccountID.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/protocol/Issue.h>
|
||||
#include <ripple/protocol/LedgerFormats.h>
|
||||
#include <ripple/protocol/SField.h>
|
||||
#include <ripple/protocol/jss.h>
|
||||
#include <ripple/protocol/tokens.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
/**
|
||||
@@ -66,6 +86,10 @@ public:
|
||||
std::optional<boost::json::object> depositPreauth;
|
||||
std::optional<boost::json::object> ticket;
|
||||
std::optional<boost::json::object> amm;
|
||||
std::optional<ripple::STXChainBridge> bridge;
|
||||
std::optional<std::string> bridgeAccount;
|
||||
std::optional<uint32_t> chainClaimId;
|
||||
std::optional<uint32_t> createAccountClaimId;
|
||||
};
|
||||
|
||||
using Result = HandlerReturnType<Output>;
|
||||
@@ -103,6 +127,24 @@ public:
|
||||
static auto const malformedRequestIntValidator =
|
||||
meta::WithCustomError{validation::Type<uint32_t>{}, Status(ClioError::rpcMALFORMED_REQUEST)};
|
||||
|
||||
static auto const bridgeJsonValidator = meta::WithCustomError{
|
||||
meta::IfType<boost::json::object>{meta::Section{
|
||||
{ripple::sfLockingChainDoor.getJsonName().c_str(),
|
||||
validation::Required{},
|
||||
validation::AccountBase58Validator},
|
||||
{ripple::sfIssuingChainDoor.getJsonName().c_str(),
|
||||
validation::Required{},
|
||||
validation::AccountBase58Validator},
|
||||
{ripple::sfLockingChainIssue.getJsonName().c_str(),
|
||||
validation::Required{},
|
||||
validation::CurrencyIssueValidator},
|
||||
{ripple::sfIssuingChainIssue.getJsonName().c_str(),
|
||||
validation::Required{},
|
||||
validation::CurrencyIssueValidator},
|
||||
}},
|
||||
Status(ClioError::rpcMALFORMED_REQUEST)
|
||||
};
|
||||
|
||||
static auto const rpcSpec = RpcSpec{
|
||||
{JS(binary), validation::Type<bool>{}},
|
||||
{JS(ledger_hash), validation::Uint256HexStringValidator},
|
||||
@@ -177,15 +219,44 @@ public:
|
||||
meta::WithCustomError{
|
||||
validation::Type<boost::json::object>{}, Status(ClioError::rpcMALFORMED_REQUEST)
|
||||
},
|
||||
validation::AMMAssetValidator},
|
||||
validation::CurrencyIssueValidator},
|
||||
{JS(asset2),
|
||||
meta::WithCustomError{validation::Required{}, Status(ClioError::rpcMALFORMED_REQUEST)},
|
||||
meta::WithCustomError{
|
||||
validation::Type<boost::json::object>{}, Status(ClioError::rpcMALFORMED_REQUEST)
|
||||
},
|
||||
validation::AMMAssetValidator},
|
||||
validation::CurrencyIssueValidator},
|
||||
},
|
||||
}}
|
||||
}},
|
||||
{JS(bridge),
|
||||
meta::WithCustomError{validation::Type<boost::json::object>{}, Status(ClioError::rpcMALFORMED_REQUEST)},
|
||||
bridgeJsonValidator},
|
||||
{JS(bridge_account),
|
||||
meta::WithCustomError{validation::AccountBase58Validator, Status(ClioError::rpcMALFORMED_REQUEST)}},
|
||||
{JS(xchain_owned_claim_id),
|
||||
meta::WithCustomError{
|
||||
validation::Type<std::string, boost::json::object>{}, Status(ClioError::rpcMALFORMED_REQUEST)
|
||||
},
|
||||
meta::IfType<std::string>{malformedRequestHexStringValidator},
|
||||
bridgeJsonValidator,
|
||||
meta::WithCustomError{
|
||||
meta::IfType<boost::json::object>{
|
||||
meta::Section{{JS(xchain_owned_claim_id), validation::Required{}, validation::Type<uint32_t>{}}}
|
||||
},
|
||||
Status(ClioError::rpcMALFORMED_REQUEST)
|
||||
}},
|
||||
{JS(xchain_owned_create_account_claim_id),
|
||||
meta::WithCustomError{
|
||||
validation::Type<std::string, boost::json::object>{}, Status(ClioError::rpcMALFORMED_REQUEST)
|
||||
},
|
||||
meta::IfType<std::string>{malformedRequestHexStringValidator},
|
||||
bridgeJsonValidator,
|
||||
meta::WithCustomError{
|
||||
meta::IfType<boost::json::object>{meta::Section{
|
||||
{JS(xchain_owned_create_account_claim_id), validation::Required{}, validation::Type<uint32_t>{}}
|
||||
}},
|
||||
Status(ClioError::rpcMALFORMED_REQUEST)
|
||||
}},
|
||||
};
|
||||
|
||||
return rpcSpec;
|
||||
|
||||
@@ -36,11 +36,13 @@
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/SField.h>
|
||||
#include <ripple/protocol/STObject.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
#include <ripple/protocol/jss.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
@@ -502,3 +504,38 @@ TEST_F(RPCHelpersTest, TransactionAndMetadataBinaryJsonV2)
|
||||
EXPECT_TRUE(json.contains(JS(tx_blob)));
|
||||
EXPECT_TRUE(json.contains(JS(meta_blob)));
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, ParseIssue)
|
||||
{
|
||||
auto issue = parseIssue(boost::json::parse(
|
||||
R"({
|
||||
"issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun",
|
||||
"currency": "JPY"
|
||||
})"
|
||||
)
|
||||
.as_object());
|
||||
EXPECT_TRUE(issue.account == GetAccountIDWithString(ACCOUNT2));
|
||||
|
||||
issue = parseIssue(boost::json::parse(R"({"currency": "XRP"})").as_object());
|
||||
EXPECT_TRUE(ripple::isXRP(issue.currency));
|
||||
|
||||
EXPECT_THROW(parseIssue(boost::json::parse(R"({"currency": 2})").as_object()), std::runtime_error);
|
||||
|
||||
EXPECT_THROW(parseIssue(boost::json::parse(R"({"currency": "XRP2"})").as_object()), std::runtime_error);
|
||||
|
||||
EXPECT_THROW(
|
||||
parseIssue(boost::json::parse(
|
||||
R"({
|
||||
"issuer": "abcd",
|
||||
"currency": "JPY"
|
||||
})"
|
||||
)
|
||||
.as_object()),
|
||||
std::runtime_error
|
||||
);
|
||||
|
||||
EXPECT_THROW(
|
||||
parseIssue(boost::json::parse(R"({"issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun"})").as_object()),
|
||||
std::runtime_error
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,10 @@
|
||||
#include <ripple/basics/strHex.h>
|
||||
#include <ripple/protocol/AccountID.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/Issue.h>
|
||||
#include <ripple/protocol/LedgerFormats.h>
|
||||
#include <ripple/protocol/STObject.h>
|
||||
#include <ripple/protocol/STXChainBridge.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
|
||||
#include <optional>
|
||||
@@ -49,6 +51,7 @@ using namespace testing;
|
||||
constexpr static auto INDEX1 = "05FB0EB4B899F056FA095537C5817163801F544BAFCEA39C995D76DB4D16F9DD";
|
||||
constexpr static auto ACCOUNT = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
|
||||
constexpr static auto ACCOUNT2 = "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun";
|
||||
constexpr static auto ACCOUNT3 = "rhzcyub9SbyZ4YF1JYskN5rLrTDUuLZG6D";
|
||||
constexpr static auto RANGEMIN = 10;
|
||||
constexpr static auto RANGEMAX = 30;
|
||||
constexpr static auto LEDGERHASH = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652";
|
||||
@@ -881,6 +884,668 @@ generateTestValuesForParametersTest()
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeMissingBridgeAccount",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeCurrencyIsNumber",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": {},
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
1,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeIssuerIsNumber",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": {}
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeIssuingChainIssueIsNotObject",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue": 1
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeWithInvalidBridgeAccount",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "abcd",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeDoorInvalid",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "abcd",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeIssuerInvalid",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "invalid"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY"
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeIssueCurrencyInvalid",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "JPJPJP",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeIssueXRPCurrencyInvalid",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP",
|
||||
"issuer": "{}"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "JPY",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
ACCOUNT2,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeIssueJPYCurrencyInvalid",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "JPY"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeMissingLockingChainDoor",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP",
|
||||
"issuer": "{}"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "JPY",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
ACCOUNT2,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeMissingIssuingChainDoor",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "JPY",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeMissingLockingChainIssue",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "JPY",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeMissingIssuingChainIssue",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge":
|
||||
{{
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "JPY",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"BridgeInvalidType",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"bridge_account": "{}",
|
||||
"bridge": "invalid"
|
||||
}})",
|
||||
ACCOUNT
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedClaimIdInvalidType",
|
||||
R"({
|
||||
"xchain_owned_claim_id": 123
|
||||
})",
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedClaimIdJsonMissingClaimId",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_claim_id":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedClaimIdJsonMissingDoor",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_claim_id":
|
||||
{{
|
||||
"xchain_owned_claim_id": 10,
|
||||
"LockingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedClaimIdJsonMissingIssue",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_claim_id":
|
||||
{{
|
||||
"xchain_owned_claim_id": 10,
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT
|
||||
),
|
||||
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedClaimIdJsonInvalidDoor",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_claim_id":
|
||||
{{
|
||||
"xchain_owned_claim_id": 10,
|
||||
"LockingChainDoor": "abcd",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedClaimIdJsonInvalidIssue",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_claim_id":
|
||||
{{
|
||||
"xchain_owned_claim_id": 10,
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY"
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedCreateAccountClaimIdInvalidType",
|
||||
R"({
|
||||
"xchain_owned_create_account_claim_id": 123
|
||||
})",
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedCreateAccountClaimIdJsonMissingClaimId",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_create_account_claim_id":
|
||||
{{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedCreateAccountClaimIdJsonMissingDoor",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_create_account_claim_id":
|
||||
{{
|
||||
"xchain_owned_create_account_claim_id": 10,
|
||||
"LockingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedCreateAccountClaimIdJsonMissingIssue",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_create_account_claim_id":
|
||||
{{
|
||||
"xchain_owned_create_account_claim_id": 10,
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT
|
||||
),
|
||||
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedCreateAccountClaimIdJsonInvalidDoor",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_create_account_claim_id":
|
||||
{{
|
||||
"xchain_owned_create_account_claim_id": 10,
|
||||
"LockingChainDoor": "abcd",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}",
|
||||
"issuer": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
"JPY",
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"OwnedCreateAccountClaimIdJsonInvalidIssue",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"xchain_owned_create_account_claim_id":
|
||||
{{
|
||||
"xchain_owned_create_account_claim_id": 10,
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue":
|
||||
{{
|
||||
"currency": "XRP"
|
||||
}},
|
||||
"IssuingChainIssue":
|
||||
{{
|
||||
"currency": "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
"JPY"
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1314,7 +1979,145 @@ generateTestValuesForNormalPathTest()
|
||||
),
|
||||
ripple::keylet::amm(GetIssue("XRP", ripple::toBase58(ripple::xrpAccount())), GetIssue("JPY", ACCOUNT2)).key,
|
||||
CreateAMMObject(ACCOUNT, "XRP", ripple::toBase58(ripple::xrpAccount()), "JPY", ACCOUNT2)
|
||||
}
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"BridgeLocking",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"binary": true,
|
||||
"bridge_account": "{}",
|
||||
"bridge": {{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue": {{
|
||||
"currency" : "XRP"
|
||||
}},
|
||||
"IssuingChainIssue": {{
|
||||
"currency" : "JPY",
|
||||
"issuer" : "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
ACCOUNT3
|
||||
),
|
||||
ripple::keylet::bridge(
|
||||
ripple::STXChainBridge(
|
||||
GetAccountIDWithString(ACCOUNT),
|
||||
ripple::xrpIssue(),
|
||||
GetAccountIDWithString(ACCOUNT2),
|
||||
GetIssue("JPY", ACCOUNT3)
|
||||
),
|
||||
ripple::STXChainBridge::ChainType::locking
|
||||
)
|
||||
.key,
|
||||
CreateBridgeObject(ACCOUNT, ACCOUNT, ACCOUNT2, "JPY", ACCOUNT3)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"BridgeIssuing",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"binary": true,
|
||||
"bridge_account": "{}",
|
||||
"bridge": {{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue": {{
|
||||
"currency" : "XRP"
|
||||
}},
|
||||
"IssuingChainIssue": {{
|
||||
"currency" : "JPY",
|
||||
"issuer" : "{}"
|
||||
}}
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT2,
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
ACCOUNT3
|
||||
),
|
||||
ripple::keylet::bridge(
|
||||
ripple::STXChainBridge(
|
||||
GetAccountIDWithString(ACCOUNT),
|
||||
ripple::xrpIssue(),
|
||||
GetAccountIDWithString(ACCOUNT2),
|
||||
GetIssue("JPY", ACCOUNT3)
|
||||
),
|
||||
ripple::STXChainBridge::ChainType::issuing
|
||||
)
|
||||
.key,
|
||||
CreateBridgeObject(ACCOUNT, ACCOUNT, ACCOUNT2, "JPY", ACCOUNT3)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"XChainOwnedClaimId",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"binary": true,
|
||||
"xchain_owned_claim_id": {{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue": {{
|
||||
"currency" : "XRP"
|
||||
}},
|
||||
"IssuingChainIssue": {{
|
||||
"currency" : "JPY",
|
||||
"issuer" : "{}"
|
||||
}},
|
||||
"xchain_owned_claim_id": 10
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
ACCOUNT3
|
||||
),
|
||||
ripple::keylet::xChainClaimID(
|
||||
ripple::STXChainBridge(
|
||||
GetAccountIDWithString(ACCOUNT),
|
||||
ripple::xrpIssue(),
|
||||
GetAccountIDWithString(ACCOUNT2),
|
||||
GetIssue("JPY", ACCOUNT3)
|
||||
),
|
||||
10
|
||||
)
|
||||
.key,
|
||||
CreateChainOwnedClaimIDObject(ACCOUNT, ACCOUNT, ACCOUNT2, "JPY", ACCOUNT3, ACCOUNT)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"XChainOwnedCreateAccountClaimId",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"binary": true,
|
||||
"xchain_owned_create_account_claim_id": {{
|
||||
"LockingChainDoor": "{}",
|
||||
"IssuingChainDoor": "{}",
|
||||
"LockingChainIssue": {{
|
||||
"currency" : "XRP"
|
||||
}},
|
||||
"IssuingChainIssue": {{
|
||||
"currency" : "JPY",
|
||||
"issuer" : "{}"
|
||||
}},
|
||||
"xchain_owned_create_account_claim_id": 10
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
ACCOUNT3
|
||||
),
|
||||
ripple::keylet::xChainCreateAccountClaimID(
|
||||
ripple::STXChainBridge(
|
||||
GetAccountIDWithString(ACCOUNT),
|
||||
ripple::xrpIssue(),
|
||||
GetAccountIDWithString(ACCOUNT2),
|
||||
GetIssue("JPY", ACCOUNT3)
|
||||
),
|
||||
10
|
||||
)
|
||||
.key,
|
||||
CreateChainOwnedClaimIDObject(ACCOUNT, ACCOUNT, ACCOUNT2, "JPY", ACCOUNT3, ACCOUNT)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <ripple/basics/Slice.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/basics/chrono.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/protocol/AMMCore.h>
|
||||
#include <ripple/protocol/AccountID.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
@@ -838,6 +839,113 @@ CreateAMMObject(
|
||||
return amm;
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
CreateBridgeObject(
|
||||
std::string_view accountId,
|
||||
std::string_view lockingDoor,
|
||||
std::string_view issuingDoor,
|
||||
std::string_view issuingCurrency,
|
||||
std::string_view issuingIssuer
|
||||
)
|
||||
{
|
||||
auto bridge = ripple::STObject(ripple::sfLedgerEntry);
|
||||
bridge.setFieldU16(ripple::sfLedgerEntryType, ripple::ltBRIDGE);
|
||||
bridge.setAccountID(ripple::sfAccount, GetAccountIDWithString(accountId));
|
||||
bridge.setFieldAmount(ripple::sfSignatureReward, ripple::STAmount(10, false));
|
||||
bridge.setFieldU64(ripple::sfXChainClaimID, 100);
|
||||
bridge.setFieldU64(ripple::sfXChainAccountCreateCount, 100);
|
||||
bridge.setFieldU64(ripple::sfXChainAccountClaimCount, 100);
|
||||
bridge.setFieldU64(ripple::sfOwnerNode, 100);
|
||||
bridge.setFieldH256(ripple::sfPreviousTxnID, ripple::uint256{});
|
||||
bridge.setFieldU32(ripple::sfPreviousTxnLgrSeq, 0);
|
||||
bridge.setFieldU32(ripple::sfFlags, 0);
|
||||
Json::Value lockingIssue;
|
||||
lockingIssue["currency"] = "XRP";
|
||||
Json::Value issuingIssue;
|
||||
issuingIssue["currency"] = std::string(issuingCurrency);
|
||||
issuingIssue["issuer"] = std::string(issuingIssuer);
|
||||
|
||||
bridge[ripple::sfXChainBridge] = ripple::STXChainBridge(
|
||||
GetAccountIDWithString(lockingDoor),
|
||||
ripple::issueFromJson(lockingIssue),
|
||||
GetAccountIDWithString(issuingDoor),
|
||||
ripple::issueFromJson(issuingIssue)
|
||||
);
|
||||
bridge.setFieldU32(ripple::sfFlags, 0);
|
||||
return bridge;
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
CreateChainOwnedClaimIDObject(
|
||||
std::string_view accountId,
|
||||
std::string_view lockingDoor,
|
||||
std::string_view issuingDoor,
|
||||
std::string_view issuingCurrency,
|
||||
std::string_view issuingIssuer,
|
||||
std::string_view otherChainSource
|
||||
)
|
||||
{
|
||||
auto chainOwnedClaimID = ripple::STObject(ripple::sfLedgerEntry);
|
||||
chainOwnedClaimID.setFieldU16(ripple::sfLedgerEntryType, ripple::ltXCHAIN_OWNED_CLAIM_ID);
|
||||
chainOwnedClaimID.setAccountID(ripple::sfAccount, GetAccountIDWithString(accountId));
|
||||
chainOwnedClaimID.setFieldAmount(ripple::sfSignatureReward, ripple::STAmount(10, false));
|
||||
chainOwnedClaimID.setFieldU64(ripple::sfXChainClaimID, 100);
|
||||
chainOwnedClaimID.setFieldU64(ripple::sfOwnerNode, 100);
|
||||
chainOwnedClaimID.setFieldH256(ripple::sfPreviousTxnID, ripple::uint256{});
|
||||
chainOwnedClaimID.setFieldU32(ripple::sfPreviousTxnLgrSeq, 0);
|
||||
chainOwnedClaimID.setFieldU32(ripple::sfFlags, 0);
|
||||
Json::Value lockingIssue;
|
||||
lockingIssue["currency"] = "XRP";
|
||||
Json::Value issuingIssue;
|
||||
issuingIssue["currency"] = std::string(issuingCurrency);
|
||||
issuingIssue["issuer"] = std::string(issuingIssuer);
|
||||
|
||||
chainOwnedClaimID[ripple::sfXChainBridge] = ripple::STXChainBridge(
|
||||
GetAccountIDWithString(lockingDoor),
|
||||
ripple::issueFromJson(lockingIssue),
|
||||
GetAccountIDWithString(issuingDoor),
|
||||
ripple::issueFromJson(issuingIssue)
|
||||
);
|
||||
chainOwnedClaimID.setFieldU32(ripple::sfFlags, 0);
|
||||
chainOwnedClaimID.setAccountID(ripple::sfOtherChainSource, GetAccountIDWithString(otherChainSource));
|
||||
chainOwnedClaimID.setFieldArray(ripple::sfXChainClaimAttestations, ripple::STArray{});
|
||||
return chainOwnedClaimID;
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
CreateChainOwnedCreateAccountClaimID(
|
||||
std::string_view accountId,
|
||||
std::string_view lockingDoor,
|
||||
std::string_view issuingDoor,
|
||||
std::string_view issuingCurrency,
|
||||
std::string_view issuingIssuer
|
||||
)
|
||||
{
|
||||
auto chainOwnedCreateAccountClaimID = ripple::STObject(ripple::sfLedgerEntry);
|
||||
chainOwnedCreateAccountClaimID.setFieldU16(ripple::sfLedgerEntryType, ripple::ltXCHAIN_OWNED_CLAIM_ID);
|
||||
chainOwnedCreateAccountClaimID.setAccountID(ripple::sfAccount, GetAccountIDWithString(accountId));
|
||||
chainOwnedCreateAccountClaimID.setFieldU64(ripple::sfXChainAccountCreateCount, 100);
|
||||
chainOwnedCreateAccountClaimID.setFieldU64(ripple::sfOwnerNode, 100);
|
||||
chainOwnedCreateAccountClaimID.setFieldH256(ripple::sfPreviousTxnID, ripple::uint256{});
|
||||
chainOwnedCreateAccountClaimID.setFieldU32(ripple::sfPreviousTxnLgrSeq, 0);
|
||||
chainOwnedCreateAccountClaimID.setFieldU32(ripple::sfFlags, 0);
|
||||
Json::Value lockingIssue;
|
||||
lockingIssue["currency"] = "XRP";
|
||||
Json::Value issuingIssue;
|
||||
issuingIssue["currency"] = std::string(issuingCurrency);
|
||||
issuingIssue["issuer"] = std::string(issuingIssuer);
|
||||
|
||||
chainOwnedCreateAccountClaimID[ripple::sfXChainBridge] = ripple::STXChainBridge(
|
||||
GetAccountIDWithString(lockingDoor),
|
||||
ripple::issueFromJson(lockingIssue),
|
||||
GetAccountIDWithString(issuingDoor),
|
||||
ripple::issueFromJson(issuingIssue)
|
||||
);
|
||||
chainOwnedCreateAccountClaimID.setFieldU32(ripple::sfFlags, 0);
|
||||
chainOwnedCreateAccountClaimID.setFieldArray(ripple::sfXChainCreateAccountAttestations, ripple::STArray{});
|
||||
return chainOwnedCreateAccountClaimID;
|
||||
}
|
||||
|
||||
void
|
||||
AMMAddVoteSlot(ripple::STObject& amm, ripple::AccountID const& accountId, uint16_t tradingFee, uint32_t voteWeight)
|
||||
{
|
||||
|
||||
@@ -303,6 +303,34 @@ CreateAMMObject(
|
||||
uint64_t ownerNode = 0u
|
||||
);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
CreateBridgeObject(
|
||||
std::string_view accountId,
|
||||
std::string_view lockingDoor,
|
||||
std::string_view issuingDoor,
|
||||
std::string_view issuingCurrency,
|
||||
std::string_view issuingIssuer
|
||||
);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
CreateChainOwnedClaimIDObject(
|
||||
std::string_view accountId,
|
||||
std::string_view lockingDoor,
|
||||
std::string_view issuingDoor,
|
||||
std::string_view issuingCurrency,
|
||||
std::string_view issuingIssuer,
|
||||
std::string_view otherChainSource
|
||||
);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
CreateChainOwnedCreateAccountClaimID(
|
||||
std::string_view accountId,
|
||||
std::string_view lockingDoor,
|
||||
std::string_view issuingDoor,
|
||||
std::string_view issuingCurrency,
|
||||
std::string_view issuingIssuer
|
||||
);
|
||||
|
||||
void
|
||||
AMMAddVoteSlot(ripple::STObject& amm, ripple::AccountID const& accountId, uint16_t tradingFee, uint32_t voteWeight);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user