Skip to content

Commit 7503266

Browse files
authored
Merge pull request #107 from smartcontractkit/sish/sui-support
Sui support
2 parents 9e1a6a9 + c1ab7c9 commit 7503266

12 files changed

Lines changed: 313 additions & 9 deletions

File tree

.changeset/immutable-config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
22
'@smartcontractkit/operator-ui': patch
33
---
4+
45
Remove legacy config chain & node mutations.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@smartcontractkit/operator-ui': minor
3+
---
4+
5+
feat: Add sui

src/components/Form/ChainConfigurationForm.test.tsx

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ describe('ChainConfigurationForm', () => {
241241
tonKeys: {
242242
results: [],
243243
},
244+
suiKeys: {
245+
results: [],
246+
},
244247
})
245248

246249
const chainType = getByRole('button', { name: 'EVM' })
@@ -287,6 +290,131 @@ describe('ChainConfigurationForm', () => {
287290
})
288291
})
289292

293+
test('should able to create SUI chain config (with selection)', async () => {
294+
const handleSubmit = jest.fn()
295+
const initialValues = emptyFormValues()
296+
initialValues.chainType = ChainTypes.EVM
297+
initialValues.adminAddr = '0x1234567'
298+
299+
const { container } = renderChainConfigurationForm(
300+
initialValues,
301+
handleSubmit,
302+
)
303+
304+
const chainType = getByRole('button', { name: 'EVM' })
305+
userEvent.click(chainType)
306+
userEvent.click(getByRole('option', { name: 'SUI' }))
307+
await screen.findByRole('button', { name: 'SUI' })
308+
309+
await selectChainIdOnUI(container, '6666')
310+
311+
const address = container.querySelector('#select-accountAddr')
312+
expect(address).toBeInTheDocument()
313+
address && userEvent.click(address)
314+
userEvent.click(getByRole('option', { name: '0x123' }))
315+
await screen.findByRole('button', { name: '0x123' })
316+
317+
await userEvent.click(getByRole('button', { name: /submit/i }))
318+
319+
await waitFor(() => {
320+
expect(handleSubmit).toHaveBeenCalledWith({
321+
accountAddr: '0x123',
322+
accountAddrPubKey: '',
323+
adminAddr: '0x1234567',
324+
chainID: '6666',
325+
chainType: 'SUI',
326+
fluxMonitorEnabled: false,
327+
ocr1Enabled: false,
328+
ocr1IsBootstrap: false,
329+
ocr1KeyBundleID: '',
330+
ocr1Multiaddr: '',
331+
ocr1P2PPeerID: '',
332+
ocr2CommitPluginEnabled: false,
333+
ocr2Enabled: false,
334+
ocr2ExecutePluginEnabled: false,
335+
ocr2ForwarderAddress: '',
336+
ocr2IsBootstrap: false,
337+
ocr2KeyBundleID: '',
338+
ocr2MedianPluginEnabled: false,
339+
ocr2MercuryPluginEnabled: false,
340+
ocr2Multiaddr: '',
341+
ocr2P2PPeerID: '',
342+
ocr2RebalancerPluginEnabled: false,
343+
})
344+
expect(handleSubmit).toHaveBeenCalledTimes(1)
345+
})
346+
})
347+
348+
test('should able to create SUI chain config (with manual input)', async () => {
349+
const handleSubmit = jest.fn()
350+
const initialValues = emptyFormValues()
351+
initialValues.chainType = ChainTypes.EVM
352+
353+
renderChainConfigurationForm(initialValues, handleSubmit, [], {
354+
aptosKeys: {
355+
results: [],
356+
},
357+
solanaKeys: {
358+
results: [],
359+
},
360+
starknetKeys: {
361+
results: [],
362+
},
363+
tronKeys: {
364+
results: [],
365+
},
366+
tonKeys: {
367+
results: [],
368+
},
369+
suiKeys: {
370+
results: [],
371+
},
372+
})
373+
374+
const chainType = getByRole('button', { name: 'EVM' })
375+
userEvent.click(chainType)
376+
userEvent.click(getByRole('option', { name: 'SUI' }))
377+
await screen.findByRole('button', { name: 'SUI' })
378+
379+
const chainIdTextBox = getByRole('textbox', { name: /chain id \*/i })
380+
userEvent.type(chainIdTextBox, '6666')
381+
382+
const accountAddrTextBox = getByRole('textbox', {
383+
name: /account address \*/i,
384+
})
385+
userEvent.type(accountAddrTextBox, '0x123')
386+
387+
await userEvent.click(getByRole('button', { name: /submit/i }))
388+
389+
await waitFor(() => {
390+
expect(handleSubmit).toHaveBeenCalledWith({
391+
accountAddr: '0x123',
392+
accountAddrPubKey: '',
393+
adminAddr: '',
394+
chainID: '6666',
395+
chainType: 'SUI',
396+
fluxMonitorEnabled: false,
397+
ocr1Enabled: false,
398+
ocr1IsBootstrap: false,
399+
ocr1KeyBundleID: '',
400+
ocr1Multiaddr: '',
401+
ocr1P2PPeerID: '',
402+
ocr2CommitPluginEnabled: false,
403+
ocr2Enabled: false,
404+
ocr2ExecutePluginEnabled: false,
405+
ocr2ForwarderAddress: '',
406+
ocr2IsBootstrap: false,
407+
ocr2KeyBundleID: '',
408+
ocr2MedianPluginEnabled: false,
409+
ocr2MercuryPluginEnabled: false,
410+
ocr2Multiaddr: '',
411+
ocr2P2PPeerID: '',
412+
ocr2RebalancerPluginEnabled: false,
413+
})
414+
expect(handleSubmit).toHaveBeenCalledTimes(1)
415+
})
416+
})
417+
290418
test('should able to create Solana chain config', async () => {
291419
const handleSubmit = jest.fn()
292420
const initialValues = emptyFormValues()
@@ -478,6 +606,9 @@ test('should be able to select OCR2 Job Type with Key Bundle ID', async () => {
478606
tonKeys: {
479607
results: [],
480608
},
609+
suiKeys: {
610+
results: [],
611+
},
481612
},
482613
)
483614

@@ -548,6 +679,11 @@ function renderChainConfigurationForm(
548679
enabled: true,
549680
network: 'ton',
550681
},
682+
{
683+
id: '6666',
684+
enabled: true,
685+
network: 'sui',
686+
},
551687
],
552688
accountsNonEvm: FetchNonEvmKeys | undefined = {
553689
aptosKeys: {
@@ -565,6 +701,9 @@ function renderChainConfigurationForm(
565701
tonKeys: {
566702
results: [{ addressBase64: '123', rawAddress: '0:456', id: 'ton_xxxx' }],
567703
},
704+
suiKeys: {
705+
results: [{ account: '0x123', id: '6666' }],
706+
},
568707
},
569708
) {
570709
return render(

src/components/Form/ChainConfigurationForm.tsx

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,46 @@ const AccountAddrField = ({
196196
))}
197197
</Field>
198198

199+
<Field
200+
component={TextField}
201+
id="accountAddrPubKey"
202+
name="accountAddrPubKey"
203+
label="Account Address Public Key"
204+
required
205+
fullWidth
206+
helperText="The public key for your account address"
207+
FormHelperTextProps={{
208+
'data-testid': 'accountAddrPubKey-helper-text',
209+
}}
210+
select
211+
value={accountAddrPubKey}
212+
onChange={handleSelectChange('accountAddrPubKey')}
213+
>
214+
{pubkeys.map((pubkey) => (
215+
<MenuItem key={pubkey} value={pubkey}>
216+
{pubkey}
217+
</MenuItem>
218+
))}
219+
</Field>
220+
</>
221+
)
222+
case 'SUI':
223+
// Show two select fields for Sui - one for the account address, and another one for the public key
224+
return (
225+
<>
226+
<Field
227+
{...props}
228+
select
229+
value={isCustom ? 'custom' : accountAddr}
230+
onChange={handleSelectChange(props.name)}
231+
>
232+
{addresses.map((address) => (
233+
<MenuItem key={address} value={address}>
234+
{address}
235+
</MenuItem>
236+
))}
237+
</Field>
238+
199239
<Field
200240
component={TextField}
201241
id="accountAddrPubKey"
@@ -312,7 +352,15 @@ export const ChainConfigurationForm = withStyles(styles)(
312352
break
313353
case ChainTypes.TON:
314354
chainAccountAddresses =
315-
accountsNonEvm?.tonKeys.results.map((acc) => acc.addressBase64) ?? []
355+
accountsNonEvm?.tonKeys.results.map(
356+
(acc) => acc.addressBase64,
357+
) ?? []
358+
break
359+
case ChainTypes.SUI:
360+
chainAccountAddresses =
361+
accountsNonEvm?.suiKeys.results.map((acc) => acc.account) ?? []
362+
chainPublicKeys =
363+
accountsNonEvm?.suiKeys.results.map((acc) => acc.id) ?? []
316364
break
317365
default:
318366
chainAccountAddresses = []
@@ -355,6 +403,9 @@ export const ChainConfigurationForm = withStyles(styles)(
355403
<MenuItem key={ChainTypes.TON} value={ChainTypes.TON}>
356404
TON
357405
</MenuItem>
406+
<MenuItem key={ChainTypes.SUI} value={ChainTypes.SUI}>
407+
SUI
408+
</MenuItem>
358409
</Field>
359410
</Grid>
360411

src/components/Form/ChainTypes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export const ChainTypes = {
66
COSMOS: 'COSMOS',
77
TRON: 'TRON',
88
TON: 'TON',
9+
SUI: 'SUI',
910
}

src/hooks/queries/useNonEvmAccountsQuery.test.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ const mockData = {
2727
__typename: 'TONKeys',
2828
results: [{ __typename: 'TONKey', id: '5' }],
2929
},
30+
suiKeys: {
31+
__typename: 'SuiKeys',
32+
results: [
33+
{ __typename: 'SuiKey', account: 'account6', id: '6' },
34+
{ __typename: 'SuiKey', account: 'account7', id: '7' },
35+
],
36+
},
3037
},
3138
}
3239

@@ -71,6 +78,13 @@ const TestComponent: React.FC = () => {
7178
<p>TON ID: {key.id}</p>
7279
</div>
7380
))}
81+
82+
{data?.suiKeys.results.map((key, i) => (
83+
<div key={i}>
84+
<p>Account: {key.account}</p>
85+
<p>Sui ID: {key.id}</p>
86+
</div>
87+
))}
7488
</div>
7589
)
7690
}
@@ -92,6 +106,11 @@ describe('useNonEvmAccountsQuery', () => {
92106
expect(screen.getByText('Solana ID: 3')).toBeInTheDocument()
93107
expect(screen.getByText('Tron ID: 4')).toBeInTheDocument()
94108
expect(screen.getByText('TON ID: 5')).toBeInTheDocument()
109+
110+
expect(screen.getByText('Account: account6')).toBeInTheDocument()
111+
expect(screen.getByText('Sui ID: 6')).toBeInTheDocument()
112+
expect(screen.getByText('Account: account7')).toBeInTheDocument()
113+
expect(screen.getByText('Sui ID: 7')).toBeInTheDocument()
95114
})
96115
})
97116
})

