blink icon indicating copy to clipboard operation
blink copied to clipboard

Amount-related properties for transactions in our database

Open vindard opened this issue 3 years ago • 4 comments

Description

With the new hedged-USD & display-currency work we're starting to get things confused with the different data fields we store in our database for a transaction.

Key issues (described below):

  1. storing ledger-related values (debit/credit and fee)
  2. storing the transaction currency vs. the conversion currency (for hedging/limits) vs. the display currency
  3. unit for display currency
  4. separating amounts and fees

Sample Transactions

BTC payment to external invoice (freecorn-left | local-dev-right)

image

USD payment to external invoice (freecorn-left | local-dev-right)

image

Issues

1. Value stored in debit/credit & fee props

The values currently stored in debit/credit should be integer values that represent units of that particular wallet currency e.g. sats for BTC wallets and cents for USD-hedged wallets.

The fee property is usually relevant to the debit/credit values of a transaction as it is sometimes used as the main amount for related transactions (bank fees, reimbursements etc.).

Current state:

  • fee is always denominated in sats
  • feeUsd is always demonimated in cents (new code) or usd (prod code)

Question: should fee always be sats, or should it be denominated in the same currency that debit/credit are denominated in?

2. Transaction currency vs. BTC equivalent vs. display currency

With our new model we now have 3 different types of currencies that will be present for all transactions:

  • BTC: relevant in all except intraledger USD-to-USD txns
  • USD: hedged value relevant for USD wallet, un-hedged equivalent relevant for limits & display conversions
  • Display: relevant for displaying in UIs, is currently USD but can be derived from USD as well when not USD e.g. CRC

Questions:

  • should we always store amounts that map to all three types separately in each transaction?
  • should we overload certain properties (debit/credit, usd), or always distinctly store all 3?

3. Unit for display currencies

The values for the usd property are currently denominated in dollars and used by interfaces like the mobile app to display fiat equivalents. These values can be floats currently.

In our new code, we've been adding the cents-equivalent usd value to this field instead which is correct for the converted fiat amount but wrong for what our UIs expect for the display currency amount. These values are also now stored only as integers from our domain.

Question: how should we handle this separation?

4. Recording amounts vs. amounts + fees

In some places we store the pre-fee amount (e.g. feeUsd in new code) and in other places we store amount + fees (e.g. in feeUsd older code, sats in very old transactions).

Also separately:

debit/credit = amount + fee (for payments)
debit/credit = amount - fee (for receipts)

Question: what should we standarize on for this?

vindard avatar Apr 25 '22 18:04 vindard

Some notes @dolcalmi and I took from a call today thinking through some of this.

For payment & fee_reimbursement transaction types:

{
    feeUsd (prod)
    displayCurrencyFee (in dollars)

    feeUsd (dev)
    usdFee (in cents)

    usd (prod)
    displayCurrencyAmount (in dollars)

    usd (dev)
    usdAmount (in cents)

    fee (prod + dev)
    satsFee

    sats (prod-old)
    satsAmount + satsFee

    satsAmount (prod-new: does not exist)
    satsAmount

    debit (prod + dev)
    satsFee + satsAmount

    credit (prod + dev)
    satsFee + satsAmount
}



{
    walletCurrency: {
        debit
        credit
        fee
        currency
    }
    btcCurrency: {
        amount
        fee
    }
    displayCurrency (CRC) {
        name
        amount
        fee
    }
}

[CRC]
paymentFlow = {
    btcAmount
    usdAmount
    displayCurrency
}

debit = amount + fee
credit = amount - fee

Limits???

vindard avatar Apr 25 '22 18:04 vindard

I think it makes sense to be redundant in our data and be as clear as possible. This would allow for flexibility in how we display the tx to the end user as well as greatly reduce the cognitive load of overloading the terminology. The downside would be storage space, but I dont think this will be a problem with mongodb. We could have the below tx schema:

- debit | credit: BigInt
- accountingCurrency: "USD" | "BTC"
- satsAmount: BigInt
- centsAmount: BigInt
- satsFee: BigInt
- centsFee: BigInt
- displayAmount: BigInt
- displayFee: BigInt
- displayCurrency: any

UncleSamtoshi avatar Apr 25 '22 19:04 UncleSamtoshi

I think it makes sense to be redundant in our data and be as clear as possible.

Agree, proposing an alternative structure just to have multiple options

{
    amounts: {
        btc: {
            amountInBase: BigInt
            baseUnit: String
            currencyCode: String
        }
        fiat: {
            amountInBase: BigInt
            baseUnit: String
            currencyCode: String
        }
        display: {
            amountInBase: BigInt
            baseUnit: String
            currencyCode: String
        }
    }
}

vindard avatar Apr 26 '22 14:04 vindard

- debit | credit: number # forced by medici
- accountingCurrency: "USD" | "BTC"
- satsAmount: BigInt
- centsAmount: BigInt
- satsFee: BigInt
- centsFee: BigInt
- displayAmount: BigInt
- displayFee: BigInt
- displayCurrency: any

bodymindarts avatar Apr 26 '22 19:04 bodymindarts