@abstract-foundation/agw-client
Version:
Abstract Global Wallet Client SDK
128 lines (120 loc) • 3.63 kB
text/typescript
import type {
Account,
Address,
BaseError,
Chain,
Client,
Hex,
PublicClient,
SendTransactionRequest,
Transport,
WalletClient,
} from "viem";
import { getChainId, sendRawTransaction } from "viem/actions";
import {
assertCurrentChain,
type GetTransactionErrorParameters,
getAction,
getTransactionError,
parseAccount,
} from "viem/utils";
import type {
ChainEIP712,
SendEip712TransactionParameters,
SendEip712TransactionReturnType,
} from "viem/zksync";
import { INSUFFICIENT_BALANCE_SELECTOR } from "../constants.js";
import { AccountNotFoundError } from "../errors/account.js";
import { InsufficientBalanceError } from "../errors/insufficientBalance.js";
import type { CustomPaymasterHandler } from "../types/customPaymaster.js";
import { prepareTransactionRequest } from "./prepareTransaction.js";
import { signTransaction } from "./signTransaction.js";
export async function sendTransactionInternal<
const request extends SendTransactionRequest<chain, chainOverride>,
chain extends ChainEIP712 | undefined = ChainEIP712 | undefined,
account extends Account | undefined = Account | undefined,
chainOverride extends ChainEIP712 | undefined = ChainEIP712 | undefined,
TReturnType = SendEip712TransactionReturnType,
>(
client: Client<Transport, ChainEIP712, Account>,
signerClient: WalletClient<Transport, ChainEIP712, Account>,
publicClient: PublicClient<Transport, ChainEIP712>,
parameters: SendEip712TransactionParameters<
chain,
account,
chainOverride,
request
>,
validator: Address,
validationHookData: Record<string, Hex> = {},
customPaymasterHandler: CustomPaymasterHandler | undefined = undefined,
sendSerializedTransaction?: (
serializedTransaction: `0x${string}`,
) => Promise<TReturnType>,
): Promise<TReturnType> {
const { chain = client.chain } = parameters;
if (!signerClient.account)
throw new AccountNotFoundError({
docsPath: "/docs/actions/wallet/sendTransaction",
});
const account = parseAccount(signerClient.account);
try {
// assertEip712Request(parameters)
// Prepare the request for signing (assign appropriate fees, etc.)
const request = await prepareTransactionRequest(
client,
signerClient,
publicClient,
{
...parameters,
parameters: ["gas", "nonce", "fees"],
isSponsored:
customPaymasterHandler !== undefined ||
(parameters as any).paymaster !== undefined,
nonceManager: account.nonceManager,
} as any,
);
let chainId: number | undefined;
if (chain !== null) {
chainId = await getAction(signerClient, getChainId, "getChainId")({});
assertCurrentChain({
currentChainId: chainId,
chain,
});
}
const serializedTransaction = await signTransaction(
client,
signerClient,
publicClient,
{
...request,
chainId,
} as any,
validator,
validationHookData,
customPaymasterHandler,
);
if (sendSerializedTransaction) {
return await sendSerializedTransaction(serializedTransaction);
}
return (await getAction(
client,
sendRawTransaction,
"sendRawTransaction",
)({
serializedTransaction,
})) as TReturnType;
} catch (err) {
if (
err instanceof Error &&
err.message.includes(INSUFFICIENT_BALANCE_SELECTOR)
) {
throw new InsufficientBalanceError();
}
throw getTransactionError(err as BaseError, {
...(parameters as GetTransactionErrorParameters),
account,
chain: chain as Chain,
});
}
}