get-keys.rst (23368B)
1 .. http:get:: /keys 2 3 Get a list of all denomination keys offered by the exchange, 4 as well as the exchange's current online signing key. 5 6 **Request:** 7 8 :query last_issue_date: Optional argument specifying the maximum value of any of the ``stamp_start`` members of the denomination keys of a ``/keys`` response that is already known to the client. Allows the exchange to only return keys that have changed since that timestamp. The given value must be an unsigned 64-bit integer representing seconds after 1970. If the timestamp does not exactly match the ``stamp_start`` of one of the denomination keys, all keys are returned. 9 10 **Response:** 11 12 :http:statuscode:`200 OK`: 13 The exchange responds with a `ExchangeKeysResponse` object. This request should 14 virtually always be successful. It only fails if the exchange is misconfigured or 15 has not yet been provisioned with key signatures via ``taler-exchange-offline``. 16 :http:statuscode:`400 Bad Request`: 17 A query parameter is malformed. 18 This response comes with a standard `ErrorDetail` response with 19 a code of ``TALER_EC_GENERIC_PARAMETER_MALFORMED``. 20 :http:statuscode:`502 Bad Gateway`: 21 A denomination or signing key helper is unavailable. 22 This response comes with a standard `ErrorDetail` response with 23 a code of ``TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE`` or 24 ``TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE``. 25 :http:statuscode:`503 Service Unavailable`: 26 The exchange has no valid denomination keys available. 27 This response comes with a standard `ErrorDetail` response with 28 a code of ``TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING``. 29 30 **Details:** 31 32 .. ts:def:: ExchangeKeysResponse 33 34 interface ExchangeKeysResponse { 35 // libtool-style representation of the Exchange protocol version, see 36 // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning 37 // The format is "current:revision:age". 38 version: string; 39 40 // The exchange's base URL. 41 base_url: string; 42 43 // The exchange's currency or asset unit. 44 currency: string; 45 46 // Shopping URL where users may find shops that accept 47 // digital cash issued by this exchange. 48 // @since protocol **v21**. 49 shopping_url?: string; 50 51 // Instructs wallets to use certain bank-specific 52 // language (for buttons) and/or other UI/UX customization 53 // for compliance with the rules of that bank. 54 // The specific customizations to apply are done on a per-wallet 55 // basis as requested by the specific bank. They only 56 // apply when it is clear that the wallet is using digital 57 // cash from that bank. This is an advisory option, not 58 // all wallets must support all compliance languages. 59 // @since protocol **v24**. 60 bank_compliance_language?: string; 61 62 // How wallets should render this currency. 63 currency_specification: CurrencySpecification; 64 65 // Small(est?) amount that can likely be transferred to 66 // the exchange. Should be the default amount for KYC 67 // authentication wire transfers to this exchange. 68 // @since protocol **v21**. Mandatory since **v33**. 69 tiny_amount?: Amount; 70 71 // Absolute cost offset for the STEFAN curve used 72 // to (over) approximate fees payable by amount. 73 stefan_abs: Amount; 74 75 // Factor to multiply the logarithm of the amount 76 // with to (over) approximate fees payable by amount. 77 // Note that the total to be paid is first to be 78 // divided by the smallest denomination to obtain 79 // the value that the logarithm is to be taken of. 80 stefan_log: Amount; 81 82 // Linear cost factor for the STEFAN curve used 83 // to (over) approximate fees payable by amount. 84 // 85 // Note that this is a scalar, as it is multiplied 86 // with the actual amount. 87 stefan_lin: Float; 88 89 // Type of the asset. "fiat", "crypto", "regional" 90 // or "stock". Wallets should adjust their UI/UX 91 // based on this value. 92 asset_type: string; 93 94 // Array of wire accounts operated by the exchange for 95 // incoming wire transfers. 96 accounts: ExchangeWireAccount[]; 97 98 // Object mapping names of wire methods (i.e. "iban" or "x-taler-bank") 99 // to wire fees. 100 wire_fees: { method : AggregateTransferFee[] }; 101 102 // List of exchanges that this exchange is partnering 103 // with to enable wallet-to-wallet transfers. 104 wads: ExchangePartnerListEntry[]; 105 106 // Set to true if this exchange allows the use 107 // of reserves for rewards. 108 // @deprecated in protocol **v18**. 109 rewards_allowed: false; 110 111 // Set to true if this exchange has KYC enabled and thus 112 // requires KYC auth wire transfers prior to a first deposit. 113 // @since in protocol **v24**. 114 kyc_enabled: boolean; 115 116 // Set to TRUE if wallets should disable the direct deposit feature 117 // and deposits should only go via Taler merchant APIs. 118 // Mainly used for regional currency and event currency deployments 119 // where wallets are not eligible to deposit back into originating 120 // bank accounts and, because KYC is not enabled, wallets are thus 121 // likely to send money to nirvana instead of where users want it. 122 // @since in protocol **v30**. 123 disable_direct_deposit: boolean; 124 125 // EdDSA master public key of the exchange, used to sign entries 126 // in ``denoms`` and ``signkeys``. 127 master_public_key: EddsaPublicKey; 128 129 // Relative duration until inactive reserves are closed; 130 // not signed (!), can change without notice. 131 reserve_closing_delay: RelativeTime; 132 133 // Threshold amounts beyond which wallet should 134 // trigger the KYC process of the issuing exchange. 135 // Optional option, if not given there is no limit. 136 // Currency must match ``currency``. 137 wallet_balance_limit_without_kyc?: Amount[]; 138 139 // Array of limits that apply to all accounts. 140 // All of the given limits will be hard limits. 141 // Wallets and merchants are expected to obey them 142 // and not even allow the user to cross them. 143 // @since protocol **v21**. 144 hard_limits: AccountLimit[]; 145 146 // Array of limits with a soft threshold of zero 147 // that apply to all accounts without KYC. 148 // Wallets and merchants are expected to trigger 149 // a KYC process before attempting any zero-limited 150 // operations. 151 // @since protocol **v21**. 152 zero_limits: ZeroLimitedOperation[]; 153 154 // Denominations offered by this exchange 155 denominations: DenomGroup[]; 156 157 // Compact EdDSA `signature` (binary-only) over the 158 // contatentation of all of the master_sigs (in reverse 159 // chronological order by group) in the arrays under 160 // "denominations". Signature of `TALER_ExchangeKeySetPS` 161 exchange_sig: EddsaSignature; 162 163 // Public EdDSA key of the exchange that was used to generate the signature. 164 // Should match one of the exchange's signing keys from ``signkeys``. It is given 165 // explicitly as the client might otherwise be confused by clock skew as to 166 // which signing key was used for the ``exchange_sig``. 167 exchange_pub: EddsaPublicKey; 168 169 // Denominations for which the exchange currently offers/requests recoup. 170 recoup: RecoupDenoms[]; 171 172 // Array of globally applicable fees by time range. 173 global_fees: GlobalFees[]; 174 175 // The date when the denomination keys were last updated. 176 list_issue_date: Timestamp; 177 178 // Auditors of the exchange. 179 auditors: AuditorKeys[]; 180 181 // The exchange's signing keys. 182 signkeys: SignKey[]; 183 184 // Optional field with a dictionary of (name, object) pairs defining the 185 // supported and enabled extensions, such as ``age_restriction``. 186 extensions?: { name: ExtensionManifest }; 187 188 // Signature by the exchange master key of the SHA-256 hash of the 189 // normalized JSON-object of field extensions, if it was set. 190 // The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS. 191 extensions_sig?: EddsaSignature; 192 193 } 194 195 The specification for the account object is: 196 197 .. ts:def:: ExchangeWireAccount 198 199 interface ExchangeWireAccount { 200 // Full ``payto://`` URI identifying the account and wire method 201 payto_uri: string; 202 203 // URI to convert amounts from or to the currency used by 204 // this wire account of the exchange. Missing if no 205 // conversion is applicable. 206 conversion_url?: string; 207 208 // Open banking gateway base URL where wallets can 209 // initiate wire transfers to withdraw 210 // digital cash from this exchange. 211 // @since protocol **v34**. 212 open_banking_gateway?: string; 213 214 // Wire transfer gateway base URL where wallets and merchants can 215 // request (short) wire transfer subjects to wire funds to this 216 // exchange without having to encode the full public key. 217 // @since protocol **v34**. 218 wire_transfer_gateway?: string; 219 220 // Restrictions that apply to bank accounts that would send 221 // funds to the exchange (crediting this exchange bank account). 222 // Optional, empty array for unrestricted. 223 credit_restrictions: AccountRestriction[]; 224 225 // Restrictions that apply to bank accounts that would receive 226 // funds from the exchange (debiting this exchange bank account). 227 // Optional, empty array for unrestricted. 228 debit_restrictions: AccountRestriction[]; 229 230 // Signature using the exchange's offline key over 231 // a `TALER_MasterWireDetailsPS` 232 // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DETAILS``. 233 master_sig: EddsaSignature; 234 235 // Display label wallets should use to show this 236 // bank account. 237 // @since protocol **v19**. 238 bank_label?: string; 239 240 // *Signed* integer with the display priority for 241 // this bank account. Optional, 0 if missing. 242 // @since protocol **v19**. 243 priority?: Integer; 244 245 } 246 247 .. ts:def:: AccountRestriction 248 249 type AccountRestriction = 250 | RegexAccountRestriction 251 | DenyAllAccountRestriction 252 253 .. ts:def:: DenyAllAccountRestriction 254 255 // Account restriction that disables this type of 256 // account for the indicated operation categorically. 257 interface DenyAllAccountRestriction { 258 259 type: "deny"; 260 } 261 262 .. ts:def:: RegexAccountRestriction 263 264 // Accounts interacting with this type of account 265 // restriction must have a normalized payto://-URI matching 266 // the given regex. 267 interface RegexAccountRestriction { 268 269 type: "regex"; 270 271 // Regular expression that the payto://-URI of the 272 // partner account must follow. The regular expression 273 // should follow posix-egrep, but without support for character 274 // classes, GNU extensions, back-references or intervals. See 275 // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html 276 // for a description of the posix-egrep syntax. Applications 277 // may support regexes with additional features, but exchanges 278 // must not use such regexes. 279 payto_regex: string; 280 281 // Hint for a human to understand the restriction 282 // (that is hopefully easier to comprehend than the regex itself). 283 human_hint: string; 284 285 // Map from IETF BCP 47 language tags to localized 286 // human hints. 287 human_hint_i18n?: { [lang_tag: string]: string }; 288 289 } 290 291 .. ts:def:: ZeroLimitedOperation 292 293 interface ZeroLimitedOperation { 294 295 // Operation that is limited to an amount of 296 // zero until the client has passed some KYC check. 297 // Must be one of "WITHDRAW", "DEPOSIT", 298 // (p2p) "MERGE", (wallet) "BALANCE", 299 // (reserve) "CLOSE", "AGGREGATE", 300 // "TRANSACTION" or "REFUND". 301 operation_type: string; 302 303 } 304 305 306 .. ts:def:: AccountLimit 307 308 interface AccountLimit { 309 310 // Operation that is limited. 311 // Must be one of "WITHDRAW", "DEPOSIT", 312 // (p2p) "MERGE", (wallet) "BALANCE", 313 // (reserve) "CLOSE", "AGGREGATE", 314 // "TRANSACTION" or "REFUND". 315 operation_type: string; 316 317 // Timeframe during which the limit applies. 318 // Not applicable for all operation_types 319 // (but always present in this object anyway). 320 timeframe: RelativeTime; 321 322 // Maximum amount allowed during the given timeframe. 323 // Zero if the operation is simply forbidden. 324 threshold: Amount; 325 326 // True if this is a soft limit that could be raised 327 // by passing KYC checks. Clients *may* deliberately 328 // try to cross limits and trigger measures resulting 329 // in 451 responses to begin KYC processes. 330 // Clients that are aware of hard limits *should* 331 // inform users about the hard limit and prevent flows 332 // in the UI that would cause violations of hard limits. 333 // Made optional in **v21** with a default of 'false' if missing. 334 soft_limit?: boolean; 335 } 336 337 .. ts:def:: GlobalFees 338 339 interface GlobalFees { 340 341 // What date (inclusive) does these fees go into effect? 342 start_date: Timestamp; 343 344 // What date (exclusive) does this fees stop going into effect? 345 end_date: Timestamp; 346 347 // Account history fee, charged when a user wants to 348 // obtain a reserve/account history. 349 history_fee: Amount; 350 351 // Annual fee charged for having an open account at the 352 // exchange. Charged to the account. If the account 353 // balance is insufficient to cover this fee, the account 354 // is automatically deleted/closed. (Note that the exchange 355 // will keep the account history around for longer for 356 // regulatory reasons.) 357 account_fee: Amount; 358 359 // Purse fee, charged only if a purse is abandoned 360 // and was not covered by the account limit. 361 purse_fee: Amount; 362 363 // How long will the exchange preserve the account history? 364 // After an account was deleted/closed, the exchange will 365 // retain the account history for legal reasons until this time. 366 history_expiration: RelativeTime; 367 368 // Non-negative number of concurrent purses that any 369 // account holder is allowed to create without having 370 // to pay the purse_fee. 371 purse_account_limit: Integer; 372 373 // How long does an exchange keep a purse around after a purse 374 // has expired (or been successfully merged)? A 'GET' request 375 // for a purse will succeed until the purse expiration time 376 // plus this value. 377 purse_timeout: RelativeTime; 378 379 // Signature of `TALER_GlobalFeesPS`. 380 master_sig: EddsaSignature; 381 382 } 383 384 .. ts:def:: DenomGroup 385 386 type DenomGroup = 387 | DenomGroupRsa 388 | DenomGroupCs 389 | DenomGroupRsaAgeRestricted 390 | DenomGroupCsAgeRestricted; 391 392 .. ts:def:: DenomGroupRsa 393 394 interface DenomGroupRsa extends DenomGroupCommon { 395 cipher: "RSA"; 396 397 denoms: ({ 398 rsa_pub: RsaPublicKey; 399 } & DenomCommon)[]; 400 } 401 402 .. ts:def:: DenomGroupCs 403 404 interface DenomGroupCs extends DenomGroupCommon { 405 cipher: "CS"; 406 407 denoms: ({ 408 cs_pub: Cs25519Point; 409 } & DenomCommon)[]; 410 } 411 412 .. ts:def:: DenomGroupRsaAgeRestricted 413 414 interface DenomGroupRsaAgeRestricted extends DenomGroupCommon { 415 cipher: "RSA+age_restricted"; 416 age_mask: AgeMask; 417 418 denoms: ({ 419 rsa_pub: RsaPublicKey; 420 } & DenomCommon)[]; 421 } 422 423 .. ts:def:: DenomGroupCsAgeRestricted 424 425 interface DenomGroupCsAgeRestricted extends DenomGroupCommon { 426 cipher: "CS+age_restricted"; 427 age_mask: AgeMask; 428 429 denoms: ({ 430 cs_pub: Cs25519Point; 431 } & DenomCommon)[]; 432 } 433 434 .. ts:def:: DenomGroupCommon 435 436 // Common attributes for all denomination groups 437 interface DenomGroupCommon { 438 // How much are coins of this denomination worth? 439 value: Amount; 440 441 // Fee charged by the exchange for withdrawing a coin of this denomination. 442 fee_withdraw: Amount; 443 444 // Fee charged by the exchange for depositing a coin of this denomination. 445 fee_deposit: Amount; 446 447 // Fee charged by the exchange for refreshing a coin of this denomination. 448 fee_refresh: Amount; 449 450 // Fee charged by the exchange for refunding a coin of this denomination. 451 fee_refund: Amount; 452 453 } 454 455 .. ts:def:: DenomCommon 456 457 interface DenomCommon { 458 // Signature of `TALER_DenominationKeyValidityPS`. 459 master_sig: EddsaSignature; 460 461 // When does the denomination key become valid? 462 stamp_start: Timestamp; 463 464 // When is it no longer possible to withdraw coins 465 // of this denomination? Note that while this option 466 // is given per denomination, all concurrently active 467 // denominations (of the same cipher type) 468 // will have exactly the same withdraw 469 // expiration time. Thus, the wallet can be sure what 470 // is the smallest denomination being offered at any 471 // particular point in time, and not worry about the 472 // exchange having merely failed to sign the key of 473 // only the smallest denomination unit. 474 stamp_expire_withdraw: Timestamp; 475 476 // When is it no longer possible to deposit coins 477 // of this denomination? 478 stamp_expire_deposit: Timestamp; 479 480 // Timestamp indicating by when legal disputes relating to these coins must 481 // be settled, as the exchange will afterwards destroy its evidence relating to 482 // transactions involving this coin. 483 stamp_expire_legal: Timestamp; 484 485 // Set to 'true' if the exchange somehow "lost" 486 // the private key. The denomination was not 487 // necessarily revoked, but still cannot be used 488 // to withdraw coins at this time (theoretically, 489 // the private key could be recovered in the 490 // future; coins signed with the private key 491 // remain valid). 492 lost?: boolean; 493 } 494 495 Fees for any of the operations can be zero, but the fields must still be 496 present. The currency of the ``fee_deposit``, ``fee_refresh`` and ``fee_refund`` must match the 497 currency of the ``value``. Theoretically, the ``fee_withdraw`` could be in a 498 different currency, but this is not currently supported by the 499 implementation. 500 501 .. ts:def:: RecoupDenoms 502 503 interface RecoupDenoms { 504 // Hash of the public key of the denomination that is being revoked under 505 // emergency protocol (see ``/recoup``). 506 h_denom_pub: HashCode; 507 508 // We do not include any signature here, as the primary use-case for 509 // this emergency involves the exchange having lost its signing keys, 510 // so such a signature here would be pretty worthless. However, the 511 // exchange will not honor ``/recoup`` requests unless they are for 512 // denomination keys listed here. 513 } 514 515 A signing key in the ``signkeys`` list is a JSON object with the following fields: 516 517 .. ts:def:: SignKey 518 519 interface SignKey { 520 // The actual exchange's EdDSA signing public key. 521 key: EddsaPublicKey; 522 523 // Initial validity date for the signing key. 524 stamp_start: Timestamp; 525 526 // Date when the exchange will stop using the signing key, allowed to overlap 527 // slightly with the next signing key's validity to allow for clock skew. 528 stamp_expire: Timestamp; 529 530 // Date when all signatures made by the signing key expire and should 531 // henceforth no longer be considered valid in legal disputes. 532 stamp_end: Timestamp; 533 534 // Signature over ``key`` and ``stamp_expire`` by the exchange master key. 535 // Signature of `TALER_ExchangeSigningKeyValidityPS`. 536 // Must have purpose ``TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY``. 537 master_sig: EddsaSignature; 538 } 539 540 An entry in the ``auditors`` list is a JSON object with the following fields: 541 542 .. ts:def:: AuditorKeys 543 544 interface AuditorKeys { 545 // The auditor's EdDSA signing public key. 546 auditor_pub: EddsaPublicKey; 547 548 // The auditor's URL. 549 auditor_url: string; 550 551 // The auditor's name (for humans). 552 auditor_name: string; 553 554 // An array of denomination keys the auditor affirms with its signature. 555 // Note that the message only includes the hash of the public key, while the 556 // signature is actually over the expanded information including expiration 557 // times and fees. The exact format is described below. 558 denomination_keys: AuditorDenominationKey[]; 559 } 560 561 .. ts:def:: AuditorDenominationKey 562 563 interface AuditorDenominationKey { 564 // Hash of the public RSA key used to sign coins of the respective 565 // denomination. Note that the auditor's signature covers more than just 566 // the hash, but this other information is already provided in ``denoms`` and 567 // thus not repeated here. 568 denom_pub_h: HashCode; 569 570 // Signature of `TALER_ExchangeKeyValidityPS`. 571 auditor_sig: EddsaSignature; 572 } 573 574 The same auditor may appear multiple times in the array for different subsets 575 of denomination keys, and the same denomination key hash may be listed 576 multiple times for the same or different auditors. The wallet or merchant 577 just should check that the denomination keys they use are in the set for at 578 least one of the auditors that they accept. 579 580 .. note:: 581 582 Both the individual denominations *and* the denomination list is signed, 583 allowing customers to prove that they received an inconsistent list. 584 585 Aggregate wire transfer fees representing the fees the exchange 586 charges per wire transfer to a merchant must be specified as an 587 array in all wire transfer response objects under ``fees``. The 588 respective array contains objects with the following members: 589 590 .. ts:def:: AggregateTransferFee 591 592 interface AggregateTransferFee { 593 // Per transfer wire transfer fee. 594 wire_fee: Amount; 595 596 // Per transfer closing fee. 597 closing_fee: Amount; 598 599 // What date (inclusive) does this fee go into effect? 600 // The different fees must cover the full time period in which 601 // any of the denomination keys are valid without overlap. 602 start_date: Timestamp; 603 604 // What date (exclusive) does this fee stop going into effect? 605 // The different fees must cover the full time period in which 606 // any of the denomination keys are valid without overlap. 607 end_date: Timestamp; 608 609 // Signature of `TALER_MasterWireFeePS` with 610 // purpose ``TALER_SIGNATURE_MASTER_WIRE_FEES``. 611 sig: EddsaSignature; 612 } 613 614 .. ts:def:: ExchangePartnerListEntry 615 616 interface ExchangePartnerListEntry { 617 // Base URL of the partner exchange. 618 partner_base_url: string; 619 620 // Public master key of the partner exchange. 621 partner_master_pub: EddsaPublicKey; 622 623 // Per exchange-to-exchange transfer (wad) fee. 624 wad_fee: Amount; 625 626 // Exchange-to-exchange wad (wire) transfer frequency. 627 wad_frequency: RelativeTime; 628 629 // When did this partnership begin (under these conditions)? 630 start_date: Timestamp; 631 632 // How long is this partnership expected to last? 633 end_date: Timestamp; 634 635 // Signature using the exchange's offline key over 636 // `TALER_WadPartnerSignaturePS` 637 // with purpose ``TALER_SIGNATURE_MASTER_PARTNER_DETAILS``. 638 master_sig: EddsaSignature; 639 }