@@ -5,9 +5,11 @@ import VueVirtualScroller from 'vue-virtual-scroller';
5
5
import { setAssetPublicPath as setVueComponentsAssetPath } from '@nimiq/vue-components' ;
6
6
// @ts -expect-error missing types for this package
7
7
import VuePortal from '@linusborg/vue-simple-portal' ;
8
+ import { init as initOasisApi } from '@nimiq/oasis-api' ;
8
9
import { init as initFastspotApi } from '@nimiq/fastspot-api' ;
9
10
10
11
import App from './App.vue' ;
12
+ import { serviceWorkerHasUpdate } from './registerServiceWorker' ;
11
13
import { launchNetwork } from './network' ;
12
14
import { useAccountStore } from './stores/Account' ;
13
15
import { dangerouslyInitializeDemo } from './lib/Demo' ;
@@ -26,6 +28,8 @@ import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';
26
28
import '@/scss/themes.scss' ;
27
29
import { launchPolygon } from './ethers' ;
28
30
import { launchElectrum } from './electrum' ;
31
+ import { useInactivityDetection } from './composables/useInactivityDetection' ;
32
+ import { useFiatStore } from './stores/Fiat' ;
29
33
30
34
// Set asset path relative to the public path defined in vue.config.json,
31
35
// see https://cli.vuejs.org/guide/mode-and-env.html#using-env-variables-in-client-side-code
@@ -40,6 +44,41 @@ Vue.use(VuePortal, { name: 'Portal' });
40
44
async function start ( ) {
41
45
dangerouslyInitializeDemo ( router ) ;
42
46
47
+ serviceWorkerHasUpdate . then ( ( hasUpdate ) => useSettingsStore ( ) . state . updateAvailable = hasUpdate ) ;
48
+
49
+ // Update exchange rates every 2 minutes or every 10 minutes, depending on whether the Wallet is currently actively
50
+ // used. If an update takes longer than that time due to a provider's rate limit, wait until the update succeeds
51
+ // before queueing the next update. If the last update before page load was less than 2 minutes ago, wait the
52
+ // remaining time first.
53
+ const { timestamp : lastSuccessfulExchangeRateUpdate , updateExchangeRates } = useFiatStore ( ) ;
54
+ const { isUserInactive } = useInactivityDetection ( ) ;
55
+ let lastTriedExchangeRateUpdate = lastSuccessfulExchangeRateUpdate . value ;
56
+ const TWO_MINUTES = 2 * 60 * 1000 ;
57
+ const TEN_MINUTES = 5 * TWO_MINUTES ;
58
+ let exchangeRateUpdateTimer = - 1 ;
59
+ function queueExchangeRateUpdate ( ) {
60
+ const interval = isUserInactive . value ? TEN_MINUTES : TWO_MINUTES ;
61
+ // Update lastTriedExchangeRateUpdate as there might have been other exchange rate updates in the meantime, for
62
+ // example on currency change.
63
+ lastTriedExchangeRateUpdate = Math . max ( lastTriedExchangeRateUpdate , lastSuccessfulExchangeRateUpdate . value ) ;
64
+ // Also set interval as upper bound to be immune to the user's system clock being wrong.
65
+ const remainingTime = Math . max ( 0 , Math . min ( lastTriedExchangeRateUpdate + interval - Date . now ( ) , interval ) ) ;
66
+ clearTimeout ( exchangeRateUpdateTimer ) ;
67
+ exchangeRateUpdateTimer = window . setTimeout ( async ( ) => {
68
+ // Silently ignore errors. If successful, this updates fiatStore.timestamp, which then also triggers price
69
+ // chart updates in PriceChart.vue.
70
+ await updateExchangeRates ( /* failGracefully */ true ) ;
71
+ // In contrast to lastSuccessfulExchangeRateUpdate also update lastTriedExchangeRateUpdate on failed
72
+ // attempts, to avoid repeated rescheduling on failure. Instead, simply skip the failed attempt and try
73
+ // again at the regular interval. We update the time after the update attempt, instead of before it, because
74
+ // exchange rates are up-to-date at the time an update successfully finishes, and get old from that point,
75
+ // and not from the time the update was started.
76
+ lastTriedExchangeRateUpdate = Date . now ( ) ;
77
+ queueExchangeRateUpdate ( ) ;
78
+ } , remainingTime ) ;
79
+ }
80
+ watch ( isUserInactive , queueExchangeRateUpdate ) ; // (Re)schedule exchange rate updates at the desired interval.
81
+
43
82
// Fetch language file
44
83
const { language } = useSettingsStore ( ) ;
45
84
loadLanguage ( language . value ) ;
@@ -52,6 +91,11 @@ async function start() {
52
91
initFastspotApi ( config . fastspot . apiEndpoint , config . fastspot . apiKey ) ;
53
92
} ) ;
54
93
94
+ watch ( ( ) => {
95
+ if ( ! config . oasis . apiEndpoint ) return ;
96
+ initOasisApi ( config . oasis . apiEndpoint ) ;
97
+ } ) ;
98
+
55
99
config . demo . enabled = true ;
56
100
// Make reactive config accessible in components
57
101
Vue . prototype . $config = config ;
0 commit comments