Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2017-2021 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file taler-exchange-wire-gateway-client.c
18 : * @brief Execute wire transfer.
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include <gnunet/gnunet_util_lib.h>
23 : #include <gnunet/gnunet_json_lib.h>
24 : #include <jansson.h>
25 : #include "taler_bank_service.h"
26 :
27 : /**
28 : * If set to #GNUNET_YES, then we'll ask the bank for a list
29 : * of incoming transactions from the account.
30 : */
31 : static int incoming_history;
32 :
33 : /**
34 : * If set to #GNUNET_YES, then we'll ask the bank for a list
35 : * of outgoing transactions from the account.
36 : */
37 : static int outgoing_history;
38 :
39 : /**
40 : * Amount to transfer.
41 : */
42 : static struct TALER_Amount amount;
43 :
44 : /**
45 : * Credit account payto://-URI.
46 : */
47 : static char *credit_account;
48 :
49 : /**
50 : * Debit account payto://-URI.
51 : */
52 : static char *debit_account;
53 :
54 : /**
55 : * Wire transfer subject.
56 : */
57 : static char *subject;
58 :
59 : /**
60 : * Which config section has the credentials to access the bank.
61 : */
62 : static char *account_section;
63 :
64 : /**
65 : * Starting row.
66 : */
67 : static unsigned long long start_row = UINT64_MAX;
68 :
69 : /**
70 : * Authentication data.
71 : */
72 : static struct TALER_BANK_AuthenticationData auth;
73 :
74 : /**
75 : * Return value from main().
76 : */
77 : static int global_ret = 1;
78 :
79 : /**
80 : * Main execution context for the main loop.
81 : */
82 : static struct GNUNET_CURL_Context *ctx;
83 :
84 : /**
85 : * Handle to ongoing credit history operation.
86 : */
87 : static struct TALER_BANK_CreditHistoryHandle *chh;
88 :
89 : /**
90 : * Handle to ongoing debit history operation.
91 : */
92 : static struct TALER_BANK_DebitHistoryHandle *dhh;
93 :
94 : /**
95 : * Handle for executing the wire transfer.
96 : */
97 : static struct TALER_BANK_TransferHandle *eh;
98 :
99 : /**
100 : * Handle to access the exchange.
101 : */
102 : static struct TALER_BANK_AdminAddIncomingHandle *op;
103 :
104 : /**
105 : * Context for running the CURL event loop.
106 : */
107 : static struct GNUNET_CURL_RescheduleContext *rc;
108 :
109 :
110 : /**
111 : * Function run when the test terminates (good or bad).
112 : * Cleans up our state.
113 : *
114 : * @param cls NULL
115 : */
116 : static void
117 4 : do_shutdown (void *cls)
118 : {
119 : (void) cls;
120 4 : if (NULL != op)
121 : {
122 0 : TALER_BANK_admin_add_incoming_cancel (op);
123 0 : op = NULL;
124 : }
125 4 : if (NULL != chh)
126 : {
127 0 : TALER_BANK_credit_history_cancel (chh);
128 0 : chh = NULL;
129 : }
130 4 : if (NULL != dhh)
131 : {
132 0 : TALER_BANK_debit_history_cancel (dhh);
133 0 : dhh = NULL;
134 : }
135 4 : if (NULL != eh)
136 : {
137 0 : TALER_BANK_transfer_cancel (eh);
138 0 : eh = NULL;
139 : }
140 4 : if (NULL != ctx)
141 : {
142 4 : GNUNET_CURL_fini (ctx);
143 4 : ctx = NULL;
144 : }
145 4 : if (NULL != rc)
146 : {
147 4 : GNUNET_CURL_gnunet_rc_destroy (rc);
148 4 : rc = NULL;
149 : }
150 4 : TALER_BANK_auth_free (&auth);
151 4 : }
152 :
153 :
154 : /**
155 : * Callback used to process ONE entry in the transaction
156 : * history returned by the bank.
157 : *
158 : * @param cls closure
159 : * @param http_status HTTP status code from server
160 : * @param ec taler error code
161 : * @param serial_id identification of the position at
162 : * which we are returning data
163 : * @param details details about the wire transfer
164 : * @param json original full response from server
165 : * @return #GNUNET_OK to continue, #GNUNET_SYSERR to
166 : * abort iteration
167 : */
168 : static enum GNUNET_GenericReturnValue
169 2 : credit_history_cb (void *cls,
170 : unsigned int http_status,
171 : enum TALER_ErrorCode ec,
172 : uint64_t serial_id,
173 : const struct TALER_BANK_CreditDetails *details,
174 : const json_t *json)
175 : {
176 : (void) cls;
177 :
178 2 : chh = NULL;
179 2 : if (MHD_HTTP_OK != http_status)
180 : {
181 1 : if ( (MHD_HTTP_NO_CONTENT != http_status) ||
182 : (TALER_EC_NONE != ec) )
183 : {
184 0 : if (0 == http_status)
185 : {
186 0 : fprintf (stderr,
187 : "Failed to obtain HTTP reply from `%s'\n",
188 : auth.wire_gateway_url);
189 : }
190 : else
191 : {
192 0 : fprintf (stderr,
193 : "Failed to obtain credit history from `%s': HTTP status %u (%s)\n",
194 : auth.wire_gateway_url,
195 : http_status,
196 : TALER_ErrorCode_get_hint (ec));
197 : }
198 0 : if (NULL != json)
199 0 : json_dumpf (json,
200 : stderr,
201 : JSON_INDENT (2));
202 0 : global_ret = 2;
203 0 : GNUNET_SCHEDULER_shutdown ();
204 0 : return GNUNET_NO;
205 : }
206 1 : fprintf (stdout,
207 : "End of transactions list.\n");
208 1 : global_ret = 0;
209 1 : GNUNET_SCHEDULER_shutdown ();
210 1 : return GNUNET_NO;
211 : }
212 :
213 : /* If credit/debit accounts were specified, use as a filter */
214 1 : if ( (NULL != credit_account) &&
215 0 : (0 != strcasecmp (credit_account,
216 : details->credit_account_uri) ) )
217 0 : return GNUNET_OK;
218 1 : if ( (NULL != debit_account) &&
219 0 : (0 != strcasecmp (debit_account,
220 : details->debit_account_uri) ) )
221 0 : return GNUNET_OK;
222 :
223 2 : fprintf (stdout,
224 : "%llu: %s->%s (%s) over %s at %s\n",
225 : (unsigned long long) serial_id,
226 : details->debit_account_uri,
227 : details->credit_account_uri,
228 1 : TALER_B2S (&details->reserve_pub),
229 : TALER_amount2s (&details->amount),
230 : GNUNET_TIME_timestamp2s (details->execution_date));
231 1 : return GNUNET_OK;
232 : }
233 :
234 :
235 : /**
236 : * Ask the bank the list of transactions for the bank account
237 : * mentioned in the config section given by the user.
238 : */
239 : static void
240 1 : execute_credit_history (void)
241 : {
242 1 : if (NULL != subject)
243 : {
244 0 : fprintf (stderr,
245 : "Specifying subject is not supported when inspecting credit history\n");
246 0 : GNUNET_SCHEDULER_shutdown ();
247 0 : return;
248 : }
249 2 : chh = TALER_BANK_credit_history (ctx,
250 : &auth,
251 : start_row,
252 : -10,
253 1 : GNUNET_TIME_UNIT_ZERO,
254 : &credit_history_cb,
255 : NULL);
256 1 : if (NULL == chh)
257 : {
258 0 : fprintf (stderr,
259 : "Could not request the credit transaction history.\n");
260 0 : GNUNET_SCHEDULER_shutdown ();
261 0 : return;
262 : }
263 : }
264 :
265 :
266 : /**
267 : * Function with the debit debit transaction history.
268 : *
269 : * @param cls closure
270 : * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
271 : * 0 if the bank's reply is bogus (fails to follow the protocol),
272 : * #MHD_HTTP_NO_CONTENT if there are no more results; on success the
273 : * last callback is always of this status (even if `abs(num_results)` were
274 : * already returned).
275 : * @param ec detailed error code
276 : * @param serial_id monotonically increasing counter corresponding to the transaction
277 : * @param details details about the wire transfer
278 : * @param json detailed response from the HTTPD, or NULL if reply was not in JSON
279 : * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
280 : */
281 : static enum GNUNET_GenericReturnValue
282 2 : debit_history_cb (void *cls,
283 : unsigned int http_status,
284 : enum TALER_ErrorCode ec,
285 : uint64_t serial_id,
286 : const struct TALER_BANK_DebitDetails *details,
287 : const json_t *json)
288 : {
289 : (void) cls;
290 :
291 2 : dhh = NULL;
292 2 : if (MHD_HTTP_OK != http_status)
293 : {
294 1 : if ( (MHD_HTTP_NO_CONTENT != http_status) ||
295 : (TALER_EC_NONE != ec) )
296 : {
297 0 : if (0 == http_status)
298 : {
299 0 : fprintf (stderr,
300 : "Failed to obtain HTTP reply from `%s'\n",
301 : auth.wire_gateway_url);
302 : }
303 : else
304 : {
305 0 : fprintf (stderr,
306 : "Failed to obtain debit history from `%s': HTTP status %u (%s)\n",
307 : auth.wire_gateway_url,
308 : http_status,
309 : TALER_ErrorCode_get_hint (ec));
310 : }
311 0 : if (NULL != json)
312 0 : json_dumpf (json,
313 : stderr,
314 : JSON_INDENT (2));
315 0 : global_ret = 2;
316 0 : GNUNET_SCHEDULER_shutdown ();
317 0 : return GNUNET_NO;
318 : }
319 1 : fprintf (stdout,
320 : "End of transactions list.\n");
321 1 : global_ret = 0;
322 1 : GNUNET_SCHEDULER_shutdown ();
323 1 : return GNUNET_NO;
324 : }
325 :
326 : /* If credit/debit accounts were specified, use as a filter */
327 1 : if ( (NULL != credit_account) &&
328 0 : (0 != strcasecmp (credit_account,
329 : details->credit_account_uri) ) )
330 0 : return GNUNET_OK;
331 1 : if ( (NULL != debit_account) &&
332 0 : (0 != strcasecmp (debit_account,
333 : details->debit_account_uri) ) )
334 0 : return GNUNET_OK;
335 :
336 2 : fprintf (stdout,
337 : "%llu: %s->%s (%s) over %s at %s\n",
338 : (unsigned long long) serial_id,
339 : details->debit_account_uri,
340 : details->credit_account_uri,
341 1 : TALER_B2S (&details->wtid),
342 : TALER_amount2s (&details->amount),
343 : GNUNET_TIME_timestamp2s (details->execution_date));
344 1 : return GNUNET_OK;
345 : }
346 :
347 :
348 : /**
349 : * Ask the bank the list of transactions for the bank account
350 : * mentioned in the config section given by the user.
351 : */
352 : static void
353 1 : execute_debit_history (void)
354 : {
355 1 : if (NULL != subject)
356 : {
357 0 : fprintf (stderr,
358 : "Specifying subject is not supported when inspecting debit history\n");
359 0 : GNUNET_SCHEDULER_shutdown ();
360 0 : return;
361 : }
362 2 : dhh = TALER_BANK_debit_history (ctx,
363 : &auth,
364 : start_row,
365 : -10,
366 1 : GNUNET_TIME_UNIT_ZERO,
367 : &debit_history_cb,
368 : NULL);
369 1 : if (NULL == dhh)
370 : {
371 0 : fprintf (stderr,
372 : "Could not request the debit transaction history.\n");
373 0 : GNUNET_SCHEDULER_shutdown ();
374 0 : return;
375 : }
376 : }
377 :
378 :
379 : /**
380 : * Callback that processes the outcome of a wire transfer
381 : * execution.
382 : *
383 : * @param cls closure
384 : * @param response_code HTTP status code
385 : * @param ec taler error code
386 : * @param row_id unique ID of the wire transfer in the bank's records
387 : * @param timestamp when did the transaction go into effect
388 : */
389 : static void
390 1 : confirmation_cb (void *cls,
391 : unsigned int response_code,
392 : enum TALER_ErrorCode ec,
393 : uint64_t row_id,
394 : struct GNUNET_TIME_Timestamp timestamp)
395 : {
396 : (void) cls;
397 1 : eh = NULL;
398 1 : if (MHD_HTTP_OK != response_code)
399 : {
400 0 : fprintf (stderr,
401 : "The wire transfer didn't execute correctly (%u/%d).\n",
402 : response_code,
403 : ec);
404 0 : GNUNET_SCHEDULER_shutdown ();
405 0 : return;
406 : }
407 :
408 1 : fprintf (stdout,
409 : "Wire transfer #%llu executed successfully at %s.\n",
410 : (unsigned long long) row_id,
411 : GNUNET_TIME_timestamp2s (timestamp));
412 1 : global_ret = 0;
413 1 : GNUNET_SCHEDULER_shutdown ();
414 : }
415 :
416 :
417 : /**
418 : * Ask the bank to execute a wire transfer.
419 : */
420 : static void
421 1 : execute_wire_transfer (void)
422 : {
423 : struct TALER_WireTransferIdentifierRawP wtid;
424 : void *buf;
425 : size_t buf_size;
426 : char *params;
427 :
428 1 : if (NULL != debit_account)
429 : {
430 0 : fprintf (stderr,
431 : "Invalid option -C specified, conflicts with -D\n");
432 0 : GNUNET_SCHEDULER_shutdown ();
433 0 : return;
434 : }
435 :
436 : /* See if subject was given as a payto-parameter. */
437 1 : if (NULL == subject)
438 0 : subject = TALER_payto_get_subject (credit_account);
439 1 : if (NULL != subject)
440 : {
441 1 : if (GNUNET_OK !=
442 1 : GNUNET_STRINGS_string_to_data (subject,
443 : strlen (subject),
444 : &wtid,
445 : sizeof (wtid)))
446 : {
447 0 : fprintf (stderr,
448 : "Error: wire transfer subject must be a WTID\n");
449 0 : GNUNET_SCHEDULER_shutdown ();
450 0 : return;
451 : }
452 : }
453 : else
454 : {
455 : /* pick one at random */
456 0 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
457 : &wtid,
458 : sizeof (wtid));
459 : }
460 1 : params = strchr (credit_account,
461 : (unsigned char) '&');
462 1 : if (NULL != params)
463 0 : *params = '\0';
464 1 : TALER_BANK_prepare_transfer (credit_account,
465 : &amount,
466 : "http://exchange.example.com/",
467 : &wtid,
468 : &buf,
469 : &buf_size);
470 1 : eh = TALER_BANK_transfer (ctx,
471 : &auth,
472 : buf,
473 : buf_size,
474 : &confirmation_cb,
475 : NULL);
476 1 : GNUNET_free (buf);
477 1 : if (NULL == eh)
478 : {
479 0 : fprintf (stderr,
480 : "Could not execute the wire transfer\n");
481 0 : GNUNET_SCHEDULER_shutdown ();
482 0 : return;
483 : }
484 : }
485 :
486 :
487 : /**
488 : * Function called with the result of the operation.
489 : *
490 : * @param cls closure
491 : * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
492 : * 0 if the bank's reply is bogus (fails to follow the protocol)
493 : * @param ec detailed error code
494 : * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
495 : * @param timestamp timestamp when the transaction got settled at the bank.
496 : * @param json detailed response from the HTTPD, or NULL if reply was not in JSON
497 : */
498 : static void
499 1 : res_cb (void *cls,
500 : unsigned int http_status,
501 : enum TALER_ErrorCode ec,
502 : uint64_t serial_id,
503 : struct GNUNET_TIME_Timestamp timestamp,
504 : const json_t *json)
505 : {
506 : (void) cls;
507 : (void) timestamp;
508 1 : op = NULL;
509 1 : switch (ec)
510 : {
511 1 : case TALER_EC_NONE:
512 1 : global_ret = 0;
513 1 : fprintf (stdout,
514 : "%llu\n",
515 : (unsigned long long) serial_id);
516 1 : break;
517 0 : default:
518 0 : fprintf (stderr,
519 : "Operation failed with status code %u/%u\n",
520 : (unsigned int) ec,
521 : http_status);
522 0 : if (NULL != json)
523 0 : json_dumpf (json,
524 : stderr,
525 : JSON_INDENT (2));
526 0 : break;
527 : }
528 1 : GNUNET_SCHEDULER_shutdown ();
529 1 : }
530 :
531 :
532 : /**
533 : * Ask the bank to execute a wire transfer to the exchange.
534 : */
535 : static void
536 1 : execute_admin_transfer (void)
537 : {
538 : struct TALER_ReservePublicKeyP reserve_pub;
539 :
540 1 : if (NULL != subject)
541 : {
542 1 : if (GNUNET_OK !=
543 1 : GNUNET_STRINGS_string_to_data (subject,
544 : strlen (subject),
545 : &reserve_pub,
546 : sizeof (reserve_pub)))
547 : {
548 0 : fprintf (stderr,
549 : "Error: wire transfer subject must be a reserve public key\n");
550 0 : return;
551 : }
552 : }
553 : else
554 : {
555 : /* pick one that is kind-of well-formed at random */
556 0 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
557 : &reserve_pub,
558 : sizeof (reserve_pub));
559 : }
560 1 : op = TALER_BANK_admin_add_incoming (ctx,
561 : &auth,
562 : &reserve_pub,
563 : &amount,
564 : debit_account,
565 : &res_cb,
566 : NULL);
567 1 : if (NULL == op)
568 : {
569 0 : fprintf (stderr,
570 : "Could not execute the wire transfer to the exchange\n");
571 0 : GNUNET_SCHEDULER_shutdown ();
572 0 : return;
573 : }
574 : }
575 :
576 :
577 : /**
578 : * Main function that will be run.
579 : *
580 : * @param cls closure
581 : * @param args remaining command-line arguments
582 : * @param cfgfile name of the configuration file used (for saving, can be NULL!)
583 : * @param cfg configuration
584 : */
585 : static void
586 4 : run (void *cls,
587 : char *const *args,
588 : const char *cfgfile,
589 : const struct GNUNET_CONFIGURATION_Handle *cfg)
590 : {
591 : (void) cls;
592 : (void) args;
593 : (void) cfgfile;
594 : (void) cfg;
595 :
596 4 : GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
597 : NULL);
598 4 : ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
599 : &rc);
600 4 : GNUNET_assert (NULL != ctx);
601 4 : rc = GNUNET_CURL_gnunet_rc_create (ctx);
602 4 : if (NULL != account_section)
603 : {
604 0 : if (0 != strncasecmp ("exchange-accountcredentials-",
605 : account_section,
606 : strlen ("exchange-accountcredentials-")))
607 : {
608 0 : fprintf (stderr,
609 : "Error: invalid section specified, must begin with `%s`\n",
610 : "exchange-accountcredentials-");
611 0 : GNUNET_SCHEDULER_shutdown ();
612 0 : return;
613 : }
614 0 : if ( (NULL != auth.wire_gateway_url) ||
615 0 : (NULL != auth.details.basic.username) ||
616 0 : (NULL != auth.details.basic.password) )
617 : {
618 0 : fprintf (stderr,
619 : "Error: Conflicting authentication options provided. Please only use one method.\n");
620 0 : GNUNET_SCHEDULER_shutdown ();
621 0 : return;
622 : }
623 0 : if (GNUNET_OK !=
624 0 : TALER_BANK_auth_parse_cfg (cfg,
625 : account_section,
626 : &auth))
627 : {
628 0 : fprintf (stderr,
629 : "Error: Authentication information not found in configuration section `%s'\n",
630 : account_section);
631 0 : GNUNET_SCHEDULER_shutdown ();
632 0 : return;
633 : }
634 : }
635 : else
636 : {
637 4 : if ( (NULL != auth.wire_gateway_url) &&
638 4 : (NULL != auth.details.basic.username) &&
639 0 : (NULL != auth.details.basic.password) )
640 : {
641 0 : auth.method = TALER_BANK_AUTH_BASIC;
642 : }
643 4 : else if (NULL == auth.wire_gateway_url)
644 : {
645 0 : fprintf (stderr,
646 : "Error: No account specified (use -b or -s options).\n");
647 0 : GNUNET_SCHEDULER_shutdown ();
648 0 : return;
649 : }
650 : }
651 4 : if ( (NULL == auth.wire_gateway_url) ||
652 4 : (0 == strlen (auth.wire_gateway_url)) ||
653 4 : (0 != strncasecmp ("http",
654 4 : auth.wire_gateway_url,
655 : strlen ("http"))) )
656 : {
657 0 : fprintf (stderr,
658 : "Error: Invalid wire gateway URL `%s' configured.\n",
659 : auth.wire_gateway_url);
660 0 : GNUNET_SCHEDULER_shutdown ();
661 0 : return;
662 : }
663 4 : if ( (GNUNET_YES == incoming_history) &&
664 1 : (GNUNET_YES == outgoing_history) )
665 : {
666 0 : fprintf (stderr,
667 : "Error: Please specify only -i or -o, but not both.\n");
668 0 : GNUNET_SCHEDULER_shutdown ();
669 0 : return;
670 : }
671 4 : if (GNUNET_YES == incoming_history)
672 : {
673 1 : execute_credit_history ();
674 1 : return;
675 : }
676 3 : if (GNUNET_YES == outgoing_history)
677 : {
678 1 : execute_debit_history ();
679 1 : return;
680 : }
681 2 : if (NULL != credit_account)
682 : {
683 1 : execute_wire_transfer ();
684 1 : return;
685 : }
686 1 : if (NULL != debit_account)
687 : {
688 1 : execute_admin_transfer ();
689 1 : return;
690 : }
691 :
692 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
693 : "No operation specified.\n");
694 0 : global_ret = 0;
695 0 : GNUNET_SCHEDULER_shutdown ();
696 : }
697 :
698 :
699 : /**
700 : * The main function of the taler-exchange-wire-gateway-client
701 : *
702 : * @param argc number of arguments from the command line
703 : * @param argv command line arguments
704 : * @return 0 ok, 1 on error
705 : */
706 : int
707 4 : main (int argc,
708 : char *const *argv)
709 : {
710 4 : const struct GNUNET_GETOPT_CommandLineOption options[] = {
711 4 : TALER_getopt_get_amount ('a',
712 : "amount",
713 : "VALUE",
714 : "value to transfer",
715 : &amount),
716 4 : GNUNET_GETOPT_option_string ('b',
717 : "bank",
718 : "URL",
719 : "Wire gateway URL to use to talk to the bank",
720 : &auth.wire_gateway_url),
721 4 : GNUNET_GETOPT_option_string ('C',
722 : "credit",
723 : "ACCOUNT",
724 : "payto URI of the bank account to credit (when making outgoing transfers)",
725 : &credit_account),
726 4 : GNUNET_GETOPT_option_string ('D',
727 : "debit",
728 : "PAYTO-URL",
729 : "payto URI of the bank account to debit (when making incoming transfers)",
730 : &debit_account),
731 4 : GNUNET_GETOPT_option_flag ('i',
732 : "credit-history",
733 : "Ask to get a list of 10 incoming transactions.",
734 : &incoming_history),
735 4 : GNUNET_GETOPT_option_flag ('o',
736 : "debit-history",
737 : "Ask to get a list of 10 outgoing transactions.",
738 : &outgoing_history),
739 4 : GNUNET_GETOPT_option_string ('p',
740 : "pass",
741 : "PASSPHRASE",
742 : "passphrase to use for authentication",
743 : &auth.details.basic.password),
744 4 : GNUNET_GETOPT_option_string ('s',
745 : "section",
746 : "ACCOUNT-SECTION",
747 : "Which config section has the credentials to access the bank. Conflicts with -b -u and -p options.\n",
748 : &account_section),
749 4 : GNUNET_GETOPT_option_string ('S',
750 : "subject",
751 : "SUBJECT",
752 : "specifies the wire transfer subject",
753 : &subject),
754 4 : GNUNET_GETOPT_option_string ('u',
755 : "user",
756 : "USERNAME",
757 : "username to use for authentication",
758 : &auth.details.basic.username),
759 4 : GNUNET_GETOPT_option_ulong ('w',
760 : "since-when",
761 : "ROW",
762 : "When asking the bank for transactions history, this option commands that all the results should have IDs settled after SW. If not given, then the 10 youngest transactions are returned.",
763 : &start_row),
764 : GNUNET_GETOPT_OPTION_END
765 : };
766 : enum GNUNET_GenericReturnValue ret;
767 :
768 : /* force linker to link against libtalerutil; if we do
769 : not do this, the linker may "optimize" libtalerutil
770 : away and skip #TALER_OS_init(), which we do need */
771 4 : (void) TALER_project_data_default ();
772 4 : if (GNUNET_OK !=
773 4 : GNUNET_STRINGS_get_utf8_args (argc, argv,
774 : &argc, &argv))
775 0 : return 4;
776 4 : global_ret = 1;
777 4 : ret = GNUNET_PROGRAM_run (
778 : argc, argv,
779 : "taler-wire-gateway-client",
780 : gettext_noop ("Client tool of the Taler Wire Gateway"),
781 : options,
782 : &run, NULL);
783 4 : GNUNET_free_nz ((void *) argv);
784 4 : if (GNUNET_SYSERR == ret)
785 0 : return 3;
786 4 : if (GNUNET_NO == ret)
787 0 : return 0;
788 4 : return global_ret;
789 : }
790 :
791 :
792 : /* end taler-wire-gateway-client.c */
|