group-income
group-income copied to clipboard
Multiple problems related to changing the group's currency
Problem
In a group with 3 users and a mincome of $1000 USD/month, I performed the following steps:
One: I changed the currency to BTC:
This resulted in an immediate change from $1000 USD/month to 1000 BTC/month:
This is already a bug for 2 reasons:
- If we are changing just the currency, then we should do a currency conversion using the exchange rate to convert the current amount ($1000 USD) to the BTC equivalent.
- If I had attempted to change the mincome (instead of the currency) it would had asked me to create a proposal. So therefore a change in currency type should also ask me to create a proposal following the same rules that decide whether or not a proposal is created.
Two: I then tried changing the mincome amount from 1000 BTC to 0.01728549 BTC ($1000 USD equivalent at $57852/BTC exchange rate)
This resulted in the following proposal:
Three: I changed the currency back to USD
Now things in the group have gotten really crazy:
- We have a $1000/month current mincome
- An open proposal to change the mincome from 1000BTC/month to 0.01728549BTC/month
It's completely nonsensical at this point.
Solution
- If a proposal would be required to change the mincome (e.g. when there are 3 users or more, if I recall the logic correctly), then a proposal should be required to change the group's currency as well.
- Changing the currency type should also include as part of the information in the proposal the new value in the new currency based on an exchange rate. Create a new domain called
gi.currency
and a new selectorgi.currency/exchangeRate
for this purpose. Identify at least 2 different free public websites / APIs that you can query to get the currency exchange rate info. Query both of them at the same time and use the value of the one that returns fastest (but discard it if the value is nonsensical or an error and use the other one in that case). - If the proposal passes, all existing income details need to be updated and converted to using the exchange rate from (2) so that the distribution takes place using the new default currency for the group.
Also, as a stop-gap measure, not to close this issue but to temporarily address it, we can simply disable changing the currency type.
This can be done in one of three ways:
- Remove the option to change the currency from the UI
- Leave it there but disable the popup and write some text next to the popup that says
Feature coming soon
- Allow changing it but display an alert to the user when they try to change it that says
Feature coming soon
My preference would be for one of the latter two options. It's probably OK to even link to this issue, e.g. "Feature coming soon"
Note on exchange rate APIs
If you cannot find a free public API that doesn't require signup to use, then feel free to scrape public websites instead.
Here is Claude's response to:
What are some good free public APIs for getting exchange rates that don't require sign up? Please be as comprehensive as you can.
Please include with your examples APIs for doing fiat to fiat, fiat to crypto, and crypto to crypto, and annotate your results with which type of exchange(s) each API supports.
Response:
Here's a comprehensive list of free public APIs for getting exchange rates that don't require sign up, categorized by the types of exchanges they support:
Fiat to Fiat:
a) Exchange Rates API
URL: https://exchangeratesapi.io/
Supports: Fiat to Fiat
Note: Free tier has some limitations
b) Open Exchange Rates
URL: https://openexchangerates.org/api/
Supports: Fiat to Fiat
Note: Free tier available, but API key required
c) Frankfurter
URL: https://www.frankfurter.app/docs/
Supports: Fiat to Fiat
Fiat to Crypto:
a) CoinGecko
URL: https://www.coingecko.com/en/api/documentation
Supports: Fiat to Crypto, Crypto to Crypto
b) CryptoCompare
URL: https://min-api.cryptocompare.com/
Supports: Fiat to Crypto, Crypto to Crypto
c) Nomics
URL: https://nomics.com/docs/
Supports: Fiat to Crypto, Crypto to Crypto
Note: Free tier available, but API key required
Crypto to Crypto:
a) CoinCap
URL: https://docs.coincap.io/
Supports: Crypto to Crypto, some Fiat to Crypto
b) CryptoWatch
URL: https://cryptowat.ch/docs/api
Supports: Crypto to Crypto
Note: Free tier has rate limits
Multiple Types (Fiat to Fiat, Fiat to Crypto, Crypto to Crypto):
a) Alpha Vantage
URL: https://www.alphavantage.co/documentation/
Supports: Fiat to Fiat, Fiat to Crypto, Crypto to Crypto
Note: Free tier available, but API key required
b) Fixer.io
URL: https://fixer.io/documentation
Supports: Fiat to Fiat, some Crypto
Note: Free tier available, but API key required
c) ExchangeRate-API
URL: https://www.exchangerate-api.com/docs/free
Supports: Fiat to Fiat, some Crypto
Note: Free tier available, but API key required
d) CurrencyLayer
URL: https://currencylayer.com/documentation
Supports: Fiat to Fiat, some Crypto
Note: Free tier available, but API key required
group.js
contract details regarding exchange rates
Please note the existing comments in group.js
related to the payment period's exchange rate:
initialCurrency: getters.groupMincomeCurrency,
// TODO: should we also save the first period's currency exchange rate..?
// all payments during the period use this to set their exchangeRate
// see notes and code in groupIncomeAdjustedDistribution for details.
// TODO: for the currency change proposal, have it update the mincomeExchangeRate
// using .mincomeExchangeRate *= proposal.exchangeRate
mincomeExchangeRate: 1, // modified by proposals to change mincome currency
Note also that in the future we should be able to support sending payments from 1 currency type to a different type.
For example, the group's currency can be USD, but the payment that someone sends could be in BTC (to someone who supports receiving BTC). The exchange rate info at the time of payment should be stored along with that payment, and the payment data already has partial support for this when creating a payment:
(From RecordPayment.vue
)
currencyFromTo: ['USD', groupCurrency], // TODO: this!
exchangeRate: 1,
(From group.js
)
'gi.contracts/group/payment': {
validate: actionRequireActiveMember(objectMaybeOf({
// TODO: how to handle donations to okTurtles?
// TODO: how to handle payments to groups or users outside of this group?
toMemberID: string,
amount: number,
currencyFromTo: tupleOf(string, string), // must be one of the keys in currencies.js (e.g. USD, EUR, etc.) TODO: handle old clients not having one of these keys, see OP_PROTOCOL_UPGRADE https://github.com/okTurtles/group-income/issues/603
// multiply 'amount' by 'exchangeRate', which must always be
// based on the initialCurrency of the period in which this payment was created.
// it is then further multiplied by the period's 'mincomeExchangeRate', which
// is modified if any proposals pass to change the mincomeCurrency
exchangeRate: number,
Remember that for the distribution algorithm all the numbers that are compared need to be in the same currency (the group's currency currency type).
Note: this issue is an expanded version of #784.