refactor: moves more client specific methods into ClientContext

This commit is contained in:
Ben Kremer 2022-02-04 16:29:07 +01:00
parent 0732b09991
commit dc120c89d2
2 changed files with 82 additions and 143 deletions

View File

@ -1,8 +1,5 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import QRCodeModal from "@walletconnect/legacy-modal";
import { SessionTypes } from "@walletconnect/types";
import { ERROR, getAppMetadata } from "@walletconnect/utils";
import * as encoding from "@walletconnect/encoding"; import * as encoding from "@walletconnect/encoding";
import { apiGetChainNamespace, ChainsMap } from "caip-api"; import { apiGetChainNamespace, ChainsMap } from "caip-api";
import { formatDirectSignDoc, stringifySignDocValues } from "cosmos-wallet"; import { formatDirectSignDoc, stringifySignDocValues } from "cosmos-wallet";
@ -13,21 +10,13 @@ import Blockchain from "./components/Blockchain";
import Column from "./components/Column"; import Column from "./components/Column";
import Header from "./components/Header"; import Header from "./components/Header";
import Modal from "./components/Modal"; import Modal from "./components/Modal";
import { DEFAULT_MAIN_CHAINS, DEFAULT_TEST_CHAINS } from "./constants";
import { import {
DEFAULT_APP_METADATA,
DEFAULT_MAIN_CHAINS,
DEFAULT_EIP155_METHODS,
DEFAULT_COSMOS_METHODS,
DEFAULT_TEST_CHAINS,
} from "./constants";
import {
apiGetAccountAssets,
AccountAction, AccountAction,
eip712, eip712,
hashPersonalMessage, hashPersonalMessage,
hashTypedDataMessage, hashTypedDataMessage,
verifySignature, verifySignature,
AccountBalances,
formatTestTransaction, formatTestTransaction,
ChainNamespaces, ChainNamespaces,
setInitialStateTestnet, setInitialStateTestnet,
@ -78,103 +67,20 @@ export default function App() {
const { const {
client, client,
session, session,
connect,
disconnect,
chains, chains,
accounts, accounts,
balances, balances,
fetching, fetching,
loading, loading,
setSession,
setPairings,
setAccounts,
setChains, setChains,
setFetching,
setBalances,
} = useWalletConnectClient(); } = useWalletConnectClient();
console.log({
client,
session,
chains,
accounts,
balances,
fetching,
loading,
setSession,
setPairings,
setAccounts,
setChains,
setFetching,
setBalances,
});
useEffect(() => { useEffect(() => {
loadChainData(); loadChainData();
}, []); }, []);
const connect = async (pairing?: { topic: string }) => {
if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
console.log("connect", pairing);
if (modal === "pairing") {
closeModal();
}
try {
const supportedNamespaces: string[] = [];
chains.forEach(chainId => {
const [namespace] = chainId.split(":");
if (!supportedNamespaces.includes(namespace)) {
supportedNamespaces.push(namespace);
}
});
const methods: string[] = supportedNamespaces
.map(namespace => {
switch (namespace) {
case "eip155":
return DEFAULT_EIP155_METHODS;
case "cosmos":
return DEFAULT_COSMOS_METHODS;
default:
throw new Error(`No default methods for namespace: ${namespace}`);
}
})
.flat();
const session = await client.connect({
metadata: getAppMetadata() || DEFAULT_APP_METADATA,
pairing,
permissions: {
blockchain: {
chains,
},
jsonrpc: {
methods,
},
},
});
onSessionConnected(session);
} catch (e) {
console.error(e);
// ignore rejection
}
// close modal in case it was open
QRCodeModal.close();
};
const disconnect = async () => {
if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
if (typeof session === "undefined") {
throw new Error("Session is not connected");
}
await client.disconnect({
topic: session.topic,
reason: ERROR.USER_DISCONNECTED.format(),
});
};
const onConnect = () => { const onConnect = () => {
if (typeof client === "undefined") { if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized"); throw new Error("WalletConnect is not initialized");
@ -185,41 +91,6 @@ export default function App() {
connect(); connect();
}; };
const onSessionConnected = async (incomingSession: SessionTypes.Settled) => {
setSession(incomingSession);
onSessionUpdate(incomingSession.state.accounts, incomingSession.permissions.blockchain.chains);
};
const onSessionUpdate = async (accounts: string[], chains: string[]) => {
setChains(chains);
setAccounts(accounts);
await getAccountBalances(accounts);
};
const getAccountBalances = async (_accounts: string[]) => {
setFetching(true);
try {
const arr = await Promise.all(
_accounts.map(async account => {
const [namespace, reference, address] = account.split(":");
const chainId = `${namespace}:${reference}`;
const assets = await apiGetAccountAssets(address, chainId);
return { account, assets };
}),
);
const balances: AccountBalances = {};
arr.forEach(({ account, assets }) => {
balances[account] = assets;
});
setBalances(balances);
} catch (e) {
console.error(e);
} finally {
setFetching(false);
}
};
const loadChainData = async () => { const loadChainData = async () => {
const namespaces = getAllChainNamespaces(); const namespaces = getAllChainNamespaces();
const chainData: ChainNamespaces = {}; const chainData: ChainNamespaces = {};

View File

@ -2,8 +2,16 @@ import Client, { CLIENT_EVENTS } from "@walletconnect/client";
import { PairingTypes, SessionTypes } from "@walletconnect/types"; import { PairingTypes, SessionTypes } from "@walletconnect/types";
import QRCodeModal from "@walletconnect/legacy-modal"; import QRCodeModal from "@walletconnect/legacy-modal";
import { createContext, ReactNode, useContext, useEffect, useState } from "react"; import { createContext, ReactNode, useContext, useEffect, useState } from "react";
import { DEFAULT_LOGGER, DEFAULT_PROJECT_ID, DEFAULT_RELAY_URL } from "../constants"; import {
DEFAULT_APP_METADATA,
DEFAULT_COSMOS_METHODS,
DEFAULT_EIP155_METHODS,
DEFAULT_LOGGER,
DEFAULT_PROJECT_ID,
DEFAULT_RELAY_URL,
} from "../constants";
import { AccountBalances, apiGetAccountAssets } from "../helpers"; import { AccountBalances, apiGetAccountAssets } from "../helpers";
import { ERROR, getAppMetadata } from "@walletconnect/utils";
/** /**
* Types * Types
@ -11,18 +19,15 @@ import { AccountBalances, apiGetAccountAssets } from "../helpers";
interface IContext { interface IContext {
client: Client | undefined; client: Client | undefined;
session: SessionTypes.Created | undefined; session: SessionTypes.Created | undefined;
connect: (pairing?: { topic: string }) => Promise<void>;
disconnect: () => Promise<void>;
loading: boolean; loading: boolean;
fetching: boolean; fetching: boolean;
chains: string[]; chains: string[];
pairings: string[]; pairings: string[];
accounts: string[]; accounts: string[];
balances: AccountBalances; balances: AccountBalances;
setSession: any;
setPairings: any;
setAccounts: any;
setChains: any; setChains: any;
setFetching: any;
setBalances: any;
} }
/** /**
@ -110,6 +115,72 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
await getAccountBalances(accounts); await getAccountBalances(accounts);
}; };
const connect = async (pairing?: { topic: string }) => {
if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
console.log("connect", pairing);
// TODO:
// if (modal === "pairing") {
// closeModal();
// }
try {
const supportedNamespaces: string[] = [];
chains.forEach(chainId => {
const [namespace] = chainId.split(":");
if (!supportedNamespaces.includes(namespace)) {
supportedNamespaces.push(namespace);
}
});
const methods: string[] = supportedNamespaces
.map(namespace => {
switch (namespace) {
case "eip155":
return DEFAULT_EIP155_METHODS;
case "cosmos":
return DEFAULT_COSMOS_METHODS;
default:
throw new Error(`No default methods for namespace: ${namespace}`);
}
})
.flat();
const session = await client.connect({
metadata: getAppMetadata() || DEFAULT_APP_METADATA,
pairing,
permissions: {
blockchain: {
chains,
},
jsonrpc: {
methods,
},
},
});
onSessionConnected(session);
} catch (e) {
console.error(e);
// ignore rejection
}
// close modal in case it was open
QRCodeModal.close();
};
const disconnect = async () => {
if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
if (typeof session === "undefined") {
throw new Error("Session is not connected");
}
console.log(client);
await client.disconnect({
topic: session.topic,
reason: ERROR.USER_DISCONNECTED.format(),
});
};
const getAccountBalances = async (_accounts: string[]) => { const getAccountBalances = async (_accounts: string[]) => {
setFetching(true); setFetching(true);
try { try {
@ -166,12 +237,9 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
chains, chains,
client, client,
session, session,
setSession, connect,
setPairings, disconnect,
setAccounts,
setChains, setChains,
setFetching,
setBalances,
}} }}
> >
{children} {children}