@indigo-labs/indigo-sdk
Version:
Indigo SDK for interacting with Indigo endpoints via lucid-evolution
131 lines (106 loc) • 3.87 kB
text/typescript
import {
EvalRedeemer,
LucidEvolution,
Provider,
TxBuilder,
TxSignBuilder,
} from '@lucid-evolution/lucid';
import { array as A } from 'fp-ts';
import { BENCHMARK_RESULTS } from '../setup';
import { MAINNET_PROTOCOL_PARAMETERS } from '../indigo-test-helpers';
type ExUnits = { mem: number; steps: number; txSize: number };
export async function calculateTxExUnits(
provider: Provider,
tx: TxSignBuilder,
): Promise<ExUnits> {
const cbor = tx.toCBOR();
const redeemersEval = await provider.evaluateTx(tx.toCBOR());
const res = A.reduce<EvalRedeemer, ExUnits>(
{ mem: 0, steps: 0, txSize: 0 },
(acc, e) => {
return {
mem: acc.mem + e.ex_units.mem,
steps: acc.steps + e.ex_units.steps,
txSize: 0,
};
},
)(redeemersEval);
return { ...res, txSize: cbor.length / 2 };
}
export type BenchmarkResult = ExUnits & {
memPercentage: number;
stepsPercentage: number;
sizePercentage: number;
};
// This function is used to benchmark a transaction and await it's successful execution.
export async function benchmarkAndAwaitTx(
name: string,
tx: TxBuilder,
lucid: LucidEvolution,
provider: Provider,
extraSigners: string[] = [],
): Promise<void> {
// Complete the transaction
const bTx = await tx.complete();
const signatures = [await bTx.partialSign.withWallet()];
for (const signer of extraSigners) {
lucid.selectWallet.fromSeed(signer);
signatures.push(await lucid.fromTx(bTx.toCBOR()).partialSign.withWallet());
}
const signedTx = bTx.assemble(signatures);
// Calculate execution units
const exUnits = await calculateTxExUnits(provider, signedTx);
// Get protocol parameters for percentages
const protocolParams = await provider.getProtocolParameters();
if (protocolParams.maxTxExMem !== MAINNET_PROTOCOL_PARAMETERS.maxTxExMem) {
throw new Error('Protocol parameters do not match Mainnet');
}
// Calculate percentages
const result = {
...exUnits,
memPercentage: (exUnits.mem / Number(protocolParams.maxTxExMem)) * 100,
stepsPercentage:
(exUnits.steps / Number(protocolParams.maxTxExSteps)) * 100,
sizePercentage: (exUnits.txSize / Number(protocolParams.maxTxSize)) * 100,
};
BENCHMARK_RESULTS[name] = result;
await lucid.awaitTx(await (await signedTx.complete()).submit());
}
// This function is used to benchmark a transaction and await it's successful execution,
// as well as to query the transaction fee.
export async function benchmarkAndAwaitTxWithTxFee(
name: string,
tx: TxBuilder,
lucid: LucidEvolution,
provider: Provider,
extraSigners: string[] = [],
): Promise<bigint> {
// Complete the transaction
const bTx = await tx.complete();
const signatures = [await bTx.partialSign.withWallet()];
for (const signer of extraSigners) {
lucid.selectWallet.fromSeed(signer);
signatures.push(await lucid.fromTx(bTx.toCBOR()).partialSign.withWallet());
}
const signedTx = bTx.assemble(signatures);
// Calculate execution units
const exUnits = await calculateTxExUnits(provider, signedTx);
// Get protocol parameters for percentages
const protocolParams = await provider.getProtocolParameters();
if (protocolParams.maxTxExMem !== MAINNET_PROTOCOL_PARAMETERS.maxTxExMem) {
throw new Error('Protocol parameters do not match Mainnet');
}
// Calculate percentages
const result = {
...exUnits,
memPercentage: (exUnits.mem / Number(protocolParams.maxTxExMem)) * 100,
stepsPercentage:
(exUnits.steps / Number(protocolParams.maxTxExSteps)) * 100,
sizePercentage: (exUnits.txSize / Number(protocolParams.maxTxSize)) * 100,
};
BENCHMARK_RESULTS[name] = result;
const completedTx = await signedTx.complete();
const txFee = completedTx.toTransaction().body().fee();
await lucid.awaitTx(await completedTx.submit());
return txFee;
}