Skip to content

Commit

Permalink
Merge branch 'main' of github.com:ChainSafe/Multix into tbaut-archive…
Browse files Browse the repository at this point in the history
…_unstable_body
  • Loading branch information
Tbaut committed Dec 19, 2024
2 parents 2c9c92b + 23f6741 commit e6e901c
Show file tree
Hide file tree
Showing 36 changed files with 714 additions and 1,252 deletions.
2 changes: 1 addition & 1 deletion packages/ui/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,5 @@
}
}
],
"ignorePatterns": ["src/interfaces/**/*", "types-and-hooks.tsx", "build"]
"ignorePatterns": ["src/interfaces/**/*", "types-and-hooks.tsx", "build", "src/gql"]
}
2 changes: 1 addition & 1 deletion packages/ui/cypress/tests/address-bar.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ describe('Account address in the address bar', () => {
cy.url({ timeout: 3000 }).should('include', address)

// react-router takes some time to get the search params inside the links
cy.wait(500)
cy.wait(1000)

topMenuItems.homeButton().click()
cy.url().should('include', address)
Expand Down
90 changes: 90 additions & 0 deletions packages/ui/cypress/tests/default-multisigs.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { accountDisplay } from '../support/page-objects/components/accountDisplay'
import { landingPageNetwork } from '../fixtures/landingData'
import { topMenuItems } from '../support/page-objects/topMenuItems'
import { multisigPage } from '../support/page-objects/multisigPage'

const lolmcshizPubKey = '0x8aee4e164d5d70ac67308f303c7e063e9156903e42c1087bbc530447487fa47f'
const polkadotSelectedMultiproxy = '13EyMuuDHwtq5RD6w3psCJ9WvJFZzDDion6Fd2FVAqxz1g7K' // CD OpenGov

const kusamaSelectedMultiproxy = 'J7UBNJqKHkRi3NkxMV6Y43cMk1ZjEJWzq4z4XmqmNCcFTfM'

describe('default Multisigs', () => {
it('can switch to a new multiproxy and remember it', () => {
cy.setupAndVisit({
url: landingPageNetwork('polkadot'),
watchedAccounts: [lolmcshizPubKey]
})

multisigPage.accountHeader().within(() => {
accountDisplay
.addressLabel()
.invoke('text')
.as('defaultPolkadotAddress')
.should('not.contain', polkadotSelectedMultiproxy.slice(0, 6))
})

cy.log('@defaultPolkadotAddress', cy.get('@defaultPolkadotAddress'))

// select another one
topMenuItems.desktopMenu().within(() =>
topMenuItems
.multiproxySelectorDesktop()
.wait(1000)
.click()
.type(`${polkadotSelectedMultiproxy.slice(0, 6)}{downArrow}{enter}`)
)

// verify that it's displayed
multisigPage.accountHeader().within(() => {
accountDisplay.addressLabel().should('contain.text', polkadotSelectedMultiproxy.slice(0, 6))
})

// go on Kusama and do the same
// check the default multiproxy
cy.visit(landingPageNetwork('kusama'))

multisigPage.accountHeader().within(() => {
accountDisplay
.addressLabel()
.invoke('text')
.as('defaultKusamaAddress')
.should('not.contain', kusamaSelectedMultiproxy.slice(0, 6))
})

cy.log('@defaultKusamaAddress', cy.get('@defaultKusamaAddress'))

// select another one
topMenuItems.desktopMenu().within(() =>
topMenuItems
.multiproxySelectorDesktop()
.wait(1000)
.click()
.type(`${kusamaSelectedMultiproxy.slice(0, 6)}{downArrow}{enter}`)
)

// verify that it's displayed
multisigPage.accountHeader().within(() => {
accountDisplay.addressLabel().should('contain.text', kusamaSelectedMultiproxy.slice(0, 6))
})

// go back on Polkadot and verify the last used one is selected
cy.visit(landingPageNetwork('polkadot'))

// verify that it's displayed
multisigPage.accountHeader().within(() => {
accountDisplay.addressLabel().should('contain.text', polkadotSelectedMultiproxy.slice(0, 6))
})

cy.url().should('include', polkadotSelectedMultiproxy)

// go back on Kusama and verify the last used one is selected
cy.visit(landingPageNetwork('kusama'))

// verify that it's displayed
multisigPage.accountHeader().within(() => {
accountDisplay.addressLabel().should('contain.text', kusamaSelectedMultiproxy.slice(0, 6))
})

cy.url().should('include', kusamaSelectedMultiproxy)
})
})
3 changes: 2 additions & 1 deletion packages/ui/cypress/tests/multisig-creation.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ describe('Multisig creation', () => {
// Step 2
newMultisigPage.step2.thresholdInput().type('2')
newMultisigPage.step2.nameInput().type(multisigName)
newMultisigPage.step2.checkboxUsePureProxy().click()
newMultisigPage.step2.checkboxUsePureProxy().should('be.checked')
newMultisigPage.nextButton().should('contain', 'Next').click()

// Step 3
Expand Down Expand Up @@ -133,7 +135,6 @@ describe('Multisig creation', () => {
// Step 2
newMultisigPage.step2.thresholdInput().type('3')
newMultisigPage.step2.nameInput().type(multisigName)
newMultisigPage.step2.checkboxUsePureProxy().click()
newMultisigPage.step2.checkboxUsePureProxy().should('not.be.checked')
newMultisigPage.nextButton().should('contain', 'Next').click()

Expand Down
8 changes: 4 additions & 4 deletions packages/ui/cypress/tests/watched-accounts.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,13 @@ describe('Watched Accounts', () => {
it('can see all multisigs that a watched signatory is a member of', () => {
const { publicKey: signatoryPublicKey } = testAccounts['Multisig Member Account 1']
const expectedAddresses = [
{
address: knownMultisigs['multisig-with-pure'].pureAddress,
expectedBadge: 'pure'
},
{
address: knownMultisigs['test-simple-multisig-1'].address,
expectedBadge: 'multi'
},
{
address: knownMultisigs['multisig-with-pure'].pureAddress,
expectedBadge: 'pure'
}
]

Expand Down
2 changes: 1 addition & 1 deletion packages/ui/graphql.config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"overwrite": true,
"schema": "https://chainsafe.squids.live/multix-arrow/v/v4/graphql",
"schema": "https://chainsafe.squids.live/multix-arrow/v/v5/graphql",
"documents": "src/**/*.graphql",
"generates": {
"src/gql/": {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@polkadot/react-identicon": "^3.11.3",
"@polkadot/util-crypto": "^13.2.3",
"@reactive-dot/core": "^0.27.1",
"@reactive-dot/react": "^0.27.1",
"@reactive-dot/react": "^0.28.0",
"@tanstack/react-query": "^5.62.2",
"@walletconnect/web3wallet": "^1.16.1",
"dayjs": "^1.11.13",
Expand Down
88 changes: 63 additions & 25 deletions packages/ui/src/components/CallInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface CreateTreeParams {
chainInfo?: ChainInfoHuman
}

const isWhiteListedCall = (type: string, value: string) => {
const isWhiteListedCall = (extrinsicName: string) => {
return [
'Balances.transfer',
'Balances.transfer_keep_alive',
Expand All @@ -57,12 +57,18 @@ const isWhiteListedCall = (type: string, value: string) => {
'ConvictionVoting.vote',
'ConvictionVoting.remove_vote',
'ConvictionVoting.undelegate',
'ConvictionVoting.unlock'
].includes(`${type}.${value}`)
'ConvictionVoting.unlock',
// Hydration
'Tokens.transfer'
].includes(extrinsicName)
}

const isBatchedCall = (type: string, value: string) => {
return ['Utility.batch', 'Utility.batch_all', 'Utility.force_batch'].includes(`${type}.${value}`)
const isPreventBalanceFormat = (extrinsicName: string) => {
return ['Tokens.transfer'].includes(extrinsicName)
}

const isBatchedCall = (extrinsicName: string) => {
return ['Utility.batch', 'Utility.batch_all', 'Utility.force_batch'].includes(extrinsicName)
}

const formatBalance = (amount: bigint, label: string, chainInfo: ChainInfoHuman, id: string) => (
Expand All @@ -74,11 +80,23 @@ const formatBalance = (amount: bigint, label: string, chainInfo: ChainInfoHuman,
</li>
)

const eachFieldRendered = (value: Record<string, any>, chainInfo: ChainInfoHuman, id: string) => {
interface EachFieldRenderedParams {
value: Record<string, any>
chainInfo: ChainInfoHuman
id: string
preventBalanceFormating?: boolean
}
const eachFieldRendered = ({
value,
chainInfo,
id,
preventBalanceFormating = false
}: EachFieldRenderedParams) => {
// for transfer, nomination, staking, bounties
const bigIntKey = ['value', 'fee', 'max_additional', 'balance'].find(
(key) => typeof value[key] === 'bigint'
)
// We should make sure this is not done for hydration
const bigIntKey =
!preventBalanceFormating &&
['value', 'fee', 'max_additional', 'balance'].find((key) => typeof value[key] === 'bigint')

if (bigIntKey) {
return formatBalance(value[bigIntKey], bigIntKey, chainInfo, id)
Expand Down Expand Up @@ -148,38 +166,53 @@ const eachFieldRendered = (value: Record<string, any>, chainInfo: ChainInfoHuman
return <li key={`not-pretty-decoded-${id}`}>{JSONprint(value)} </li>
}

const preparedCall = (
decodedCall: CreateTreeParams['decodedCall'],
chainInfo: ChainInfoHuman,
isBatch = false
) => {
interface PreparedCallParams {
decodedCall: CreateTreeParams['decodedCall']
chainInfo: ChainInfoHuman
isBatch?: boolean
isFirstCall?: boolean
}
const preparedCall = ({
decodedCall,
chainInfo,
isBatch = false,
isFirstCall = false
}: PreparedCallParams) => {
if (!decodedCall) return

if (isBatchedCall(decodedCall.type, decodedCall.value.type)) {
const extrinsicName = getExtrinsicName(decodedCall.type, decodedCall.value.type)
const preventBalanceFormating = isPreventBalanceFormat(extrinsicName)

if (isBatchedCall(extrinsicName)) {
const lowerLevelCalls = decodedCall.value.value.calls as Array<Record<string, any>>

return lowerLevelCalls.map((call, index) => {
return (
<BatchCallStyled key={`${call.type}-${index}`}>
{preparedCall(call as CreateTreeParams['decodedCall'], chainInfo, true)}
{preparedCall({
decodedCall: call as CreateTreeParams['decodedCall'],
chainInfo,
isBatch: true
})}
</BatchCallStyled>
)
})
}

if (isWhiteListedCall(decodedCall.type, decodedCall.value.type)) {
if (isWhiteListedCall(extrinsicName)) {
const lowerLevelCall = decodedCall.value.value
if (typeof lowerLevelCall === 'object') {
return (
<>
{isBatch && (
<ExtrinsicNameStyled>
{getExtrinsicName(decodedCall.type, decodedCall.value.type)}
</ExtrinsicNameStyled>
)}
{isBatch && <ExtrinsicNameStyled>{extrinsicName}</ExtrinsicNameStyled>}
<ul>
{Object.entries(lowerLevelCall).map(([key, value], index) =>
eachFieldRendered({ [key]: value }, chainInfo, `${decodedCall.type}-${index}`)
eachFieldRendered({
value: { [key]: value },
chainInfo,
id: `${decodedCall.type}-${index}`,
preventBalanceFormating
})
)}
</ul>
</>
Expand All @@ -189,6 +222,10 @@ const preparedCall = (
}
}

if (isFirstCall) {
return <PreStyled>{JSONprint(decodedCall.value.value)}</PreStyled>
}

return <PreStyled>{JSONprint(decodedCall)}</PreStyled>
}

Expand All @@ -197,7 +234,7 @@ const createUlTree = ({ name, decodedCall, chainInfo }: CreateTreeParams) => {
if (!name) return
if (!chainInfo) return

return preparedCall(decodedCall, chainInfo)
return preparedCall({ decodedCall, chainInfo, isFirstCall: true })
}

const filterProxyProxy = (agg: Props['aggregatedData']): Props['aggregatedData'] => {
Expand Down Expand Up @@ -237,7 +274,7 @@ const CallInfo = ({
() => aggregatedData.callData && getDecodeUrl(aggregatedData.callData),
[aggregatedData, getDecodeUrl]
)
const hasArgs = useMemo(() => decodedCall && Object.keys(decodedCall).length > 0, [decodedCall])
const hasArgs = useMemo(() => decodedCall && decodedCall?.value?.value, [decodedCall])

return (
<div
Expand Down Expand Up @@ -299,6 +336,7 @@ const LinkStyled = styled(Link)`
`

const PreStyled = styled('pre')`
margin-top: 0;
overflow: auto;
`

Expand Down
Loading

0 comments on commit e6e901c

Please sign in to comment.