Skip to content

Commit 9877242

Browse files
canton-network-daDA Automation
andauthored
Update Splice from CCI (#140)
Signed-off-by: DA Automation <splice-maintainers@digitalasset.com> Co-authored-by: DA Automation <splice-maintainers@digitalasset.com>
1 parent 20723f9 commit 9877242

File tree

20 files changed

+475
-115
lines changed

20 files changed

+475
-115
lines changed

apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/SplitwellTestUtil.scala

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,21 @@ trait SplitwellTestUtil extends TestCommon with WalletTestUtil with TimeTestUtil
3939
topEndpoint.toURI(false).toString
4040
}
4141

42-
participant.domains.connect(splitwellUpgradeAlias, url)
43-
4442
// This can be a bit slow since it first pushes all vetting transactions before pushing
4543
// the PartyToParticipant transaction.
46-
eventually(40.seconds) {
47-
splitwellBackend
48-
.getConnectedDomains(ensurePartyIsOnNewDomain)
49-
.map(_.uid.identifier.str) should contain("splitwellUpgrade")
50-
}
44+
actAndCheck(
45+
timeUntilSuccess = 40.seconds
46+
)(
47+
"Connect splitwell upgrade domain",
48+
participant.domains.connect(splitwellUpgradeAlias, url),
49+
)(
50+
s"Wait for splitwell upgrade domain to be connected for party $ensurePartyIsOnNewDomain",
51+
_ => {
52+
splitwellBackend
53+
.getConnectedDomains(ensurePartyIsOnNewDomain)
54+
.map(_.uid.identifier.str) should contain("splitwellUpgrade")
55+
},
56+
)
5157
}
5258

5359
protected def disconnectSplitwellUpgradeDomain(participant: ParticipantClientReference) =

apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletManualRoundsIntegrationTest.scala

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,22 @@ class WalletManualRoundsIntegrationTest
171171

172172
advanceRoundsByOneTickViaAutomation()
173173

174-
lockAmulets(
175-
aliceValidatorBackend,
176-
aliceUserParty,
177-
aliceValidatorParty,
178-
aliceWalletClient.list().amulets,
179-
lockedQty,
180-
sv1ScanBackend,
181-
Duration.ofHours(60),
182-
CantonTimestamp.now(),
183-
)
174+
eventuallySucceeds() {
175+
// The lockAmulets function is not atomic, it first fetches round data from Scan, and then
176+
// uses it to submit ledger transactions directly to the participant. It therefore might fail
177+
// when rounds are advancing. We do the same thing we expect an app to do, which is simply retry
178+
// on such failures.
179+
lockAmulets(
180+
aliceValidatorBackend,
181+
aliceUserParty,
182+
aliceValidatorParty,
183+
aliceWalletClient.list().amulets,
184+
lockedQty,
185+
sv1ScanBackend,
186+
Duration.ofHours(60),
187+
CantonTimestamp.now(),
188+
)
189+
}
184190

