Skip to content

Commit

Permalink
send tx #5285
Browse files Browse the repository at this point in the history
  • Loading branch information
2nthony committed Feb 13, 2025
1 parent 108aa3a commit ca57322
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 26 deletions.
45 changes: 20 additions & 25 deletions packages/next-common/context/walletconnect/index.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// polkadot-cloud/polkadot-staking-dashboard/packages/app/src/contexts/WalletConnect/index.tsx
// https://github.com/polkadot-cloud/polkadot-staking-dashboard/blob/main/packages/app/src/contexts/WalletConnect/index.tsx

import { WalletConnectModal } from "@walletconnect/modal";
import UniversalProvider from "@walletconnect/universal-provider";
Expand All @@ -7,13 +7,14 @@ import dayjs from "dayjs";
import useChainInfo from "next-common/hooks/connect/useChainInfo";
import { createContext, useContext, useEffect, useRef, useState } from "react";
import { useChain } from "../chain";
import { normalizedSubstrateAccounts } from "next-common/utils/substrate";
import WalletTypes from "next-common/utils/consts/walletTypes";
import { useConnectedAccountContext } from "../connectedAccount";

// FIXME: use company project id
// `projectId` is configured on `https://cloud.walletconnect.com/`
const projectId = "16c4de5fd6fec3e0f3b6bdf2a67f2160";

const relayUrl = "wss://relay.walletconnect.com";

