Skip to content

Commit

Permalink
feat: WalletConnect
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 committed Dec 3, 2024
1 parent b7b71c6 commit 183aae3
Show file tree
Hide file tree
Showing 13 changed files with 2,712 additions and 320 deletions.
2,836 changes: 2,518 additions & 318 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"@fontsource/noto-sans": "^5.1.0",
"@ledgerhq/hw-app-eth": "6.38.2",
"@ledgerhq/hw-transport-webhid": "^6.29.4",
"@reown/appkit": "^1.5.3",
"@reown/appkit-adapter-ethers": "^1.5.3",
"@scure/base": "^1.2.1",
"@solid-primitives/i18n": "^2.1.1",
"@solid-primitives/storage": "^4.2.1",
Expand Down
File renamed without changes
File renamed without changes
1 change: 1 addition & 0 deletions src/assets/wallet-connect.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/components/ConnectWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import "../style/web3.scss";
import { formatError } from "../utils/errors";
import { cropString, isMobile } from "../utils/helper";
import HardwareDerivationPaths, { connect } from "./HardwareDerivationPaths";
import { WalletConnect } from "./WalletConnect";

const Modal = (props: {
derivationPath: string;
Expand Down Expand Up @@ -213,6 +214,7 @@ export const ConnectAddress = (props: {
);
}
}}>
<WalletConnect />
{t("connect_to_address")}
</button>
);
Expand Down Expand Up @@ -276,6 +278,7 @@ const ConnectWallet = (props: {
{t("no_wallet")}
</button>
}>
<WalletConnect />
<Show
when={address() !== undefined}
fallback={
Expand Down
93 changes: 93 additions & 0 deletions src/components/WalletConnect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { createAppKit } from "@reown/appkit";
import { EthersAdapter } from "@reown/appkit-adapter-ethers";
import { BrowserProvider } from "ethers";
import log from "loglevel";
import { createEffect, createMemo } from "solid-js";

import { config } from "../config";
import { RBTC } from "../consts/Assets";
import { useWeb3Signer } from "../context/Web3";
import WalletConnectProvider from "../utils/WalletConnectProvider";

// 1. Get projectId
const projectId = "ba2fd40da144b7017436e42851ec62ae";

// 3. Create a metadata object - optional
const metadata = {
name: "Boltz Testnet",
description: "AppKit Example",
url: "https://webapp-mainnet-git-wallet-connect-boltz.vercel.app/", // origin must match your domain & subdomain
icons: [
"https://raw.githubusercontent.com/BoltzExchange/logo/refs/heads/master/boltz-logo_circle_1024x1024.png",
],
};

export const WalletConnect = () => {
const { openWalletConnectModal, setOpenWalletConnectModal } =
useWeb3Signer();

const appKit = createMemo(() => {
const configRsk = config.assets[RBTC];

return createAppKit({
adapters: [new EthersAdapter()],
networks: [
{
id: configRsk.network.chainId,
name: configRsk.network.chainName,
nativeCurrency: {
name: RBTC,
symbol: RBTC,
decimals: 18,
},
rpcUrls: {
default: {
http: configRsk.network.rpcUrls,
},
},
blockExplorers: {
default: {
name: "Explorer",
url: configRsk.blockExplorerUrl.normal,
},
},
},
],
metadata,
projectId,
themeMode: "dark",
debug: true,
enableEIP6963: false,
enableInjected: false,
features: {
email: false,
socials: false,
analytics: true,
},
});
});

appKit().subscribeEvents(async (ev) => {

Check warning on line 70 in src/components/WalletConnect.tsx

View workflow job for this annotation

GitHub Actions / ci

The reactive variable 'appKit' should be used within JSX, a tracked scope (like createEffect), or inside an event handler function, or else changes will be ignored

Check warning on line 70 in src/components/WalletConnect.tsx

View workflow job for this annotation

GitHub Actions / ci

This function should be passed to a tracked scope (like createEffect) or an event handler because it contains reactivity, or else changes will be ignored
log.debug(`WalletConnect event: ${ev.data.event}`);

if (ev.data.event !== "MODAL_CLOSE") {
setOpenWalletConnectModal(false);
return;
}

const address = appKit().getAddress();
const provider = new BrowserProvider(
await appKit().getUniversalProvider(),
);

WalletConnectProvider.resolveClosePromise(provider, address);
});

createEffect(() => {
if (openWalletConnectModal()) {
appKit().open().then();

Check failure on line 88 in src/components/WalletConnect.tsx

View workflow job for this annotation

GitHub Actions / ci

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
}
});

return <></>;
};
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type Asset = {
};
network?: {
chainName: string;
chainId: number;
rpcUrls: string[];
nativeCurrency: {
name: string;
Expand Down
1 change: 1 addition & 0 deletions src/configs/beta.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"network": {
"chainName": "Rootstock",
"chainId": 30,
"rpcUrls": ["https://public-node.rsk.co"],
"nativeCurrency": {
"name": "RBTC",
Expand Down
1 change: 1 addition & 0 deletions src/configs/mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
},
"network": {
"chainName": "Rootstock",
"chainId": 30,
"rpcUrls": ["https://public-node.rsk.co"],
"nativeCurrency": {
"name": "RBTC",
Expand Down
1 change: 1 addition & 0 deletions src/configs/testnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"network": {
"chainName": "Rootstock Testnet",
"chainId": 31,
"rpcUrls": ["https://public-node.testnet.rsk.co"],
"nativeCurrency": {
"name": "RBTC",
Expand Down
27 changes: 25 additions & 2 deletions src/context/Web3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,26 @@ import {
Accessor,
JSXElement,
Resource,
Setter,
createContext,
createResource,
createSignal,
onMount,
useContext,
} from "solid-js";

import LedgerIcon from "../assets/ledger.svg";
import TrezorIcon from "../assets/trezor.svg";
import WalletConnectIcon from "../assets/wallet-connect.svg";
import { config } from "../config";
import { RBTC } from "../consts/Assets";
import { EIP1193Provider, EIP6963ProviderDetail } from "../consts/Types";
import WalletConnectProvider from "../utils/WalletConnectProvider";
import { Contracts, getContracts } from "../utils/boltzClient";
import { HardwareSigner } from "../utils/hardware/HadwareSigner";
import LedgerSigner from "../utils/hardware/LedgerSigner";
import TrezorSigner from "../utils/hardware/TrezorSigner";
import { useGlobalContext } from "./Global";
import LedgerIcon from "/ledger.svg";
import TrezorIcon from "/trezor.svg";

declare global {
interface WindowEventMap {
Expand Down Expand Up @@ -57,6 +60,7 @@ enum HardwareRdns {
}

const browserRdns = "browser";
const walletConnectRdns = "wallet-connect";

const customDerivationPathRdns: string[] = [
HardwareRdns.Ledger,
Expand All @@ -80,6 +84,9 @@ const Web3SignerContext = createContext<{

getContracts: Resource<Contracts>;
getEtherSwap: () => EtherSwap;

openWalletConnectModal: Accessor<boolean>;
setOpenWalletConnectModal: Setter<boolean>;
}>();

const Web3SignerProvider = (props: {
Expand Down Expand Up @@ -114,13 +121,27 @@ const Web3SignerProvider = (props: {
rdns: HardwareRdns.Trezor,
},
},
[walletConnectRdns]: {
provider: new WalletConnectProvider(),
info: {
name: "WalletConnect",
uuid: "wallet-connect",
icon: WalletConnectIcon,
isHardware: false,
rdns: walletConnectRdns,
},
},
});
const [signer, setSigner] = createSignal<Signer | undefined>(undefined);
const [rawProvider, setRawProvider] = createSignal<
EIP1193Provider | undefined
>(undefined);
const [hasBrowserWallet, setHasBrowserWallet] =
createSignal<boolean>(false);
const [openWalletConnectModal, setOpenWalletConnectModal] =
createSignal<boolean>(false);

WalletConnectProvider.setOpenModal(setOpenWalletConnectModal);

onMount(() => {
if (window.ethereum !== undefined) {
Expand Down Expand Up @@ -278,6 +299,8 @@ const Web3SignerProvider = (props: {
switchNetwork,
connectProvider,
hasBrowserWallet,
openWalletConnectModal,
setOpenWalletConnectModal,
connectProviderForAddress,
getContracts: contracts,
clearSigner: () => {
Expand Down
66 changes: 66 additions & 0 deletions src/utils/WalletConnectProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { BrowserProvider } from "ethers";
import { Setter } from "solid-js";

import { EIP1193Provider } from "../consts/Types";

class WalletConnectProvider implements EIP1193Provider {
private static provider: BrowserProvider;
private static openModal: Setter<boolean>;
private static closePromiseResolver: {
resolve: (addresses: string[]) => void;
reject: (reason?: any) => void;

Check failure on line 11 in src/utils/WalletConnectProvider.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type
};

constructor() {}

public static setOpenModal = (openModal: Setter<boolean>) => {
WalletConnectProvider.openModal = openModal;
};

public static resolveClosePromise = (
provider: BrowserProvider,
address: string,
) => {
if (WalletConnectProvider.closePromiseResolver === undefined) {
return;
}
if (address === undefined) {
WalletConnectProvider.closePromiseResolver.reject(
"No wallet connected",
);
} else {
WalletConnectProvider.provider = provider;
WalletConnectProvider.closePromiseResolver.resolve([address]);
}

WalletConnectProvider.closePromiseResolver = undefined;
};

public request = async (request: {
method: string;
params?: Array<unknown>;
}) => {
switch (request.method) {
case "eth_requestAccounts": {
WalletConnectProvider.openModal(true);
return new Promise<string[]>((resolve, reject) => {
WalletConnectProvider.closePromiseResolver = {
resolve,
reject,
};
});
}
}

return (await WalletConnectProvider.provider.send(
request.method,
request.params,
)) as never;
};

public on = () => {};

public removeAllListeners = () => {};
}

export default WalletConnectProvider;

0 comments on commit 183aae3

Please sign in to comment.