185191
clue("Check balance after advancing round and locking amulets") {
186192
val feeCeiling = walletUsdToAmulet(1)

apps/common/frontend-test-handlers/src/mocks/handlers/dso-info-handler.ts

Lines changed: 238 additions & 1 deletion
Large diffs are not rendered by default.

apps/common/frontend/src/components/Header.tsx

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,43 +24,44 @@ const Header: React.FC<HeaderProps> = ({ children, title, titleVariant, navLinks
2424
};
2525

2626
return (
27-
<Toolbar
28-
sx={{
29-
borderBottom: noBorder ? 0 : 1,
30-
borderColor: 'divider',
31-
display: 'flex',
32-
justifyContent: 'space-between',
33-
alignItems: 'center',
34-
padding: { xs: 0, sm: 0, md: 0, lg: 0, xl: 0 },
35-
}}
36-
>
37-
<Typography
38-
id="app-title"
39-
textTransform="uppercase"
40-
variant={titleVariant || 'h5'}
41-
fontFamily={theme => theme.fonts.monospace.fontFamily}
42-
fontWeight={theme => theme.fonts.monospace.fontWeight}
27+
<>
28+
<Toolbar
29+
sx={{
30+
borderBottom: noBorder ? 0 : 1,
31+
borderColor: 'divider',
32+
display: 'flex',
33+
justifyContent: 'space-between',
34+
alignItems: 'center',
35+
padding: { xs: 0, sm: 0, md: 0, lg: 0, xl: 0 },
36+
}}
4337
>
44-
{title}
45-
</Typography>
38+
<Typography
39+
id="app-title"
40+
textTransform="uppercase"
41+
variant={titleVariant || 'h5'}
42+
fontFamily={theme => theme.fonts.monospace.fontFamily}
43+
fontWeight={theme => theme.fonts.monospace.fontWeight}
44+
>
45+
{title}
46+
</Typography>
4647

47-
{navLinks && (
48-
<Stack direction="row" spacing={4} alignItems="center">
49-
{navLinks.map((navLink, index) => (
50-
<NavLink
51-
key={index}
52-
id={`navlink-${navLink.path}`}
53-
to={navLink.path}
54-
style={p => applyNavStyle(p.isActive)}
55-
>
56-
{navLink.name}
57-
</NavLink>
58-
))}
59-
</Stack>
60-
)}
61-
62-
{children}
63-
</Toolbar>
48+
{navLinks && (
49+
<Stack direction="row" spacing={4} alignItems="center">
50+
{navLinks.map((navLink, index) => (
51+
<NavLink
52+
key={index}
53+
id={`navlink-${navLink.path}`}
54+
to={navLink.path}
55+
style={p => applyNavStyle(p.isActive)}
56+
>
57+
{navLink.name}
58+
</NavLink>
59+
))}
60+
</Stack>
61+
)}
62+
{children}
63+
</Toolbar>
64+
</>
6465
);
6566
};
6667

apps/common/frontend/src/theme/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,21 @@ declare module '@mui/material/styles' {
2626
colors: {
2727
neutral: Record<string, string>;
2828
primary: Record<string, string>;
29+
mainnet: string;
30+
testnet: string;
31+
devnet: string;
32+
scratchnet: string;
2933
};
3034
}
3135
// allow configuration using `createTheme`
3236
interface PaletteOptions {
3337
colors?: {
3438
neutral?: Record<string, string>;
3539
primary?: Record<string, string>;
40+
mainnet: string;
41+
testnet: string;
42+
devnet: string;
43+
scratchnet: string;
3644
};
3745
}
3846
}
@@ -67,6 +75,10 @@ let theme = createTheme({
6775
colors: {
6876
neutral: generateHslPalette(0, 0, [0, 10, 15, 25, 30, 40, 50, 60, 70, 80]),
6977
primary: generateHslPalette(195, 96, [79, 89]),
78+
mainnet: '#F8FDCD',
79+
testnet: '#C8F1FE',
80+
devnet: '#C6B2FF',
81+
scratchnet: '#FFFFFF',
7082
},
7183
},
7284
});

