Skip to content

Commit 2c54f6d

Browse files
author
Nikita Khateev
committed
Add verify functionality for libindy
Signed-off-by: Nikita Khateev <[email protected]>
1 parent a2dc6f4 commit 2c54f6d

File tree

5 files changed

+305
-4
lines changed

5 files changed

+305
-4
lines changed

libindy/src/api/payments.rs

Lines changed: 149 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ pub type BuildGetTxnFeesReqCB = extern fn(command_handle: i32,
254254
///
255255
/// # Params
256256
/// command_handle: command handle to map callback to context
257-
/// payment_method: payment method to use
258257
/// resp_json: response for Indy request for getting fees
259258
///
260259
/// # Return
@@ -270,6 +269,47 @@ pub type ParseGetTxnFeesResponseCB = extern fn(command_handle: i32,
270269
err: ErrorCode,
271270
fees_json: *const c_char) -> ErrorCode>) -> ErrorCode;
272271

272+
/// Builds Indy request for information to verify the receipt
273+
///
274+
/// # Params
275+
/// command_handle
276+
/// wallet_handle
277+
/// submitter_did
278+
/// receipt -- receipt to verify
279+
///
280+
/// # Return
281+
/// verify_txn_json -- request to be sent to ledger
282+
283+
pub type BuildVerifyReqCB = extern fn(command_handle: i32,
284+
wallet_handle: i32,
285+
submitter_did: *const c_char,
286+
receipt: *const c_char,
287+
cb: Option<extern fn(command_handle_: i32,
288+
err: ErrorCode,
289+
verify_txn_json: *const c_char) -> ErrorCode>) -> ErrorCode;
290+
291+
/// Parses Indy response with information to verify receipt
292+
///
293+
/// # Params
294+
/// command_handle
295+
/// resp_json -- response of the ledger for verify txn
296+
///
297+
/// # Return
298+
/// txn_json: {
299+
/// sources: [<str>, ]
300+
/// receipts: [ {
301+
/// recipient: <str>, // payment address of recipient
302+
/// receipt: <str>, // receipt that can be used for payment referencing and verification
303+
/// amount: <int>, // amount
304+
/// }, ]
305+
/// extra: <str>, //optional data
306+
/// }
307+
pub type ParseVerifyResponseCB = extern fn(command_handle: i32,
308+
resp_json: *const c_char,
309+
cb: Option<extern fn(command_handle_: i32,
310+
err: ErrorCode,
311+
txn_json: *const c_char) -> ErrorCode>) -> ErrorCode;
312+
273313
/// Register custom payment implementation.
274314
///
275315
/// It allows library user to provide custom payment method implementation as set of handlers.
@@ -300,6 +340,8 @@ pub extern fn indy_register_payment_method(command_handle: i32,
300340
build_set_txn_fees_req: Option<BuildSetTxnFeesReqCB>,
301341
build_get_txn_fees_req: Option<BuildGetTxnFeesReqCB>,
302342
parse_get_txn_fees_response: Option<ParseGetTxnFeesResponseCB>,
343+
build_verify_req: Option<BuildVerifyReqCB>,
344+
parse_verify_response: Option<ParseVerifyResponseCB>,
303345
cb: Option<extern fn(command_handle_: i32,
304346
err: ErrorCode)>) -> ErrorCode {
305347
trace!("indy_register_payment_method: >>> payment_method: {:?}", payment_method);
@@ -316,7 +358,9 @@ pub extern fn indy_register_payment_method(command_handle: i32,
316358
check_useful_c_callback!(build_set_txn_fees_req, ErrorCode::CommonInvalidParam11);
317359
check_useful_c_callback!(build_get_txn_fees_req, ErrorCode::CommonInvalidParam12);
318360
check_useful_c_callback!(parse_get_txn_fees_response, ErrorCode::CommonInvalidParam13);
319-
check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam14);
361+
check_useful_c_callback!(build_verify_req, ErrorCode::CommonInvalidParam14);
362+
check_useful_c_callback!(parse_verify_response, ErrorCode::CommonInvalidParam15);
363+
check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam16);
320364