src/hooks/queries/useNonEvmAccountsQuery.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,20 @@ export const TON_KEYS_PAYLOAD__RESULTS_FIELDS = gql`
3333
}
3434
`
3535

36+
export const SUI_KEYS_PAYLOAD__RESULTS_FIELDS = gql`
37+
fragment SuiKeysPayload_ResultsFields on SuiKey {
38+
account
39+
id
40+
}
41+
`
42+
3643
export const NON_EVM_KEYS_QUERY = gql`
3744
${APTOS_KEYS_PAYLOAD__RESULTS_FIELDS}
3845
${SOLANA_KEYS_PAYLOAD__RESULTS_FIELDS}
3946
${STARKNET_KEYS_PAYLOAD__RESULTS_FIELDS}
4047
${TRON_KEYS_PAYLOAD__RESULTS_FIELDS}
4148
${TON_KEYS_PAYLOAD__RESULTS_FIELDS}
49+
${SUI_KEYS_PAYLOAD__RESULTS_FIELDS}
4250
query FetchNonEvmKeys {
4351
aptosKeys {
4452
results {
@@ -65,6 +73,11 @@ export const NON_EVM_KEYS_QUERY = gql`
6573
...TONKeysPayload_ResultsFields
6674
}
6775
}
76+
suiKeys {
77+
results {
78+
...SuiKeysPayload_ResultsFields
79+
}
80+
}
6881
}
6982
`
7083

src/index.css

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ body {
1111
overflow-y: auto !important;
1212
}
1313

14-
#task-list-graph-d3-graph-wrapper .task-run-icon-pending:hover{
15-
filter:drop-shadow(0px 0px 2px gray);
14+
#task-list-graph-d3-graph-wrapper .task-run-icon-pending:hover {
15+
filter: drop-shadow(0px 0px 2px gray);
1616
}
17-
#task-list-graph-d3-graph-wrapper .task-run-icon-success:hover{
18-
filter:drop-shadow(0px 0px 2px green);
17+
#task-list-graph-d3-graph-wrapper .task-run-icon-success:hover {
18+
filter: drop-shadow(0px 0px 2px green);
19+
}
20+
#task-list-graph-d3-graph-wrapper .task-run-icon-error:hover {
21+
filter: drop-shadow(0px 0px 2px red);
1922
}
20-
#task-list-graph-d3-graph-wrapper .task-run-icon-error:hover{
21-
filter:drop-shadow(0px 0px 2px red);
22-
}

src/screens/FeedsManager/SupportedChainsCard.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,12 @@ export const SupportedChainsCard = withStyles(styles)(
523523
<DetailsCardItemValue value={cfg.accountAddrPubKey} />
524524
</Grid>
525525
)}
526+
{cfg.chainType === 'SUI' && (
527+
<Grid item xs={12} sm={6}>
528+
<DetailsCardItemTitle title="Account Public Key" />
529+
<DetailsCardItemValue value={cfg.accountAddrPubKey} />
530+
</Grid>
531+
)}
526532
<Grid item xs={12} sm={6}>
527533
<DetailsCardItemTitle title="Admin Address" />
528534
<DetailsCardItemValue value={cfg.adminAddr} />

0 commit comments

Comments
 (0)