-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Working WalletConnect integration with Umami: - listing dApps connected with WalletConnect - tezos_getAccounts returns the current account - tezos_sign signs payload with the current account - tezos_send supports all perations: - transaction signing - delegate / undelegate - origination, calling smart contract - stake, unstake, finalize - approve and reject by user - success and error from Tezos node Limitations: - the operation result is not shown to the user - pairings list doesn't work on remote disconnect - no tests - no documentation - several lint errors
- Loading branch information
1 parent
2273e92
commit 75b3263
Showing
41 changed files
with
16,806 additions
and
7,139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
apps/web/src/components/SendFlow/WalletConnect/PairingCard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
|
||
import { Button, Card, CardBody, Link, Text, Tooltip } from "@chakra-ui/react" | ||
import { truncate } from "@umami/tezos" | ||
|
||
import { CrossedCircleIcon } from "../../../assets/icons" | ||
|
||
/** | ||
* Types | ||
*/ | ||
interface IProps { | ||
name?: string | ||
url?: string | ||
topic?: string | ||
onDelete: () => Promise<void> | ||
} | ||
|
||
/** | ||
* Component | ||
*/ | ||
export default function PairingCard({ name, url, topic, onDelete }: IProps) { | ||
return ( | ||
<Card className="relative mb-6 min-h-[70px] border border-light"> | ||
<CardBody className="flex flex-row items-center justify-between overflow-hidden p-4"> | ||
<div className="flex-1"> | ||
<Text className="ml-9" data-testid={"pairing-text-" + topic}> | ||
{name} | ||
</Text> | ||
<Link className="ml-9" data-testid={"pairing-text-" + topic} href={url}> | ||
{truncate(url?.split("https://")[1] ?? "Unknown", 23)} | ||
</Link> | ||
</div> | ||
<Tooltip content="Delete" placement="left"> | ||
<Button className="min-w-auto text-error border-0 p-1 hover:bg-red-100 transition-all" | ||
data-testid={"pairing-delete-" + topic} | ||
onClick={onDelete} | ||
> | ||
<CrossedCircleIcon alt="delete icon" /> | ||
</Button> | ||
</Tooltip> | ||
</CardBody> | ||
</Card> | ||
) | ||
} |
49 changes: 49 additions & 0 deletions
49
apps/web/src/components/SendFlow/WalletConnect/pairings.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
|
||
import { Text } from "@chakra-ui/react" | ||
import { SettingsStore, web3wallet } from "@umami/state" | ||
import { type PairingTypes } from "@walletconnect/types" | ||
import { getSdkError } from "@walletconnect/utils" | ||
import { Fragment, useEffect } from "react" | ||
import { useSnapshot } from "valtio" | ||
|
||
import PairingCard from "./PairingCard" | ||
|
||
export default function PairingsPage() { | ||
const { pairings } = useSnapshot(SettingsStore.state) | ||
// const [walletPairings ] = useState(web3wallet.core.pairing.getPairings()) | ||
|
||
async function onDelete(topic: string) { | ||
await web3wallet.disconnectSession({ topic, reason: getSdkError("USER_DISCONNECTED") }) | ||
const newPairings = pairings.filter(pairing => pairing.topic !== topic) | ||
SettingsStore.setPairings(newPairings as PairingTypes.Struct[]) | ||
} | ||
|
||
useEffect(() => { | ||
SettingsStore.setPairings(web3wallet.core.pairing.getPairings()) | ||
}, []) | ||
|
||
// console.log("pairings", walletPairings) | ||
return ( | ||
<Fragment> | ||
{pairings.length ? ( | ||
pairings.map(pairing => { | ||
const { peerMetadata } = pairing | ||
|
||
return ( | ||
<PairingCard | ||
key={pairing.topic} | ||
data-testid={"pairing-" + pairing.topic} | ||
logo={peerMetadata?.icons[0]} | ||
name={peerMetadata?.name} | ||
onDelete={() => onDelete(pairing.topic)} | ||
topic={pairing.topic} | ||
url={peerMetadata?.url} | ||
/> | ||
) | ||
}) | ||
) : ( | ||
<Text css={{ opacity: "0.5", textAlign: "center", marginTop: "$20" }}>No pairings</Text> | ||
)} | ||
</Fragment> | ||
) | ||
} |
74 changes: 74 additions & 0 deletions
74
apps/web/src/components/SendFlow/WalletConnect/useSignWithWalletConnect.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { formatJsonRpcError, formatJsonRpcResult } from "@json-rpc-tools/utils"; | ||
import { type TezosToolkit } from "@taquito/taquito"; | ||
import { | ||
type Account, | ||
type ImplicitAccount, | ||
type SecretKeyAccount, | ||
estimate, | ||
executeOperations, | ||
toAccountOperations, | ||
} from "@umami/core"; | ||
import { | ||
TEZOS_SIGNING_METHODS, | ||
} from "@umami/state"; | ||
import { type Network } from "@umami/tezos"; | ||
import { type SignClientTypes } from "@walletconnect/types"; | ||
import { getSdkError } from "@walletconnect/utils"; | ||
|
||
export async function approveTezosRequest( | ||
requestEvent: SignClientTypes.EventArguments["session_request"], | ||
tezosToolkit: TezosToolkit, | ||
signer: Account, | ||
network: Network | ||
) { | ||
const { params, id } = requestEvent; | ||
const { request } = params; | ||
|
||
console.log("approveTezosRequest", request); | ||
|
||
switch (request.method) { | ||
case TEZOS_SIGNING_METHODS.TEZOS_GET_ACCOUNTS: { | ||
console.log("TEZOS_GET_ACCOUNTS"); | ||
return formatJsonRpcResult(id, [{ | ||
algo: (signer as SecretKeyAccount).curve, | ||
address: signer.address.pkh, | ||
pubkey: (signer as SecretKeyAccount).pk, | ||
}]); | ||
} | ||
|
||
case TEZOS_SIGNING_METHODS.TEZOS_SEND: { | ||
console.log("TEZOS_SEND"); | ||
try { | ||
const operation = toAccountOperations(request.params.operations, signer as ImplicitAccount); | ||
const estimatedOperations = await estimate(operation, network); | ||
console.log("TEZOS_SEND: executing operation", estimatedOperations); | ||
const { opHash } = await executeOperations(estimatedOperations, tezosToolkit); | ||
console.log("TEZOS_SEND: executed operation", request.params.method, operation, opHash); | ||
return formatJsonRpcResult(id, { hash: opHash }); | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
console.error("Tezos_send operation failed with error: ", error.message); | ||
return formatJsonRpcError(id, error.message); | ||
} else { | ||
console.error("Tezos_send operation failed with unknown error: ", error); | ||
return formatJsonRpcError(id, "TEZOS_SEND failed with unknown error."); | ||
} | ||
} | ||
} | ||
|
||
case TEZOS_SIGNING_METHODS.TEZOS_SIGN: { | ||
const result = await tezosToolkit.signer.sign(request.params.payload); | ||
console.log("TEZOS_SIGN", result.prefixSig); | ||
return formatJsonRpcResult(id, { signature: result.prefixSig }); | ||
} | ||
|
||
default: | ||
throw new Error(getSdkError("INVALID_METHOD").message); | ||
} | ||
} | ||
|
||
export function rejectTezosRequest(request: SignClientTypes.EventArguments["session_request"]) { | ||
const { id } = request; | ||
|
||
return formatJsonRpcError(id, getSdkError("USER_REJECTED_METHODS").message); | ||
} |
16 changes: 16 additions & 0 deletions
16
apps/web/src/components/WalletConnect/ChainAddressMini.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
interface Props { | ||
address?: string; | ||
} | ||
|
||
export default function ChainAddressMini({ address }: Props) { | ||
if (!address || address === "N/A") {return <></>;} | ||
return ( | ||
<> | ||
<div> | ||
<span style={{ marginLeft: "5px" }}> | ||
{address.substring(0, 6)}...{address.substring(address.length - 6)} | ||
</span> | ||
</div> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Card, CardBody } from "@chakra-ui/react"; | ||
import { type ReactNode } from "react"; | ||
|
||
interface Props { | ||
children: ReactNode | ReactNode[]; | ||
rgb: string; | ||
flexDirection: "row" | "col"; | ||
alignItems: "center" | "flex-start"; | ||
flexWrap?: "wrap" | "nowrap"; | ||
} | ||
|
||
export default function ChainCard({ rgb, children, flexDirection, alignItems, flexWrap }: Props) { | ||
return ( | ||
<Card | ||
className="mb-6 min-h-[70px] shadow-md rounded-lg border" | ||
style={{ | ||
borderColor: `rgba(${rgb}, 0.4)`, | ||
boxShadow: `0 0 10px 0 rgba(${rgb}, 0.15)`, | ||
backgroundColor: `rgba(${rgb}, 0.25)`, | ||
}} | ||
> | ||
<CardBody | ||
className={`flex justify-between overflow-hidden | ||
${flexWrap === "wrap" ? "flex-wrap" : "flex-nowrap"} | ||
${flexDirection === "row" ? "flex-row" : "flex-col"} | ||
${alignItems === "center" ? "items-center" : "items-start"} | ||
`} | ||
> | ||
{children} | ||
</CardBody> | ||
</Card> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { getChainData } from "@umami/state"; | ||
import { useMemo } from "react"; | ||
|
||
import { TezosLogoIcon } from "../../assets/icons"; | ||
|
||
interface Props { | ||
chainId?: string; // namespace + ":" + reference | ||
} | ||
|
||
export default function ChainDataMini({ chainId }: Props) { | ||
const chainData = useMemo(() => getChainData(chainId), [chainId]); | ||
|
||
if (!chainData) {return <></>;} | ||
return ( | ||
<> | ||
<div> | ||
<TezosLogoIcon size="sm" /> | ||
<span style={{ marginLeft: "5px" }}>{chainData.name}</span> | ||
</div> | ||
</> | ||
); | ||
} |
23 changes: 23 additions & 0 deletions
23
apps/web/src/components/WalletConnect/ChainSmartAddressMini.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Card } from "@chakra-ui/react"; | ||
|
||
import ChainAddressMini from "./ChainAddressMini"; | ||
|
||
type SmartAccount = { | ||
address: string; | ||
type: string; | ||
}; | ||
|
||
interface Props { | ||
account: SmartAccount; | ||
} | ||
|
||
export default function ChainSmartAddressMini({ account }: Props) { | ||
return ( | ||
<div> | ||
<div> | ||
<Card>({account.type})</Card> | ||
<ChainAddressMini address={account.address} /> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Card, Divider } from "@chakra-ui/react"; | ||
import { ModalStore } from "@umami/state"; | ||
import { useSnapshot } from "valtio"; | ||
|
||
import RequestModalContainer from "./RequestModalContainer"; | ||
|
||
|
||
export default function LoadingModal() { | ||
const state = useSnapshot(ModalStore.state); | ||
const message = state.data?.loadingMessage; | ||
|
||
return ( | ||
<RequestModalContainer title=""> | ||
<div style={{ textAlign: "center", padding: "20px" }}> | ||
<div> | ||
<div> | ||
<h3>Loading your request...</h3> | ||
</div> | ||
</div> | ||
{message ? ( | ||
<div style={{ textAlign: "center" }}> | ||
<Divider /> | ||
<Card>{message}</Card> | ||
</div> | ||
) : null} | ||
</div> | ||
</RequestModalContainer> | ||
); | ||
} |
Oops, something went wrong.