Skip to content

Commit

Permalink
feat(adapters): Add toViemPublicClient and toViemWalletClient functions
Browse files Browse the repository at this point in the history
  • Loading branch information
jnsdls committed Feb 26, 2024
1 parent 18851d7 commit 770b0d6
Showing 1 changed file with 152 additions and 1 deletion.
153 changes: 152 additions & 1 deletion packages/thirdweb/src/adapters/viem.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import type { GetContractReturnType } from "viem";
import {
createPublicClient,
http,
type GetContractReturnType,
type PublicClient,
type Chain as ViemChain,
type WalletClient,
createWalletClient,
custom,
} from "viem";
import { getContract, type ThirdwebContract } from "../contract/contract.js";
import type { Abi } from "abitype";
import type { Chain } from "../chains/types.js";
import type { ThirdwebClient } from "../client/client.js";
import { resolveContractAbi } from "../contract/actions/resolve-abi.js";
import { getRpcUrlForChain } from "../chains/utils.js";
import type { Account, Wallet } from "../wallets/interfaces/wallet.js";
import type { Prettify } from "../utils/type-utils.js";
import { toAccount } from "viem/accounts";

export const viemAdapter = {
contract: {
Expand Down Expand Up @@ -35,6 +48,43 @@ export const viemAdapter = {
*/
toViem: toViemContract,
},

/**
* Converts options to a Viem public client.
* @param options - The options for creating the Viem public client.
* @returns The Viem public client.
* @example
* ```ts
* import { viemAdapter } from "thirdweb/adapters";
*
* const publicClient = viemAdapter.publicClient.toViem({
* chain: ethereum,
* client,
* });
* ```
*/
publicClient: {
toViem: toViemPublicClient,
},

walletClient: {
/**
* Converts options to a Viem Wallet client.
* @param options - The options for creating the Viem Wallet client.
* @returns The Viem Wallet client.
* @example
* ```ts
* import { viemAdapter } from "thirdweb/adapters";
*
* const walletClient = viemAdapter.walletClient.toViem({
* wallet: wallet,
* client,
* chain: ethereum,
* });
* ```
*/
toViem: toViemWalletClient,
},
};

type FromViemContractOptions<TAbi extends Abi> = {
Expand Down Expand Up @@ -62,3 +112,104 @@ async function toViemContract<const TAbi extends Abi>(
abi: await resolveContractAbi(contract),
};
}

type ToViemPublicClientOptions = {
client: ThirdwebClient;
chain: Chain;
};

function toViemPublicClient(options: ToViemPublicClientOptions): PublicClient {
const { chain, client } = options;
const rpcUrl = getRpcUrlForChain({ chain, client });
const viemChain: ViemChain = {
id: chain.id,
name: chain.name || "",
rpcUrls: {
default: { http: [rpcUrl] },
},
nativeCurrency: {
name: chain.nativeCurrency?.name || "Ether",
symbol: chain.nativeCurrency?.symbol || "ETH",
decimals: chain.nativeCurrency?.decimals || 18,
},
};
return createPublicClient({
transport: http(rpcUrl, {
fetchOptions: client.secretKey
? {
headers: {
"x-secret-key": client.secretKey,
},
}
: undefined,
}),
chain: viemChain,
});
}

type ToViemWalletClientOptions = Prettify<
(
| {
wallet: Wallet;
account?: never;
}
| {
wallet?: never;
account: Account;
}
) & {
client: ThirdwebClient;
chain: Chain;
}
>;

function toViemWalletClient(options: ToViemWalletClientOptions): WalletClient {
const account = options.account || options.wallet.getAccount();
// this *may* exist as a private function on the wallet
const provider = (options.wallet as any)?.provider;
if (!account) {
throw new Error("Wallet not connected.");
}

const { chain, client } = options;
const rpcUrl = getRpcUrlForChain({ chain, client });
const viemChain: ViemChain = {
id: chain.id,
name: chain.name || "",
rpcUrls: {
default: { http: [rpcUrl] },
},
nativeCurrency: {
name: chain.nativeCurrency?.name || "Ether",
symbol: chain.nativeCurrency?.symbol || "ETH",
decimals: chain.nativeCurrency?.decimals || 18,
},
};

const transport = provider
? custom(provider)
: http(rpcUrl, {
fetchOptions: options.client.secretKey
? { headers: { "x-secret-key": options.client.secretKey } }
: undefined,
});

return createWalletClient({
transport,
account: account.signTransaction
? toAccount({
address: account.address,
signMessage: account.signMessage,
signTransaction: (tx) => {
if (!account.signTransaction) {
throw new Error("signTransaction not supported");
}
return account.signTransaction(tx);
},
signTypedData: account.signTypedData,
})
: account.address,
chain: viemChain,
key: "thirdweb-wallet",
});
}

0 comments on commit 770b0d6

Please sign in to comment.