mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-15 19:30:38 +08:00
Add WalletConnect support
Co-authored-by: Njoku Emmanuel <kalunjoku123@gmail.com> Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
co-authored by
Njoku Emmanuel
parent
767355b782
commit
400a2df0a4
+140
-36
@@ -1,9 +1,13 @@
|
||||
import { writable } from "svelte/store";
|
||||
import type { Writable } from "svelte/store";
|
||||
import { ethers } from "ethers";
|
||||
import type { TypedDataSigner } from '@ethersproject/abstract-signer';
|
||||
import SafeServiceClient from "@gnosis.pm/safe-service-client";
|
||||
import CeramicClient from "@ceramicnetwork/http-client";
|
||||
import { IDX } from "@ceramicstudio/idx";
|
||||
import WalletConnect from "@walletconnect/client";
|
||||
import config from "@app/config.json";
|
||||
import { WalletConnectSigner } from "./WalletConnectSigner";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -12,6 +16,15 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gas limits for various transactions.
|
||||
const gasLimits = {
|
||||
createOrg: 1_200_000,
|
||||
};
|
||||
|
||||
export type WalletConnectState =
|
||||
{ state: "close" }
|
||||
| { state: "open"; uri: string; onClose: any };
|
||||
|
||||
export class Config {
|
||||
network: { name: string; chainId: number };
|
||||
registrar: { address: string; domain: string };
|
||||
@@ -21,7 +34,14 @@ export class Config {
|
||||
orgs: { subgraph: string; contractHash: string };
|
||||
gasLimits: { createOrg: number };
|
||||
provider: ethers.providers.JsonRpcProvider;
|
||||
signer: ethers.Signer & TypedDataSigner | null;
|
||||
signer: ethers.Signer & TypedDataSigner | WalletConnectSigner | null;
|
||||
walletConnect: {
|
||||
client: WalletConnect;
|
||||
bridge: string;
|
||||
signer: WalletConnectSigner;
|
||||
state: Writable<WalletConnectState>;
|
||||
};
|
||||
metamaskSigner: ethers.Signer & TypedDataSigner | null;
|
||||
safe: {
|
||||
api?: string;
|
||||
client?: SafeServiceClient;
|
||||
@@ -36,29 +56,31 @@ export class Config {
|
||||
|
||||
constructor(
|
||||
network: { name: string; chainId: number },
|
||||
provider: ethers.providers.JsonRpcProvider | null,
|
||||
signer: ethers.Signer & TypedDataSigner | null,
|
||||
provider: ethers.providers.JsonRpcProvider,
|
||||
metamaskSigner: ethers.Signer & TypedDataSigner | null,
|
||||
) {
|
||||
const cfg = (<Record<string, any>> config)[network.name];
|
||||
const api = config.radicle.api;
|
||||
|
||||
if (! cfg) {
|
||||
throw `Network ${network.name} is not supported`;
|
||||
}
|
||||
|
||||
// Use Alchemy in production, on mainnet.
|
||||
provider = network.name === "homestead" && import.meta.env.PROD
|
||||
? new ethers.providers.AlchemyProvider(network.name, config.alchemy.key)
|
||||
: provider;
|
||||
|
||||
if (! provider) {
|
||||
throw `No Web3 provider available.`;
|
||||
}
|
||||
|
||||
const cfg = (<Record<string, any>> config)[network.name];
|
||||
const ceramic = new CeramicClient(config.ceramic.api);
|
||||
const idx = new IDX({ ceramic });
|
||||
|
||||
const walletConnectState = writable<WalletConnectState>(
|
||||
{ state: "close" }
|
||||
);
|
||||
const wc = Config.initializeWalletConnect(
|
||||
config.walletConnect.bridge,
|
||||
walletConnectState,
|
||||
provider
|
||||
);
|
||||
|
||||
this.network = network;
|
||||
this.metamaskSigner = metamaskSigner;
|
||||
this.walletConnect = {
|
||||
bridge: config.walletConnect.bridge,
|
||||
client: wc.connector,
|
||||
signer: wc.signer,
|
||||
state: walletConnectState,
|
||||
};
|
||||
this.seed = { api };
|
||||
this.registrar = cfg.registrar;
|
||||
this.radToken = cfg.radToken;
|
||||
@@ -70,7 +92,7 @@ export class Config {
|
||||
? new SafeServiceClient(this.safe.api)
|
||||
: undefined;
|
||||
this.provider = provider;
|
||||
this.signer = signer;
|
||||
this.signer = null;
|
||||
this.gasLimits = gasLimits;
|
||||
this.abi = config.abi;
|
||||
this.idx = { client: idx };
|
||||
@@ -83,6 +105,10 @@ export class Config {
|
||||
);
|
||||
}
|
||||
|
||||
setSigner(signer: ethers.Signer & TypedDataSigner | WalletConnectSigner): void {
|
||||
this.signer = signer;
|
||||
}
|
||||
|
||||
// Return the config with an overwritten seed URL.
|
||||
withSeed(seed: string): Config {
|
||||
const cfg = {} as Config;
|
||||
@@ -91,31 +117,109 @@ export class Config {
|
||||
|
||||
return cfg;
|
||||
}
|
||||
}
|
||||
|
||||
/// Gas limits for various transactions.
|
||||
const gasLimits = {
|
||||
createOrg: 1_200_000,
|
||||
};
|
||||
getWalletConnectSigner(): WalletConnectSigner {
|
||||
if (this.walletConnect.client.connected) {
|
||||
this.setSigner(this.walletConnect.signer);
|
||||
return this.walletConnect.signer;
|
||||
}
|
||||
const wc = Config.initializeWalletConnect(
|
||||
this.walletConnect.bridge,
|
||||
this.walletConnect.state,
|
||||
this.provider
|
||||
);
|
||||
this.walletConnect.client = wc.connector;
|
||||
this.walletConnect.signer = wc.signer;
|
||||
this.setSigner(wc.signer);
|
||||
|
||||
return wc.signer;
|
||||
}
|
||||
|
||||
static initializeWalletConnect(
|
||||
bridge: string,
|
||||
state: Writable<WalletConnectState>,
|
||||
provider: ethers.providers.JsonRpcProvider
|
||||
): {
|
||||
connector: WalletConnect;
|
||||
signer: WalletConnectSigner;
|
||||
} {
|
||||
const walletConnect = new WalletConnect({
|
||||
bridge: config.walletConnect.bridge,
|
||||
qrcodeModal: {
|
||||
open: (uri: string, onClose) => {
|
||||
state.set({ state: "open", uri, onClose });
|
||||
},
|
||||
close: () => {
|
||||
state.set({ state: "close" });
|
||||
}
|
||||
},
|
||||
clientMeta: {
|
||||
name: "Radicle",
|
||||
description: "Radicle Interface",
|
||||
url: window.location.host,
|
||||
icons: [
|
||||
`${window.location.protocol}//${window.location.host}/favicon.ico`,
|
||||
`${window.location.protocol}//${window.location.host}/favicon.svg`
|
||||
],
|
||||
}
|
||||
});
|
||||
walletConnect.on("modal_closed", () => {
|
||||
state.set({ state: "close" });
|
||||
});
|
||||
|
||||
const walletConnectSigner = new WalletConnectSigner(walletConnect, provider);
|
||||
|
||||
return {
|
||||
connector: walletConnect,
|
||||
signer: walletConnectSigner,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function isMetamaskInstalled(): boolean {
|
||||
const { ethereum } = window;
|
||||
return Boolean(ethereum && ethereum.isMetaMask);
|
||||
}
|
||||
|
||||
export async function getConfig(): Promise<Config> {
|
||||
let config: Config;
|
||||
|
||||
if (isMetamaskInstalled()) {
|
||||
const metamask = new ethers.providers.Web3Provider(window.ethereum);
|
||||
const network = await metamask.ready;
|
||||
config = new Config(network, metamask, metamask.getSigner());
|
||||
function getProvider(
|
||||
network: { name: string },
|
||||
config: Record<string, any>,
|
||||
metamask: ethers.providers.JsonRpcProvider | null,
|
||||
): ethers.providers.JsonRpcProvider {
|
||||
// Use Alchemy in production, on mainnet. Otherwise use Metamask if installed.
|
||||
if (network.name === "homestead" && import.meta.env.PROD) {
|
||||
return new ethers.providers.AlchemyProvider(network.name, config.alchemy.key);
|
||||
} else if (metamask) {
|
||||
return metamask;
|
||||
} else {
|
||||
// If we don't have Metamask, we default to Homestead.
|
||||
const network = { name: "homestead", chainId: 1 };
|
||||
config = new Config(network, null, null);
|
||||
throw new Error("No Web3 provider available.");
|
||||
}
|
||||
console.log(config);
|
||||
}
|
||||
|
||||
return config;
|
||||
export async function getConfig(): Promise<Config> {
|
||||
const metamask = isMetamaskInstalled()
|
||||
? new ethers.providers.Web3Provider(window.ethereum)
|
||||
: null;
|
||||
const metamaskSigner = metamask?.getSigner() || null;
|
||||
|
||||
let network = { name: "homestead", chainId: 1 };
|
||||
if (metamask) {
|
||||
// If Metamask is detected, we use the network configured there.
|
||||
network = await metamask.ready;
|
||||
}
|
||||
|
||||
const networkConfig = (<Record<string, any>> config)[network.name];
|
||||
if (! networkConfig) {
|
||||
throw new Error(`Network ${network.name} is not supported`);
|
||||
}
|
||||
|
||||
const provider = getProvider(network, networkConfig, metamask);
|
||||
const cfg = new Config(
|
||||
network,
|
||||
provider,
|
||||
metamaskSigner,
|
||||
);
|
||||
console.log(cfg, "config");
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user