-
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.
feat: WalletConnect integration, part 6, request
requests are supported. Tested: - send tez - delegate / undelegate - originate / call contract - stake / unstake / finalize unstake
- Loading branch information
1 parent
5d7d5c7
commit 17d9d12
Showing
6 changed files
with
192 additions
and
10 deletions.
There are no files selected for viewing
53 changes: 53 additions & 0 deletions
53
apps/web/src/components/SendFlow/WalletConnect/useSignWithWc.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,53 @@ | ||
import { type TezosToolkit } from "@taquito/taquito"; | ||
import { useDynamicModalContext } from "@umami/components"; | ||
import { executeOperations, totalFee } from "@umami/core"; | ||
import { useAsyncActionHandler, walletKit } from "@umami/state"; | ||
import { formatJsonRpcResult } from "@walletconnect/jsonrpc-utils"; | ||
import { useForm } from "react-hook-form"; | ||
|
||
import { SuccessStep } from "../SuccessStep"; | ||
import { type CalculatedSignProps, type SdkSignPageProps } from "../utils"; | ||
|
||
export const useSignWithWalletConnect = ({ | ||
operation, | ||
headerProps, | ||
requestId, | ||
}: SdkSignPageProps): CalculatedSignProps => { | ||
const { isLoading: isSigning, handleAsyncAction } = useAsyncActionHandler(); | ||
const { openWith } = useDynamicModalContext(); | ||
|
||
const form = useForm({ defaultValues: { executeParams: operation.estimates } }); | ||
|
||
if (requestId.sdkType !== "walletconnect") { | ||
return { | ||
fee: 0, | ||
isSigning: false, | ||
onSign: async () => {}, | ||
network: null, | ||
}; | ||
} | ||
|
||
const onSign = async (tezosToolkit: TezosToolkit) => | ||
handleAsyncAction( | ||
async () => { | ||
const { opHash } = await executeOperations( | ||
{ ...operation, estimates: form.watch("executeParams") }, | ||
tezosToolkit | ||
); | ||
|
||
const response = formatJsonRpcResult(requestId.id, { hash: opHash }); | ||
await walletKit.respondSessionRequest({ topic: requestId.topic, response }); | ||
return openWith(<SuccessStep hash={opHash} />); | ||
}, | ||
error => ({ | ||
description: `Failed to confirm Beacon operation: ${error.message}`, | ||
}) | ||
); | ||
|
||
return { | ||
fee: totalFee(form.watch("executeParams")), | ||
isSigning, | ||
onSign, | ||
network: headerProps.network, | ||
}; | ||
}; |
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
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
122 changes: 122 additions & 0 deletions
122
apps/web/src/components/WalletConnect/useHandleWcRequest.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,122 @@ | ||
import { useToast } from "@chakra-ui/react"; | ||
import { useDynamicModalContext } from "@umami/components"; | ||
import { type ImplicitAccount, estimate, toAccountOperations } from "@umami/core"; | ||
import { | ||
useAsyncActionHandler, | ||
useFindNetwork, | ||
useGetOwnedAccountSafe, | ||
walletKit, | ||
} from "@umami/state"; | ||
import { formatJsonRpcError } from "@walletconnect/jsonrpc-utils"; | ||
import { type SessionTypes, type SignClientTypes, type Verify } from "@walletconnect/types"; | ||
import { getSdkError } from "@walletconnect/utils"; | ||
|
||
import { BatchSignPage } from "../SendFlow/common/BatchSignPage"; | ||
import { SingleSignPage } from "../SendFlow/common/SingleSignPage"; | ||
import { type SdkSignPageProps, type SignHeaderProps } from "../SendFlow/utils"; | ||
|
||
/** | ||
* @returns a function that handles a beacon message and opens a modal with the appropriate content | ||
* | ||
* For operation requests it will also try to convert the operation(s) to our {@link Operation} format, | ||
* estimate the fee and open the BeaconSignPage only if it succeeds | ||
*/ | ||
export const useHandleWcRequest = () => { | ||
const { openWith } = useDynamicModalContext(); | ||
const { handleAsyncActionUnsafe } = useAsyncActionHandler(); | ||
const getAccount = useGetOwnedAccountSafe(); | ||
const findNetwork = useFindNetwork(); | ||
const toast = useToast(); | ||
|
||
return async ( | ||
event: { | ||
verifyContext: Verify.Context; | ||
} & SignClientTypes.BaseEventArgs<{ | ||
request: { | ||
method: string; | ||
params: any; | ||
expiryTimestamp?: number; | ||
}; | ||
chainId: string; | ||
}>, | ||
session: SessionTypes.Struct | ||
) => { | ||
await handleAsyncActionUnsafe( | ||
async () => { | ||
const { id, topic, params } = event; | ||
const { request, chainId } = params; | ||
|
||
let modal; | ||
let onClose; | ||
|
||
switch (request.method) { | ||
case "tezos_getAccounts": { | ||
const response = formatJsonRpcError(id, getSdkError("INVALID_METHOD").message); | ||
await walletKit.respondSessionRequest({ topic, response }); | ||
return; | ||
} | ||
|
||
case "tezos_sign": { | ||
// onClose = async () => { | ||
// const response = formatJsonRpcError(id, getSdkError("USER_REJECTED").message); | ||
// await walletKit.respondSessionRequest({ topic, response }); | ||
// }; | ||
// return openWith(<SignPayloadRequestModal request={"FIXME"} />, { onClose }); | ||
const response = formatJsonRpcError(id, getSdkError("INVALID_METHOD").message); | ||
await walletKit.respondSessionRequest({ topic, response }); | ||
return; | ||
} | ||
|
||
case "tezos_send": { | ||
if (!request.params.account) { | ||
throw new Error("Missing account in request"); | ||
} | ||
const signer = getAccount(request.params.account); | ||
if (!signer) { | ||
throw new Error(`Unknown account, no signer: ${request.params.account}`); | ||
} | ||
const operation = toAccountOperations( | ||
request.params.operations, | ||
signer as ImplicitAccount | ||
); | ||
const network = findNetwork(chainId.split(":")[1]); | ||
if (!network) { | ||
const response = formatJsonRpcError(id, getSdkError("INVALID_EVENT").message); | ||
await walletKit.respondSessionRequest({ topic, response }); | ||
toast({ description: `Unsupported network: ${chainId}`, status: "error" }); | ||
return; | ||
} | ||
const estimatedOperations = await estimate(operation, network); | ||
const headerProps: SignHeaderProps = { | ||
network, | ||
appName: session.peer.metadata.name, | ||
appIcon: session.peer.metadata.icons[0], | ||
}; | ||
const signProps: SdkSignPageProps = { | ||
headerProps: headerProps, | ||
operation: estimatedOperations, | ||
requestId: { sdkType: "walletconnect", id: id, topic }, | ||
}; | ||
|
||
if (operation.operations.length === 1) { | ||
modal = <SingleSignPage {...signProps} />; | ||
} else { | ||
modal = <BatchSignPage {...signProps} {...event.params.request.params} />; | ||
} | ||
onClose = async () => { | ||
const response = formatJsonRpcError(id, getSdkError("USER_REJECTED").message); | ||
await walletKit.respondSessionRequest({ topic, response }); | ||
}; | ||
|
||
return openWith(modal, { onClose }); | ||
} | ||
default: | ||
throw new Error(`Unsupported method ${request.method}`); | ||
} | ||
} | ||
// error => ({ | ||
// description: `Error while processing WalletConnect request: ${error.message}`, | ||
// }) | ||
); | ||
}; | ||
}; |