321365
trace!("indy_register_payment_method: entities >>> payment_method: {:?}", payment_method);
322366

@@ -331,7 +375,9 @@ pub extern fn indy_register_payment_method(command_handle: i32,
331375
build_mint_req,
332376
build_set_txn_fees_req,
333377
build_get_txn_fees_req,
334-
parse_get_txn_fees_response
378+
parse_get_txn_fees_response,
379+
build_verify_req,
380+
parse_verify_response,
335381
);
336382
let result =
337383
CommandExecutor::instance().send(
@@ -998,4 +1044,104 @@ pub extern fn indy_parse_get_txn_fees_response(command_handle: i32,
9981044
trace!("indy_parse_get_txn_fees_response: <<< res: {:?}", res);
9991045

10001046
res
1047+
}
1048+
1049+
/// Builds Indy request for information to verify the receipt
1050+
///
1051+
/// # Params
1052+
/// command_handle
1053+
/// wallet_handle
1054+
/// submitter_did
1055+
/// receipt -- receipt to verify
1056+
///
1057+
/// # Return
1058+
/// verify_txn_json -- request to be sent to ledger
1059+
/// payment_method
1060+
#[no_mangle]
1061+
pub extern fn indy_build_verify_req(command_handle: i32,
1062+
wallet_handle: i32,
1063+
submitter_did: *const c_char,
1064+
receipt: *const c_char,
1065+
cb: Option<extern fn(command_handle_: i32,
1066+
err: ErrorCode,
1067+
verify_txn_json: *const c_char,
1068+
payment_method: *const c_char)>) -> ErrorCode {
1069+
trace!("indy_build_verify_req: >>> wallet_handle {:?}, submitter_did: {:?}, receipt: {:?}", wallet_handle, submitter_did, receipt);
1070+
check_useful_c_str!(submitter_did, ErrorCode::CommonInvalidParam3);
1071+
check_useful_c_str!(receipt, ErrorCode::CommonInvalidParam4);
1072+
check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam5);
1073+
1074+
trace!("indy_build_verify_req: entities >>> wallet_handle {:?}, submitter_did: {:?}, receipt: {:?}", wallet_handle, submitter_did, receipt);
1075+
1076+
let result = CommandExecutor::instance()
1077+
.send(Command::Payments(
1078+
PaymentsCommand::BuildVerifyReq(
1079+
wallet_handle,
1080+
submitter_did,
1081+
receipt,
1082+
Box::new(move |result| {
1083+
let (err, verify_txn_json, payment_method) = result_to_err_code_2!(result, String::new(), String::new());
1084+
trace!("indy_build_verify_req: verify_txn_json: {:?}, payment_method: {:?}", verify_txn_json, payment_method);
1085+
let verify_txn_json = CStringUtils::string_to_cstring(verify_txn_json);
1086+
let payment_method = CStringUtils::string_to_cstring(payment_method);
1087+
cb(command_handle, err, verify_txn_json.as_ptr(), payment_method.as_ptr());
1088+
})
1089+
)));
1090+
1091+
let result = result_to_err_code!(result);
1092+
1093+
trace!("indy_build_verify_req: <<< result: {:?}", result);
1094+
1095+
result
1096+
}
1097+
1098+
/// Parses Indy response with information to verify receipt
1099+
///
1100+
/// # Params
1101+
/// command_handle
1102+
/// payment_method
1103+
/// resp_json -- response of the ledger for verify txn
1104+
///
1105+
/// # Return
1106+
/// txn_json: {
1107+
/// sources: [<str>, ]
1108+
/// receipts: [ {
1109+
/// recipient: <str>, // payment address of recipient
1110+
/// receipt: <str>, // receipt that can be used for payment referencing and verification
1111+
/// amount: <int>, // amount
1112+
/// }, ]
1113+
/// extra: <str>, //optional data
1114+
/// }
1115+
#[no_mangle]
1116+
pub extern fn indy_parse_verify_response(command_handle: i32,
1117+
payment_method: *const c_char,
1118+
resp_json: *const c_char,
1119+
cb: Option<extern fn(command_handle_: i32,
1120+
err: ErrorCode,
1121+
txn_json: *const c_char)>) -> ErrorCode {
1122+
trace!("indy_parse_payment_response: >>> resp_json: {:?}", resp_json);
1123+
check_useful_c_str!(payment_method, ErrorCode::CommonInvalidParam2);
1124+
check_useful_c_str!(resp_json, ErrorCode::CommonInvalidParam3);
1125+
check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam4);
1126+
1127+
trace!("indy_parse_payment_response: entities >>> resp_json: {:?}", resp_json);
1128+
1129+
let result = CommandExecutor::instance()
1130+
.send(Command::Payments(
1131+
PaymentsCommand::ParseVerifyResponse(
1132+
payment_method,
1133+
resp_json,
1134+
Box::new(move |result| {
1135+
let (err, txn_json) = result_to_err_code_1!(result, String::new());
1136+
trace!("indy_build_verify_req: txn_json: {:?}", txn_json);
1137+
let txn_json = CStringUtils::string_to_cstring(txn_json);
1138+
cb(command_handle, err, txn_json.as_ptr());
1139+
})
1140+
)));
1141+
1142+
let result = result_to_err_code!(result);
1143+
1144+
trace!("indy_parse_payment_response: <<< result: {:?}", result);
1145+
1146+
result
10011147
}

