feat: add all currencies currently supported on coingecko

This commit is contained in:
benalleng
2023-11-08 16:52:01 -05:00
committed by Paul Miller
parent 602f0fe9d4
commit ff93a0e49f
8 changed files with 335 additions and 222 deletions

View File

@@ -22,9 +22,7 @@ import { useI18n } from "~/i18n/context";
import { Network } from "~/logic/mutinyWalletSetup";
import { useMegaStore } from "~/state/megaStore";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
import { fiatToSats, satsToFiat } from "~/utils";
import { Currency } from "./ChooseCurrency";
import { Currency, fiatToSats, satsToFiat } from "~/utils";
// Checks the users locale to determine if decimals should be a "." or a ","
const decimalDigitDivider = Number(1.0)

View File

@@ -1,119 +1,37 @@
import { createForm } from "@modular-forms/solid";
import { createSignal, Show } from "solid-js";
import { createSignal, For, Show } from "solid-js";
import { useNavigate } from "solid-start";
import {
Button,
ExternalLink,
InfoBox,
NiceP,
SelectField,
VStack
} from "~/components";
import { Button, ExternalLink, InfoBox, NiceP, VStack } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { eify, timeout } from "~/utils";
export interface Currency {
value: string;
label: string;
hasSymbol?: string;
maxFractionalDigits: number;
}
import {
BTC_OPTION,
Currency,
eify,
FIAT_OPTIONS,
timeout,
USD_OPTION
} from "~/utils";
type ChooseCurrencyForm = {
fiatCurrency: string;
};
/**
* FIAT_OPTIONS is an array of possible currencies
* All available currencies can be found here https://api.coingecko.com/api/v3/simple/supported_vs_currencies
* @Currency
* @param {string} label - should be in the format {Name} {ISO code}
* @param {string} values - are uppercase ISO 4217 currency code
* @param {string?} hasSymbol - if the currency has a symbol it should be represented as a string
* @param {number} maxFractionalDigits - the standard fractional units used by the currency should be set with maxFractionalDigits
*
* Bitcoin is represented as:
* {
* label: "bitcoin BTC",
* value: "BTC",
* hasSymbol: "₿",
* maxFractionalDigits: 8
* }
*/
export const FIAT_OPTIONS: Currency[] = [
{
label: "Bitcoin BTC",
value: "BTC",
hasSymbol: "₿",
maxFractionalDigits: 8
},
{
label: "United States Dollar USD",
value: "USD",
hasSymbol: "$",
maxFractionalDigits: 2
},
{ label: "Swiss Franc CHF", value: "CHF", maxFractionalDigits: 2 },
{
label: "Chinese Yuan CNY",
value: "CNY",
hasSymbol: "¥",
maxFractionalDigits: 2
},
{
label: "Euro EUR",
value: "EUR",
hasSymbol: "€",
maxFractionalDigits: 2
},
{
label: "Brazilian Real BRL",
value: "BRL",
hasSymbol: "R$",
maxFractionalDigits: 2
},
{
label: "British Pound GBP",
value: "GBP",
hasSymbol: "₤",
maxFractionalDigits: 2
},
{
label: "Australia Dollar AUD",
value: "AUD",
hasSymbol: "$",
maxFractionalDigits: 2
},
{
label: "Japanese Yen JPY",
value: "JPY",
hasSymbol: "¥",
maxFractionalDigits: 0
},
{
label: "Korean Won KRW",
value: "KRW",
hasSymbol: "₩",
maxFractionalDigits: 0
},
{ label: "Kuwaiti Dinar KWD", value: "KWD", maxFractionalDigits: 3 }
].sort((a, b) => (a.value > b.value ? 1 : b.value > a.value ? -1 : 0));
export const USD_INDEX = FIAT_OPTIONS.findIndex((fo) => fo.value === "USD");
export const BTC_INDEX = FIAT_OPTIONS.findIndex((fo) => fo.value === "BTC");
const COMBINED_OPTIONS: Currency[] = [USD_OPTION, BTC_OPTION, ...FIAT_OPTIONS];
export function ChooseCurrency() {
const i18n = useI18n();
const [error, setError] = createSignal<Error>();
const [state, actions] = useMegaStore();
const [_state, actions] = useMegaStore();
const [loading, setLoading] = createSignal(false);
const navigate = useNavigate();
function findCurrencyByValue(value: string) {
return FIAT_OPTIONS.find((currency) => currency.value === value);
return (
COMBINED_OPTIONS.find((currency) => currency.value === value) ??
USD_OPTION
);
}
const [_chooseCurrencyForm, { Form, Field }] =
@@ -135,7 +53,7 @@ export function ChooseCurrency() {
const handleFormSubmit = async (f: ChooseCurrencyForm) => {
setLoading(true);
try {
actions.saveFiat(findCurrencyByValue(f.fiatCurrency) || state.fiat);
actions.saveFiat(findCurrencyByValue(f.fiatCurrency));
await timeout(1000);
navigate("/");
@@ -157,16 +75,17 @@ export function ChooseCurrency() {
<VStack>
<Field name="fiatCurrency">
{(field, props) => (
<SelectField
<select
{...props}
value={field.value}
error={field.error}
placeholder={state.fiat.label}
options={FIAT_OPTIONS}
label={i18n.t(
"settings.currency.select_currency_label"
)}
/>
class="w-full rounded-lg bg-m-grey-750 py-2 pl-4 pr-12 text-base font-normal text-white"
>
<For each={COMBINED_OPTIONS}>
{({ value, label }) => (
<option value={value}>{label}</option>
)}
</For>
</select>
)}
</Field>
<Show when={error()}>

View File

@@ -1,101 +0,0 @@
import { Select as KSelect } from "@kobalte/core";
import { JSX, Show, splitProps } from "solid-js";
import check from "~/assets/icons/check.svg";
import upDown from "~/assets/icons/up-down.svg";
interface IOption {
value: string;
label: string;
}
type SelectProps = {
options: IOption[];
multiple?: boolean;
size?: string | number;
caption?: string;
name: string;
label?: string | undefined;
placeholder?: string | undefined;
value: string | undefined;
error: string;
required?: boolean | undefined;
disabled?: boolean | undefined;
ref: (element: HTMLSelectElement) => void;
onInput: JSX.EventHandler<HTMLSelectElement, InputEvent>;
onChange: JSX.EventHandler<HTMLSelectElement, Event>;
onBlur: JSX.EventHandler<HTMLSelectElement, FocusEvent>;
};
export function SelectField(props: SelectProps) {
// Split select element props
const [rootProps, selectProps] = splitProps(
props,
["name", "placeholder", "options", "required", "disabled"],
["placeholder", "ref", "onInput", "onChange", "onBlur"]
);
return (
<div class="relative flex items-center">
<KSelect.Root
{...rootProps}
class="flex w-full flex-col gap-2 text-sm font-semibold"
optionValue="value"
optionTextValue="label"
sameWidth
validationState={props.error ? "invalid" : "valid"}
itemComponent={(props) => (
<KSelect.Item
item={props.item}
class="flex w-full justify-between rounded-lg p-1 hover:bg-m-grey-800"
>
<Show when={props.item.rawValue.label}>
<KSelect.ItemLabel>
{props.item.rawValue.label}
</KSelect.ItemLabel>
</Show>
<KSelect.ItemIndicator>
<img
src={check}
alt="check"
height={20}
width={20}
/>
</KSelect.ItemIndicator>
</KSelect.Item>
)}
>
<Show when={props.label}>
<KSelect.Label class="uppercase">
{props.label}
</KSelect.Label>
</Show>
<KSelect.HiddenSelect {...selectProps} />
<KSelect.Trigger
class="flex w-full justify-between rounded-lg bg-m-grey-750 px-4 py-2 text-base font-normal text-white"
aria-label="selectField"
>
<KSelect.Value<IOption>>
{(state) => state.selectedOption().label}
</KSelect.Value>
<KSelect.Icon class="ml-2 self-center">
<img src={upDown} alt="upDown" height={20} width={20} />
</KSelect.Icon>
</KSelect.Trigger>
<Show when={props.caption}>
<KSelect.Description class="text-sm font-normal text-neutral-400">
{props.caption}
</KSelect.Description>
</Show>
<KSelect.Portal>
<KSelect.Content>
<KSelect.Listbox class="w-full cursor-default rounded-lg bg-[#0a0a0a] p-2" />
</KSelect.Content>
</KSelect.Portal>
<KSelect.ErrorMessage class="text-m-red">
{props.error}
</KSelect.ErrorMessage>
</KSelect.Root>
</div>
);
}

View File

@@ -6,7 +6,6 @@ export * from "./Linkify";
export * from "./Misc";
export * from "./ProgressBar";
export * from "./Radio";
export * from "./SelectField";
export * from "./TextField";
export * from "./ExternalLink";
export * from "./LoadingSpinner";

View File

@@ -12,12 +12,6 @@ import {
import { createStore } from "solid-js/store";
import { useNavigate, useSearchParams } from "solid-start";
import {
BTC_INDEX,
Currency,
FIAT_OPTIONS,
USD_INDEX
} from "~/components/ChooseCurrency";
import { checkBrowserCompatibility } from "~/logic/browserCompatibility";
import {
doubleInitDefense,
@@ -27,7 +21,14 @@ import {
setupMutinyWallet
} from "~/logic/mutinyWalletSetup";
import { ParsedParams, toParsedParams } from "~/logic/waila";
import { eify, MutinyTagItem, subscriptionValid } from "~/utils";
import {
BTC_OPTION,
Currency,
eify,
MutinyTagItem,
subscriptionValid,
USD_OPTION
} from "~/utils";
const MegaStoreContext = createContext<MegaStore>();
@@ -97,7 +98,7 @@ export const Provider: ParentComponent = (props) => {
price: 0,
fiat: localStorage.getItem("fiat_currency")
? (JSON.parse(localStorage.getItem("fiat_currency")!) as Currency)
: FIAT_OPTIONS[USD_INDEX],
: USD_OPTION,
has_backed_up: localStorage.getItem("has_backed_up") === "true",
balance: undefined as MutinyBalance | undefined,
last_sync: undefined as number | undefined,
@@ -272,7 +273,7 @@ export const Provider: ParentComponent = (props) => {
balance: newBalance,
last_sync: Date.now(),
price: 1,
fiat: FIAT_OPTIONS[BTC_INDEX]
fiat: BTC_OPTION
});
}
}

View File

@@ -1,6 +1,6 @@
import { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { Currency } from "~/components/ChooseCurrency";
import { Currency } from "./currencies";
/** satsToFiat
* returns a toLocaleString() based on the bitcoin price in the chosen currency

296
src/utils/currencies.ts Normal file
View File

@@ -0,0 +1,296 @@
export interface Currency {
value: string;
label: string;
hasSymbol?: string;
maxFractionalDigits: number;
}
/**
* BTC_USD_OPTIONS is an array of BTC and USD currencies
* These are separated from the rest of the list for ease of access by the user and necessary access in the megaStore
*/
export const BTC_OPTION: Currency = {
label: "Bitcoin BTC",
value: "BTC",
hasSymbol: "₿",
maxFractionalDigits: 8
};
export const USD_OPTION: Currency = {
label: "United States Dollar USD",
value: "USD",
hasSymbol: "$",
maxFractionalDigits: 2
};
/**
* FIAT_OPTIONS is an array of all available currencies on the coingecko api https://api.coingecko.com/api/v3/simple/supported_vs_currencies
* @Currency
* @param {string} label - should be in the format {Name} {ISO code}
* @param {string} values - are uppercase ISO 4217 currency code
* @param {string?} hasSymbol - if the currency has a symbol it should be represented as a string
* @param {number} maxFractionalDigits - the standard fractional units used by the currency should be set with maxFractionalDigits
*
* Bitcoin is represented as:
* {
* label: "bitcoin BTC",
* value: "BTC",
* hasSymbol: "₿",
* maxFractionalDigits: 8
* }
*/
export const FIAT_OPTIONS: Currency[] = [
{
label: "United Arab Emirates Dirham AED",
value: "AED",
maxFractionalDigits: 2
},
{
label: "Argentine Peso ARS",
value: "ARS",
hasSymbol: "$",
maxFractionalDigits: 2
},
{
label: "Australian Dollar AUD",
value: "AUD",
hasSymbol: "$",
maxFractionalDigits: 2
},
{
label: "Bangladeshi Taka BDT",
value: "BDT",
hasSymbol: "৳",
maxFractionalDigits: 2
},
{
label: "Bahraini Dinar BHD",
value: "BHD",
hasSymbol: "BD",
maxFractionalDigits: 3
},
{
label: "Bermuda Dollar BMD",
value: "BMD",
hasSymbol: "$",
maxFractionalDigits: 2
},
{
label: "Brazilian Real BRL",
value: "BRL",
hasSymbol: "R$",
maxFractionalDigits: 2
},
{
label: "Canadian Dollar CAD",
value: "CAD",
hasSymbol: "$",
maxFractionalDigits: 2
},
{ label: "Swiss Franc CHF", value: "CHF", maxFractionalDigits: 2 },
{
label: "Chilean Peso CLP",
value: "CLP",
hasSymbol: "$",
maxFractionalDigits: 0
},
{
label: "Chinese Yuan CNY",
value: "CNY",
hasSymbol: "¥",
maxFractionalDigits: 2
},
{
label: "Czech Koruna CZK",
value: "CZK",
hasSymbol: "Kč",
maxFractionalDigits: 2
},
{
label: "Danish Krone DKK",
value: "DKK",
hasSymbol: "kr",
maxFractionalDigits: 2
},
{
label: "Euro EUR",
value: "EUR",
hasSymbol: "€",
maxFractionalDigits: 2
},
{
label: "British Pound GBP",
value: "GBP",
hasSymbol: "₤",
maxFractionalDigits: 2
},
{
label: "Hong Kong Dollar HKD",
value: "HKD",
hasSymbol: "$",
maxFractionalDigits: 2
},
{
label: "Hungarian Forint HUF",
value: "HUF",
hasSymbol: "Ft",
maxFractionalDigits: 2
},
{
label: "Israeli New Shekel ILS",
value: "ILS",
hasSymbol: "₪",
maxFractionalDigits: 2
},
{
label: "Indian Rupee INR",
value: "INR",
hasSymbol: "₹",
maxFractionalDigits: 2
},
{
label: "Japanese Yen JPY",
value: "JPY",
hasSymbol: "¥",
maxFractionalDigits: 0
},
{
label: "Korean Won KRW",
value: "KRW",
hasSymbol: "₩",
maxFractionalDigits: 0
},
{
label: "Kuwaiti Dinar KWD",
value: "KWD",
maxFractionalDigits: 3
},
{
label: "Sri Lankan Rupee LKR",
value: "LKR",
hasSymbol: "Rs",
maxFractionalDigits: 2
},
{
label: "Myanmar Kyat MMK",
value: "MMK",
hasSymbol: "Ks",
maxFractionalDigits: 2
},
{
label: "Mexican Peso MXN",
value: "MXN",
hasSymbol: "$",
maxFractionalDigits: 2
},
{
label: "Malaysian Ringgit MYR",
value: "MYR",
hasSymbol: "RM",
maxFractionalDigits: 2
},
{
label: "Norwegian Krone NOK",
value: "NOK",
hasSymbol: "kr",
maxFractionalDigits: 2
},
{
label: "Nigerian Naira NGN",
value: "NGN",
hasSymbol: "₦",
maxFractionalDigits: 2
},
{
label: "New Zealand Dollar NZD",
value: "NZD",
hasSymbol: "$",
maxFractionalDigits: 2
},
{
label: "Philippine Peso PHP",
value: "PHP",
hasSymbol: "₱",
maxFractionalDigits: 2
},
{
label: "Pakistani Rupee PKR",
value: "PKR",
hasSymbol: "₨",
maxFractionalDigits: 2
},
{
label: "Polish Złoty PLN",
value: "PLN",
hasSymbol: "zł",
maxFractionalDigits: 2
},
{
label: "Russian Ruble RUB",
value: "RUB",
hasSymbol: "₽",
maxFractionalDigits: 2
},
{
label: "Saudi Riyal SAR",
value: "SAR",
hasSymbol: "SR",
maxFractionalDigits: 2
},
{
label: "Swedish Krona SEK",
value: "SEK",
hasSymbol: "kr",
maxFractionalDigits: 2
},
{
label: "Singapore Dollar SGD",
value: "SGD",
hasSymbol: "$",
maxFractionalDigits: 2
},
{
label: "Thai Baht THB",
value: "THB",
hasSymbol: "฿",
maxFractionalDigits: 2
},
{
label: "Turkish Lira TRY",
value: "TRY",
hasSymbol: "₺",
maxFractionalDigits: 2
},
{
label: "New Taiwan Dollar TWD",
value: "TWD",
hasSymbol: "NT$",
maxFractionalDigits: 2
},
{
label: "Ukrainian Hryvnia UAH",
value: "UAH",
hasSymbol: "₴",
maxFractionalDigits: 2
},
{
label: "Venezuelan Bolívar VEF",
value: "VEF",
hasSymbol: "Bs",
maxFractionalDigits: 2
},
{
label: "Vietnamese Dong VND",
value: "VND",
hasSymbol: "₫",
maxFractionalDigits: 0
},
{
label: "South African Rand ZAR",
value: "ZAR",
hasSymbol: "R",
maxFractionalDigits: 2
}
];

View File

@@ -18,3 +18,4 @@ export * from "./fetchZaps";
export * from "./vibrate";
export * from "./openLinkProgrammatically";
export * from "./nostr";
export * from "./currencies";