rippled
Loading...
Searching...
No Matches
GatewayBalances_test.cpp
1#include <test/jtx.h>
2#include <test/jtx/WSClient.h>
3
4#include <xrpl/beast/unit_test.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/jss.h>
7
8namespace xrpl {
9namespace test {
10
12{
13public:
14 void
16 {
17 using namespace std::chrono_literals;
18 using namespace jtx;
19 Env env(*this, features);
20
21 {
22 // Gateway account and assets
23 Account const alice{"alice"};
24 env.fund(XRP(10000), "alice");
25 auto USD = alice["USD"];
26 auto CNY = alice["CNY"];
27 auto JPY = alice["JPY"];
28
29 // Create a hotwallet
30 Account const hw{"hw"};
31 env.fund(XRP(10000), "hw");
32 env.close();
33 env(trust(hw, USD(10000)));
34 env(trust(hw, JPY(10000)));
35 env(pay(alice, hw, USD(5000)));
36 env(pay(alice, hw, JPY(5000)));
37
38 // Create some clients
39 Account const bob{"bob"};
40 env.fund(XRP(10000), "bob");
41 env.close();
42 env(trust(bob, USD(100)));
43 env(trust(bob, CNY(100)));
44 env(pay(alice, bob, USD(50)));
45
46 Account const charley{"charley"};
47 env.fund(XRP(10000), "charley");
48 env.close();
49 env(trust(charley, CNY(500)));
50 env(trust(charley, JPY(500)));
51 env(pay(alice, charley, CNY(250)));
52 env(pay(alice, charley, JPY(250)));
53
54 Account const dave{"dave"};
55 env.fund(XRP(10000), "dave");
56 env.close();
57 env(trust(dave, CNY(100)));
58 env(pay(alice, dave, CNY(30)));
59
60 // give the gateway an asset
61 env(trust(alice, charley["USD"](50)));
62 env(pay(charley, alice, USD(10)));
63
64 // freeze dave
65 env(trust(alice, dave["CNY"](0), dave, tfSetFreeze));
66
67 env.close();
68
69 auto wsc = makeWSClient(env.app().config());
70
71 Json::Value qry;
72 qry[jss::account] = alice.human();
73 qry[jss::hotwallet] = hw.human();
74
75 auto jv = wsc->invoke("gateway_balances", qry);
76 expect(jv[jss::status] == "success");
77 if (wsc->version() == 2)
78 {
79 expect(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
80 expect(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
81 expect(jv.isMember(jss::id) && jv[jss::id] == 5);
82 }
83
84 auto const& result = jv[jss::result];
85 expect(result[jss::account] == alice.human());
86 expect(result[jss::status] == "success");
87
88 {
89 auto const& balances = result[jss::balances];
90 expect(balances.isObject(), "balances is not an object");
91 expect(balances.size() == 1, "balances size is not 1");
92
93 auto const& hwBalance = balances[hw.human()];
94 expect(hwBalance.isArray(), "hwBalance is not an array");
95 expect(hwBalance.size() == 2);
96 auto c1 = hwBalance[0u][jss::currency];
97 auto c2 = hwBalance[1u][jss::currency];
98 expect(c1 == "USD" || c2 == "USD");
99 expect(c1 == "JPY" || c2 == "JPY");
100 expect(hwBalance[0u][jss::value] == "5000" && hwBalance[1u][jss::value] == "5000");
101 }
102
103 {
104 auto const& fBalances = result[jss::frozen_balances];
105 expect(fBalances.isObject());
106 expect(fBalances.size() == 1);
107
108 auto const& fBal = fBalances[dave.human()];
109 expect(fBal.isArray());
110 expect(fBal.size() == 1);
111 expect(fBal[0u].isObject());
112 expect(fBal[0u][jss::currency] == "CNY");
113 expect(fBal[0u][jss::value] == "30");
114 }
115
116 {
117 auto const& assets = result[jss::assets];
118 expect(assets.isObject(), "assets it not an object");
119 expect(assets.size() == 1, "assets size is not 1");
120
121 auto const& cAssets = assets[charley.human()];
122 expect(cAssets.isArray());
123 expect(cAssets.size() == 1);
124 expect(cAssets[0u][jss::currency] == "USD");
125 expect(cAssets[0u][jss::value] == "10");
126 }
127
128 {
129 auto const& obligations = result[jss::obligations];
130 expect(obligations.isObject(), "obligations is not an object");
131 expect(obligations.size() == 3);
132 expect(obligations["CNY"] == "250");
133 expect(obligations["JPY"] == "250");
134 expect(obligations["USD"] == "50");
135 }
136 }
137 }
138
139 void
141 {
142 using namespace std::chrono_literals;
143 using namespace jtx;
144 Env env(*this, features);
145
146 // Gateway account and assets
147 Account const alice{"alice"};
148 env.fund(XRP(10000), alice);
149 Account const hw{"hw"};
150 env.fund(XRP(10000), hw);
151 env.close();
152
153 auto wsc = makeWSClient(env.app().config());
154
155 Json::Value qry2;
156 qry2[jss::account] = alice.human();
157 qry2[jss::hotwallet] = "asdf";
158
159 forAllApiVersions([&, this](unsigned apiVersion) {
160 qry2[jss::api_version] = apiVersion;
161 auto jv = wsc->invoke("gateway_balances", qry2);
162 expect(jv[jss::status] == "error");
163
164 auto response = jv[jss::result];
165 auto const error = apiVersion < 2u ? "invalidHotWallet" : "invalidParams";
166 BEAST_EXPECT(response[jss::error] == error);
167 });
168 }
169
170 void
172 {
173 using namespace std::chrono_literals;
174 using namespace jtx;
175 Env env(*this);
176
177 // Gateway account and assets
178 Account const alice{"alice"};
179 env.fund(XRP(10000), alice);
180 env.close();
181 auto USD = alice["USD"];
182
183 // The largest valid STAmount of USD:
184 STAmount const maxUSD(USD.issue(), STAmount::cMaxValue, STAmount::cMaxOffset);
185
186 // Create a hotwallet
187 Account const hw{"hw"};
188 env.fund(XRP(10000), hw);
189 env.close();
190 env(trust(hw, maxUSD));
191 env.close();
192 env(pay(alice, hw, maxUSD));
193
194 // Create some clients
195 Account const bob{"bob"};
196 env.fund(XRP(10000), bob);
197 env.close();
198 env(trust(bob, maxUSD));
199 env.close();
200 env(pay(alice, bob, maxUSD));
201
202 Account const charley{"charley"};
203 env.fund(XRP(10000), charley);
204 env.close();
205 env(trust(charley, maxUSD));
206 env.close();
207 env(pay(alice, charley, maxUSD));
208
209 env.close();
210
211 auto wsc = makeWSClient(env.app().config());
212
213 Json::Value query;
214 query[jss::account] = alice.human();
215 query[jss::hotwallet] = hw.human();
216
217 // Note that the sum of bob's and charley's USD balances exceeds
218 // the amount that can be represented in an STAmount. Nevertheless
219 // we get a valid "obligations" that shows the maximum valid
220 // STAmount.
221 auto jv = wsc->invoke("gateway_balances", query);
222 expect(jv[jss::status] == "success");
223 expect(jv[jss::result][jss::obligations]["USD"] == maxUSD.getText());
224 }
225
226 void
227 run() override
228 {
229 using namespace jtx;
230 auto const sa = testable_amendments();
231 for (auto feature : {sa - featurePermissionedDEX, sa})
232 {
233 testGWB(feature);
234 testGWBApiVersions(feature);
235 }
236
238 }
239};
240
241BEAST_DEFINE_TESTSUITE(GatewayBalances, rpc, xrpl);
242
243} // namespace test
244} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
A testsuite class.
Definition suite.h:51
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:221
virtual Config & config()=0
static constexpr std::uint64_t cMaxValue
Definition STAmount.h:51
std::string getText() const override
Definition STAmount.cpp:639
static int const cMaxOffset
Definition STAmount.h:46
void testGWB(FeatureBitset features)
void run() override
Runs the suite.
void testGWBApiVersions(FeatureBitset features)
Immutable cryptographic account descriptor.
Definition Account.h:19
A transaction testing environment.
Definition Env.h:119
Application & app()
Definition Env.h:251
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:98
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:261
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:15
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition trust.cpp:13
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:90
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:11
FeatureBitset testable_amendments()
Definition Env.h:76
std::unique_ptr< WSClient > makeWSClient(Config const &cfg, bool v2, unsigned rpc_version, std::unordered_map< std::string, std::string > const &headers)
Returns a client operating through WebSockets/S.
Definition WSClient.cpp:285
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
void forAllApiVersions(Fn const &fn, Args &&... args)
Definition ApiVersion.h:144
constexpr std::uint32_t tfSetFreeze
Definition TxFlags.h:98