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();
116 auto const borrowerSignParams = [&]() {
118 params[jss::passphrase] = borrowerPass;
119 params[jss::key_type] =
"ed25519";
120 params[jss::signature_target] =
"Destination";
121 params[jss::tx_json] = txJson;
124 auto const jSignBorrower = env.
rpc(
"json",
"sign",
to_string(borrowerSignParams));
126 jSignBorrower.isMember(jss::result) &&
127 jSignBorrower[jss::result].isMember(jss::error) &&
128 jSignBorrower[jss::result][jss::error] ==
"invalidParams" &&
129 jSignBorrower[jss::result].isMember(jss::error_message) &&
130 jSignBorrower[jss::result][jss::error_message] ==
"Destination");
133 testcase(
"RPC LoanSet - sign and submit borrower initiated");
136 txJson[sfTransactionType] =
"LoanSet";
137 txJson[sfAccount] = borrower.
human();
138 txJson[sfCounterparty] = lender.
human();
139 txJson[sfLoanBrokerID] =
140 "FF924CD18A236C2B49CF8E80A351CEAC6A10171DC9F110025646894FEC"
143 txJson[sfPrincipalRequested] =
"100000000";
144 txJson[sfPaymentTotal] = 10000;
145 txJson[sfPaymentInterval] = 3600;
146 txJson[sfGracePeriod] = 300;
147 txJson[sfFlags] = 65536;
148 txJson[sfFee] =
to_string(24 * baseFee / 10);
151 auto const borrowerSignParams = [&]() {
153 params[jss::passphrase] = borrowerPass;
154 params[jss::key_type] =
"ed25519";
155 params[jss::tx_json] = txJson;
158 auto const jSignBorrower = env.
rpc(
"json",
"sign",
to_string(borrowerSignParams));
160 jSignBorrower.isMember(jss::result) &&
161 jSignBorrower[jss::result].isMember(jss::tx_json),
163 auto const txBorrowerSignResult = jSignBorrower[jss::result][jss::tx_json];
164 auto const txBorrowerSignBlob = jSignBorrower[jss::result][jss::tx_blob].asString();
170 auto const jSubmitBlob = env.
rpc(
"submit", txBorrowerSignBlob);
171 BEAST_EXPECT(jSubmitBlob.isMember(jss::result));
172 auto const jSubmitBlobResult = jSubmitBlob[jss::result];
173 BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json));
177 jSubmitBlobResult.isMember(jss::engine_result) &&
178 jSubmitBlobResult[jss::engine_result].asString() ==
"temBAD_SIGNER");
183 auto const lenderSignParams = [&]() {
185 params[jss::passphrase] = lenderPass;
186 params[jss::key_type] =
"ed25519";
187 params[jss::signature_target] =
"CounterpartySignature";
188 params[jss::tx_json] = txBorrowerSignResult;
191 auto const jSignLender = env.
rpc(
"json",
"sign",
to_string(lenderSignParams));
193 jSignLender.isMember(jss::result) &&
194 jSignLender[jss::result].isMember(jss::tx_json));
195 auto const txLenderSignResult = jSignLender[jss::result][jss::tx_json];
196 auto const txLenderSignBlob = jSignLender[jss::result][jss::tx_blob].asString();
200 auto const jSubmitBlob = env.
rpc(
"submit", txLenderSignBlob);
201 BEAST_EXPECT(jSubmitBlob.isMember(jss::result));
202 auto const jSubmitBlobResult = jSubmitBlob[jss::result];
203 BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json));
204 auto const jSubmitBlobTx = jSubmitBlobResult[jss::tx_json];
209 jSubmitBlobResult.isMember(jss::engine_result) &&
210 jSubmitBlobResult[jss::engine_result].asString() ==
"tecNO_ENTRY",
214 !jSubmitBlob.isMember(jss::error) && !jSubmitBlobResult.isMember(jss::error));
221 auto const jSubmitJson = env.
rpc(
"json",
"submit",
to_string(lenderSignParams));
222 BEAST_EXPECT(jSubmitJson.isMember(jss::result));
223 auto const jSubmitJsonResult = jSubmitJson[jss::result];
224 BEAST_EXPECT(jSubmitJsonResult.isMember(jss::tx_json));
225 auto const jSubmitJsonTx = jSubmitJsonResult[jss::tx_json];
229 jSubmitJsonResult.isMember(jss::engine_result) &&
230 jSubmitJsonResult[jss::engine_result].asString() ==
"tefPAST_SEQ",
234 !jSubmitJson.isMember(jss::error) && !jSubmitJsonResult.isMember(jss::error));
236 BEAST_EXPECT(jSubmitBlobTx == jSubmitJsonTx);
240 testcase(
"RPC LoanSet - sign and submit lender initiated");
243 txJson[sfTransactionType] =
"LoanSet";
244 txJson[sfAccount] = lender.
human();
245 txJson[sfCounterparty] = borrower.
human();
246 txJson[sfLoanBrokerID] =
247 "FF924CD18A236C2B49CF8E80A351CEAC6A10171DC9F110025646894FEC"
250 txJson[sfPrincipalRequested] =
"100000000";
251 txJson[sfPaymentTotal] = 10000;
252 txJson[sfPaymentInterval] = 3600;
253 txJson[sfGracePeriod] = 300;
254 txJson[sfFlags] = 65536;
255 txJson[sfFee] =
to_string(24 * baseFee / 10);
258 auto const lenderSignParams = [&]() {
260 params[jss::passphrase] = lenderPass;
261 params[jss::key_type] =
"ed25519";
262 params[jss::tx_json] = txJson;
265 auto const jSignLender = env.
rpc(
"json",
"sign",
to_string(lenderSignParams));
267 jSignLender.isMember(jss::result) &&
268 jSignLender[jss::result].isMember(jss::tx_json));
269 auto const txLenderSignResult = jSignLender[jss::result][jss::tx_json];
270 auto const txLenderSignBlob = jSignLender[jss::result][jss::tx_blob].asString();
276 auto const jSubmitBlob = env.
rpc(
"submit", txLenderSignBlob);
277 BEAST_EXPECT(jSubmitBlob.isMember(jss::result));
278 auto const jSubmitBlobResult = jSubmitBlob[jss::result];
279 BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json));
283 jSubmitBlobResult.isMember(jss::engine_result) &&
284 jSubmitBlobResult[jss::engine_result].asString() ==
"temBAD_SIGNER");
289 auto const borrowerSignParams = [&]() {
291 params[jss::passphrase] = borrowerPass;
292 params[jss::key_type] =
"ed25519";
293 params[jss::signature_target] =
"CounterpartySignature";
294 params[jss::tx_json] = txLenderSignResult;
297 auto const jSignBorrower = env.
rpc(
"json",
"sign",
to_string(borrowerSignParams));
299 jSignBorrower.isMember(jss::result) &&
300 jSignBorrower[jss::result].isMember(jss::tx_json));
301 auto const txBorrowerSignResult = jSignBorrower[jss::result][jss::tx_json];
302 auto const txBorrowerSignBlob = jSignBorrower[jss::result][jss::tx_blob].asString();
306 auto const jSubmitBlob = env.
rpc(
"submit", txBorrowerSignBlob);
307 BEAST_EXPECT(jSubmitBlob.isMember(jss::result));
308 auto const jSubmitBlobResult = jSubmitBlob[jss::result];
309 BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json));
310 auto const jSubmitBlobTx = jSubmitBlobResult[jss::tx_json];
315 jSubmitBlobResult.isMember(jss::engine_result) &&
316 jSubmitBlobResult[jss::engine_result].asString() ==
"tecNO_ENTRY",
320 !jSubmitBlob.isMember(jss::error) && !jSubmitBlobResult.isMember(jss::error));
327 auto const jSubmitJson = env.
rpc(
"json",
"submit",
to_string(borrowerSignParams));
328 BEAST_EXPECT(jSubmitJson.isMember(jss::result));
329 auto const jSubmitJsonResult = jSubmitJson[jss::result];
330 BEAST_EXPECT(jSubmitJsonResult.isMember(jss::tx_json));
331 auto const jSubmitJsonTx = jSubmitJsonResult[jss::tx_json];
335 jSubmitJsonResult.isMember(jss::engine_result) &&
336 jSubmitJsonResult[jss::engine_result].asString() ==
"tefPAST_SEQ",
340 !jSubmitJson.isMember(jss::error) && !jSubmitJsonResult.isMember(jss::error));
342 BEAST_EXPECT(jSubmitBlobTx == jSubmitJsonTx);