rippled
Loading...
Searching...
No Matches
GatewayBalances_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5 Permission to use, copy, modify, and/or distribute this software for any
6 purpose with or without fee is hereby granted, provided that the above
7 copyright notice and this permission notice appear in all copies.
8 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*/
16//==============================================================================
17
18#include <test/jtx.h>
19#include <test/jtx/WSClient.h>
20
21#include <xrpl/beast/unit_test.h>
22#include <xrpl/protocol/Feature.h>
23#include <xrpl/protocol/jss.h>
24
25namespace ripple {
26namespace test {
27
29{
30public:
31 void
33 {
34 using namespace std::chrono_literals;
35 using namespace jtx;
36 Env env(*this, features);
37
38 {
39 // Gateway account and assets
40 Account const alice{"alice"};
41 env.fund(XRP(10000), "alice");
42 auto USD = alice["USD"];
43 auto CNY = alice["CNY"];
44 auto JPY = alice["JPY"];
45
46 // Create a hotwallet
47 Account const hw{"hw"};
48 env.fund(XRP(10000), "hw");
49 env.close();
50 env(trust(hw, USD(10000)));
51 env(trust(hw, JPY(10000)));
52 env(pay(alice, hw, USD(5000)));
53 env(pay(alice, hw, JPY(5000)));
54
55 // Create some clients
56 Account const bob{"bob"};
57 env.fund(XRP(10000), "bob");
58 env.close();
59 env(trust(bob, USD(100)));
60 env(trust(bob, CNY(100)));
61 env(pay(alice, bob, USD(50)));
62
63 Account const charley{"charley"};
64 env.fund(XRP(10000), "charley");
65 env.close();
66 env(trust(charley, CNY(500)));
67 env(trust(charley, JPY(500)));
68 env(pay(alice, charley, CNY(250)));
69 env(pay(alice, charley, JPY(250)));
70
71 Account const dave{"dave"};
72 env.fund(XRP(10000), "dave");
73 env.close();
74 env(trust(dave, CNY(100)));
75 env(pay(alice, dave, CNY(30)));
76
77 // give the gateway an asset
78 env(trust(alice, charley["USD"](50)));
79 env(pay(charley, alice, USD(10)));
80
81 // freeze dave
82 env(trust(alice, dave["CNY"](0), dave, tfSetFreeze));
83
84 env.close();
85
86 auto wsc = makeWSClient(env.app().config());
87
88 Json::Value qry;
89 qry[jss::account] = alice.human();
90 qry[jss::hotwallet] = hw.human();
91
92 auto jv = wsc->invoke("gateway_balances", qry);
93 expect(jv[jss::status] == "success");
94 if (wsc->version() == 2)
95 {
96 expect(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0");
97 expect(
98 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0");
99 expect(jv.isMember(jss::id) && jv[jss::id] == 5);
100 }
101
102 auto const& result = jv[jss::result];
103 expect(result[jss::account] == alice.human());
104 expect(result[jss::status] == "success");
105
106 {
107 auto const& balances = result[jss::balances];
108 expect(balances.isObject(), "balances is not an object");
109 expect(balances.size() == 1, "balances size is not 1");
110
111 auto const& hwBalance = balances[hw.human()];
112 expect(hwBalance.isArray(), "hwBalance is not an array");
113 expect(hwBalance.size() == 2);
114 auto c1 = hwBalance[0u][jss::currency];
115 auto c2 = hwBalance[1u][jss::currency];
116 expect(c1 == "USD" || c2 == "USD");
117 expect(c1 == "JPY" || c2 == "JPY");
118 expect(
119 hwBalance[0u][jss::value] == "5000" &&
120 hwBalance[1u][jss::value] == "5000");
121 }
122
123 {
124 auto const& fBalances = result[jss::frozen_balances];
125 expect(fBalances.isObject());
126 expect(fBalances.size() == 1);
127
128 auto const& fBal = fBalances[dave.human()];
129 expect(fBal.isArray());
130 expect(fBal.size() == 1);
131 expect(fBal[0u].isObject());
132 expect(fBal[0u][jss::currency] == "CNY");
133 expect(fBal[0u][jss::value] == "30");
134 }
135
136 {
137 auto const& assets = result[jss::assets];
138 expect(assets.isObject(), "assets it not an object");
139 expect(assets.size() == 1, "assets size is not 1");
140
141 auto const& cAssets = assets[charley.human()];
142 expect(cAssets.isArray());
143 expect(cAssets.size() == 1);
144 expect(cAssets[0u][jss::currency] == "USD");
145 expect(cAssets[0u][jss::value] == "10");
146 }
147
148 {
149 auto const& obligations = result[jss::obligations];
150 expect(obligations.isObject(), "obligations is not an object");
151 expect(obligations.size() == 3);
152 expect(obligations["CNY"] == "250");
153 expect(obligations["JPY"] == "250");
154 expect(obligations["USD"] == "50");
155 }
156 }
157 }
158
159 void
161 {
162 using namespace std::chrono_literals;
163 using namespace jtx;
164 Env env(*this, features);
165
166 // Gateway account and assets
167 Account const alice{"alice"};
168 env.fund(XRP(10000), alice);
169 Account const hw{"hw"};
170 env.fund(XRP(10000), hw);
171 env.close();
172
173 auto wsc = makeWSClient(env.app().config());
174
175 Json::Value qry2;
176 qry2[jss::account] = alice.human();
177 qry2[jss::hotwallet] = "asdf";
178
179 forAllApiVersions([&, this](unsigned apiVersion) {
180 qry2[jss::api_version] = apiVersion;
181 auto jv = wsc->invoke("gateway_balances", qry2);
182 expect(jv[jss::status] == "error");
183
184 auto response = jv[jss::result];
185 auto const error =
186 apiVersion < 2u ? "invalidHotWallet" : "invalidParams";
187 BEAST_EXPECT(response[jss::error] == error);
188 });
189 }
190
191 void
193 {
194 using namespace std::chrono_literals;
195 using namespace jtx;
196 Env env(*this);
197
198 // Gateway account and assets
199 Account const alice{"alice"};
200 env.fund(XRP(10000), alice);
201 env.close();
202 auto USD = alice["USD"];
203
204 // The largest valid STAmount of USD:
205 STAmount const maxUSD(
207
208 // Create a hotwallet
209 Account const hw{"hw"};
210 env.fund(XRP(10000), hw);
211 env.close();
212 env(trust(hw, maxUSD));
213 env.close();
214 env(pay(alice, hw, maxUSD));
215
216 // Create some clients
217 Account const bob{"bob"};
218 env.fund(XRP(10000), bob);
219 env.close();
220 env(trust(bob, maxUSD));
221 env.close();
222 env(pay(alice, bob, maxUSD));
223
224 Account const charley{"charley"};
225 env.fund(XRP(10000), charley);
226 env.close();
227 env(trust(charley, maxUSD));
228 env.close();
229 env(pay(alice, charley, maxUSD));
230
231 env.close();
232
233 auto wsc = makeWSClient(env.app().config());
234
235 Json::Value query;
236 query[jss::account] = alice.human();
237 query[jss::hotwallet] = hw.human();
238
239 // Note that the sum of bob's and charley's USD balances exceeds
240 // the amount that can be represented in an STAmount. Nevertheless
241 // we get a valid "obligations" that shows the maximum valid
242 // STAmount.
243 auto jv = wsc->invoke("gateway_balances", query);
244 expect(jv[jss::status] == "success");
245 expect(jv[jss::result][jss::obligations]["USD"] == maxUSD.getText());
246 }
247
248 void
249 run() override
250 {
251 using namespace jtx;
252 auto const sa = testable_amendments();
253 for (auto feature : {sa - featurePermissionedDEX, sa})
254 {
255 testGWB(feature);
256 testGWBApiVersions(feature);
257 }
258
260 }
261};
262
263BEAST_DEFINE_TESTSUITE(GatewayBalances, rpc, ripple);
264
265} // namespace test
266} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
A testsuite class.
Definition suite.h:55
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:229
virtual Config & config()=0
static int const cMaxOffset
Definition STAmount.h:66
static std::uint64_t const cMaxValue
Definition STAmount.h:70
std::string getText() const override
Definition STAmount.cpp:683
void testGWBApiVersions(FeatureBitset features)
void run() override
Runs the suite.
void testGWB(FeatureBitset features)
Immutable cryptographic account descriptor.
Definition Account.h:39
A transaction testing environment.
Definition Env.h:121
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:122
Application & app()
Definition Env.h:261
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:290
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:35
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition trust.cpp:32
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:30
FeatureBitset testable_amendments()
Definition Env.h:74
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:111
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:323
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
void forAllApiVersions(Fn const &fn, Args &&... args)
Definition ApiVersion.h:177
constexpr std::uint32_t tfSetFreeze
Definition TxFlags.h:118