-
Notifications
You must be signed in to change notification settings - Fork 0
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
[Import Multisig] Added import multisig data logic #35
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,18 @@ | ||
import isPropValid from "@emotion/is-prop-valid"; | ||
import styled from "@emotion/styled"; | ||
import { Stack, StackProps } from "@mui/material"; | ||
|
||
export const StyledStack = styled(Stack)< | ||
StackProps & { logoSize?: { width: number; height: number } } | ||
>(({ logoSize }) => ({ | ||
display: "flex", | ||
flexDirection: "row", | ||
alignItems: "center", | ||
gap: ".25rem", | ||
"& img": { | ||
width: logoSize?.width ?? "auto", | ||
height: logoSize?.height ?? "auto", | ||
}, | ||
})); | ||
export const StyledStack = styled(Stack, { | ||
shouldForwardProp: (prop) => isPropValid(prop) && prop !== "logoSize", | ||
})<StackProps & { logoSize?: { width: number; height: number } }>( | ||
({ logoSize }) => ({ | ||
display: "flex", | ||
flexDirection: "row", | ||
alignItems: "center", | ||
gap: ".25rem", | ||
"& img": { | ||
width: logoSize?.width ?? "auto", | ||
height: logoSize?.height ?? "auto", | ||
}, | ||
}) | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,10 @@ | ||
import { Box, Link, TextField, Typography } from "@mui/material"; | ||
import { | ||
Box, | ||
CircularProgress, | ||
Link, | ||
TextField, | ||
Typography, | ||
} from "@mui/material"; | ||
import { useEffect, useState } from "react"; | ||
import { ArrayOneOrMore } from "useink/dist/core"; | ||
|
||
|
@@ -15,6 +21,7 @@ function WalletImportStep({ | |
handleOwners, | ||
handleThreshold, | ||
errors, | ||
setErrors, | ||
step, | ||
walletName, | ||
address, | ||
|
@@ -26,11 +33,15 @@ function WalletImportStep({ | |
handleThreshold: (threshold: number) => void; | ||
handleAddress: (address: string, step: number, field?: number) => void; | ||
errors: Array<ValidationError[]>; | ||
setErrors: React.Dispatch<React.SetStateAction<ValidationError[][]>>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
step: number; | ||
address: string; | ||
}) { | ||
const { network } = usePolkadotContext(); | ||
const { data, error, isLoading } = useFetchSignersAccount({ address }); | ||
const { data, error, isLoading } = useFetchSignersAccount({ | ||
address, | ||
walletName, | ||
}); | ||
const [tempAddress, setTempAddress] = useState(address); | ||
const { logo, name: networkName } = getChain(network); | ||
|
||
|
@@ -42,6 +53,20 @@ function WalletImportStep({ | |
[tempAddress] | ||
); | ||
|
||
useEffect(() => { | ||
if (!isLoading && address) { | ||
if (error || !data) { | ||
setErrors((prev: Array<Array<ValidationError>>) => { | ||
const newErrors = [...prev]; | ||
newErrors[step][0] = { | ||
error: true, | ||
message: "Multisig not found.", | ||
}; | ||
return newErrors; | ||
}); | ||
} | ||
} | ||
}, [error, isLoading, data, address, setErrors, step]); | ||
useEffect(() => { | ||
handleAddress(address, step); | ||
}, []); | ||
|
@@ -75,6 +100,9 @@ function WalletImportStep({ | |
margin="normal" | ||
error={errors[step][0]?.error} | ||
helperText={errors[step][0]?.message} | ||
InputProps={{ | ||
endAdornment: isLoading && <CircularProgress size={20} />, | ||
}} | ||
/> | ||
<TextField | ||
label="Name" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this logic focuses on getting the owners given an xsignerAccount, a name like And in case you imagine it will have more than one hook, its own |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,59 @@ | ||
import { useEffect, useState } from "react"; | ||
import { useQuery } from "@apollo/client"; | ||
import gql from "graphql-tag"; | ||
import { ArrayOneOrMore } from "useink/dist/core"; | ||
|
||
import { usePolkadotContext } from "@/context/usePolkadotContext"; | ||
import { SignatoriesAccount } from "@/domain/SignatoriesAccount"; | ||
import { Owner } from "@/domain/SignatoriesAccount"; | ||
import { customReportError } from "@/utils/error"; | ||
|
||
interface Props { | ||
address: string; | ||
walletName: string; | ||
} | ||
|
||
export function useFetchSignersAccount({ address }: Props) { | ||
const [data, setData] = useState<SignatoriesAccount | undefined>(undefined); | ||
const { accountConnected } = usePolkadotContext(); | ||
const [isLoading, setIsLoading] = useState(false); | ||
const [error, setError] = useState<string | null>(null); | ||
|
||
useEffect(() => { | ||
if (!address) return; | ||
|
||
const fetchData = async () => { | ||
setIsLoading(true); | ||
setError(null); | ||
try { | ||
// mock fake promise - This will be replaced once we have the API | ||
const result = await new Promise<SignatoriesAccount>((resolve) => { | ||
setTimeout(() => { | ||
resolve({ | ||
address, | ||
name: "My-imported-wallet", | ||
threshold: 1, | ||
owners: [ | ||
{ | ||
address: accountConnected?.address ?? "", | ||
name: "Signer 1", | ||
}, | ||
], | ||
} as SignatoriesAccount); | ||
}, 1000); | ||
}); | ||
setData(result); | ||
} catch (err) { | ||
const errorFormated = customReportError(err); | ||
setError(errorFormated); | ||
} finally { | ||
setIsLoading(false); | ||
} | ||
}; | ||
interface MultisigData { | ||
id: string; | ||
addressHex: string; | ||
addressSS58: string; | ||
owners: string[]; | ||
threshold: number; | ||
} | ||
|
||
interface MyQueryResponse { | ||
multisigs: MultisigData[]; | ||
} | ||
|
||
fetchData(); | ||
}, [accountConnected?.address, address]); | ||
const FETCH_MULTISIG = gql` | ||
query MyQuery($address: String!) { | ||
multisigs(where: { addressSS58_eq: $address }) { | ||
owners | ||
threshold | ||
addressSS58 | ||
addressHex | ||
} | ||
} | ||
`; | ||
|
||
export function useFetchSignersAccount({ address, walletName }: Props) { | ||
const { loading, error, data } = useQuery<MyQueryResponse>(FETCH_MULTISIG, { | ||
variables: { address }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would to keep the third parties logic on a repository pattern like the others cases (Index DB, LocalStorage). Something like that: class XsignerOwnersRepository implements IXsignerOwnersRepository {
constructor(private client: ApolloClient<MyQueryResponse, MyQueryVariables>) {}
async getMultisigByAddress(address: string): Promise<MultisigData | null> {
const { data } = await this.client.query<MyQueryResponse, MyQueryVariables>({
query: FETCH_MULTISIG,
variables: { address },
});
return data?.multisigs[0] || null;
}
} And then use it in this hook. |
||
skip: !address, | ||
}); | ||
|
||
const formattedData = data?.multisigs[0] | ||
? { | ||
address: data.multisigs[0].addressSS58, | ||
name: walletName, | ||
threshold: data.multisigs[0].threshold, | ||
owners: data.multisigs[0].owners.map((address, index) => ({ | ||
address, | ||
name: `Signer ${index + 1}`, | ||
})) as ArrayOneOrMore<Owner>, | ||
} | ||
: undefined; | ||
|
||
return { data, isLoading, error }; | ||
return { | ||
data: formattedData, | ||
isLoading: loading, | ||
error: error ? customReportError(error) : null, | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is definitely the way to go, however when there are several properties it becomes very tedious. But for one or 2 properties let's go this way and lastly try with
ownerState
or lowercase 😅