Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

Commit

Permalink
feat: FIAT currencies (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
dzbo authored Oct 20, 2023
1 parent b8035a7 commit d373c60
Show file tree
Hide file tree
Showing 18 changed files with 272 additions and 28 deletions.
25 changes: 16 additions & 9 deletions app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ const checkConnectionExpiry = () => {
setInterval(expiryCheck, CONNECTION_EXPIRY_CHECK_INTERVAL_MS)
}
const setupCurrencies = async () => {
const { currencyList } = storeToRefs(useCurrencyStore())
const { fetchCurrencies } = useCurrency()
currencyList.value = await fetchCurrencies()
}
onMounted(async () => {
setupTranslations()
setupWeb3Instances()
Expand All @@ -122,21 +129,21 @@ onMounted(async () => {
try {
const profileAddress = useRouter().currentRoute.value.params?.profileAddress
if (!profileAddress) {
return
}
if (isAddress(profileAddress)) {
await setupViewedProfile(profileAddress)
await setupViewedAssets(profileAddress)
} else {
navigateTo(notFoundRoute())
if (profileAddress) {
if (isAddress(profileAddress)) {
await setupViewedProfile(profileAddress)
await setupViewedAssets(profileAddress)
} else {
navigateTo(notFoundRoute())
}
}
} catch (error) {
console.error(error)
}
setStatus('isProfileLoaded', true)
await setupCurrencies()
})
onUnmounted(() => {
Expand Down
13 changes: 9 additions & 4 deletions components/TokenListCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ onMounted(async () => {

<template>
<lukso-card size="small" is-hoverable is-full-width @click="handleShowAsset"
><div slot="content" class="p-4">
><div slot="content" class="p-4 h-full grid grid-rows-[max-content,auto]">
<div class="h-7 flex justify-end items-start">
<lukso-tag
v-if="asset.standard"
Expand All @@ -80,7 +80,7 @@ onMounted(async () => {
#{{ asset.address?.slice(2, 8) }}
</div>
</div>
<div class="flex flex-col w-full">
<div class="grid w-full grid-rows-[max-content,max-content,auto]">
<div class="heading-inter-14-bold pb-1">{{ asset.name }}</div>
<div class="heading-inter-21-semi-bold flex items-center pb-1">
<span
Expand All @@ -103,8 +103,13 @@ onMounted(async () => {
>{{ asset.symbol }}</span
>
</div>
<div class="paragraph-inter-12-regular hidden">$ 123.24</div>
<div class="flex justify-end w-full">
<div
v-if="asset.amount && asset.symbol"
class="paragraph-inter-12-regular"
>
{{ $formatCurrency(asset.amount, asset.symbol) }}
</div>
<div class="flex justify-end w-full items-end">
<lukso-button
v-if="
status.isConnected &&
Expand Down
12 changes: 10 additions & 2 deletions components/TokenListLyxCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,17 @@ onMounted(async () => {
>{{ appStore.currentNetwork.token.symbol }}</span
>
</div>
<div class="paragraph-inter-12-regular pb-4 hidden">$ 123.24</div>
<div class="paragraph-inter-12-regular pb-4">
{{
$formatCurrency(
viewedProfile.balance,
CURRENCY_API_LYX_TOKEN_NAME
)
}}
</div>
</div>
</div>
<div class="flex justify-end w-full pt-4">
<div class="flex justify-end w-full">
<lukso-button
v-if="
status.isConnected &&
Expand All @@ -95,6 +102,7 @@ onMounted(async () => {
size="small"
variant="secondary"
@click="handleSendAsset"
class="transition-opacity hover:opacity-70"
>{{ $formatMessage('button_send') }}</lukso-button
>
</div>
Expand Down
38 changes: 38 additions & 0 deletions composables/useCurrency.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { CurrencyCache, CurrencyList } from '@/types/currency'

const fetchCurrencies = async () => {
const cache = await caches.open(CACHE_KEY.CURRENCY_CACHE)
const compareTokens = [CURRENCY_API_LYX_TOKEN_NAME] // we can add more tokens here if needed
const url = `https://min-api.cryptocompare.com/data/pricemulti?fsyms=${compareTokens.join(
','
)}&tsyms=${CURRENCY_API_SYMBOLS.join(`,`)}`
const cacheData = await cache.match(url)

if (cacheData) {
const cacheDataJson: CurrencyCache = await cacheData.json()

if (cacheDataJson.expires > Date.now()) {
return cacheDataJson.currencies
} else {
caches.delete(url)
}
}

const currencies = await fetcher<CurrencyList, Record<string, never>>({
url,
method: 'GET',
})
const cacheObject = {
currencies,
expires: Date.now() + 1000 * 60 * CURRENCY_CACHE_EXPIRY_IN_MINUTES,
}
await cache.put(url, new Response(JSON.stringify(cacheObject)))

return currencies
}

export const useCurrency = () => {
return {
fetchCurrencies,
}
}
32 changes: 32 additions & 0 deletions composables/useIntl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
IntlConfig,
IntlShape,
} from '@formatjs/intl'
import { fromWei } from 'web3-utils'

import defaultMessages from '@/translations/en_US.json'

Expand Down Expand Up @@ -74,16 +75,47 @@ const formatDate = (date?: string | number | Date) => {
return intl.value?.formatDate(date)
}

/**
* Time formatting based on the locale
*
* @param date - date to format
* @returns - formatted time
*/
const formatTime = (date?: string | number | Date) => {
return intl.value?.formatTime(date)
}

/**
* Currency formatting based on the locale
*
* @param value - number to format
* @param symbol - currency symbol
* @returns - formatted string
*/
const formatCurrency = (value: string, symbol: string) => {
const { getCurrencyMultiplier, currentCurrencySymbol } = useCurrencyStore()
const currencyMultiplier = getCurrencyMultiplier()(symbol)

if (!value || !currencyMultiplier) {
return ''
}

const currencyValue = parseFloat(fromWei(value)) * currencyMultiplier

return formatNumber(currencyValue, {
maximumFractionDigits: 2,
style: 'currency',
currency: currentCurrencySymbol,
})
}

export const useIntl = () => {
return {
setupIntl,
formatMessage,
formatNumber,
formatDate,
formatTime,
formatCurrency,
}
}
13 changes: 6 additions & 7 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ export default defineNuxtConfig({
},
modules: [
'@nuxtjs/tailwindcss',
[
'@pinia/nuxt',
{
autoImports: ['defineStore', 'acceptHMRUpdate'],
},
],
'@pinia/nuxt',
'@pinia-plugin-persistedstate/nuxt',
'@nuxtjs/device',
'@nuxtjs/plausible',
'@nuxtjs/algolia',
Expand Down Expand Up @@ -106,7 +102,7 @@ export default defineNuxtConfig({
presets: [
{
from: 'pinia',
imports: ['storeToRefs'],
imports: ['storeToRefs', 'defineStore', 'acceptHMRUpdate'],
},
],
},
Expand All @@ -115,4 +111,7 @@ export default defineNuxtConfig({
},
ssr: false,
spaLoadingTemplate: 'public/loading-template.html',
piniaPersistedstate: {
storage: 'localStorage',
},
})
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@nuxtjs/device": "^3.1.0",
"@nuxtjs/plausible": "^0.2.1",
"@nuxtjs/tailwindcss": "^6.8.0",
"@pinia-plugin-persistedstate/nuxt": "^1.1.2",
"@pinia/nuxt": "^0.4.11",
"@playwright/test": "1.36.2",
"@typechain/web3-v1": "^6.0.7",
Expand Down Expand Up @@ -66,6 +67,7 @@
"lint-staged": "13.2.3",
"npm-run-all": "4.1.5",
"nuxt": "^3.6.5",
"pinia": "^2.1.7",
"postcss-html": "^1.5.0",
"prettier": "3.0.1",
"rollup-plugin-polyfill-node": "^0.12.0",
Expand Down
2 changes: 2 additions & 0 deletions plugins/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ declare module '#app' {
$formatNumber(value: string | number, options?: FormatNumberOptions): string
$formatDate(date?: string | number | Date): string
$formatTime(date?: string | number | Date): string
$formatCurrency(value: string, symbol: string): string
}
}

Expand All @@ -15,6 +16,7 @@ declare module '@vue/runtime-core' {
$formatNumber(value: string | number, options?: FormatNumberOptions): string
$formatDate(date?: string | number | Date): string
$formatTime(date?: string | number | Date): string
$formatCurrency(value: string, symbol: string): string
}
}

Expand Down
10 changes: 9 additions & 1 deletion plugins/intl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import { FormatNumberOptions } from '@formatjs/intl'
* e.g. $formatMessage('example_key')
*/
export default defineNuxtPlugin(() => {
const { formatMessage, formatNumber, formatDate, formatTime } = useIntl()
const {
formatMessage,
formatNumber,
formatDate,
formatTime,
formatCurrency,
} = useIntl()

return {
provide: {
Expand All @@ -16,6 +22,8 @@ export default defineNuxtPlugin(() => {
formatNumber(value, options),
formatDate: (date?: string | number | Date) => formatDate(date),
formatTime: (date?: string | number | Date) => formatTime(date),
formatCurrency: (value: string, symbol: string) =>
formatCurrency(value, symbol),
},
}
})
14 changes: 13 additions & 1 deletion shared/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const ASSET_ICON_PLACEHOLDER_URL = '/images/token-default.svg'
export const ASSET_LYX_ICON_URL = '/images/lyx-token.svg'

// number of decimal places for LYX token
export const ASSET_LYX_DECIMALS = '18'
export const ASSET_LYX_DECIMALS = 18

// url of the ipfs gateway
export const IPFS_URL = 'https://2eff.lukso.dev/ipfs/'
Expand Down Expand Up @@ -76,3 +76,15 @@ export const SEARCH_RESULTS_LIMIT = 100

// base universalprofile address
export const BASE_UP_CLOUD_URL = 'https://universalprofile.cloud/'

// default currency symbol
export const DEFAULT_CURRENCY_SYMBOL = 'USD'

// list of currencies to fetch from the api
export const CURRENCY_API_SYMBOLS = ['USD', 'EUR', 'GBP', 'PLN']

// atm cryptocompare only supports LYXE token, swap to LYX when got avail
export const CURRENCY_API_LYX_TOKEN_NAME = 'LYXE'

// currency cache expiry time in minutes
export const CURRENCY_CACHE_EXPIRY_IN_MINUTES = 60
5 changes: 5 additions & 0 deletions shared/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export enum STORAGE_KEY {
CONNECTED_ADDRESS = 'LUKSO_WALLET:connectedAddress',
CONNECTION_EXPIRY = 'LUKSO_WALLET:connectionExpiry',
RECONNECT_ADDRESS = 'LUKSO_WALLET:reconnectAddress',
CURRENCY_STORE = 'LUKSO_WALLET:currencyStore',
}

export enum CACHE_KEY {
CURRENCY_CACHE = 'LUKSO_WALLET:currencyCache',
}

// We use ?referrer=XXX in the URL queries to enable/disable specific features
Expand Down
4 changes: 2 additions & 2 deletions stores/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Modal } from '@/types/modal'
import { NetworkInfo, NetworkId } from '@/types/network'

/**
* Connection store
* Keeps the information about connected profile and it's status
* App store
* Keeps the information about app non persistent state
*
*/
export const useAppStore = defineStore('app', () => {
Expand Down
34 changes: 34 additions & 0 deletions stores/currency.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { CurrencyList, CurrencySymbol } from '@/types/currency'

/**
* Currency store
* Keeps the information about currency settings
* Data is stored in local storage
*
*/
export const useCurrencyStore = defineStore(
'currency',
() => {
const currencyList = ref<CurrencyList>()
const currentCurrencySymbol = ref<CurrencySymbol>(DEFAULT_CURRENCY_SYMBOL)

const getCurrencyMultiplier = () => {
return (symbol: string) =>
currencyList.value &&
currencyList.value[symbol] &&
currencyList.value[symbol][currentCurrencySymbol.value]
}

return {
currentCurrencySymbol,
currencyList,
getCurrencyMultiplier,
}
},
{
persist: {
storage: persistedState.localStorage,
key: STORAGE_KEY.CURRENCY_STORE,
},
}
)
Binary file modified tests/e2e/index.spec.ts-snapshots/landing-no-extension-chrome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions types/currency.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type CurrencySymbol = 'USD' | 'EUR' | 'GBP' | 'PLN'

export type CurrencyList = {
[key: string]: {
[key in CurrencySymbol]: number
}
}

export type CurrencyCache = { currencies: CurrencyList; expires: number }
1 change: 0 additions & 1 deletion utils/fetchLSP8Assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export const fetchLsp8Assets = async (
profileAddress: Address
) => {
const { contract } = useWeb3(PROVIDERS.RPC)

const lsp8Contract = contract<LSP8IdentifiableDigitalAssetInterface>(
LSP8IdentifiableDigitalAsset.abi as any,
address
Expand Down
Loading

0 comments on commit d373c60

Please sign in to comment.