Skip to content

Commit

Permalink
feat: opt session key error tips (#905)
Browse files Browse the repository at this point in the history
* feat: opt session key error tips

* feat: fix dashboard build error
  • Loading branch information
yubing744 authored Oct 3, 2023
1 parent 7aafeb9 commit a4f25e2
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 18 deletions.
12 changes: 11 additions & 1 deletion dashboard/src/@core/components/session/SessionGuard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
DialogContent,
DialogContentText,
DialogTitle,
Snackbar,
Alert,
} from '@mui/material'

// ** Next Import
Expand Down Expand Up @@ -89,13 +91,14 @@ const SessionGuard = (props: SessionGuardProps) => {

const auth = useAuth()
const router = useRouter()
const { account, requestAuthorize } = useSession()
const { account, requestAuthorize, close, errorMsg } = useSession()

const handleAuth = (scope: Array<string>, maxInactiveInterval: number) => {
requestAuthorize && requestAuthorize(scope, maxInactiveInterval)
}

const hanleLogout = () => {
close && close()
auth.logout()

if (router.asPath !== '/') {
Expand All @@ -120,6 +123,13 @@ const SessionGuard = (props: SessionGuardProps) => {
onReqAuthorize={handleAuth}
onLogout={hanleLogout}
></AuthDialog>
<Snackbar
open={errorMsg !== null}
autoHideDuration={6000}
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
>
<Alert severity="error">{errorMsg}</Alert>
</Snackbar>
</div>
<div>{children}</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Icon from 'src/@core/components/icon'

// ** Context
import { useAuth } from 'src/hooks/useAuth'
import { useSession } from 'src/hooks/useSessionAccount'

// ** Type Imports
import { Settings } from 'src/@core/context/settingsContext'
Expand All @@ -45,6 +46,7 @@ const UserDropdown = (props: Props) => {
// ** Hooks
const router = useRouter()
const { logout } = useAuth()
const { close } = useSession()

// ** Vars
const { direction } = settings
Expand Down Expand Up @@ -76,6 +78,7 @@ const UserDropdown = (props: Props) => {
}

const handleLogout = () => {
close()
logout()
handleDropdownClose()
}
Expand Down
65 changes: 54 additions & 11 deletions dashboard/src/context/session/SessionContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
addressToSeqNumber,
parseRoochErrorSubStatus,
ErrorCategory,
getErrorCategoryName,
} from '@rooch/sdk'

// ** React Imports
Expand All @@ -37,17 +38,21 @@ type Props = {
const SessionContext = createContext<Session>({
loading: false,
account: null,
errorMsg: null,
requestAuthorize: undefined,
close: () => {},
})

const makeSessionAccountStoreKey = (address: string) => {
return `rooch::dashboard::account::${address}::current-session-key`
const makeSessionAccountStoreKey = (chainId: number, address: string) => {
return `rooch::${chainId}::dashboard::account::${address}::current-session-key`
}

const loadSessionAccountFromSessionStorage = (provider: IProvider, roochAddress: string) => {
try {
// Get from local storage by key
const secretKey = window.sessionStorage.getItem(makeSessionAccountStoreKey(roochAddress))
const secretKey = window.sessionStorage.getItem(
makeSessionAccountStoreKey(provider.getChainId(), roochAddress),
)

if (secretKey) {
let sk = bcsTypes.fromB64(secretKey)
Expand All @@ -70,9 +75,12 @@ const loadSessionAccountFromSessionStorage = (provider: IProvider, roochAddress:
return null
}

const clearSessionAccountInSessionStorage = (roochAddress: string) => {
const clearSessionAccountInSessionStorage = (provider: IProvider, roochAddress: string) => {
try {
window.sessionStorage.setItem(makeSessionAccountStoreKey(roochAddress), '')
window.sessionStorage.setItem(
makeSessionAccountStoreKey(provider.getChainId(), roochAddress),
'',
)
} catch (error) {
// If error also return initialValue
console.log(error)
Expand All @@ -85,7 +93,8 @@ const SessionProvider = ({ children }: Props) => {
const auth = useAuth()
const rooch = useRooch()

const [loading, setLoading] = useState(false)
const [loading, setLoading] = useState<boolean>(false)
const [errorMsg, setErrorMsg] = useState<string | null>(null)

const filterdProvider = useMemo(() => {
const sessionKeyInvalidFilterFunc: FilterFunc = async (
Expand All @@ -106,7 +115,7 @@ const SessionProvider = ({ children }: Props) => {

const defaultAccount = auth.defaultAccount
if (defaultAccount) {
clearSessionAccountInSessionStorage(defaultAccount.roochAddress)
clearSessionAccountInSessionStorage(rooch.provider!, defaultAccount.roochAddress)
}
}

Expand Down Expand Up @@ -258,15 +267,25 @@ const SessionProvider = ({ children }: Props) => {
maxInactiveInterval,
)

const key = makeSessionAccountStoreKey(account.roochAddress)
const key = makeSessionAccountStoreKey(provider.getChainId(), account.roochAddress)
window.sessionStorage.setItem(key, pk.export().privateKey)
const authorizer = new PrivateKeyAuth(pk)

return new Account(provider, account.roochAddress, authorizer)
} catch (err: any) {
console.log(`registerSessionKey error:`, err)

return null
const subStatus = parseRoochErrorSubStatus(err.message)
if (subStatus) {
throw new Error(
'create session key fail, error category: ' +
getErrorCategoryName(subStatus.category) +
', reason: ' +
subStatus.reason,
)
}

throw new Error('create session key error, reason:' + err.message)
}
}

Expand All @@ -282,15 +301,25 @@ const SessionProvider = ({ children }: Props) => {
try {
await account.registerSessionKey(roochAddress, scope, maxInactiveInterval)

const key = makeSessionAccountStoreKey(account.getAddress())
const key = makeSessionAccountStoreKey(provider.getChainId(), account.getAddress())
window.sessionStorage.setItem(key, pk.export().privateKey)
const authorizer = new PrivateKeyAuth(pk)

return new Account(provider, roochAddress, authorizer)
} catch (err: any) {
console.log(`registerSessionKey error:`, err)

return null
const subStatus = parseRoochErrorSubStatus(err.message)
if (subStatus) {
throw new Error(
'create session key fail, error category: ' +
getErrorCategoryName(subStatus.category) +
', reason: ' +
subStatus.reason,
)
}

throw new Error('create session key error, reason:' + err.message)
}
}

Expand Down Expand Up @@ -334,15 +363,29 @@ const SessionProvider = ({ children }: Props) => {
}
}
}
} catch (e: any) {
setErrorMsg(e.message)
setTimeout(() => {
setErrorMsg(null)
}, 5000)
} finally {
setLoading(false)
}
}

const closeSession = () => {
const defaultAccount = auth.defaultAccount
if (defaultAccount) {
clearSessionAccountInSessionStorage(rooch.provider!, defaultAccount.roochAddress)
}
}

const session = {
loading,
account: sessionAccount,
errorMsg,
requestAuthorize,
close: closeSession,
} as Session

return <SessionContext.Provider value={session}>{children}</SessionContext.Provider>
Expand Down
2 changes: 2 additions & 0 deletions dashboard/src/context/session/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ import { IAccount } from '@rooch/sdk'
export interface Session {
account: IAccount | null
loading: boolean
errorMsg: string | null
requestAuthorize?: (scope: Array<string>, maxInactiveInterval: number) => Promise<void>
close: () => void
}
30 changes: 28 additions & 2 deletions dashboard/src/store/session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
ISessionKey,
JsonRpcProvider,
ListAnnotatedStateResultPageView,
parseRoochErrorSubStatus,
getErrorCategoryName,
} from '@rooch/sdk'

interface DataParams {
Expand Down Expand Up @@ -98,7 +100,19 @@ export const fetchData = createAsyncThunk('state/fetchData', async (params: Data
}
}
} catch (e: any) {
params.dispatch(error(e.toString()))
const subStatus = parseRoochErrorSubStatus(e.message)
if (subStatus) {
params.dispatch(
error(
'list session keys fail, error category: ' +
getErrorCategoryName(subStatus.category) +
', reason: ' +
subStatus.reason,
),
)
} else {
params.dispatch(error(`list session keys fail, reason: ${e.message}`))
}

setTimeout(() => {
params.dispatch(error(null))
Expand All @@ -117,7 +131,19 @@ export const removeRow = createAsyncThunk('state/removeRow', async (params: Remo

params.refresh()
} catch (e: any) {
params.dispatch(error(e.toString()))
const subStatus = parseRoochErrorSubStatus(e.message)
if (subStatus) {
params.dispatch(
error(
'remove session key fail, error category: ' +
getErrorCategoryName(subStatus.category) +
', reason: ' +
subStatus.reason,
),
)
} else {
params.dispatch(error(`remove session key fail, reason: ${e.message}`))
}

setTimeout(() => {
params.dispatch(error(null))
Expand Down
8 changes: 5 additions & 3 deletions dashboard/src/views/feature/SessionKeyList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Button from '@mui/material/Button'
import Alert from '@mui/material/Alert'
import Snackbar from '@mui/material/Snackbar'
import Dialog from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions'
Expand Down Expand Up @@ -253,10 +254,11 @@ export default function SessionKeyList() {
/>
<Snackbar
open={!!error}
autoHideDuration={5000}
message={error}
autoHideDuration={6000}
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
/>
>
<Alert severity="error">{error}</Alert>
</Snackbar>
<Dialog
open={confirmDeleteDialog.open}
onClose={handleConfirmDeleteDialogClose}
Expand Down
25 changes: 24 additions & 1 deletion sdk/typescript/src/utils/error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
// SPDX-License-Identifier: Apache-2.0

import { describe, it, expect } from 'vitest'
import { parseRoochErrorCode, parseRoochErrorSubStatus, ErrorCategory } from './error'
import {
parseRoochErrorCode,
parseRoochErrorSubStatus,
ErrorCategory,
getErrorCategoryName,
} from './error'

describe('err', () => {
describe('parseRoochErrorCode', () => {
Expand Down Expand Up @@ -41,4 +46,22 @@ describe('err', () => {
expect(parseRoochErrorSubStatus(errorMessage)).toBeNull()
})
})

describe('getErrorCategoryName', () => {
it('should return the correct string representation of the enum', () => {
expect(getErrorCategoryName(ErrorCategory.INVALID_ARGUMENT)).toBe('INVALID_ARGUMENT')
expect(getErrorCategoryName(ErrorCategory.OUT_OF_RANGE)).toBe('OUT_OF_RANGE')
expect(getErrorCategoryName(ErrorCategory.INVALID_STATE)).toBe('INVALID_STATE')
expect(getErrorCategoryName(ErrorCategory.UNAUTHENTICATED)).toBe('UNAUTHENTICATED')
expect(getErrorCategoryName(ErrorCategory.PERMISSION_DENIED)).toBe('PERMISSION_DENIED')
expect(getErrorCategoryName(ErrorCategory.NOT_FOUND)).toBe('NOT_FOUND')
expect(getErrorCategoryName(ErrorCategory.ABORTED)).toBe('ABORTED')
expect(getErrorCategoryName(ErrorCategory.ALREADY_EXISTS)).toBe('ALREADY_EXISTS')
expect(getErrorCategoryName(ErrorCategory.RESOURCE_EXHAUSTED)).toBe('RESOURCE_EXHAUSTED')
expect(getErrorCategoryName(ErrorCategory.CANCELLED)).toBe('CANCELLED')
expect(getErrorCategoryName(ErrorCategory.INTERNAL)).toBe('INTERNAL')
expect(getErrorCategoryName(ErrorCategory.NOT_IMPLEMENTED)).toBe('NOT_IMPLEMENTED')
expect(getErrorCategoryName(ErrorCategory.UNAVAILABLE)).toBe('UNAVAILABLE')
})
})
})
5 changes: 5 additions & 0 deletions sdk/typescript/src/utils/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,8 @@ export function parseRoochErrorSubStatus(errorMessage: string | null): SubStatus
reason: errorCode & 0xffff,
}
}

// Get the string representation of an enumeration
export function getErrorCategoryName(code: ErrorCategory): string {
return ErrorCategory[code]
}

0 comments on commit a4f25e2

Please sign in to comment.