|
1 | | -export {}; |
| 1 | +import type { |
| 2 | + ExecutionPlan, |
| 3 | + InsufficientBalanceError, |
| 4 | + TransactionRequest, |
| 5 | +} from '@aave/graphql'; |
| 6 | +import { |
| 7 | + errAsync, |
| 8 | + invariant, |
| 9 | + ResultAsync, |
| 10 | + type TxHash, |
| 11 | + txHash, |
| 12 | +} from '@aave/types'; |
| 13 | +import type { Hash, WalletClient } from 'viem'; |
| 14 | +import { |
| 15 | + sendTransaction as sendEip1559Transaction, |
| 16 | + waitForTransactionReceipt, |
| 17 | +} from 'viem/actions'; |
| 18 | +import { SigningError, ValidationError } from './errors'; |
| 19 | +import type { ExecutionPlanHandler } from './types'; |
| 20 | + |
| 21 | +async function sendTransaction( |
| 22 | + walletClient: WalletClient, |
| 23 | + request: TransactionRequest, |
| 24 | +): Promise<Hash> { |
| 25 | + return sendEip1559Transaction(walletClient, { |
| 26 | + account: request.from, |
| 27 | + data: request.data, |
| 28 | + to: request.to, |
| 29 | + value: BigInt(request.value), |
| 30 | + chain: request.chainId, |
| 31 | + }); |
| 32 | +} |
| 33 | + |
| 34 | +/** |
| 35 | + * @internal |
| 36 | + */ |
| 37 | +export function sendTransactionAndWait( |
| 38 | + walletClient: WalletClient, |
| 39 | + request: TransactionRequest, |
| 40 | +): ResultAsync<TxHash, SigningError> { |
| 41 | + return ResultAsync.fromPromise( |
| 42 | + sendTransaction(walletClient, request), |
| 43 | + (err) => SigningError.from(err), |
| 44 | + ) |
| 45 | + .map(async (hash) => |
| 46 | + waitForTransactionReceipt(walletClient, { |
| 47 | + hash, |
| 48 | + pollingInterval: 100, |
| 49 | + retryCount: 20, |
| 50 | + retryDelay: 50, |
| 51 | + }), |
| 52 | + ) |
| 53 | + .map((receipt) => txHash(receipt.transactionHash)); |
| 54 | +} |
| 55 | + |
| 56 | +/** |
| 57 | + * Sends transactions using the provided wallet client. |
| 58 | + * |
| 59 | + * Handles {@link TransactionRequest} by signing and sending, {@link ApprovalRequired} by sending both approval and original transactions, and returns validation errors for {@link InsufficientBalanceError}. |
| 60 | + */ |
| 61 | +export function sendWith( |
| 62 | + walletClient: WalletClient | undefined, |
| 63 | +): ExecutionPlanHandler { |
| 64 | + return ( |
| 65 | + result: ExecutionPlan, |
| 66 | + ): ResultAsync< |
| 67 | + TxHash, |
| 68 | + SigningError | ValidationError<InsufficientBalanceError> |
| 69 | + > => { |
| 70 | + if ('hash' in result) { |
| 71 | + return okAsync(result.hash); |
| 72 | + } |
| 73 | + |
| 74 | + invariant( |
| 75 | + walletClient, |
| 76 | + 'Expected a WalletClient to handle the operation result.', |
| 77 | + ); |
| 78 | + |
| 79 | + switch (result.__typename) { |
| 80 | + case 'TransactionRequest': |
| 81 | + return sendTransactionAndWait(walletClient, result); |
| 82 | + |
| 83 | + case 'ApprovalRequired': |
| 84 | + return sendTransactionAndWait(walletClient, result.approval).andThen( |
| 85 | + () => |
| 86 | + sendTransactionAndWait(walletClient, result.originalTransaction), |
| 87 | + ); |
| 88 | + |
| 89 | + case 'InsufficientBalanceError': |
| 90 | + return errAsync(ValidationError.fromGqlNode(result)); |
| 91 | + } |
| 92 | + }; |
| 93 | +} |
0 commit comments