export const defaultWalletConnect = {
connectProvider: () => Promise.resolve(),
wcInitialized: false,
Expand All @@ -31,29 +32,24 @@ export function useWalletConnect() {
return useContext(WalletConnectContext);
}

export function useWalletConnectAccounts() {
const { fetchAddresses } = useWalletConnect();
const [accounts, setAccounts] = useState([]);
function useWalletConnectCaip() {
const chainInfo = useChainInfo();

useEffect(() => {
fetchAddresses().then((addresses) => {
setAccounts(
normalizedSubstrateAccounts(
addresses.map((address) => {
return { address };
}),
WalletTypes.WALLETCONNECT,
),
);
});
}, [fetchAddresses]);
return chainInfo
? chainInfo?.genesisHash.substring(2).substring(0, 32)
: null;
}

function useWalletConnectChainId() {
const caip = useWalletConnectCaip();
const chain = useChain();

return accounts;
return caip ? `${chain}:${caip}` : null;
}

export default function WalletConnectProvider({ children }) {
const chain = useChain();
const chainInfo = useChainInfo();
const { disconnect: disconnectAccount } = useConnectedAccountContext();

// The WalletConnect provider
const wcProvider = useRef(null);
Expand All @@ -76,17 +72,15 @@ export default function WalletConnectProvider({ children }) {
// Store the set of chain id the most recent session is connected to
const sessionChain = useRef();

const caip = chainInfo
? chainInfo?.genesisHash.substring(2).substring(0, 32)
: null;
const caip = useWalletConnectCaip();

const chainId = caip ? `${chain}:${caip}` : null;
const chainId = useWalletConnectChainId();

// Init WalletConnect provider & modal, and update as wcInitialized
async function initProvider() {
const provider = await UniversalProvider.init({
projectId,
relayUrl: "wss://relay.walletconnect.com",
relayUrl,
});

const modal = new WalletConnectModal({
Expand All @@ -98,6 +92,7 @@ export default function WalletConnectProvider({ children }) {
// Subscribe to session delete
wcProvider.current.on("session_delete", () => {
disconnectWcSession();
disconnectAccount();
});

wcModal.current = modal;
Expand Down
30 changes: 29 additions & 1 deletion packages/next-common/hooks/useSendTransaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import { useSignetSdk } from "next-common/context/signet";
import { isEmptyFunc } from "next-common/utils/isEmptyFunc";
import isHydradx from "next-common/utils/isHydradx";
import { HydradxAssets } from "next-common/utils/hydradx";
import { useWalletConnect } from "next-common/context/walletconnect";
import { sendWalletConnectTx } from "next-common/utils/sendTransaction/sendWalletConnectTx";
import { useWalletConnectBuildPayload } from "next-common/hooks/useWalletConnectBuildPayload";

function shouldSendEvmTx(signerAccount) {
const isWalletMetamask = signerAccount?.meta?.source === WalletTypes.METAMASK;
Expand All @@ -48,6 +51,10 @@ function shouldSendMimirTx(signerAccount) {
return signerAccount?.meta?.source === WalletTypes.MIMIR;
}

function shouldSendWalletConnectTx(signerAccount) {
return signerAccount?.meta?.source === WalletTypes.WALLETCONNECT;
}

async function shouldSendHydraDXMultiFeeTx(api, signerAccount) {
// Multi fee tx support on HydraDX chain only
if (!isHydradx()) {
Expand Down Expand Up @@ -78,6 +85,9 @@ export function useSendTransaction() {
const signerAccount = useSignerAccount();
const { sdk: signetSdk } = useSignetSdk();

const { signWcTx } = useWalletConnect();
const buildPayload = useWalletConnectBuildPayload();

const sendTxFunc = useCallback(
async ({
api,
Expand Down Expand Up @@ -211,6 +221,23 @@ export function useSendTransaction() {
return;
}

if (shouldSendWalletConnectTx(signerAccount)) {
await sendWalletConnectTx({
api,
tx,
signerAddress: signerAccount?.address,
buildPayload,
signWcTx,
onStarted,
onInBlock: _onInBlock,
onSubmitted: _onSubmitted,
onFinalized: _onFinalized,
onError,
});

return;
}

await sendSubstrateTx({
api,
tx,
Expand All @@ -223,10 +250,11 @@ export function useSendTransaction() {
});
} catch (e) {
dispatch(newErrorToast(e.message));
} finally {
setIsSubmitting(false);
}
},
[dispatch, signerAccount, signetSdk],
[buildPayload, dispatch, signWcTx, signerAccount, signetSdk],
);

return {
Expand Down
54 changes: 54 additions & 0 deletions packages/next-common/hooks/useWalletConnectBuildPayload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useSignerAccount } from "next-common/components/popupWithSigner/context";
import { useContextApi } from "next-common/context/api";
import { useSubAccount } from "./account/useSubAccount";
import { useCallback } from "react";

/**
* @file https://github.com/polkadot-cloud/polkadot-developer-console/blob/main/packages/app/src/hooks/useBuildPayload/index.tsx
* @link https://docs.reown.com/advanced/multichain/polkadot/dapp-integration-guide#example-namespace-and-sign-client-connect-call
*/
export function useWalletConnectBuildPayload() {
const api = useContextApi();
const signerAccount = useSignerAccount();
const from = signerAccount?.address;

const { data } = useSubAccount(from);

const nonceRaw = data?.account?.nonce?.toNumber() || 0;

return useCallback(
async (tx) => {
const lastHeader = await api.rpc.chain.getHeader();
const blockNumber = api.registry.createType(
"BlockNumber",
lastHeader.number.toNumber(),
);
const method = api.createType("Call", tx);
const era = api.registry.createType("ExtrinsicEra", {
current: lastHeader.number.toNumber(),
period: 64,
});

const nonce = api.registry.createType("Compact<Index>", nonceRaw);

const payload = {
specVersion: api.runtimeVersion.specVersion.toHex(),
transactionVersion: api.runtimeVersion.transactionVersion.toHex(),
runtimeVersion: api.runtimeVersion,
version: tx.version,
address: from,
blockHash: lastHeader.hash.toHex(),
blockNumber: blockNumber.toHex(),
era: era.toHex(),
genesisHash: api.genesisHash.toHex(),
method: method.toHex(),
nonce: nonce.toHex(),
signedExtensions: api.registry.signedExtensions,
tip: api.registry.createType("Compact<Balance>", 0).toHex(),
};

return payload;
},
[api, nonceRaw, from],
);
}
42 changes: 42 additions & 0 deletions packages/next-common/utils/sendTransaction/sendWalletConnectTx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { noop } from "lodash-es";
import { createSendTxEventHandler } from "./sendSubstrateTx";

export async function sendWalletConnectTx({
api,
tx,
signerAddress,
buildPayload = noop,
signWcTx = noop,
onStarted = noop,
onInBlock = noop,
onSubmitted = noop,
onFinalized = noop,
onError = noop,
}) {
onStarted();

try {
const payload = await buildPayload(tx);
const { signature } = await signWcTx(payload);
const rawPayload = api.registry.createType("ExtrinsicPayload", payload, {
version: payload.version,
});

tx.addSignature(signerAddress, signature, rawPayload);

const unsub = await tx.send(
createSendTxEventHandler({
onFinalized,
onInBlock,
onError,
unsub: () => unsub(),
}),
);

onSubmitted();
} catch (error) {
onError(error);
}

return true;
}

0 comments on commit ca57322

Please sign in to comment.