Skip to content

Commit

Permalink
Merge pull request #2062 from oasisprotocol/mz/chainContext
Browse files Browse the repository at this point in the history
Delay GetChainContext request until needed
  • Loading branch information
buberdds authored Sep 26, 2024
2 parents e90e33c + 12e740b commit aa5dee4
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 20 deletions.
1 change: 1 addition & 0 deletions .changelog/2062.internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Delay GetChainContext request until needed
2 changes: 1 addition & 1 deletion src/app/components/TransactionPreview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { TransactionTypeFormatter } from '../TransactionTypeFormatter'
interface Props {
preview: Preview
walletAddress: string
chainContext: string
chainContext?: string
}

export const TransactionPreview = memo((props: Props) => {
Expand Down
8 changes: 6 additions & 2 deletions src/app/state/importaccounts/saga.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ describe('importAccounts Sagas', () => {
const mockTransport = { close: jest.fn() }

return expectSaga(sign, mockSigner as unknown as LedgerSigner, {} as any)
.withState({ network: {} })
.withState({
network: { chainContext: '0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76' },
})
.provide([
[matchers.call.fn(TransportWebUSB.isSupported), true],
[matchers.call.fn(TransportWebUSB.create), mockTransport],
Expand All @@ -212,7 +214,9 @@ describe('importAccounts Sagas', () => {
expect(err).toEqual(new Error('Dummy error'))
}
})
.withState({ network: {} })
.withState({
network: { chainContext: '0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76' },
})
.provide([
[matchers.call.fn(TransportWebUSB.isSupported), true],
[matchers.call.fn(TransportWebUSB.create), mockTransport],
Expand Down
4 changes: 2 additions & 2 deletions src/app/state/importaccounts/saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { all, call, delay, fork, put, select, takeEvery } from 'typed-redux-saga
import { ErrorPayload, WalletError, WalletErrors } from 'types/errors'
import { LedgerWalletType, WalletType } from 'app/state/wallet/types'
import { importAccountsActions } from '.'
import { selectChainContext } from '../network/selectors'
import { ImportAccountsListAccount, ImportAccountsStep } from './types'
import type Transport from '@ledgerhq/hw-transport'
import {
Expand All @@ -22,6 +21,7 @@ import {
import { getAccountBalanceWithFallback } from '../../lib/getAccountBalanceWithFallback'
import BleTransport from '@oasisprotocol/ionic-ledger-hw-transport-ble/lib'
import { ScanResult } from '@capacitor-community/bluetooth-le'
import { getChainContext } from '../network/saga'

function* setStep(step: ImportAccountsStep) {
yield* put(importAccountsActions.setStep(step))
Expand Down Expand Up @@ -233,7 +233,7 @@ export function* sign<T>(signer: LedgerSigner, tw: oasis.consensus.TransactionWr
} else {
transport = yield* getUSBTransport()
}
const chainContext = yield* select(selectChainContext)
const chainContext = yield* call(getChainContext)

signer.setTransport(transport)
try {
Expand Down
9 changes: 7 additions & 2 deletions src/app/state/network/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ export const networkSlice = createSlice({
initialState,
reducers: {
initializeNetwork() {},
selectNetwork(state, action: PayloadAction<NetworkType>) {},
selectNetwork(state, action: PayloadAction<NetworkType>) {
state.chainContext = initialState.chainContext
},
initialNetworkSelected(state, action: PayloadAction<NetworkState>) {
Object.assign(state, action.payload)
},
networkSelected(state, action: PayloadAction<NetworkState>) {
Object.assign(state, action.payload)
Object.assign(state, action.payload, { chainContext: initialState.chainContext })
},
setChainContext(state, action: PayloadAction<string>) {
state.chainContext = action.payload
},
},
})
Expand Down
41 changes: 39 additions & 2 deletions src/app/state/network/saga.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { testSaga } from 'redux-saga-test-plan'
import { expectSaga, testSaga } from 'redux-saga-test-plan'
import * as matchers from 'redux-saga-test-plan/matchers'
import { getChainContext, getOasisNic, networkSaga, selectNetwork } from './saga'
import { networkActions } from '.'
import { networkSaga, selectNetwork } from './saga'

describe('Network Sagas', () => {
const env = process.env
Expand All @@ -22,4 +23,40 @@ describe('Network Sagas', () => {
.next()
.isDone()
})

describe('getChainContext', () => {
const mockChainContext = '0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76'
const mockSelectedNetwork = 'testnet'
const mockNic = {
consensusGetChainContext: jest.fn().mockResolvedValue(mockChainContext),
}

it('should return existing chainContext if available', () => {
return expectSaga(getChainContext)
.withState({
network: {
chainContext: mockChainContext,
selectedNetwork: mockSelectedNetwork,
},
})
.returns(mockChainContext)
.run()
})

it('should fetch and return chainContext when not present in state', () => {
return expectSaga(getChainContext)
.withState({
network: {
selectedNetwork: mockSelectedNetwork,
},
})
.provide([
[matchers.call.fn(getOasisNic), mockNic],
[matchers.call.fn(mockNic.consensusGetChainContext), mockChainContext],
])
.put(networkActions.setChainContext(mockChainContext))
.returns(mockChainContext)
.run()
})
})
})
24 changes: 20 additions & 4 deletions src/app/state/network/saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { backend, backendApi } from 'vendors/backend'

import { networkActions } from '.'
import { SyncedRootState } from '../persist/types'
import { selectSelectedNetwork } from './selectors'
import { selectChainContext, selectSelectedNetwork } from './selectors'
import { NetworkType } from './types'
import { WalletError, WalletErrors } from 'types/errors'

/**
* Return a nic client for the specified network,
Expand All @@ -32,6 +33,23 @@ export function* getExplorerAPIs() {
return backendApi(url)
}

export function* getChainContext() {
const chainContext = yield* select(selectChainContext)
if (chainContext) {
return chainContext
}

try {
const selectedNetwork = yield* select(selectSelectedNetwork)
const nic = yield* call(getOasisNic, selectedNetwork)
const fetchedChainContext = yield* call([nic, nic.consensusGetChainContext])
yield* put(networkActions.setChainContext(fetchedChainContext))
return fetchedChainContext
} catch (error) {
throw new WalletError(WalletErrors.UnknownGrpcError, 'Could not fetch data')
}
}

export function* selectNetwork({
network,
isInitializing,
Expand All @@ -40,12 +58,10 @@ export function* selectNetwork({
isInitializing: boolean
}) {
const nic = yield* call(getOasisNic, network)
const { epoch, chainContext } = yield* all({
const { epoch } = yield* all({
epoch: call([nic, nic.beaconGetEpoch], oasis.consensus.HEIGHT_LATEST),
chainContext: call([nic, nic.consensusGetChainContext]),
})
const networkState = {
chainContext: chainContext,
ticker: config[network].ticker,
epoch: Number(epoch), // Will lose precision in a few billion years at 1 epoch per hour
selectedNetwork: network,
Expand Down
2 changes: 1 addition & 1 deletion src/app/state/network/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface NetworkState {
ticker: string

/** chainContext / Genesis Hash */
chainContext: string
chainContext?: string

/** Current epoch */
epoch: number
Expand Down
1 change: 1 addition & 0 deletions src/app/state/persist/syncTabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const whitelistTabSyncActions: Record<AllActions, boolean> = {
[rootSlices.wallet.actions.walletOpened.type]: true,
[rootSlices.wallet.actions.updateBalance.type]: true,
[rootSlices.network.actions.networkSelected.type]: true,
[rootSlices.network.actions.setChainContext.type]: true,
[rootSlices.persist.actions.setUnlockedRootState.type]: true,
[rootSlices.persist.actions.resetRootState.type]: true,
[rootSlices.persist.actions.skipUnlocking.type]: true,
Expand Down
4 changes: 4 additions & 0 deletions src/app/state/transaction/saga.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const makeState = (wallet: Partial<Wallet>, rootState: DeepPartialRootState = {}
wallets: { [wallet.address!]: wallet },
selectedWallet: wallet.address,
},
network: {
selectedNetwork: 'testnet',
chainContext: '0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76',
},
...rootState,
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/app/state/transaction/saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { call, delay, put, race, select, take, takeEvery } from 'typed-redux-sag
import { ErrorPayload, ExhaustedTypeError, WalletError, WalletErrors } from 'types/errors'
import { transactionActions } from '.'
import { sign } from '../importaccounts/saga'
import { getOasisNic } from '../network/saga'
import { getChainContext, getOasisNic } from '../network/saga'
import { selectAccountAddress, selectAccountAllowances } from '../account/selectors'
import { selectChainContext, selectSelectedNetwork } from '../network/selectors'
import { selectSelectedNetwork } from '../network/selectors'
import { selectActiveWallet } from '../wallet/selectors'
import { Wallet, WalletType } from '../wallet/types'
import { Transaction, TransactionPayload, TransactionStatus, TransactionStep, TransactionType } from './types'
Expand Down Expand Up @@ -137,7 +137,7 @@ function* prepareReclaimEscrow(signer: Signer, shares: bigint, validator: string
export function* doTransaction(action: PayloadAction<TransactionPayload>) {
const wallet = yield* select(selectActiveWallet)
const nic = yield* call(getOasisNic)
const chainContext = yield* select(selectChainContext)
const chainContext = yield* call(getChainContext)
const networkType = yield* select(selectSelectedNetwork)

try {
Expand Down Expand Up @@ -282,7 +282,7 @@ export function* submitParaTimeTransaction(runtime: Runtime, transaction: ParaTi
? yield* call(getEvmBech32Address, privateToEthAddress(transaction.ethPrivateKey))
: yield* select(selectAccountAddress)
const nic = yield* call(getOasisNic)
const chainContext = yield* select(selectChainContext)
const chainContext = yield* call(getChainContext)
const paraTimeTransactionSigner = transaction.ethPrivateKey
? yield* call(signerFromEthPrivateKey, misc.fromHex(transaction.ethPrivateKey))
: yield* getSigner()
Expand Down
4 changes: 2 additions & 2 deletions src/utils/__fixtures__/test-inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const privateKeyUnlockedState = {
},
network: {
ticker: 'ROSE',
chainContext: 'b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535',
chainContext: '',
selectedNetwork: 'mainnet',
epoch: 18372,
minimumStakingAmount: 100,
Expand Down Expand Up @@ -271,7 +271,7 @@ export const walletExtensionV0UnlockedState = {
showBleLedgerDevicesModal: false,
},
network: {
chainContext: 'b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535',
chainContext: '',
ticker: 'ROSE',
selectedNetwork: 'mainnet',
epoch: 27884,
Expand Down

0 comments on commit aa5dee4

Please sign in to comment.