LCOV - code coverage report
Current view: top level - util - contract_serialize.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 73.8 % 107 79
Test Date: 2026-04-12 12:58:13 Functions: 83.3 % 12 10

            Line data    Source code
       1              : /*
       2              :   This file is part of GNU Taler
       3              :   Copyright (C) 2024, 2025 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 util/contract_serialize.c
      18              :  * @brief shared logic for contract terms serialization
      19              :  * @author Iván Ávalos
      20              :  * @author Christian Grothoff
      21              :  */
      22              : 
      23              : #include "taler/platform.h"
      24              : #include <gnunet/gnunet_json_lib.h>
      25              : #include <gnunet/gnunet_common.h>
      26              : #include <taler/taler_json_lib.h>
      27              : #include <jansson.h>
      28              : #include "taler/taler_util.h"
      29              : #include "taler/taler_merchant_util.h"
      30              : 
      31              : /**
      32              :  * Get JSON representation of merchant details.
      33              :  *
      34              :  * @param[in] contract contract terms
      35              :  * @return JSON object with merchant details; NULL on error
      36              :  */
      37              : static json_t *
      38            2 : json_from_merchant_details (
      39              :   const struct TALER_MERCHANT_Contract *contract)
      40              : {
      41            2 :   return GNUNET_JSON_PACK (
      42              :     GNUNET_JSON_pack_string ("name",
      43              :                              contract->merchant.name),
      44              :     GNUNET_JSON_pack_allow_null (
      45              :       GNUNET_JSON_pack_string ("email",
      46              :                                contract->merchant.email)),
      47              :     GNUNET_JSON_pack_allow_null (
      48              :       GNUNET_JSON_pack_string ("website",
      49              :                                contract->merchant.website)),
      50              :     GNUNET_JSON_pack_allow_null (
      51              :       GNUNET_JSON_pack_string ("logo",
      52              :                                contract->merchant.logo)),
      53              :     GNUNET_JSON_pack_allow_null (
      54              :       GNUNET_JSON_pack_object_steal ("address",
      55              :                                      contract->merchant.address)),
      56              :     GNUNET_JSON_pack_allow_null (
      57              :       GNUNET_JSON_pack_object_steal ("jurisdiction",
      58              :                                      contract->merchant.jurisdiction)));
      59              : }
      60              : 
      61              : 
      62              : /**
      63              :  * Get JSON representation of contract choice input.
      64              :  *
      65              :  * @param[in] input contract terms choice input
      66              :  * @return JSON representation of @a input; NULL on error
      67              :  */
      68              : static json_t *
      69            1 : json_from_contract_input (
      70              :   const struct TALER_MERCHANT_ContractInput *input)
      71              : {
      72            1 :   switch (input->type)
      73              :   {
      74            0 :   case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID:
      75            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
      76              :                 "invalid contract input type");
      77            0 :     GNUNET_assert (0);
      78              :     return NULL;
      79            1 :   case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
      80            1 :     return GNUNET_JSON_PACK (
      81              :       GNUNET_JSON_pack_string ("type",
      82              :                                "token"),
      83              :       GNUNET_JSON_pack_string ("token_family_slug",
      84              :                                input->details.token.token_family_slug),
      85              :       GNUNET_JSON_pack_int64 ("count",
      86              :                               input->details.token.count));
      87              :   }
      88              : 
      89            0 :   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
      90              :               "unsupported contract input type %d",
      91              :               input->type);
      92            0 :   GNUNET_assert (0);
      93              :   return NULL;
      94              : }
      95              : 
      96              : 
      97              : /**
      98              :  * Get JSON representation of contract choice output.
      99              :  *
     100              :  * @param[in] output contract terms choice output
     101              :  * @return JSON representation of @a output; NULL on error
     102              :  */
     103              : static json_t *
     104            2 : json_from_contract_output (
     105              :   const struct TALER_MERCHANT_ContractOutput *output)
     106              : {
     107            2 :   switch (output->type)
     108              :   {
     109            0 :   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
     110            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     111              :                 "invalid contract output type");
     112            0 :     GNUNET_assert (0);
     113              :     return NULL;
     114            1 :   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
     115            1 :     return GNUNET_JSON_PACK (
     116              :       GNUNET_JSON_pack_string ("type",
     117              :                                "token"),
     118              :       GNUNET_JSON_pack_string ("token_family_slug",
     119              :                                output->details.token.token_family_slug),
     120              :       GNUNET_JSON_pack_uint64 ("count",
     121              :                                output->details.token.count),
     122              :       GNUNET_JSON_pack_uint64 ("key_index",
     123              :                                output->details.token.key_index));
     124            1 :   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
     125              :     {
     126              :       json_t *donau_urls;
     127              : 
     128            1 :       donau_urls = json_array ();
     129            1 :       GNUNET_assert (NULL != donau_urls);
     130            1 :       for (unsigned i = 0;
     131            4 :            i < output->details.donation_receipt.donau_urls_len;
     132            3 :            i++)
     133            3 :         GNUNET_assert (0 ==
     134              :                        json_array_append_new (
     135              :                          donau_urls,
     136              :                          json_string (
     137              :                            output->details.donation_receipt.donau_urls[i])));
     138              : 
     139            1 :       return GNUNET_JSON_PACK (
     140              :         GNUNET_JSON_pack_string ("type",
     141              :                                  "tax-receipt"),
     142              :         GNUNET_JSON_pack_array_steal ("donau_urls",
     143              :                                       donau_urls),
     144              :         GNUNET_JSON_pack_allow_null (
     145              :           TALER_JSON_pack_amount ("amount",
     146              :                                   &output->details.donation_receipt.amount)));
     147              :     }
     148              :   }
     149            0 :   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     150              :               "Unsupported contract output type %d",
     151              :               output->type);
     152            0 :   GNUNET_assert (0);
     153              :   return NULL;
     154              : }
     155              : 
     156              : 
     157              : json_t *
     158            1 : TALER_MERCHANT_json_from_contract_choice (
     159              :   const struct TALER_MERCHANT_ContractChoice *choice,
     160              :   bool order)
     161              : {
     162              :   json_t *inputs;
     163              :   json_t *outputs;
     164              : 
     165            1 :   inputs = json_array ();
     166            1 :   GNUNET_assert (NULL != inputs);
     167            2 :   for (unsigned int i = 0; i < choice->inputs_len; i++)
     168            1 :     GNUNET_assert (0 ==
     169              :                    json_array_append_new (inputs,
     170              :                                           json_from_contract_input (
     171              :                                             &choice->inputs[i])));
     172            1 :   outputs = json_array ();
     173            1 :   GNUNET_assert (NULL != outputs);
     174            3 :   for (unsigned int i = 0; i < choice->outputs_len; i++)
     175            2 :     GNUNET_assert (0 ==
     176              :                    json_array_append_new (outputs,
     177              :                                           json_from_contract_output (
     178              :                                             &choice->outputs[i])));
     179              : 
     180            1 :   return GNUNET_JSON_PACK (
     181              :     TALER_JSON_pack_amount ("amount",
     182              :                             &choice->amount),
     183              :     GNUNET_JSON_pack_allow_null (
     184              :       TALER_JSON_pack_amount ("tip",
     185              :                               choice->no_tip
     186              :                               ? NULL
     187              :                               : &choice->tip)),
     188              :     GNUNET_JSON_pack_allow_null (
     189              :       GNUNET_JSON_pack_string ("description",
     190              :                                choice->description)),
     191              :     GNUNET_JSON_pack_allow_null (
     192              :       GNUNET_JSON_pack_object_incref ("description_i18n",
     193              :                                       choice->description_i18n)),
     194              :     (order)
     195              :     ? GNUNET_JSON_pack_allow_null (
     196              :       TALER_JSON_pack_amount (
     197              :         "max_fee",
     198              :         /* workaround for nullable amount */
     199              :         (GNUNET_OK ==
     200              :          TALER_amount_is_valid (&choice->max_fee))
     201              :         ? &choice->max_fee
     202              :         : NULL))
     203              :     : TALER_JSON_pack_amount ("max_fee",
     204              :                               &choice->max_fee),
     205              :     (order)
     206              :     ? GNUNET_JSON_pack_allow_null (
     207              :       GNUNET_JSON_pack_array_steal ("inputs",
     208              :                                     inputs))
     209              :     : GNUNET_JSON_pack_array_steal ("inputs",
     210              :                                     inputs),
     211              :     (order)
     212              :     ? GNUNET_JSON_pack_allow_null (
     213              :       GNUNET_JSON_pack_array_steal ("outputs",
     214              :                                     outputs))
     215              :     : GNUNET_JSON_pack_array_steal ("outputs",
     216              :                                     outputs));
     217              : }
     218              : 
     219              : 
     220              : /**
     221              :  * Get JSON representation of contract token family key.
     222              :  *
     223              :  * @param[in] key contract token family key
     224              :  * @return JSON representation of @a key; NULL on error
     225              :  */
     226              : static json_t *
     227            2 : json_from_token_family_key (
     228              :   const struct TALER_MERCHANT_ContractTokenFamilyKey *key)
     229              : {
     230            2 :   return GNUNET_JSON_PACK (
     231              :     GNUNET_JSON_pack_timestamp ("signature_validity_start",
     232              :                                 key->valid_after),
     233              :     GNUNET_JSON_pack_timestamp ("signature_validity_end",
     234              :                                 key->valid_before),
     235              :     TALER_JSON_pack_token_pub (NULL,
     236              :                                &key->pub));
     237              : }
     238              : 
     239              : 
     240              : /**
     241              :  * Get JSON representation of contract token family details.
     242              :  *
     243              :  * @param[in] family contract token family
     244              :  * @return JSON representation of @a family->details; NULL on error
     245              :  */
     246              : static json_t *
     247            2 : json_from_token_family_details (
     248              :   const struct TALER_MERCHANT_ContractTokenFamily *family)
     249              : {
     250            2 :   switch (family->kind)
     251              :   {
     252            0 :   case TALER_MERCHANT_CONTRACT_TOKEN_KIND_INVALID:
     253            0 :     break;
     254            1 :   case TALER_MERCHANT_CONTRACT_TOKEN_KIND_SUBSCRIPTION:
     255              :     {
     256              :       json_t *trusted_domains;
     257              : 
     258            1 :       trusted_domains = json_array ();
     259            1 :       GNUNET_assert (NULL != trusted_domains);
     260            1 :       for (unsigned int i = 0;
     261            4 :            i < family->details.subscription.trusted_domains_len;
     262            3 :            i++)
     263            3 :         GNUNET_assert (0 ==
     264              :                        json_array_append_new (
     265              :                          trusted_domains,
     266              :                          json_string (
     267              :                            family->details.subscription.trusted_domains[i])));
     268              : 
     269            1 :       return GNUNET_JSON_PACK (
     270              :         GNUNET_JSON_pack_string ("class",
     271              :                                  "subscription"),
     272              :         GNUNET_JSON_pack_array_steal ("trusted_domains",
     273              :                                       trusted_domains));
     274              :     }
     275            1 :   case TALER_MERCHANT_CONTRACT_TOKEN_KIND_DISCOUNT:
     276              :     {
     277              :       json_t *expected_domains;
     278              : 
     279            1 :       expected_domains = json_array ();
     280            1 :       GNUNET_assert (NULL != expected_domains);
     281            1 :       for (unsigned int i = 0;
     282            4 :            i < family->details.discount.expected_domains_len;
     283            3 :            i++)
     284            3 :         GNUNET_assert (0 ==
     285              :                        json_array_append_new (
     286              :                          expected_domains,
     287              :                          json_string (
     288              :                            family->details.discount.expected_domains[i])));
     289              : 
     290            1 :       return GNUNET_JSON_PACK (
     291              :         GNUNET_JSON_pack_string ("class",
     292              :                                  "discount"),
     293              :         GNUNET_JSON_pack_array_steal ("expected_domains",
     294              :                                       expected_domains));
     295              :     }
     296              :   }
     297              : 
     298            0 :   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     299              :               "unsupported token family kind %d",
     300              :               family->kind);
     301            0 :   GNUNET_assert (0);
     302              :   return NULL;
     303              : }
     304              : 
     305              : 
     306              : json_t *
     307            2 : TALER_MERCHANT_json_from_token_family (
     308              :   const struct TALER_MERCHANT_ContractTokenFamily *family)
     309              : {
     310              :   json_t *keys;
     311              : 
     312            2 :   keys = json_array ();
     313            2 :   GNUNET_assert (NULL != keys);
     314            4 :   for (unsigned int i = 0; i < family->keys_len; i++)
     315            2 :     GNUNET_assert (0 == json_array_append_new (
     316              :                      keys,
     317              :                      json_from_token_family_key (
     318              :                        &family->keys[i])));
     319              : 
     320            2 :   return GNUNET_JSON_PACK (
     321              :     GNUNET_JSON_pack_string ("name",
     322              :                              family->name),
     323              :     GNUNET_JSON_pack_string ("description",
     324              :                              family->description),
     325              :     GNUNET_JSON_pack_object_incref ("description_i18n",
     326              :                                     family->description_i18n),
     327              :     GNUNET_JSON_pack_array_steal ("keys",
     328              :                                   keys),
     329              :     GNUNET_JSON_pack_object_steal ("details",
     330              :                                    json_from_token_family_details (family)),
     331              :     GNUNET_JSON_pack_bool ("critical",
     332              :                            family->critical));
     333              : }
     334              : 
     335              : 
     336              : /**
     337              :  * Get JSON object with contract terms v0-specific fields.
     338              :  *
     339              :  * @param[in] input contract terms v0
     340              :  * @return JSON object with @a input v0 fields; NULL on error
     341              :  */
     342              : static json_t *
     343            1 : json_from_contract_v0 (
     344              :   const struct TALER_MERCHANT_Contract *input)
     345              : {
     346            1 :   return GNUNET_JSON_PACK (
     347              :     TALER_JSON_pack_amount ("amount",
     348              :                             &input->details.v0.brutto),
     349              :     GNUNET_JSON_pack_allow_null (
     350              :       TALER_JSON_pack_amount ("tip",
     351              :                               input->details.v0.no_tip
     352              :                               ? NULL
     353              :                               : &input->details.v0.tip)),
     354              :     TALER_JSON_pack_amount ("max_fee",
     355              :                             &input->details.v0.max_fee));
     356              : }
     357              : 
     358              : 
     359              : /**
     360              :  * Get JSON object with contract terms v1-specific fields.
     361              :  *
     362              :  * @param[in] input contract terms v1
     363              :  * @return JSON object with @a input v1 fields; NULL on error
     364              :  */
     365              : static json_t *
     366            1 : json_from_contract_v1 (
     367              :   const struct TALER_MERCHANT_Contract *input)
     368              : {
     369              :   json_t *choices;
     370              :   json_t *families;
     371              : 
     372            1 :   choices = json_array ();
     373            1 :   GNUNET_assert (0 != choices);
     374            2 :   for (unsigned i = 0; i < input->details.v1.choices_len; i++)
     375            1 :     GNUNET_assert (0 == json_array_append_new (
     376              :                      choices,
     377              :                      TALER_MERCHANT_json_from_contract_choice (
     378              :                        &input->details.v1.choices[i],
     379              :                        false)));
     380              : 
     381            1 :   families = json_object ();
     382            1 :   GNUNET_assert (0 != families);
     383            3 :   for (unsigned i = 0; i < input->details.v1.token_authorities_len; i++)
     384            2 :     GNUNET_assert (0 == json_object_set_new (
     385              :                      families,
     386              :                      input->details.v1.token_authorities[i].slug,
     387              :                      TALER_MERCHANT_json_from_token_family (
     388              :                        &input->details.v1.token_authorities[i])));
     389              : 
     390            1 :   return GNUNET_JSON_PACK (
     391              :     GNUNET_JSON_pack_array_steal ("choices",
     392              :                                   choices),
     393              :     GNUNET_JSON_pack_object_steal ("token_families",
     394              :                                    families));
     395              : }
     396              : 
     397              : 
     398              : /**
     399              :  * Convert quantity @a q into a string for JSON serialization
     400              :  *
     401              :  * @param q quantity to convert
     402              :  * @return formatted string
     403              :  */
     404              : static const char *
     405            0 : quantity_to_string (const struct TALER_MERCHANT_ProductQuantity *q)
     406              : {
     407              :   static char res[64];
     408              : 
     409            0 :   TALER_MERCHANT_vk_format_fractional_string (TALER_MERCHANT_VK_QUANTITY,
     410            0 :                                               q->integer,
     411            0 :                                               q->fractional,
     412              :                                               sizeof (res),
     413              :                                               res);
     414            0 :   return res;
     415              : }
     416              : 
     417              : 
     418              : json_t *
     419            0 : TALER_MERCHANT_product_sold_serialize (
     420              :   const struct TALER_MERCHANT_ProductSold *p)
     421              : {
     422              :   json_t *prices;
     423              : 
     424            0 :   prices = json_array ();
     425            0 :   GNUNET_assert (NULL != prices);
     426            0 :   for (unsigned int i = 0; i<p->prices_length; i++)
     427            0 :     GNUNET_assert (0 ==
     428              :                    json_array_append_new (prices,
     429              :                                           TALER_JSON_from_amount (
     430              :                                             &p->prices[i])));
     431            0 :   return GNUNET_JSON_PACK (
     432              :     GNUNET_JSON_pack_allow_null (
     433              :       GNUNET_JSON_pack_string ("product_id",
     434              :                                p->product_id)),
     435              :     GNUNET_JSON_pack_allow_null (
     436              :       GNUNET_JSON_pack_string ("product_name",
     437              :                                p->product_name)),
     438              :     GNUNET_JSON_pack_allow_null (
     439              :       GNUNET_JSON_pack_string ("description",
     440              :                                p->description)),
     441              :     GNUNET_JSON_pack_allow_null (
     442              :       GNUNET_JSON_pack_object_incref ("description_i18n",
     443              :                                       (json_t *) p->description_i18n)),
     444              :     GNUNET_JSON_pack_allow_null (
     445              :       ( (0 != p->unit_quantity.integer) ||
     446              :         (0 != p->unit_quantity.fractional) )
     447              :       ? GNUNET_JSON_pack_string ("unit_quantity",
     448              :                                  quantity_to_string (&p->unit_quantity))
     449              :       : GNUNET_JSON_pack_string ("dummy",
     450              :                                  NULL) ),
     451              :     /* Legacy */
     452              :     GNUNET_JSON_pack_allow_null (
     453              :       (0 == p->unit_quantity.fractional)
     454              :       ? GNUNET_JSON_pack_uint64 ("quantity",
     455              :                                  p->unit_quantity.integer)
     456              :       : GNUNET_JSON_pack_string ("dummy",
     457              :                                  NULL) ),
     458              :     GNUNET_JSON_pack_allow_null (
     459              :       GNUNET_JSON_pack_string ("unit",
     460              :                                p->unit)),
     461              :     /* Deprecated, use prices! */
     462              :     GNUNET_JSON_pack_allow_null (
     463              :       TALER_JSON_pack_amount ("price",
     464              :                               0 < p->prices_length
     465              :                               ? &p->prices[0]
     466              :                               : NULL)),
     467              :     GNUNET_JSON_pack_array_steal ("prices",
     468              :                                   prices),
     469              :     GNUNET_JSON_pack_allow_null (
     470              :       GNUNET_JSON_pack_string ("image",
     471              :                                p->image)),
     472              :     GNUNET_JSON_pack_allow_null (
     473              :       GNUNET_JSON_pack_array_incref ("taxes",
     474              :                                      (json_t *) p->taxes)),
     475              :     GNUNET_JSON_pack_allow_null (
     476              :       GNUNET_TIME_absolute_is_never (p->delivery_date.abs_time)
     477              :       ? GNUNET_JSON_pack_string ("dummy",
     478              :                                  NULL)
     479              :       : GNUNET_JSON_pack_timestamp ("delivery_date",
     480              :                                     p->delivery_date)),
     481              :     GNUNET_JSON_pack_uint64 ("product_money_pot",
     482              :                              p->product_money_pot));
     483              : }
     484              : 
     485              : 
     486              : json_t *
     487            2 : TALER_MERCHANT_contract_serialize (
     488              :   const struct TALER_MERCHANT_Contract *input,
     489              :   bool nonce_optional)
     490              : {
     491              :   json_t *details;
     492              :   json_t *products;
     493              : 
     494            2 :   switch (input->version)
     495              :   {
     496            1 :   case TALER_MERCHANT_CONTRACT_VERSION_0:
     497            1 :     details = json_from_contract_v0 (input);
     498            1 :     goto success;
     499            1 :   case TALER_MERCHANT_CONTRACT_VERSION_1:
     500            1 :     details = json_from_contract_v1 (input);
     501            1 :     goto success;
     502              :   }
     503              : 
     504            0 :   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     505              :               "unknown contract type version %d",
     506              :               input->version);
     507            0 :   GNUNET_assert (0);
     508              :   return NULL;
     509              : 
     510            2 : success:
     511            2 :   products = json_array ();
     512            2 :   GNUNET_assert (NULL != products);
     513            2 :   for (size_t i = 0; i<input->products_len; i++)
     514              :   {
     515            0 :     GNUNET_assert (
     516              :       0 ==
     517              :       json_array_append_new (products,
     518              :                              TALER_MERCHANT_product_sold_serialize (
     519              :                                &input->products[i])));
     520              :   }
     521              : 
     522            2 :   return GNUNET_JSON_PACK (
     523              :     GNUNET_JSON_pack_uint64 ("version",
     524              :                              input->version),
     525              :     GNUNET_JSON_pack_string ("summary",
     526              :                              input->summary),
     527              :     GNUNET_JSON_pack_allow_null (
     528              :       GNUNET_JSON_pack_object_steal ("summary_i18n",
     529              :                                      input->summary_i18n)),
     530              :     GNUNET_JSON_pack_string ("order_id",
     531              :                              input->order_id),
     532              :     GNUNET_JSON_pack_allow_null (
     533              :       GNUNET_JSON_pack_string ("public_reorder_url",
     534              :                                input->public_reorder_url)),
     535              :     GNUNET_JSON_pack_allow_null (
     536              :       GNUNET_JSON_pack_string ("fulfillment_url",
     537              :                                input->fulfillment_url)),
     538              :     GNUNET_JSON_pack_allow_null (
     539              :       GNUNET_JSON_pack_string ("fulfillment_message",
     540              :                                input->fulfillment_message)),
     541              :     GNUNET_JSON_pack_allow_null (
     542              :       GNUNET_JSON_pack_object_steal ("fulfillment_message_i18n",
     543              :                                      input->fulfillment_message_i18n)),
     544              :     GNUNET_JSON_pack_array_steal ("products",
     545              :                                   products),
     546              :     GNUNET_JSON_pack_timestamp ("timestamp",
     547              :                                 input->timestamp),
     548              :     GNUNET_JSON_pack_timestamp ("refund_deadline",
     549              :                                 input->refund_deadline),
     550              :     GNUNET_JSON_pack_timestamp ("pay_deadline",
     551              :                                 input->pay_deadline),
     552              :     GNUNET_JSON_pack_timestamp ("wire_transfer_deadline",
     553              :                                 input->wire_deadline),
     554              :     GNUNET_JSON_pack_data_auto ("merchant_pub",
     555              :                                 &input->merchant_pub.eddsa_pub),
     556              :     GNUNET_JSON_pack_string ("merchant_base_url",
     557              :                              input->merchant_base_url),
     558              :     GNUNET_JSON_pack_object_steal ("merchant",
     559              :                                    json_from_merchant_details (input)),
     560              :     GNUNET_JSON_pack_data_auto ("h_wire",
     561              :                                 &input->h_wire),
     562              :     GNUNET_JSON_pack_string ("wire_method",
     563              :                              input->wire_method),
     564              :     GNUNET_JSON_pack_array_steal ("exchanges",
     565              :                                   input->exchanges),
     566              :     GNUNET_JSON_pack_allow_null (
     567              :       GNUNET_JSON_pack_object_steal ("delivery_location",
     568              :                                      input->delivery_location)),
     569              :     GNUNET_JSON_pack_allow_null (
     570              :       GNUNET_JSON_pack_timestamp ("delivery_date",
     571              :                                   input->delivery_date)),
     572              :     (nonce_optional)
     573              :     ? GNUNET_JSON_pack_allow_null (
     574              :       GNUNET_JSON_pack_string ("nonce",
     575              :                                input->nonce))
     576              :     : GNUNET_JSON_pack_string ("nonce",
     577              :                                input->nonce),
     578              :     GNUNET_JSON_pack_allow_null (
     579              :       GNUNET_JSON_pack_time_rel ("auto_refund",
     580              :                                  input->auto_refund)),
     581              :     GNUNET_JSON_pack_allow_null (
     582              :       GNUNET_JSON_pack_object_steal ("extra",
     583              :                                      input->extra)),
     584              :     GNUNET_JSON_pack_allow_null (
     585              :       GNUNET_JSON_pack_uint64 ("minimum_age",
     586              :                                input->minimum_age)),
     587              :     (0 == input->default_money_pot)
     588              :     ? GNUNET_JSON_pack_allow_null (
     589              :       GNUNET_JSON_pack_string ("dummy",
     590              :                                NULL))
     591              :     : GNUNET_JSON_pack_uint64 ("default_money_pot",
     592              :                                input->default_money_pot),
     593              :     GNUNET_JSON_pack_object_steal (NULL,
     594              :                                    details));
     595              : }
        

Generated by: LCOV version 2.0-1