apps/common/src/main/scala/org/lfdecentralizedtrust/splice/environment/ParticipantAdminConnection.scala

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -306,14 +306,19 @@ class ParticipantAdminConnection(
306306
def uploadAcsSnapshot(acsBytes: ByteString)(implicit
307307
traceContext: TraceContext
308308
): Future[Unit] = {
309-
runCmd(
310-
ParticipantAdminCommands.ParticipantRepairManagement
311-
.ImportAcs(
312-
acsBytes,
313-
IMPORT_ACS_WORKFLOW_ID_PREFIX,
314-
allowContractIdSuffixRecomputation = false,
315-
)
316-
).map(_ => ())
309+
retryProvider.retryForClientCalls(
310+
"import_acs",
311+
"Imports the acs in the participantl",
312+
runCmd(
313+
ParticipantAdminCommands.ParticipantRepairManagement
314+
.ImportAcs(
315+
acsBytes,
316+
IMPORT_ACS_WORKFLOW_ID_PREFIX,
317+
allowContractIdSuffixRecomputation = false,
318+
)
319+
).map(_ => ()),
320+
logger,
321+
)
317322
}
318323

319324
def getParticipantId()(implicit traceContext: TraceContext): Future[ParticipantId] =

apps/sv/frontend/src/App.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22
// SPDX-License-Identifier: Apache-2.0
33
import * as React from 'react';
44
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5-
import { AuthProvider, ErrorBoundary, ErrorRouterPage, UserProvider, theme } from 'common-frontend';
5+
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
6+
import {
7+
AuthProvider,
8+
ErrorBoundary,
9+
ErrorRouterPage,
10+
UserProvider,
11+
theme,
12+
SvClientProvider,
13+
} from 'common-frontend';
614
import { replaceEqualDeep } from 'common-frontend-utils';
715
import { Helmet, HelmetProvider } from 'react-helmet-async';
816
import {
@@ -31,8 +39,8 @@ import { useConfigPollInterval, useSvConfig } from './utils';
3139
const Providers: React.FC<React.PropsWithChildren> = ({ children }) => {
3240
const config = useSvConfig();
3341
const refetchInterval = useConfigPollInterval();
34-
3542
const navigate = useNavigate();
43+
3644
const queryClient = new QueryClient({
3745
defaultOptions: {
3846
queries: {
@@ -46,15 +54,19 @@ const Providers: React.FC<React.PropsWithChildren> = ({ children }) => {
4654
warn: () => {},
4755
},
4856
});
57+
4958
return (
5059
<AuthProvider authConf={config.auth} redirect={(path: string) => navigate(path)}>
5160
<QueryClientProvider client={queryClient}>
61+
<ReactQueryDevtools initialIsOpen={false} />
5262
<UserProvider authConf={config.auth} testAuthConf={config.testAuth}>
53-
<SvAppVotesHooksProvider>
54-
<SvAdminClientProvider url={config.services.sv.url}>
55-
<LocalizationProvider dateAdapter={AdapterDayjs}>{children}</LocalizationProvider>
56-
</SvAdminClientProvider>
57-
</SvAppVotesHooksProvider>
63+
<SvClientProvider url={config.services.sv.url}>
64+
<SvAppVotesHooksProvider>
65+
<SvAdminClientProvider url={config.services.sv.url}>
66+
<LocalizationProvider dateAdapter={AdapterDayjs}>{children}</LocalizationProvider>
67+
</SvAdminClientProvider>
68+
</SvAppVotesHooksProvider>
69+
</SvClientProvider>
5870
</UserProvider>
5971
</QueryClientProvider>
6072
</AuthProvider>
@@ -84,6 +96,7 @@ const App: React.FC = () => {
8496
</Route>
8597
)
8698
);
99+
87100
return (
88101
<ErrorBoundary>
89102
<ThemeProvider theme={theme}>

apps/sv/frontend/src/__tests__/config-diffs.test.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ describe('SV can see config diffs of SRARC_SetConfig', () => {
145145
const user = userEvent.setup();
146146
render(<AppWithConfig />);
147147

148-
await goToGovernanceTabAndClickOnAction('Action Needed', action, user);
148+
await goToGovernanceTabAndClickOnAction('Action Needed', action, user, 1);
149149
const mockHtmlContent = getExpectedDsoRulesConfigDiffsHTML('1600', '2100');
150150
await checkDsoRulesExpectedConfigDiffsHTML(mockHtmlContent);
151151

@@ -157,7 +157,7 @@ describe('SV can see config diffs of SRARC_SetConfig', () => {
157157
const user = userEvent.setup();
158158
render(<AppWithConfig />);
159159

160-
await goToGovernanceTabAndClickOnAction('Executed', 'SRARC_SetConfig', user, 0);
160+
await goToGovernanceTabAndClickOnAction('Executed', action, user, 1);
161161

162162
const mockHtmlContent = getExpectedDsoRulesConfigDiffsHTML('1800', '2200');
163163

@@ -171,7 +171,7 @@ describe('SV can see config diffs of SRARC_SetConfig', () => {
171171
const user = userEvent.setup();
172172
render(<AppWithConfig />);
173173

174-
await goToGovernanceTabAndClickOnAction('Executed', 'SRARC_SetConfig', user, 1);
174+
await goToGovernanceTabAndClickOnAction('Executed', action, user, 2);
175175

176176
const mockJsonContent = getMockJsonContentForDsoRules('1800');
177177

@@ -184,7 +184,7 @@ describe('SV can see config diffs of SRARC_SetConfig', () => {
184184
const user = userEvent.setup();
185185
render(<AppWithConfig />);
186186

187-
await goToGovernanceTabAndClickOnAction('Rejected', action, user);
187+
await goToGovernanceTabAndClickOnAction('Rejected', action, user, 1);
188188

189189
const mockHtmlContent = getMockJsonContentForDsoRules('2000');
190190

@@ -218,7 +218,11 @@ async function goToGovernanceTabAndClickOnAction(
218218
await user.click(screen.getByText(tableType));
219219

220220
expect(await screen.findAllByText(action)).toBeDefined();
221-
await user.click(screen.getAllByText(action)[index]);
221+
222+
// eslint-disable-next-line testing-library/no-node-access
223+
const row = document.querySelector(`[data-id="${index}"]`);
224+
225+
await user.click(row!);
222226
}
223227

224228
function getMockJsonContentForDsoRules(acsCommitmentReconciliationInterval: string): string {

apps/sv/frontend/src/__tests__/sv.test.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ describe('SV user can', () => {
3232
expect(await screen.findAllByDisplayValue(svPartyId)).toBeDefined();
3333
});
3434

35+
test('can see the network name banner', async () => {
36+
userEvent.setup();
37+
render(<AppWithConfig />);
38+
39+
await screen.findByText('You are on ScratchNet');
40+
});
41+
3542
test('browse to the governance tab', async () => {
3643
const user = userEvent.setup();
3744
render(<AppWithConfig />);

apps/sv/frontend/src/components/Layout.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import * as React from 'react';
44
import { Header, useUserState } from 'common-frontend';
55

66
import { Logout } from '@mui/icons-material';
7-
import { Box, Button, Divider, Stack } from '@mui/material';
7+
import { Box, Button, Divider, Stack, Typography } from '@mui/material';
88
import Container from '@mui/material/Container';
99
import Link from '@mui/material/Link';
1010

11+
import { useNetworkInstanceName } from '../hooks/index';
1112
import { useSvConfig } from '../utils';
1213

1314
interface LayoutProps {
@@ -17,9 +18,30 @@ interface LayoutProps {
1718
const Layout: React.FC<LayoutProps> = (props: LayoutProps) => {
1819
const config = useSvConfig();
1920
const { logout } = useUserState();
21+
const networkInstanceName = useNetworkInstanceName();
22+
const networkInstanceNameColor = `colors.${networkInstanceName?.toLowerCase()}`;
2023

2124
return (
2225
<Box bgcolor="colors.neutral.20" display="flex" flexDirection="column" minHeight="100vh">
26+
{networkInstanceName === undefined ? (
27+
<></>
28+
) : (
29+
<Stack
30+
direction="row"
31+
alignItems="center"
32+
justifyContent="center"
33+
sx={{
34+
backgroundColor: `${networkInstanceNameColor}`,
35+
color: 'black',
36+
height: '50px',
37+
width: '100%',
38+
}}
39+
>
40+
<Typography id="network-instance-name" data-testid="network-instance-name" variant="h6">
41+
<b>You are on {networkInstanceName} </b>
42+
</Typography>
43+
</Stack>
44+
)}
2345
<Container maxWidth="xl">
2446
<Header
2547
title="Super Validator Operations"

0 commit comments

Comments
 (0)