diff --git a/src/components/App.tsx b/src/components/App.tsx index 44d0934be..8ea90d21c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -51,9 +51,9 @@ export default function App() { const isReloadingWalletInfo = useMemo(() => reloadingWalletInfoCounter > 0, [reloadingWalletInfoCounter]) const startWallet = useCallback( - (name: Api.WalletName, token: Api.ApiToken) => { - setSession({ name, token }) - setCurrentWallet({ name, token }) + (name: Api.WalletName, auth: Api.ApiAuthContext) => { + setSession({ name, auth }) + setCurrentWallet({ name, token: auth.token }) }, [setCurrentWallet], ) diff --git a/src/components/BitcoinQR.jsx b/src/components/BitcoinQR.jsx index d2e902c3e..4d082d257 100644 --- a/src/components/BitcoinQR.jsx +++ b/src/components/BitcoinQR.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import QRCode from 'qrcode' import { satsToBtc } from '../utils' diff --git a/src/components/CoinjoinPreconditionViolationAlert.tsx b/src/components/CoinjoinPreconditionViolationAlert.tsx index d8b3bfbaf..bafee07d8 100644 --- a/src/components/CoinjoinPreconditionViolationAlert.tsx +++ b/src/components/CoinjoinPreconditionViolationAlert.tsx @@ -1,4 +1,4 @@ -import React, { forwardRef } from 'react' +import { Ref, forwardRef } from 'react' import * as rb from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' import { useSettings } from '../context/SettingsContext' @@ -14,7 +14,7 @@ interface CoinjoinPreconditionViolationAlertProps { } export const CoinjoinPreconditionViolationAlert = forwardRef( - ({ summary, i18nPrefix = '' }: CoinjoinPreconditionViolationAlertProps, ref: React.Ref) => { + ({ summary, i18nPrefix = '' }: CoinjoinPreconditionViolationAlertProps, ref: Ref) => { const { t } = useTranslation() const settings = useSettings() diff --git a/src/components/CreateWallet.jsx b/src/components/CreateWallet.jsx index b69ff2a36..0db208591 100644 --- a/src/components/CreateWallet.jsx +++ b/src/components/CreateWallet.jsx @@ -99,8 +99,15 @@ export default function CreateWallet({ parentRoute, startWallet }) { const res = await Api.postWalletCreate({}, { walletname: walletName, password }) const body = await (res.ok ? res.json() : Api.Helper.throwError(res)) - const { seedphrase, token, walletname: createdWalletFileName } = body - setCreatedWallet({ walletFileName: createdWalletFileName, seedphrase, password, token }) + const { seedphrase, walletname: createdWalletFileName } = body + const auth = { + token: body.token, + token_type: body.token_type, + expires_in: body.expires_in, + scope: body.scope, + refresh_token: body.refresh_token, + } + setCreatedWallet({ walletFileName: createdWalletFileName, seedphrase, password, auth }) } catch (e) { const message = t('create_wallet.error_creating_failed', { reason: e.message || 'Unknown reason', @@ -112,9 +119,9 @@ export default function CreateWallet({ parentRoute, startWallet }) { ) const walletConfirmed = useCallback(() => { - if (createdWallet?.walletFileName && createdWallet?.token) { + if (createdWallet?.walletFileName && createdWallet?.auth) { setAlert(null) - startWallet(createdWallet.walletFileName, createdWallet.token) + startWallet(createdWallet.walletFileName, createdWallet.auth) navigate(routes.wallet) } else { setAlert({ variant: 'danger', message: t('create_wallet.alert_confirmation_failed') }) diff --git a/src/components/EarnReport.tsx b/src/components/EarnReport.tsx index 34a5f41cb..9bf6ad9c9 100644 --- a/src/components/EarnReport.tsx +++ b/src/components/EarnReport.tsx @@ -7,7 +7,6 @@ import { useTheme } from '@table-library/react-table-library/theme' import * as rb from 'react-bootstrap' import { useTranslation } from 'react-i18next' import * as Api from '../libs/JmWalletApi' -// @ts-ignore import { useSettings } from '../context/SettingsContext' import Balance from './Balance' import Sprite from './Sprite' diff --git a/src/components/ImportWallet.tsx b/src/components/ImportWallet.tsx index 04751c1d3..c3a1a78e3 100644 --- a/src/components/ImportWallet.tsx +++ b/src/components/ImportWallet.tsx @@ -374,7 +374,7 @@ enum ImportWalletSteps { interface ImportWalletProps { parentRoute: Route - startWallet: (name: Api.WalletName, token: Api.ApiToken) => void + startWallet: (name: Api.WalletName, auth: Api.ApiAuthContext) => void } export default function ImportWallet({ parentRoute, startWallet }: ImportWalletProps) { @@ -388,9 +388,9 @@ export default function ImportWallet({ parentRoute, startWallet }: ImportWalletP const [alert, setAlert] = useState() const [createWalletFormValues, setCreateWalletFormValues] = useState() const [importDetailsFormValues, setImportDetailsFormValues] = useState() - const [recoveredWallet, setRecoveredWallet] = useState<{ walletFileName: Api.WalletName; token: Api.ApiToken }>() + const [recoveredWallet, setRecoveredWallet] = useState<{ walletFileName: Api.WalletName; auth: Api.ApiAuthContext }>() - const isRecovered = useMemo(() => !!recoveredWallet?.walletFileName && recoveredWallet?.token, [recoveredWallet]) + const isRecovered = useMemo(() => !!recoveredWallet?.walletFileName && recoveredWallet?.auth, [recoveredWallet]) const canRecover = useMemo( () => !isRecovered && !serviceInfo?.walletName && !serviceInfo?.rescanning, [isRecovered, serviceInfo], @@ -441,13 +441,20 @@ export default function ImportWallet({ parentRoute, startWallet }: ImportWalletP const recoverBody = await (recoverResponse.ok ? recoverResponse.json() : Api.Helper.throwError(recoverResponse)) const { walletname: importedWalletFileName } = recoverBody - setRecoveredWallet({ walletFileName: importedWalletFileName, token: recoverBody.token }) + let auth: Api.ApiAuthContext = { + token: recoverBody.token, + token_type: recoverBody.token_type, + expires_in: recoverBody.token_type, + scope: recoverBody.token_type, + refresh_token: recoverBody.token_type, + } + setRecoveredWallet({ walletFileName: importedWalletFileName, auth }) // Step #2: update the gaplimit config value if necessary const originalGaplimit = await refreshConfigValues({ signal, keys: [JM_GAPLIMIT_CONFIGKEY], - wallet: { name: importedWalletFileName, token: recoverBody.token }, + wallet: { name: importedWalletFileName, token: auth.token }, }) .then((it) => it[JM_GAPLIMIT_CONFIGKEY.section] || {}) .then((it) => parseInt(it[JM_GAPLIMIT_CONFIGKEY.field] || String(JM_GAPLIMIT_DEFAULT), 10)) @@ -465,16 +472,23 @@ export default function ImportWallet({ parentRoute, startWallet }: ImportWalletP value: String(gaplimit), }, ], - wallet: { name: importedWalletFileName, token: recoverBody.token }, + wallet: { name: importedWalletFileName, token: auth.token }, }) } // Step #3: lock and unlock the wallet (for new addresses to be imported) - const lockResponse = await Api.getWalletLock({ walletName: importedWalletFileName, token: recoverBody.token }) + const lockResponse = await Api.getWalletLock({ walletName: importedWalletFileName, token: auth.token }) if (!lockResponse.ok) await Api.Helper.throwError(lockResponse) const unlockResponse = await Api.postWalletUnlock({ walletName: importedWalletFileName }, { password }) const unlockBody = await (unlockResponse.ok ? unlockResponse.json() : Api.Helper.throwError(unlockResponse)) + auth = { + token: unlockBody.token, + token_type: unlockBody.token_type, + expires_in: unlockBody.expires_in, + scope: unlockBody.scope, + refresh_token: unlockBody.refresh_token, + } // Step #4: reset `gaplimit´ to previous value if necessary if (gaplimitUpdateNecessary) { @@ -487,7 +501,7 @@ export default function ImportWallet({ parentRoute, startWallet }: ImportWalletP value: String(originalGaplimit), }, ], - wallet: { name: importedWalletFileName, token: unlockBody.token }, + wallet: { name: importedWalletFileName, token: auth.token }, }) } @@ -508,7 +522,7 @@ export default function ImportWallet({ parentRoute, startWallet }: ImportWalletP }) } - startWallet(importedWalletFileName, unlockBody.token) + startWallet(importedWalletFileName, auth) navigate(routes.wallet) } catch (e: any) { if (signal.aborted) return diff --git a/src/components/LogOverlay.tsx b/src/components/LogOverlay.tsx index 4ffb4571e..29e30efb6 100644 --- a/src/components/LogOverlay.tsx +++ b/src/components/LogOverlay.tsx @@ -1,9 +1,8 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import * as rb from 'react-bootstrap' import { useTranslation } from 'react-i18next' import { Helper as ApiHelper } from '../libs/JmWalletApi' import { fetchLog } from '../libs/JamApi' -// @ts-ignore import { useSettings } from '../context/SettingsContext' import { CurrentWallet } from '../context/WalletContext' import Sprite from './Sprite' diff --git a/src/components/ToggleSwitch.tsx b/src/components/ToggleSwitch.tsx index 2f83f9a69..de6f2b5c3 100644 --- a/src/components/ToggleSwitch.tsx +++ b/src/components/ToggleSwitch.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import { ChangeEvent } from 'react' import styles from './ToggleSwitch.module.css' interface ToggleSwitchProps { @@ -16,7 +16,7 @@ export default function ToggleSwitch({ toggledOn, disabled = false, }: ToggleSwitchProps) { - const onChange = (e: React.ChangeEvent) => { + const onChange = (e: ChangeEvent) => { e.stopPropagation() onToggle(e.currentTarget.checked) } diff --git a/src/components/Wallets.jsx b/src/components/Wallets.jsx index 37fe6e99d..6e5fca85f 100644 --- a/src/components/Wallets.jsx +++ b/src/components/Wallets.jsx @@ -65,8 +65,14 @@ export default function Wallets({ currentWallet, startWallet, stopWallet }) { setUnlockWalletName(undefined) - const { walletname: unlockedWalletName, token } = body - startWallet(unlockedWalletName, token) + const auth = { + token: body.token, + token_type: body.token_type, + expires_in: body.expires_in, + scope: body.scope, + refresh_token: body.refresh_token, + } + startWallet(body.walletname, auth) navigate(routes.wallet) } catch (e) { const message = e.message.replace('Wallet', walletName) diff --git a/src/components/jar_details/DisplayBranch.tsx b/src/components/jar_details/DisplayBranch.tsx index 99c6a4202..65da72bd2 100644 --- a/src/components/jar_details/DisplayBranch.tsx +++ b/src/components/jar_details/DisplayBranch.tsx @@ -1,9 +1,7 @@ -import React from 'react' +import { ReactNode } from 'react' import * as rb from 'react-bootstrap' import { useTranslation } from 'react-i18next' -// @ts-ignore import Balance from '../Balance' -// @ts-ignore import { useSettings } from '../../context/SettingsContext' import { Branch, BranchEntry } from '../../context/WalletContext' import styles from './DisplayBranch.module.css' @@ -28,7 +26,7 @@ const toSimpleStatus = (value: string) => { return value.substring(0, indexOfBracket).trim() } -const toLabelNode = (simpleStatus: string): React.ReactNode => { +const toLabelNode = (simpleStatus: string): ReactNode => { if (simpleStatus === 'new') return {simpleStatus} if (simpleStatus === 'used') return {simpleStatus} diff --git a/src/context/ServiceConfigContext.tsx b/src/context/ServiceConfigContext.tsx index 73a38c54f..f7a547404 100644 --- a/src/context/ServiceConfigContext.tsx +++ b/src/context/ServiceConfigContext.tsx @@ -1,5 +1,4 @@ -import React, { createContext, useCallback, useContext, useEffect, useRef } from 'react' -// @ts-ignore +import { PropsWithChildren, createContext, useCallback, useContext, useEffect, useRef } from 'react' import { CurrentWallet, useCurrentWallet } from './WalletContext' import * as Api from '../libs/JmWalletApi' @@ -105,7 +104,7 @@ export interface ServiceConfigContextEntry { const ServiceConfigContext = createContext(undefined) -const ServiceConfigProvider = ({ children }: React.PropsWithChildren<{}>) => { +const ServiceConfigProvider = ({ children }: PropsWithChildren<{}>) => { const currentWallet = useCurrentWallet() const serviceConfig = useRef(null) diff --git a/src/context/ServiceInfoContext.tsx b/src/context/ServiceInfoContext.tsx index 63ea11bac..ebb80f5ec 100644 --- a/src/context/ServiceInfoContext.tsx +++ b/src/context/ServiceInfoContext.tsx @@ -1,5 +1,14 @@ -import React, { createContext, useCallback, useContext, useReducer, useState, useEffect, useRef } from 'react' -// @ts-ignore +import { + PropsWithChildren, + Dispatch, + createContext, + useCallback, + useContext, + useReducer, + useState, + useEffect, + useRef, +} from 'react' import { useCurrentWallet, useSetCurrentWallet } from './WalletContext' // @ts-ignore import { useWebsocket } from './WebsocketContext' @@ -101,13 +110,13 @@ const toSemVer = (data: JmGetInfoData): SemVer => { interface ServiceInfoContextEntry { serviceInfo: ServiceInfo | null reloadServiceInfo: ({ signal }: { signal: AbortSignal }) => Promise - dispatchServiceInfo: React.Dispatch> + dispatchServiceInfo: Dispatch> connectionError?: Error } const ServiceInfoContext = createContext(undefined) -const ServiceInfoProvider = ({ children }: React.PropsWithChildren<{}>) => { +const ServiceInfoProvider = ({ children }: PropsWithChildren<{}>) => { const currentWallet = useCurrentWallet() const setCurrentWallet = useSetCurrentWallet() const websocket = useWebsocket() diff --git a/src/context/WalletContext.tsx b/src/context/WalletContext.tsx index f3423f8fa..ea253ba18 100644 --- a/src/context/WalletContext.tsx +++ b/src/context/WalletContext.tsx @@ -153,10 +153,10 @@ const WalletContext = createContext(undefined) const restoreWalletFromSession = (): CurrentWallet | null => { const session = getSession() - return session && session.name && session.token + return session && session.name && session.auth && session.auth.token ? { name: session.name, - token: session.token, + token: session.auth.token, } : null } diff --git a/src/index.tsx b/src/index.tsx index cd9270cc3..fe113b939 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,8 +1,7 @@ -import React from 'react' +import { StrictMode } from 'react' import ReactDOM from 'react-dom' -// @ts-ignore + import App from './components/App' -// @ts-ignore import { SettingsProvider } from './context/SettingsContext' // @ts-ignore import { WebsocketProvider } from './context/WebsocketContext' @@ -15,7 +14,7 @@ import './index.css' import './i18n/config' ReactDOM.render( - + @@ -27,6 +26,6 @@ ReactDOM.render( - , + , document.getElementById('root'), ) diff --git a/src/libs/JmWalletApi.ts b/src/libs/JmWalletApi.ts index 86cb8d88c..1adee0a2d 100644 --- a/src/libs/JmWalletApi.ts +++ b/src/libs/JmWalletApi.ts @@ -24,19 +24,19 @@ export type TxId = string export type UtxoId = `${TxId}:${Vout}` // for JM versions <0.9.11 -export type SingleApiTokenContext = { +export type SingleTokenAuthContext = { token: ApiToken } // for JM versions >=0.9.11 -export type RefreshApiTokenContext = SingleApiTokenContext & { +export type RefreshTokenAuthContext = SingleTokenAuthContext & { token_type: string // "bearer" expires_in: Seconds // 1800 scope: string refresh_token: ApiToken } -export type ApiTokenContext = SingleApiTokenContext | RefreshApiTokenContext +export type ApiAuthContext = SingleTokenAuthContext | RefreshTokenAuthContext type WithWalletName = { walletName: WalletName diff --git a/src/session.ts b/src/session.ts index 6a2cdf4e3..dacaf43f7 100644 --- a/src/session.ts +++ b/src/session.ts @@ -1,19 +1,19 @@ -import { WalletName, ApiToken } from './libs/JmWalletApi' +import { WalletName, ApiAuthContext } from './libs/JmWalletApi' const SESSION_KEY = 'joinmarket' export interface SessionItem { name: WalletName - token: ApiToken + auth: ApiAuthContext } export const setSession = (session: SessionItem) => sessionStorage.setItem(SESSION_KEY, JSON.stringify(session)) export const getSession = (): SessionItem | null => { const json = sessionStorage.getItem(SESSION_KEY) - const { name, token }: any = (json && JSON.parse(json)) || {} - if (name && token) { - return { name, token } + const { name, auth }: any = (json && JSON.parse(json)) || {} + if (name && auth?.token) { + return { name, auth } } else { clearSession() return null diff --git a/src/testUtils.tsx b/src/testUtils.tsx index 5377a6631..9dd81d03f 100644 --- a/src/testUtils.tsx +++ b/src/testUtils.tsx @@ -1,18 +1,17 @@ -import React from 'react' +import { StrictMode, ReactElement } from 'react' import { render, RenderOptions } from '@testing-library/react' import { I18nextProvider } from 'react-i18next' import { WalletProvider } from './context/WalletContext' import { ServiceInfoProvider } from './context/ServiceInfoContext' import { ServiceConfigProvider } from './context/ServiceConfigContext' -// @ts-ignore import { SettingsProvider } from './context/SettingsContext' // @ts-ignore import { WebsocketProvider } from './context/WebsocketContext' import i18n from './i18n/testConfig' -const AllTheProviders = ({ children }: { children: React.ReactElement }) => { +const AllTheProviders = ({ children }: { children: ReactElement }) => { return ( - + @@ -24,12 +23,11 @@ const AllTheProviders = ({ children }: { children: React.ReactElement }) => { - + ) } -const customRender = (ui: React.ReactElement, options?: RenderOptions) => - render(ui, { wrapper: AllTheProviders, ...options }) +const customRender = (ui: ReactElement, options?: RenderOptions) => render(ui, { wrapper: AllTheProviders, ...options }) // re-export everything export * from '@testing-library/react'