51 Env env(*
this, features);
53 auto lowerFee = [&]() {
59 auto const baseFee = env.
current()->fees().base;
64 auto const lenderPass =
"lender";
67 env.
fund(
XRP(1'000'000), alice, lender, borrower);
79 txJson[sfTransactionType] =
"AccountSet";
80 txJson[sfAccount] = borrower.
human();
82 auto const signParams = [&]() {
84 signParams[jss::passphrase] = borrowerPass;
85 signParams[jss::key_type] =
"ed25519";
86 signParams[jss::tx_json] = txJson;
89 auto const jSign = env.
rpc(
"json",
"sign",
to_string(signParams));
90 BEAST_EXPECT(jSign.isMember(jss::result) && jSign[jss::result].isMember(jss::tx_json));
91 auto txSignResult = jSign[jss::result][jss::tx_json];
92 auto txSignBlob = jSign[jss::result][jss::tx_blob].asString();
93 txSignResult.removeMember(jss::hash);
95 auto const jtx = env.
jt(txJson,
Sig(borrower));
96 BEAST_EXPECT(txSignResult ==
jtx.jv);
99 auto const jSubmit = env.
rpc(
"submit", txSignBlob);
101 jSubmit.isMember(jss::result) &&
102 jSubmit[jss::result].isMember(jss::engine_result) &&
103 jSubmit[jss::result][jss::engine_result].asString() ==
"tesSUCCESS");
110 testcase(
"RPC LoanSet - illegal signature_target");
113 txJson[sfTransactionType] =
"AccountSet";
114 txJson[sfAccount] = borrower.
human();
118 for (
char const* target : {
"Destination",
"Book",
"Signer"})
120 auto const borrowerSignParams = [&]() {
122 params[jss::passphrase] = borrowerPass;
123 params[jss::key_type] =
"ed25519";
124 params[jss::signature_target] = target;
125 params[jss::tx_json] = txJson;
128 auto const jSignBorrower = env.
rpc(
"json",
"sign",
to_string(borrowerSignParams));
130 jSignBorrower.isMember(jss::result) &&
131 jSignBorrower[jss::result].isMember(jss::error) &&
132 jSignBorrower[jss::result][jss::error] ==
"invalidParams" &&
133 jSignBorrower[jss::result].isMember(jss::error_message) &&
134 jSignBorrower[jss::result][jss::error_message] == target);
138 testcase(
"RPC LoanSet - sign and submit borrower initiated");
141 txJson[sfTransactionType] =
"LoanSet";
142 txJson[sfAccount] = borrower.
human();
143 txJson[sfCounterparty] = lender.
human();
144 txJson[sfLoanBrokerID] =
145 "FF924CD18A236C2B49CF8E80A351CEAC6A10171DC9F110025646894FEC"
148 txJson[sfPrincipalRequested] =
"100000000";
149 txJson[sfPaymentTotal] = 10000;
150 txJson[sfPaymentInterval] = 3600;
151 txJson[sfGracePeriod] = 300;
152 txJson[sfFlags] = 65536;
153 txJson[sfFee] =
to_string(24 * baseFee / 10);
156 auto const borrowerSignParams = [&]() {
158 params[jss::passphrase] = borrowerPass;
159 params[jss::key_type] =
"ed25519";
160 params[jss::tx_json] = txJson;
163 auto const jSignBorrower = env.
rpc(
"json",
"sign",
to_string(borrowerSignParams));
165 jSignBorrower.isMember(jss::result) &&
166 jSignBorrower[jss::result].isMember(jss::tx_json),
168 auto const txBorrowerSignResult = jSignBorrower[jss::result][jss::tx_json];
169 auto const txBorrowerSignBlob = jSignBorrower[jss::result][jss::tx_blob].asString();
175 auto const jSubmitBlob = env.
rpc(
"submit", txBorrowerSignBlob);
176 BEAST_EXPECT(jSubmitBlob.isMember(jss::result));
177 auto const jSubmitBlobResult = jSubmitBlob[jss::result];
178 BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json));
182 jSubmitBlobResult.isMember(jss::engine_result) &&
183 jSubmitBlobResult[jss::engine_result].asString() ==
"temBAD_SIGNER");
188 auto const lenderSignParams = [&]() {
190 params[jss::passphrase] = lenderPass;
191 params[jss::key_type] =
"ed25519";
192 params[jss::signature_target] =
"CounterpartySignature";
193 params[jss::tx_json] = txBorrowerSignResult;
196 auto const jSignLender = env.
rpc(
"json",
"sign",
to_string(lenderSignParams));
198 jSignLender.isMember(jss::result) &&
199 jSignLender[jss::result].isMember(jss::tx_json));
200 auto const txLenderSignResult = jSignLender[jss::result][jss::tx_json];
201 auto const txLenderSignBlob = jSignLender[jss::result][jss::tx_blob].asString();
205 auto const jSubmitBlob = env.
rpc(
"submit", txLenderSignBlob);
206 BEAST_EXPECT(jSubmitBlob.isMember(jss::result));
207 auto const jSubmitBlobResult = jSubmitBlob[jss::result];
208 BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json));
209 auto const jSubmitBlobTx = jSubmitBlobResult[jss::tx_json];
214 jSubmitBlobResult.isMember(jss::engine_result) &&
215 jSubmitBlobResult[jss::engine_result].asString() ==
"tecNO_ENTRY",
219 !jSubmitBlob.isMember(jss::error) && !jSubmitBlobResult.isMember(jss::error));
226 auto const jSubmitJson = env.
rpc(
"json",
"submit",
to_string(lenderSignParams));
227 BEAST_EXPECT(jSubmitJson.isMember(jss::result));
228 auto const jSubmitJsonResult = jSubmitJson[jss::result];
229 BEAST_EXPECT(jSubmitJsonResult.isMember(jss::tx_json));
230 auto const jSubmitJsonTx = jSubmitJsonResult[jss::tx_json];
234 jSubmitJsonResult.isMember(jss::engine_result) &&
235 jSubmitJsonResult[jss::engine_result].asString() ==
"tefPAST_SEQ",
239 !jSubmitJson.isMember(jss::error) && !jSubmitJsonResult.isMember(jss::error));
241 BEAST_EXPECT(jSubmitBlobTx == jSubmitJsonTx);
245 testcase(
"RPC LoanSet - sign and submit lender initiated");
248 txJson[sfTransactionType] =
"LoanSet";
249 txJson[sfAccount] = lender.
human();
250 txJson[sfCounterparty] = borrower.
human();
251 txJson[sfLoanBrokerID] =
252 "FF924CD18A236C2B49CF8E80A351CEAC6A10171DC9F110025646894FEC"
255 txJson[sfPrincipalRequested] =
"100000000";
256 txJson[sfPaymentTotal] = 10000;
257 txJson[sfPaymentInterval] = 3600;
258 txJson[sfGracePeriod] = 300;
259 txJson[sfFlags] = 65536;
260 txJson[sfFee] =
to_string(24 * baseFee / 10);
263 auto const lenderSignParams = [&]() {
265 params[jss::passphrase] = lenderPass;
266 params[jss::key_type] =
"ed25519";
267 params[jss::tx_json] = txJson;
270 auto const jSignLender = env.
rpc(
"json",
"sign",
to_string(lenderSignParams));
272 jSignLender.isMember(jss::result) &&
273 jSignLender[jss::result].isMember(jss::tx_json));
274 auto const txLenderSignResult = jSignLender[jss::result][jss::tx_json];
275 auto const txLenderSignBlob = jSignLender[jss::result][jss::tx_blob].asString();
281 auto const jSubmitBlob = env.
rpc(
"submit", txLenderSignBlob);
282 BEAST_EXPECT(jSubmitBlob.isMember(jss::result));
283 auto const jSubmitBlobResult = jSubmitBlob[jss::result];
284 BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json));
288 jSubmitBlobResult.isMember(jss::engine_result) &&
289 jSubmitBlobResult[jss::engine_result].asString() ==
"temBAD_SIGNER");
294 auto const borrowerSignParams = [&]() {
296 params[jss::passphrase] = borrowerPass;
297 params[jss::key_type] =
"ed25519";
298 params[jss::signature_target] =
"CounterpartySignature";
299 params[jss::tx_json] = txLenderSignResult;
302 auto const jSignBorrower = env.
rpc(
"json",
"sign",
to_string(borrowerSignParams));
304 jSignBorrower.isMember(jss::result) &&
305 jSignBorrower[jss::result].isMember(jss::tx_json));
306 auto const txBorrowerSignResult = jSignBorrower[jss::result][jss::tx_json];
307 auto const txBorrowerSignBlob = jSignBorrower[jss::result][jss::tx_blob].asString();
311 auto const jSubmitBlob = env.
rpc(
"submit", txBorrowerSignBlob);
312 BEAST_EXPECT(jSubmitBlob.isMember(jss::result));
313 auto const jSubmitBlobResult = jSubmitBlob[jss::result];
314 BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json));
315 auto const jSubmitBlobTx = jSubmitBlobResult[jss::tx_json];
320 jSubmitBlobResult.isMember(jss::engine_result) &&
321 jSubmitBlobResult[jss::engine_result].asString() ==
"tecNO_ENTRY",
325 !jSubmitBlob.isMember(jss::error) && !jSubmitBlobResult.isMember(jss::error));
332 auto const jSubmitJson = env.
rpc(
"json",
"submit",
to_string(borrowerSignParams));
333 BEAST_EXPECT(jSubmitJson.isMember(jss::result));
334 auto const jSubmitJsonResult = jSubmitJson[jss::result];
335 BEAST_EXPECT(jSubmitJsonResult.isMember(jss::tx_json));
336 auto const jSubmitJsonTx = jSubmitJsonResult[jss::tx_json];
340 jSubmitJsonResult.isMember(jss::engine_result) &&
341 jSubmitJsonResult[jss::engine_result].asString() ==
"tefPAST_SEQ",
345 !jSubmitJson.isMember(jss::error) && !jSubmitJsonResult.isMember(jss::error));
347 BEAST_EXPECT(jSubmitBlobTx == jSubmitJsonTx);