Skip to content

Instantly share code, notes, and snippets.

@tunnckoCore
Last active September 14, 2024 15:35
Show Gist options
  • Save tunnckoCore/2cb59432a48494d694167e2cd8cb3afd to your computer and use it in GitHub Desktop.
Save tunnckoCore/2cb59432a48494d694167e2cd8cb3afd to your computer and use it in GitHub Desktop.
Facet actions / clients for Viem, or standalone
import { english, generateMnemonic, mnemonicToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";
import { createFacetClient } from "./index.ts";
const mnemonic = generateMnemonic(english, 256);
const account = mnemonicToAccount(mnemonic);
const facet = createFacetClient({
account,
chain: sepolia,
transport: http("https://sepolia.drpc.org"),
});
const hash = await facet.walletClient.sendFacetTransaction({
to: "0x3e7a28d96f19b65676F4309531418a03039Ee5b5",
maxFeePerGas: 10,
// gasLimit: 500_000,
data: "0x234",
// data: setValueData as `0x${string}`,
});
console.log("facet eth txhash:", hash);
const facetTxReceipt =
await facet.publicClient.waitForFacetTransactionReceipt(hash);
console.log("facetTxReceipt:", facetTxReceipt);
import { english, generateMnemonic, mnemonicToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";
import { createWalletClient, createPublicClient, http } from "viem";
import { walletClientAcctions, publicClientActions } from "./index.ts";
const mnemonic = generateMnemonic(english, 256);
const account = mnemonicToAccount(mnemonic);
const wallet = createWalletClient({
account,
chain: sepolia,
transport: http("https://sepolia.drpc.org"),
}).extend(walletClientAcctions);
const client = createPublicClient({
chain: sepolia,
transport: http("https://sepolia.drpc.org"),
}).extend(publicClientActions);
// or wallet.sendFacetTransaction
const hash = await wallet.sendTransaction({
to: "0x3e7a28d96f19b65676F4309531418a03039Ee5b5",
maxFeePerGas: 10,
gasLimit: 50_000,
data: "0x234",
// data: setValueData as `0x${string}`,
});
console.log('eth facet txhash:', hash);
// or client.waitForFacetTransactionReceipt(hash)
const txReceipt = await client.waitForTransactionReceipt({ hash });
console.log('receipt:', txReceipt);
import {
createPublicClient,
createWalletClient,
toBytes,
toHex,
toRlp,
type Client,
type WalletClient,
} from "viem";
export function prepareFacetTransactionRequest(args: any) {
const facetInboxAddress = `0x00000000000000000000000000000000000FacE7`;
let chainId = args.chain?.id || args.network;
if (chainId === 1) {
chainId = 0xface7;
} else if (chainId === 11155111) {
chainId = 0xface7a;
} else {
throw new Error("Unsupported facet network, chainId");
}
const facetTxType = toBytes(70);
const rlpEncoded = toRlp(
[
toHex(chainId),
args.to || "0x",
toHex(args.value ?? 0),
toHex(args.maxFeePerGas ?? 0),
toHex(args.gasLimit ?? 10_000),
args.data || "0x",
],
"bytes",
);
const facetCalldata = new Uint8Array([...facetTxType, ...rlpEncoded]);
const tx = {
from: args.account?.address || null,
to: facetInboxAddress as `0x${string}`,
data: toHex(facetCalldata),
};
return tx;
}
export async function checkFacetTransaction(
hash: string,
baseUrl: string = "https://testnet-alpha.facet.org",
) {
const ethTxApi = `https://${baseUrl.replace("https://", "")}/eth_transactions/${hash}`;
let ethTxData;
let attempts = 0;
const maxAttempts = 6;
const baseDelay = 1000;
while (attempts < maxAttempts) {
const response = await fetch(ethTxApi);
ethTxData = await response.json();
if (ethTxData.error !== "Transaction not found") {
break;
}
attempts++;
if (attempts < maxAttempts) {
const delay = baseDelay * Math.pow(2, attempts - 1);
console.log(
`Transaction not found. Retrying in ${delay / 1000} seconds...`,
);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
if (ethTxData.error === "Transaction not found") {
throw new Error("Failed to fetch transaction data after 5 attempts");
} else {
const facetTransaction: any = {
...ethTxData.result.facet_transactions[0],
facet_transaction_receipt:
ethTxData.result.facet_transactions[0].facet_transaction_receipt,
};
return facetTransaction;
}
}
export async function sendFacetTransaction(wallet: WalletClient, args: any) {
const txRequest = prepareFacetTransactionRequest({
...args,
chain: wallet.chain,
account: wallet.account,
});
return wallet.sendTransaction(txRequest as any);
}
export const walletClientActions = (wallet: WalletClient) => ({
async sendTransaction(args: any) {
return sendFacetTransaction(wallet, args);
},
async sendFacetTransaction(args: any) {
return sendFacetTransaction(wallet, args);
},
});
export const publicClientActions = (_client: Client) => ({
async waitForTransactionReceipt(args: any) {
const hash = (typeof args === "string" ? args : args.hash) as `0x${string}`;
return checkFacetTransaction(hash);
},
async waitForFacetTransactionReceipt(args: any) {
const hash = (typeof args === "string" ? args : args.hash) as `0x${string}`;
return checkFacetTransaction(hash);
},
});
export function createFacetClient(args: any) {
const walletClient = createWalletClient(args).extend(walletClientActions);
const publicClient = createPublicClient(args).extend(publicClientActions);
return { walletClient, publicClient };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment