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 ripple {
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(
81 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
82 expect(jv.isMember(jss::id) && jv[jss::id] == 5);
83 }
84
85 auto const& result = jv[jss::result];
86 expect(result[jss::account] == alice.human());
87 expect(result[jss::status] == "success");
88
89 {
90 auto const& balances = result[jss::balances];
91 expect(balances.isObject(), "balances is not an object");
92 expect(balances.size() == 1, "balances size is not 1");
93
94 auto const& hwBalance = balances[hw.human()];
95 expect(hwBalance.isArray(), "hwBalance is not an array");
96 expect(hwBalance.size() == 2);
97 auto c1 = hwBalance[0u][jss::currency];
98 auto c2 = hwBalance[1u][jss::currency];
99 expect(c1 == "USD" || c2 == "USD");
100 expect(c1 == "JPY" || c2 == "JPY");
101 expect(
102 hwBalance[0u][jss::value] == "5000" &&
103 hwBalance[1u][jss::value] == "5000");
104 }
105
106 {
107 auto const& fBalances = result[jss::frozen_balances];
108 expect(fBalances.isObject());
109 expect(fBalances.size() == 1);
110
111 auto const& fBal = fBalances[dave.human()];
112 expect(fBal.isArray());
113 expect(fBal.size() == 1);
114 expect(fBal[0u].isObject());
115 expect(fBal[0u][jss::currency] == "CNY");
116 expect(fBal[0u][jss::value] == "30");
117 }
118
119 {
120 auto const& assets = result[jss::assets];
121 expect(assets.isObject(), "assets it not an object");
122 expect(assets.size() == 1, "assets size is not 1");
123
124 auto const& cAssets = assets[charley.human()];
125 expect(cAssets.isArray());
126 expect(cAssets.size() == 1);
127 expect(cAssets[0u][jss::currency] == "USD");
128 expect(cAssets[0u][jss::value] == "10");
129 }
130
131 {
132 auto const& obligations = result[jss::obligations];
133 expect(obligations.isObject(), "obligations is not an object");
134 expect(obligations.size() == 3);
135 expect(obligations["CNY"] == "250");
136 expect(obligations["JPY"] == "250");
137 expect(obligations["USD"] == "50");
138 }
139 }
140 }
141
142 void
144 {
145 using namespace std::chrono_literals;
146 using namespace jtx;
147 Env env(*this, features);
148
149 // Gateway account and assets
150 Account const alice{"alice"};
151 env.fund(XRP(10000), alice);
152 Account const hw{"hw"};
153 env.fund(XRP(10000), hw);
154 env.close();
155
156 auto wsc = makeWSClient(env.app().config());
157
158 Json::Value qry2;
159 qry2[jss::account] = alice.human();
160 qry2[jss::hotwallet] = "asdf";
161
162 forAllApiVersions([&, this](unsigned apiVersion) {
163 qry2[jss::api_version] = apiVersion;
164 auto jv = wsc->invoke("gateway_balances", qry2);
165 expect(jv[jss::status] == "error");
166
167 auto response = jv[jss::result];
168 auto const error =
169 apiVersion < 2u ? "invalidHotWallet" : "invalidParams";
170 BEAST_EXPECT(response[jss::error] == error);
171 });
172 }
173
174 void
176 {
177 using namespace std::chrono_literals;
178 using namespace jtx;
179 Env env(*this);
180
181 // Gateway account and assets
182 Account const alice{"alice"};
183 env.fund(XRP(10000), alice);
184 env.close();
185 auto USD = alice["USD"];
186
187 // The largest valid STAmount of USD:
188 STAmount const maxUSD(
190
191 // Create a hotwallet
192 Account const hw{"hw"};
193 env.fund(XRP(10000), hw);
194 env.close();
195 env(trust(hw, maxUSD));
196 env.close();
197 env(pay(alice, hw, maxUSD));
198
199 // Create some clients
200 Account const bob{"bob"};
201 env.fund(XRP(10000), bob);
202 env.close();
203 env(trust(bob, maxUSD));
204 env.close();
205 env(pay(alice, bob, maxUSD));
206
207 Account const charley{"charley"};
208 env.fund(XRP(10000), charley);
209 env.close();
210 env(trust(charley, maxUSD));
211 env.close();
212 env(pay(alice, charley, maxUSD));
213
214 env.close();
215
216 auto wsc = makeWSClient(env.app().config());
217
218 Json::Value query;
219 query[jss::account] = alice.human();
220 query[jss::hotwallet] = hw.human();
221
222 // Note that the sum of bob's and charley's USD balances exceeds
223 // the amount that can be represented in an STAmount. Nevertheless
224 // we get a valid "obligations" that shows the maximum valid
225 // STAmount.
226 auto jv = wsc->invoke("gateway_balances", query);
227 expect(jv[jss::status] == "success");
228 expect(jv[jss::result][jss::obligations]["USD"] == maxUSD.getText());
229 }
230
231 void
232 run() override
233 {
234 using namespace jtx;
235 auto const sa = testable_amendments();
236 for (auto feature : {sa - featurePermissionedDEX, sa})
237 {
238 testGWB(feature);
239 testGWBApiVersions(feature);
240 }
241
243 }
244};
245
246BEAST_DEFINE_TESTSUITE(GatewayBalances, rpc, ripple);
247
248} // namespace test
249} // namespace ripple
Represents a JSON value.
Definition json_value.h:130
A testsuite class.
Definition suite.h:52
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:226
virtual Config & config()=0
static int const cMaxOffset
Definition STAmount.h:47
static std::uint64_t const cMaxValue
Definition STAmount.h:51
std::string getText() const override
Definition STAmount.cpp:664
void testGWBApiVersions(FeatureBitset features)
void run() override
Runs the suite.
void testGWB(FeatureBitset features)
Immutable cryptographic account descriptor.
Definition Account.h:20
A transaction testing environment.
Definition Env.h:102
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:103
Application & app()
Definition Env.h:242
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:271
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:16
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition trust.cpp:13
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:11
FeatureBitset testable_amendments()
Definition Env.h:55
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
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:304
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
void forAllApiVersions(Fn const &fn, Args &&... args)
Definition ApiVersion.h:158
constexpr std::uint32_t tfSetFreeze
Definition TxFlags.h:99