libindy/src/commands/payments.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,21 @@ pub enum PaymentsCommand {
109109
String, //response
110110
Box<Fn(Result<String, IndyError>) + Send>),
111111
ParseGetTxnFeesResponseAck(
112+
i32,
113+
Result<String, PaymentsError>),
114+
BuildVerifyReq(
115+
i32, //wallet_handle
116+
String, //submitter_did
117+
String, //receipt
118+
Box<Fn(Result<(String, String), IndyError>) + Send>),
119+
BuildVerifyReqAck(
120+
i32,
121+
Result<String, PaymentsError>),
122+
ParseVerifyResponse(
123+
String, //payment_method
124+
String, //resp_json
125+
Box<Fn(Result<String, IndyError>) + Send>),
126+
ParseVerifyResponseAck(
112127
i32,
113128
Result<String, PaymentsError>)
114129
}
@@ -228,6 +243,22 @@ impl PaymentsCommandExecutor {
228243
info!(target: "payments_command_executor", "ParseGetTxnFeesResponseAck command received");
229244
self.parse_get_txn_fees_response_ack(cmd_handle, result);
230245
}
246+
PaymentsCommand::BuildVerifyReq(wallet_handle, submitter_did, receipt, cb) => {
247+
info!(target: "payments_command_executor", "BuildVerifyReq command received");
248+
self.build_verify_request(wallet_handle, &submitter_did, &receipt, cb);
249+
}
250+
PaymentsCommand::BuildVerifyReqAck(command_handle, result) => {
251+
info!(target: "payments_command_executor", "BuildVerifyReqAck command received");
252+
self.build_verify_request_ack(command_handle, result);
253+
}
254+
PaymentsCommand::ParseVerifyResponse(payment_method, resp_json, cb) => {
255+
info!(target: "payments_command_executor", "ParseVerifyResponse command received");
256+
self.parse_verify_response(&payment_method, &resp_json, cb);
257+
}
258+
PaymentsCommand::ParseVerifyResponseAck(command_handle, result) => {
259+
info!(target: "payments_command_executor", "ParseVerifyResponseAck command received");
260+
self.parse_verify_response_ack(command_handle, result);
261+
}
231262
}
232263
}
233264

@@ -537,6 +568,50 @@ impl PaymentsCommandExecutor {
537568
trace!("parse_get_txn_fees_response_ack <<<");
538569
}
539570

