Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DPA-1265]: feat(chain-config): support create solana config #94

Merged
merged 1 commit into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/flat-impalas-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@smartcontractkit/operator-ui': minor
---

Support creating solana chain config
157 changes: 117 additions & 40 deletions src/components/Form/ChainConfigurationForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ describe('ChainConfigurationForm', () => {
initialValues={initialValues}
onSubmit={handleSubmit}
accountsEVM={[]}
accountsAptos={[]}
chains={[]}
p2pKeys={[]}
ocrKeys={[]}
Expand Down Expand Up @@ -46,7 +45,6 @@ describe('ChainConfigurationForm', () => {
initialValues={initialValues}
onSubmit={handleSubmit}
accountsEVM={[]}
accountsAptos={[]}
chains={[]}
p2pKeys={[]}
ocrKeys={[]}
Expand Down Expand Up @@ -85,7 +83,6 @@ describe('ChainConfigurationForm', () => {
initialValues={initialValues}
onSubmit={handleSubmit}
accountsEVM={[]}
accountsAptos={[]}
chains={[]}
p2pKeys={[]}
ocrKeys={[]}
Expand Down Expand Up @@ -125,43 +122,9 @@ describe('ChainConfigurationForm', () => {
initialValues.chainType = ChainTypes.EVM
initialValues.adminAddr = '0x1234567'

const { container } = render(
<ChainConfigurationForm
initialValues={initialValues}
onSubmit={(x, _) => handleSubmit(x)}
accountsEVM={[
{
address: '0x1111',
chain: {
id: '1111',
},
createdAt: '2021-10-06T00:00:00Z',
isDisabled: false,
},
]}
accountsAptos={[
{
account: '0x123',
id: '2222',
},
]}
chains={[
{
id: '1111',
enabled: true,
network: 'evm',
},
{
id: '2222',
enabled: true,
network: 'aptos',
},
]}
p2pKeys={[]}
ocrKeys={[]}
ocr2Keys={[]}
showSubmit
/>,
const { container } = renderChainConfigurationForm(
initialValues,
handleSubmit,
)

const chainType = getByRole('button', { name: 'EVM' })
Expand Down Expand Up @@ -217,6 +180,69 @@ describe('ChainConfigurationForm', () => {
})
})

test('should able to create Solana chain config', async () => {
const handleSubmit = jest.fn()
const initialValues = emptyFormValues()
initialValues.chainType = ChainTypes.EVM
initialValues.adminAddr = '0x1234567'

const { container } = renderChainConfigurationForm(
initialValues,
handleSubmit,
)

const chainType = getByRole('button', { name: 'EVM' })
userEvent.click(chainType)
userEvent.click(getByRole('option', { name: 'SOLANA' }))
await screen.findByRole('button', { name: 'SOLANA' })

// no easy way to use react testing framework to do what i want,
// had to resort to using #id and querySelector
// formik does not seem to work well with react testing framework
const chainId = container.querySelector('#select-chainID')
expect(chainId).toBeInTheDocument()
// workaround ts lint warning - unable to use chainId!
chainId && userEvent.click(chainId)
userEvent.click(getByRole('option', { name: '3333' }))
await screen.findByRole('button', { name: '3333' })

const address = container.querySelector('#select-accountAddr')
expect(address).toBeInTheDocument()
address && userEvent.click(address)
userEvent.click(getByRole('option', { name: 'solana_xxxx' }))
await screen.findByRole('button', { name: 'solana_xxxx' })

await userEvent.click(getByRole('button', { name: /submit/i }))

await waitFor(() => {
expect(handleSubmit).toHaveBeenCalledWith({
accountAddr: 'solana_xxxx',
accountAddrPubKey: '',
adminAddr: '0x1234567',
chainID: '3333',
chainType: 'SOLANA',
fluxMonitorEnabled: false,
ocr1Enabled: false,
ocr1IsBootstrap: false,
ocr1KeyBundleID: '',
ocr1Multiaddr: '',
ocr1P2PPeerID: '',
ocr2CommitPluginEnabled: false,
ocr2Enabled: false,
ocr2ExecutePluginEnabled: false,
ocr2ForwarderAddress: '',
ocr2IsBootstrap: false,
ocr2KeyBundleID: '',
ocr2MedianPluginEnabled: false,
ocr2MercuryPluginEnabled: false,
ocr2Multiaddr: '',
ocr2P2PPeerID: '',
ocr2RebalancerPluginEnabled: false,
})
expect(handleSubmit).toHaveBeenCalledTimes(1)
})
})

function emptyFormValues(): FormValues {
return {
chainID: '',
Expand All @@ -243,3 +269,54 @@ function emptyFormValues(): FormValues {
ocr2ForwarderAddress: '',
}
}

function renderChainConfigurationForm(
initialValues: FormValues,
onSubmit: (x: FormValues) => void,
) {
return render(
<ChainConfigurationForm
initialValues={initialValues}
onSubmit={(x, _) => onSubmit(x)}
accountsEVM={[
{
address: '0x1111',
chain: {
id: '1111',
},
createdAt: '2021-10-06T00:00:00Z',
isDisabled: false,
},
]}
accountsNonEvm={{
aptosKeys: {
results: [{ account: '0x123', id: '2222' }],
},
solanaKeys: {
results: [{ id: 'solana_xxxx' }],
},
}}
chains={[
{
id: '1111',
enabled: true,
network: 'evm',
},
{
id: '2222',
enabled: true,
network: 'aptos',
},
{
id: '3333',
enabled: true,
network: 'solana',
},
]}
p2pKeys={[]}
ocrKeys={[]}
ocr2Keys={[]}
showSubmit
/>,
)
}
36 changes: 24 additions & 12 deletions src/components/Form/ChainConfigurationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export interface Props extends WithStyles<typeof styles> {
) => void | Promise<any>
chains: ReadonlyArray<ChainsPayload_ResultsFields>
accountsEVM: ReadonlyArray<EthKeysPayload_ResultsFields>
accountsAptos: ReadonlyArray<AptosKeysPayload_ResultsFields>
accountsNonEvm?: FetchNonEvmKeys
p2pKeys: ReadonlyArray<P2PKeysPayload_ResultsFields>
ocrKeys: ReadonlyArray<OcrKeyBundlesPayload_ResultsFields>
ocr2Keys: ReadonlyArray<Ocr2KeyBundlesPayload_ResultsFields>
Expand All @@ -222,7 +222,7 @@ export const ChainConfigurationForm = withStyles(styles)(
onSubmit,
chains = [],
accountsEVM = [],
accountsAptos = [],
accountsNonEvm,
p2pKeys = [],
ocrKeys = [],
ocr2Keys = [],
Expand All @@ -237,17 +237,26 @@ export const ChainConfigurationForm = withStyles(styles)(
>
{({ values }) => {
let chainAccountAddresses: string[] = []
if (values.chainType === ChainTypes.EVM) {
chainAccountAddresses = accountsEVM
.filter(
(acc) => acc.chain.id == values.chainID && !acc.isDisabled,
)
.map((acc) => acc.address)
switch (values.chainType) {
case ChainTypes.EVM:
chainAccountAddresses = accountsEVM
.filter(
(acc) => acc.chain.id == values.chainID && !acc.isDisabled,
)
.map((acc) => acc.address)
break
case ChainTypes.APTOS:
chainAccountAddresses =
accountsNonEvm?.aptosKeys.results.map((acc) => acc.account) ??
[]
break
case ChainTypes.SOLANA:
chainAccountAddresses =
accountsNonEvm?.solanaKeys.results.map((acc) => acc.id) ?? []
break
default:
chainAccountAddresses = []
}
if (values.chainType === ChainTypes.APTOS) {
chainAccountAddresses = accountsAptos.map((acc) => acc.account)
}

return (
<Form
data-testid="feeds-manager-form"
Expand All @@ -273,6 +282,9 @@ export const ChainConfigurationForm = withStyles(styles)(
<MenuItem key={ChainTypes.APTOS} value={ChainTypes.APTOS}>
APTOS
</MenuItem>
<MenuItem key={ChainTypes.SOLANA} value={ChainTypes.SOLANA}>
SOLANA
</MenuItem>
</Field>
</Grid>

Expand Down
24 changes: 0 additions & 24 deletions src/hooks/queries/useAptosAccountsQuery.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React from 'react'
import { render, screen, waitFor } from '@testing-library/react'
import { MockedProvider } from '@apollo/client/testing'
import {
useAptosAccountsQuery,
APTOS_KEYS_QUERY,
} from './useAptosAccountsQuery'
useNonEvmAccountsQuery,
NON_EVM_KEYS_QUERY,
} from './useNonEvmAccountsQuery'

const mockData = {
data: {
Expand All @@ -15,20 +15,24 @@ const mockData = {
{ __typename: 'AptosKey', account: 'account2', id: '2' },
],
},
solanaKeys: {
__typename: 'SolanaKeys',
results: [{ __typename: 'SolanaKey', id: '3' }],
},
},
}

const mocks = [
{
request: {
query: APTOS_KEYS_QUERY,
query: NON_EVM_KEYS_QUERY,
},
result: mockData,
},
]

const TestComponent: React.FC = () => {
const { data, loading, error } = useAptosAccountsQuery()
const { data, loading, error } = useNonEvmAccountsQuery()

if (loading) return <p>Loading... </p>
if (error) return <p>Error: {error.message}</p>
Expand All @@ -38,14 +42,20 @@ const TestComponent: React.FC = () => {
{data?.aptosKeys.results.map((key, i) => (
<div key={i}>
<p>Account: {key.account}</p>
<p>ID: {key.id}</p>
<p>Aptos ID: {key.id}</p>
</div>
))}

{data?.solanaKeys.results.map((key, i) => (
<div key={i}>
<p>Solana ID: {key.id}</p>
</div>
))}
</div>
)
}

describe('useAptosAccountsQuery', () => {
describe('useNonEvmAccountsQuery', () => {
test('renders data with correct graphql query', async () => {
render(
<MockedProvider mocks={mocks} addTypename={false}>
Expand All @@ -55,9 +65,11 @@ describe('useAptosAccountsQuery', () => {

await waitFor(() => {
expect(screen.getByText('Account: account1')).toBeInTheDocument()
expect(screen.getByText('ID: 1')).toBeInTheDocument()
expect(screen.getByText('Aptos ID: 1')).toBeInTheDocument()
expect(screen.getByText('Account: account2')).toBeInTheDocument()
expect(screen.getByText('ID: 2')).toBeInTheDocument()
expect(screen.getByText('Aptos ID: 2')).toBeInTheDocument()

expect(screen.getByText('Solana ID: 3')).toBeInTheDocument()
})
})
})
Loading
Loading