041-wallet-balance-amount-definitions.rst (12191B)
1 DD 41: Wallet Balance and Amount Definitions 2 ############################################ 3 4 :Design status: Draft 5 :Implementation status: Partial 6 :DD shepherd: TBD 7 :Historical contributors: Sebastian, Christian Grothoff, Florian Dold, Marc Stibane 8 :First published: 2023-03-30 9 :Last substantive change: 2024-09-12 10 :Normative references: ``wallet/wallet-core.md`` 11 12 Summary 13 ======= 14 15 This design document discusses terminology and concepts used in the wallet 16 for balances and amounts. 17 18 Motivation 19 ========== 20 21 There are many different types of balances and amounts, and they need 22 to have a clear definition. 23 24 Furthermore, the user in some situations needs to know/decide whether 25 an amount that the user chooses includes fees or not. 26 27 28 Proposed Solution 29 ================= 30 31 Amounts 32 ------- 33 34 * ``effective``: An effective amount always represents the direct effect on the 35 wallet's balance of the same currency. 36 * ``raw``: The raw amount always refers to the amount with fees applied. 37 The exact interpretation of that depends on the transaction type. 38 * ``instructed``: An instructed amount always refers to the amount that 39 a user has explicitly specified as an input. It is not directly a property 40 of transactions, but might be added as metadata to transactions for 41 informational purposes. How the instructed amount is interpreted 42 differs based on the "instructed amount mode" that is specified 43 together with the amount. 44 * ``counterparty-effective``: An amount that **estimates** the effect 45 of the transaction of the balance (either wallet or bank account) of the other 46 party. This is usually a conservative estimate, i.e. when sending money, 47 this is the lower bound for the funds that the other party will obtain 48 *after* fees. 49 50 Instructed Amount Modes 51 ----------------------- 52 53 * ``raw-mode``: The instructed amount represents the raw amount. This is the default. 54 * ``effective-mode``: The instructed amount represents the effective amount, i.e. 55 the direct change to the balance. 56 * ``counterparty-effective-mode``: The instructed amount represents the effective 57 amount seen from the counterparty. In other words, it is the direct 58 difference to the counterparty's balance. 59 60 Balances 61 -------- 62 63 The following types of balances are defined: 64 65 - ``available``: Balance that the wallet believes will certainly be available 66 for spending, modulo any failures of the exchange or double spending issues. 67 This includes available coins *not* allocated to any 68 spending/refresh/... operation. Pending withdrawals are *not* counted 69 towards this balance, because they are not certain to succeed. 70 Pending refreshes *are* counted towards this balance. 71 This balance type is nice to show to the user, because it does not 72 temporarily decrease after payment when we are waiting for refreshes 73 74 - ``material``: Balance that the wallet believes it could spend *right now*, 75 without waiting for any operations to complete. 76 This balance type is important when showing "insufficient balance" error messages. 77 78 - ``age-acceptable``: Subset of the material balance that can be spent 79 with age restrictions applied. 80 81 - ``counterparty-acceptable``: Subset of the material balance that can be spent with a particular 82 merchant or peer-to-peer transfer. 83 84 - ``counterparty-depositable``: Subset of the receiver-acceptable balance that the counterpary 85 can accept via their supported wire methods. 86 87 - ``exchange-depositable``: Subset of the receiver-acceptable balance that the counterpary 88 can accept via their supported wire methods. 89 90 While not quite a balance, we also define the following balance-related term: 91 92 - ``max-merchant-effective-deposit-amount``: Estimated maximum amount that the 93 wallet could pay for, under the assumption that the merchant pays absolutely 94 no fees. 95 96 97 98 99 Raw Amount Definitions 100 ---------------------- 101 Raw amount is… 102 103 Manual Withdrawal 104 … the money that is wired from the user's bank account to the 105 exchange's bank account for the withdrawal. 106 107 Deposit 108 … the amount leaving the exchange account without the wire fees. 109 110 Peer Pull Credit 111 … the amount that is withdrawn from the purse (via merge reserve) that 112 the counterparty fills. 113 114 Peer Push Debit 115 … what the counterparty expects in the purse. 116 117 Peer Push Credit 118 … the purse_value in the exchange to be withdrawn. 119 120 Merchant Payment 121 … the amount the merchant should get if is not doing aggregated transaction. 122 Wire fees are ignored. 123 124 Peer Pull Debit 125 … the net value of the invoice without fees. 126 127 Refund 128 … the amount that the merchant refunded. 129 130 131 132 Details per Transaction Type 133 ---------------------------- 134 135 .. warning:: 136 137 This section is possibly incomplete / out of date. 138 139 Manual Withdrawal 140 ~~~~~~~~~~~~~~~~~ 141 142 .. code:: none 143 144 if instructed_amount mode = raw 145 raw_amount = instructed_amount 146 147 effective_amount = instructed_amount - coins.withdrawal_fee 148 149 if instructed_amount mode = effective 150 raw_amount = instructed_amount + coins.withdrawal_fee 151 152 effective_amount = instructed_amount 153 154 Deposit 155 ~~~~~~~ 156 157 .. code:: none 158 159 if instructed_amount mode = raw 160 raw_amount = instructed_amount 161 162 effective_amount = instructed_amount + coins.deposit_fee + coins.refresh_fee + wire.transfer_fee 163 164 if instructed_amount mode = effective 165 raw_amount = instructed_amount - coins.deposit_fee - coins.refresh_fee - wire.transfer_fee 166 167 effective_amount = instructed_amount 168 169 Peer Pull Credit 170 ~~~~~~~~~~~~~~~~ 171 172 .. code:: none 173 174 if instructed_amount mode = raw 175 raw_amount = instructed_amount 176 177 effective_amount = instructed_amount - coins.withdrawal_fee - purse_fee 178 179 if instructed_amount mode = effective 180 raw_amount = instructed_amount + coins.withdrawal_fee + purse_fee 181 182 effective_amount = instructed_amount 183 184 if instructed_amount mode = counterparty 185 raw_amount = instructed_amount - coins.counterparty_deposit_fee 186 187 effective_amount = instructed_amount - coins.counterparty_deposit_fee - coins.withdrawal_fee - purse_fee 188 189 counterparty_raw_amount = raw_amount 190 191 counterparty_effective_amount = raw_amount + coins.counterparty_deposit_fee 192 193 .. note:: 194 195 counterparty_effective_amount is an estimation since refresh fee is not included. 196 Refresh fee can't be calculated because depends on the coins available in the wallet 197 of the counterparty 198 199 .. note:: 200 coins.counterparty_deposit_fee is the minimum deposit_fee that can be calculated for the 201 given exchange. Counter-party may pay more if it have different preferences doing the coin 202 selection. 203 204 205 Peer Push Debit 206 ~~~~~~~~~~~~~~~ 207 208 .. code:: none 209 210 coins = select-coin-for-operation(debit, mode, instructed_amount) 211 212 if instructed_amount mode = raw 213 raw_amount = instructed_amount 214 215 effective_amount = instructed_amount + coins.deposit_fee + purse_fee 216 217 if instructed_amount mode = effective 218 raw_amount = instructed_amount - coins.deposit_fee - purse_fee 219 220 effective_amount = instructed_amount 221 222 if instructed_amount mode = counterparty 223 raw_amount = instructed_amount + coins.counterparty_withdraw_fee 224 225 effective_amount = instructed_amount - coins.counterparty_withdraw_fee - coins.withdrawal_fee - purse_fee 226 227 counterparty_raw_amount = raw_amount 228 229 counterparty_effective_amount = raw_amount - coins.counterparty_withdraw_fee 230 231 .. note:: 232 ``coins.counterparty_withdraw_fee`` is the minimum withdraw_fee that can be calculated for the 233 given exchange. Counter-party may pay more if it have different preferences doing the coin 234 selection. 235 236 237 .. note :: 238 how much wire_fee the merchant is willing to pay 239 240 merchant_wire_fee = min(wire.transfer_fee / contractTerms.amortization_factor, contractTerms.max_wire_fee) 241 242 merchant_deposit_fee = min(contractTerms.max_fee, contract_wire_fee) 243 244 245 Merchant Payment 246 ~~~~~~~~~~~~~~~~ 247 248 .. code:: none 249 250 251 instructed_amount = contractTerms.amount 252 253 coins = select-coin-for-operation(debit, mode, raw_amount) 254 255 raw_amount = instructed_amount - merchant_deposit_fee 256 257 effective_amount = instructed_amount + coins.deposit_fee + coins.refresh_fee + (wire.transfer_fee - merchant_wire_fee) 258 259 .. note:: 260 The current coin-selection algorithm the order_price is neither raw_amount nor effective_amount. 261 We can calculate the raw_amount of the payment as (contractTerms.amount - max_merchant_fee) and then this 262 operation becomes equivalent than a deposit (in terms of fee calculation). 263 264 Peer Push Credit 265 ~~~~~~~~~~~~~~~~ 266 267 268 ``instructed_amount`` = p2pContract.amount 269 270 ``coins`` = select-coin-for-operation(credit, mode, raw_amount) 271 272 ``raw_amount`` = instructed_amount 273 274 ``effective_amount`` = instructed_amount - coins.withdrawal_fee 275 276 .. note:: 277 In the case that the withdrawal_fee of the coin selection for the push-credit amount 278 is higher than the wire_fee of the exchange, can the wallet ask the exchange to make 279 a wire transfer of the purse instead of proceeding? 280 281 Peer Pull Debit 282 ~~~~~~~~~~~~~~~ 283 284 285 ``instructed_amount`` = p2pContract.amount 286 287 ``coins`` = select-coin-for-operation(debit, mode, raw_amount) 288 289 ``raw_amount`` = instructed_amount 290 291 ``effective_amount`` = instructed_amount + coins.deposit_fee + coins.refresh_fee + wire.transfer_fee 292 293 Refund 294 ~~~~~~ 295 296 297 ``instructed_amount`` = refund.amount 298 299 ``raw_amount`` = instructed_amount 300 301 ``effective_amount`` = instructed_amount - refund_fee - refresh_fee 302 303 .. note:: 304 There may be the case that the merchant should refund all the value of the purchase 305 and that may include paying for the refund_fee. 306 307 Is there a way that the merchant can initiate a refund of purchase + refund_fee so 308 the wallet will get the same effective_amount? 309 310 311 312 Illustrative Example 313 -------------------- 314 315 .. warning:: 316 317 This section is possibly incomplete / out of date. 318 319 To explain the differences between raw, effective and instructed amounts, consider the following scenario: Alice wants to send money 320 to Bob via a P2P push payment. 321 322 Example 1: 323 324 * Alice starts a withdrawal of ``KUDOS:10`` from her bank's web interface into her Taler 325 wallet. The instructed amount is ``KUDOS:10`` and (by default for bank-integrated withdrawals), 326 the mode is ``raw-mode``. After fees, ``KUDOS:9.8`` arrive in her Taler wallet. 327 328 Example 3: 329 330 * Alice wants to pay for a ``KUDOS:10`` monthly magazine subscription. Her Taler wallet is empty though. 331 * She starts withdrawal through her Android wallet app, where she selects ``KUDOS:10`` as the instructed 332 amount with ``mode=effective-mode``. This translates to ``amountEffective=KUDOS:10`` and ``amountRaw=KUDOS:10.10``. 333 * Alice is redirected to her banking app where she transfers ``KUDOS:10.10`` to the exchange. 334 * Her Taler wallet balance will be ``KUDOS:10.10`` after the withdrawal completes. 335 336 Note that on the amount she chooses and the fees / denom structure of the exchange, the ``amountEffective`` might be *higher* 337 than the instructed amount. 338 339 FIXME(dold): That flow does not work if withdrawal starts in the bank. Maybe there needs to be a mechanism 340 where the wallet tells the bank the adjusted amount that needs to be transferred? That would be a new 341 feature in the bank integration API. 342 343 Example 4: 344 345 * Alice has ``KUDOS:10`` in her wallet. 346 * Alice wants to initiate a peer-push payment with ``amountInstructed=KUDOS:8`` 347 and ``mode=effective-mode``. That means that after the payment, she expects 348 exactly ``KUDOS:2`` to remain in her wallet. 349 * Due to the fee configuration, her wallet computes ``amountRaw=KUDOS:7.5`` and ``amountEffective=KUDOS:7.8``. 350 The effective amount in this case does **not** equal the instructed amount, despite the ``mode=effective-mode``. 351 That's because there no amount that can be spend so that the spend amount with resulting refresh 352 fees equal ``KUDOS:8``. 353 * Alice confirms the peer-push payment initiation, and exactly ``KUDOS:7.5`` are credited 354 to the purse that her wallet creates. 355 * Bob merges the purse into his reserve. Bob's wallet automatically withdraws 356 from the reserve, and his wallet balance increases by ``KUDOS:7.1``, since 357 withdrawal fees are deducted. 358 359 360 Discussion / Q&A 361 ================ 362 363 (This should be filled in with results from discussions on mailing lists / personal communication.)