571+
fn build_verify_request(&self, wallet_handle: i32, submitter_did: &str, receipt: &str, cb: Box<Fn(Result<(String, String), IndyError>) + Send>) {
572+
trace!("build_verify_request >>> wallet_handle: {:?}, submitter_did: {:?}, receipt: {:?}", wallet_handle, submitter_did, receipt);
573+
match self.crypto_service.validate_did(submitter_did).map_err(map_err_err!()) {
574+
Err(err) => return cb(Err(IndyError::from(err))),
575+
_ => ()
576+
}
577+
match self.wallet_service.check(wallet_handle).map_err(map_err_err!()) {
578+
Err(err) => return cb(Err(IndyError::from(err))),
579+
_ => (),
580+
};
581+
582+
let method = match self.payments_service.parse_method_from_payment_address(receipt) {
583+
Ok(method) => method,
584+
Err(err) => {
585+
cb(Err(IndyError::from(err)));
586+
return;
587+
}
588+
};
589+
let method_copy = method.to_string();
590+
self._process_method(
591+
Box::new(move |get_sources_txn_json| cb(get_sources_txn_json.map(|s| (s, method.to_string())))),
592+
&|i| self.payments_service.build_verify_req(i, &method_copy, wallet_handle, &submitter_did, receipt)
593+
);
594+
trace!("build_get_payment_sources_request <<<");
595+
}
596+
597+
fn build_verify_request_ack(&self, cmd_handle: i32, result: Result<String, PaymentsError>) {
598+
trace!("build_verify_request_ack >>> result: {:?}", result);
599+
self._common_ack_payments(cmd_handle, result, "BuildVerifyRequestAck");
600+
trace!("build_verify_request_ack <<<");
601+
}
602+
603+
fn parse_verify_response(&self, type_: &str, resp_json: &str, cb: Box<Fn(Result<String, IndyError>) + Send>) {
604+
trace!("parse_verify_response >>> response: {:?}", resp_json);
605+
self._process_method(cb, &|i| self.payments_service.parse_verify_response(i, type_, resp_json));
606+
trace!("parse_verify_response <<<");
607+
}
608+
609+
fn parse_verify_response_ack(&self, cmd_handle: i32, result: Result<String, PaymentsError>) {
610+
trace!("parse_verify_response_ack >>> result: {:?}", result);
611+
self._common_ack_payments(cmd_handle, result, "ParseVerifyResponseAck");
612+
trace!("parse_verify_response_ack <<<");
613+
}
614+
540615
// HELPERS
541616

