|
| 1 | +import type { TransactionInstruction } from "@solana/web3.js"; |
| 2 | + |
| 3 | +import { invariant } from "../../lib/assertions.js"; |
| 4 | +import type { ComputePriceEstimate, IInteractSolanaExt, ITransactionSolanaExtResolved } from "../types.js"; |
| 5 | +import { createVersionedTransaction } from "../utils.js"; |
| 6 | +import { pk } from "./public-key.js"; |
| 7 | +import { resolveTransactionAccounts } from "./deserialize-raw-transaction.js"; |
| 8 | + |
| 9 | +const createTestTransaction = ( |
| 10 | + ixs: Parameters<typeof createVersionedTransaction>[0], |
| 11 | + payer: Parameters<typeof createVersionedTransaction>[1], |
| 12 | + recentBlockhash?: Parameters<typeof createVersionedTransaction>[2], |
| 13 | + partialSigners?: Parameters<typeof createVersionedTransaction>[3], |
| 14 | +) => { |
| 15 | + return createVersionedTransaction(ixs, payer, recentBlockhash ?? "11111111111111111111111111111111", partialSigners); |
| 16 | +}; |
| 17 | + |
| 18 | +export async function estimateComputeUnitPrice( |
| 19 | + estimate: ComputePriceEstimate, |
| 20 | + testTx: ReturnType<typeof createTestTransaction>, |
| 21 | +): Promise<number> { |
| 22 | + return estimate(resolveTransactionAccounts(testTx).writableAccounts); |
| 23 | +} |
| 24 | + |
| 25 | +export async function createAndEstimateTransaction< |
| 26 | + ParamsT extends ITransactionSolanaExtResolved<IInteractSolanaExt>, |
| 27 | + CreateFn extends (extParams: ParamsT) => Promise<TransactionInstruction[]>, |
| 28 | +>(createFn: CreateFn, extParams: ParamsT): Promise<Awaited<ReturnType<CreateFn>>>; |
| 29 | + |
| 30 | +export async function createAndEstimateTransaction< |
| 31 | + ParamsT extends ITransactionSolanaExtResolved<IInteractSolanaExt>, |
| 32 | + CreateFn extends (extParams: ParamsT) => Promise<any>, |
| 33 | +>( |
| 34 | + createFn: CreateFn, |
| 35 | + extParams: ParamsT, |
| 36 | + select: (result: Awaited<ReturnType<CreateFn>>) => TransactionInstruction[] |
| 37 | +): Promise<Awaited<ReturnType<CreateFn>>>; |
| 38 | + |
| 39 | +export async function createAndEstimateTransaction< |
| 40 | + ParamsT extends ITransactionSolanaExtResolved<IInteractSolanaExt>, |
| 41 | + CreateFn extends (extParams: ParamsT) => Promise<any>, |
| 42 | +>( |
| 43 | + createFn: CreateFn, |
| 44 | + extParams: ParamsT, |
| 45 | + select?: (result: Awaited<ReturnType<CreateFn>>) => TransactionInstruction[], |
| 46 | +): Promise<Awaited<ReturnType<CreateFn>>> { |
| 47 | + select = select ?? ((value: Awaited<ReturnType<CreateFn>>) => value); |
| 48 | + const createResult = await createFn(extParams); |
| 49 | + const prepareIxs = select(createResult); |
| 50 | + |
| 51 | + const { computePrice, computeLimit } = extParams; |
| 52 | + const invoker = extParams.invoker.publicKey; |
| 53 | + invariant(invoker, "Invoker's PublicKey is not available, check passed wallet adapter!"); |
| 54 | + const testTx = createTestTransaction(prepareIxs, pk(invoker), undefined, undefined); |
| 55 | + const estimatedComputeLimit = typeof computeLimit === "function" ? await computeLimit(testTx) : computeLimit; |
| 56 | + |
| 57 | + if (typeof computePrice !== "function") { |
| 58 | + if (typeof computeLimit !== "function") { |
| 59 | + return createResult; |
| 60 | + } |
| 61 | + |
| 62 | + return createFn({ |
| 63 | + ...extParams, |
| 64 | + computeLimit: estimatedComputeLimit, |
| 65 | + }); |
| 66 | + } |
| 67 | + |
| 68 | + const estimatedComputeUnitPrice = |
| 69 | + typeof computePrice === "function" |
| 70 | + ? await estimateComputeUnitPrice(computePrice, testTx) |
| 71 | + : // unachievable because we don't execute estimation for constant or undefined priority fee |
| 72 | + computePrice; |
| 73 | + |
| 74 | + return createFn({ |
| 75 | + ...extParams, |
| 76 | + computePrice: estimatedComputeUnitPrice, |
| 77 | + computeLimit: estimatedComputeLimit, |
| 78 | + }); |
| 79 | +} |
0 commit comments