Skip to content

Commit e6f8bc7

Browse files
authored
Add additional metadata to simulate response (#5754)
1 parent fbd60fc commit e6f8bc7

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

src/test/rpc/Simulate_test.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,32 @@ class Simulate_test : public beast::unit_test::suite
131131
std::to_string(env.current()->txCount()));
132132
}
133133

134+
void
135+
testTxJsonMetadataField(
136+
jtx::Env& env,
137+
Json::Value const& tx,
138+
std::function<void(
139+
Json::Value const&,
140+
Json::Value const&,
141+
Json::Value const&)> const& validate,
142+
Json::Value const& expectedMetadataKey,
143+
bool testSerialized = true)
144+
{
145+
env.close();
146+
147+
Json::Value params;
148+
params[jss::tx_json] = tx;
149+
validate(
150+
env.rpc("json", "simulate", to_string(params)),
151+
tx,
152+
expectedMetadataKey);
153+
validate(env.rpc("simulate", to_string(tx)), tx, expectedMetadataKey);
154+
155+
BEAST_EXPECTS(
156+
env.current()->txCount() == 0,
157+
std::to_string(env.current()->txCount()));
158+
}
159+
134160
Json::Value
135161
getJsonMetadata(Json::Value txResult) const
136162
{
@@ -1186,6 +1212,83 @@ class Simulate_test : public beast::unit_test::suite
11861212
}
11871213
}
11881214

1215+
void
1216+
testSuccessfulTransactionAdditionalMetadata()
1217+
{
1218+
testcase("Successful transaction with additional metadata");
1219+
1220+
using namespace jtx;
1221+
Env env{*this, envconfig([&](std::unique_ptr<Config> cfg) {
1222+
cfg->NETWORK_ID = 1025;
1223+
return cfg;
1224+
})};
1225+
1226+
Account const alice("alice");
1227+
1228+
env.fund(XRP(10000), alice);
1229+
env.close();
1230+
1231+
{
1232+
auto validateOutput = [&](Json::Value const& resp,
1233+
Json::Value const& tx,
1234+
Json::Value const& expectedMetadataKey) {
1235+
auto result = resp[jss::result];
1236+
1237+
BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS");
1238+
BEAST_EXPECT(result[jss::engine_result_code] == 0);
1239+
BEAST_EXPECT(
1240+
result[jss::engine_result_message] ==
1241+
"The simulated transaction would have been applied.");
1242+
1243+
if (BEAST_EXPECT(
1244+
result.isMember(jss::meta) ||
1245+
result.isMember(jss::meta_blob)))
1246+
{
1247+
Json::Value const metadata = getJsonMetadata(result);
1248+
1249+
BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0);
1250+
BEAST_EXPECT(
1251+
metadata[sfTransactionResult.jsonName] == "tesSUCCESS");
1252+
BEAST_EXPECT(
1253+
metadata.isMember(expectedMetadataKey.asString()));
1254+
}
1255+
};
1256+
1257+
{
1258+
Json::Value tx;
1259+
tx[jss::Account] = env.master.human();
1260+
tx[jss::TransactionType] = jss::Payment;
1261+
tx[sfDestination] = alice.human();
1262+
tx[sfAmount] = "100";
1263+
1264+
// test delivered amount
1265+
testTxJsonMetadataField(
1266+
env, tx, validateOutput, jss::delivered_amount);
1267+
}
1268+
1269+
{
1270+
Json::Value tx;
1271+
tx[jss::Account] = env.master.human();
1272+
tx[jss::TransactionType] = jss::NFTokenMint;
1273+
tx[sfNFTokenTaxon] = 1;
1274+
1275+
// test nft synthetic
1276+
testTxJsonMetadataField(
1277+
env, tx, validateOutput, jss::nftoken_id);
1278+
}
1279+
1280+
{
1281+
Json::Value tx;
1282+
tx[jss::Account] = env.master.human();
1283+
tx[jss::TransactionType] = jss::MPTokenIssuanceCreate;
1284+
1285+
// test mpt issuance id
1286+
testTxJsonMetadataField(
1287+
env, tx, validateOutput, jss::mpt_issuance_id);
1288+
}
1289+
}
1290+
}
1291+
11891292
public:
11901293
void
11911294
run() override
@@ -1202,6 +1305,7 @@ class Simulate_test : public beast::unit_test::suite
12021305
testMultisignedBadPubKey();
12031306
testDeleteExpiredCredentials();
12041307
testSuccessfulTransactionNetworkID();
1308+
testSuccessfulTransactionAdditionalMetadata();
12051309
}
12061310
};
12071311

src/xrpld/rpc/handlers/Simulate.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@
2424
#include <xrpld/app/misc/TxQ.h>
2525
#include <xrpld/app/tx/apply.h>
2626
#include <xrpld/rpc/Context.h>
27+
#include <xrpld/rpc/DeliveredAmount.h>
2728
#include <xrpld/rpc/GRPCHandlers.h>
29+
#include <xrpld/rpc/MPTokenIssuanceID.h>
2830
#include <xrpld/rpc/detail/TransactionSign.h>
2931

3032
#include <xrpl/protocol/ErrorCodes.h>
33+
#include <xrpl/protocol/NFTSyntheticSerializer.h>
3134
#include <xrpl/protocol/RPCErr.h>
3235
#include <xrpl/protocol/STParsedJSON.h>
3336
#include <xrpl/resource/Fees.h>
@@ -272,6 +275,17 @@ simulateTxn(RPC::JsonContext& context, std::shared_ptr<Transaction> transaction)
272275
else
273276
{
274277
jvResult[jss::meta] = result.metadata->getJson(JsonOptions::none);
278+
RPC::insertDeliveredAmount(
279+
jvResult[jss::meta],
280+
view,
281+
transaction->getSTransaction(),
282+
*result.metadata);
283+
RPC::insertNFTSyntheticInJson(
284+
jvResult, transaction->getSTransaction(), *result.metadata);
285+
RPC::insertMPTokenIssuanceID(
286+
jvResult[jss::meta],
287+
transaction->getSTransaction(),
288+
*result.metadata);
275289
}
276290
}
277291

0 commit comments

Comments
 (0)