542617
fn _process_method(&self, cb: Box<Fn(Result<String, IndyError>) + Send>,

libindy/src/services/payments.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub struct PaymentsMethod {
2828
build_set_txn_fees_req: BuildSetTxnFeesReqCB,
2929
build_get_txn_fees_req: BuildGetTxnFeesReqCB,
3030
parse_get_txn_fees_response: ParseGetTxnFeesResponseCB,
31+
build_verify_req: BuildVerifyReqCB,
32+
parse_verify_response: ParseVerifyResponseCB,
3133
}
3234

3335
pub type PaymentsMethodCBs = PaymentsMethod;
@@ -43,7 +45,9 @@ impl PaymentsMethodCBs {
4345
build_mint_req: BuildMintReqCB,
4446
build_set_txn_fees_req: BuildSetTxnFeesReqCB,
4547
build_get_txn_fees_req: BuildGetTxnFeesReqCB,
46-
parse_get_txn_fees_response: ParseGetTxnFeesResponseCB) -> Self {
48+
parse_get_txn_fees_response: ParseGetTxnFeesResponseCB,
49+
build_verify_req: BuildVerifyReqCB,
50+
parse_verify_response: ParseVerifyResponseCB) -> Self {
4751
PaymentsMethodCBs {
4852
create_address,
4953
add_request_fees,
@@ -56,6 +60,8 @@ impl PaymentsMethodCBs {
5660
build_set_txn_fees_req,
5761
build_get_txn_fees_req,
5862
parse_get_txn_fees_response,
63+
build_verify_req,
64+
parse_verify_response,
5965
}
6066
}
6167
}
@@ -259,6 +265,39 @@ impl PaymentsService {
259265
res
260266
}
261267

268+
pub fn build_verify_req(&self, cmd_handle: i32, type_: &str, wallet_handle: i32, submitter_did: &str, receipt: &str) -> Result<(), PaymentsError> {
269+
trace!("build_verify_req >>> type_: {:?}, wallet_handle: {:?}, submitter_did: {:?}, receipt: {:?}", type_, wallet_handle, submitter_did, receipt);
270+
let build_verify_req: BuildVerifyReqCB = self.methods.borrow().get(type_)
271+
.ok_or(PaymentsError::UnknownType(format!("Unknown payment method {}", type_)))?.build_verify_req;
272+
273+
let submitter_did = CString::new(submitter_did)?;
274+
let receipt = CString::new(receipt)?;
275+
276+
let err = build_verify_req(cmd_handle, wallet_handle, submitter_did.as_ptr(), receipt.as_ptr(), cbs::build_verify_req(cmd_handle));
277+
278+
let res = PaymentsService::consume_result(err);
279+
280+
trace!("build_verify_req <<< result: {:?}", res);
281+
282+
res
283+
}
284+
285+
pub fn parse_verify_response(&self, cmd_handle: i32, type_: &str, resp_json: &str) -> Result<(), PaymentsError> {
286+
trace!("parse_verify_response >>> type_: {:?}, resp_json: {:?}", type_, resp_json);
287+
let parse_verify_response: ParseVerifyResponseCB = self.methods.borrow().get(type_)
288+
.ok_or(PaymentsError::UnknownType(format!("Unknown payment method {}", type_)))?.parse_verify_response;
289+
290+
let resp_json = CString::new(resp_json)?;
291+
292+
let err = parse_verify_response(cmd_handle, resp_json.as_ptr(), cbs::parse_verify_response(cmd_handle));
293+
294+
let res = PaymentsService::consume_result(err);
295+
296+
trace!("parse_verify_response <<< result: {:?}", res);
297+
298+
res
299+
}
300+
262301
pub fn parse_method_from_inputs(&self, inputs: &str) -> Result<String, PaymentsError> {
263302
trace!("parse_method_from_inputs >>> inputs: {:?}", inputs);
264303
let inputs: Vec<&str> = serde_json::from_str(inputs).map_err(|_| PaymentsError::CommonError(CommonError::InvalidStructure("Unable to parse inputs".to_string())))?;
@@ -452,6 +491,18 @@ mod cbs {
452491
send_ack(cmd_handle, Box::new(move |cmd_handle, result| PaymentsCommand::ParseGetTxnFeesResponseAck(cmd_handle, result)))
453492
}
454493

494+
pub fn build_verify_req(cmd_handle: i32) -> Option<extern fn(command_handle: i32,
495+
err: ErrorCode,
496+
c_str: *const c_char) -> ErrorCode> {
497+
send_ack(cmd_handle, Box::new(move |cmd_handle, result| PaymentsCommand::BuildVerifyReqAck(cmd_handle, result)))
498+
}
499+
500+
pub fn parse_verify_response(cmd_handle: i32) -> Option<extern fn(command_handle: i32,
501+
err: ErrorCode,
502+
c_str: *const c_char) -> ErrorCode> {
503+
send_ack(cmd_handle, Box::new(move |cmd_handle, result| PaymentsCommand::ParseVerifyResponseAck(cmd_handle, result)))
504+
}
505+
455506
fn send_ack(cmd_handle: i32, builder: Box<Fn(i32, Result<String, PaymentsError>) -> PaymentsCommand + Send>) -> Option<extern fn(command_handle: i32,
456507
err: ErrorCode,
457508
c_str: *const c_char) -> ErrorCode> {

0 commit comments

Comments
 (0)