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