Extracts a list of all necessary blockchain data required to validate a Cardano transaction. This function analyzes the transaction structure and identifies all UTXOs, accounts, stake pools, DReps, governance actions, and committee members that are referenced in the transaction.
function get_necessary_data_list_js(tx_hex: string): string| Parameter | Type | Description |
|---|---|---|
tx_hex |
string |
Hexadecimal-encoded Cardano transaction in CBOR format |
Returns a JSON string representing a NecessaryInputData object with the following structure:
interface NecessaryInputData {
utxos: TxInput[];
accounts: string[];
pools: string[];
dReps: string[];
govActions: GovernanceActionId[];
lastEnactedGovAction: GovernanceActionType[];
committeeMembersCold: LocalCredential[];
committeeMembersHot: LocalCredential[];
}-
utxos: Array of transaction inputs that need to be resolved- Includes regular inputs, collateral inputs, and reference inputs
- Each element contains
txHashandoutputIndex
-
accounts: Array of bech32-encoded reward account addresses- Includes accounts from withdrawals and certificates
-
pools: Array of stake pool IDs (bech32 format)- Includes pools from delegation certificates and pool registration/retirement certificates
-
dReps: Array of DRep identifiers (bech32 format)- Includes DReps from vote delegation certificates and voting procedures
-
govActions: Array of governance action identifiers- Includes actions referenced in voting procedures and proposals
-
lastEnactedGovAction: Array of governance action types- Types of the last enacted governance actions that the transaction may depend on
-
committeeMembersCold: Array of cold credentials for committee members- Committee members whose cold keys are referenced in the transaction
-
committeeMembersHot: Array of hot credentials for committee members- Committee members whose hot keys are referenced in the transaction
import { get_necessary_data_list_js } from 'cquisitor-lib';
// Example transaction hex
const txHex = "84a400..."; // Your transaction hex
try {
const necessaryDataJson = get_necessary_data_list_js(txHex);
const necessaryData = JSON.parse(necessaryDataJson);
console.log('Required UTXOs:', necessaryData.utxos);
console.log('Required accounts:', necessaryData.accounts);
console.log('Required pools:', necessaryData.pools);
// Fetch the required data from your blockchain data source
// before calling validate_transaction_js
} catch (error) {
console.error('Failed to get necessary data:', error);
}The function throws a JsError if:
- The transaction hex is malformed or cannot be parsed
- The transaction CBOR structure is invalid
- Serialization of the result fails
This function is typically used as a first step before transaction validation:
- Parse the transaction to identify all required data
- Fetch the identified data from a blockchain indexer or node
- Construct a
ValidationInputContextwith the fetched data - Call
validate_transaction_jswith the transaction and context
This two-step approach allows for efficient data fetching, as you only retrieve the specific blockchain state that the transaction references.
The data required to populate ValidationInputContext based on NecessaryInputData can be obtained from third-party blockchain APIs such as:
- Blockfrost - Provides endpoints for UTXOs, accounts, pools, governance actions, and protocol parameters
- Koios - Provides richer API to retrieve blockchain data
- Cardano Node - Direct access via cardano-cli or cardano-db-sync
- Other indexers - Any service that provides Cardano blockchain state data
When using these APIs, map the NecessaryInputData fields as follows:
utxos→ Query UTxO endpoints with transaction hash and output indexaccounts→ Query stake account endpoints with reward addressespools→ Query stake pool endpoints with pool IDsdReps→ Query DRep endpoints (available on supported networks)govActions→ Query governance action endpoints- Additionally fetch current
protocolParametersand set correctslotandnetworkTypefor the validation context
Performs comprehensive validation of a Cardano transaction according to the Cardano ledger rules. This includes both Phase 1 validation (ledger rules, balances, fees, witnesses) and Phase 2 validation (Plutus script execution). The function checks the transaction against protocol parameters, UTXOs, accounts, pools, and governance state provided in the validation context.
function validate_transaction_js(
tx_hex: string,
validation_context: string
): string| Parameter | Type | Description |
|---|---|---|
tx_hex |
string |
Hexadecimal-encoded Cardano transaction in CBOR format |
validation_context |
string |
JSON-encoded ValidationInputContext containing all blockchain state required for validation |
The validation_context parameter must be a JSON string representing the following structure:
interface ValidationInputContext {
slot: bigint; // Current blockchain slot
networkType: NetworkType; // "mainnet", "preview", or "preprod"
protocolParameters: ProtocolParameters; // Current protocol parameters
utxoSet: UtxoInputContext[]; // Referenced UTXOs
accountContexts: AccountInputContext[]; // Stake account states
poolContexts: PoolInputContext[]; // Stake pool states
drepContexts: DrepInputContext[]; // DRep states
govActionContexts: GovActionInputContext[]; // Governance action states
lastEnactedGovAction: GovActionInputContext[]; // Last enacted actions
currentCommitteeMembers: CommitteeInputContext[]; // Current committee
potentialCommitteeMembers: CommitteeInputContext[]; // Potential committee
treasuryValue: bigint; // Current treasury value
}See the type definitions file for detailed structures of nested types.
Returns a JSON string representing a ValidationResult object:
interface ValidationResult {
errors: ValidationPhase1Error[];
warnings: ValidationPhase1Warning[];
phase2_errors: ValidationPhase2Error[];
phase2_warnings: ValidationPhase2Warning[];
eval_redeemer_results: EvalRedeemerResult[];
}-
errors: Array of Phase 1 validation errors- Includes balance errors, fee errors, witness errors, collateral errors, etc.
- Any error in this array means the transaction is invalid
-
warnings: Array of Phase 1 validation warnings- Non-critical issues (e.g., fee is higher than necessary)
- Transaction may still be valid but might be sub-optimal
-
phase2_errors: Array of Phase 2 (Plutus script) validation errors- Script execution failures, budget exceeded, missing cost models, etc.
- Any error here means the transaction is invalid
-
phase2_warnings: Array of Phase 2 validation warnings- Script budget is higher than needed, etc.
-
eval_redeemer_results: Detailed results for each redeemer execution- Contains success/failure status, execution units, error messages, and logs
The validation process is performed in the following order:
-
Balance Validation
- Verifies that total inputs equal total outputs plus fees
- Checks value conservation for all assets (ADA and multi-assets)
- Validates withdrawal amounts match account balances
- Checks deposits and refunds
- Validates treasury value if specified
-
Fee Validation
- Calculates minimum required fee based on transaction size
- Includes reference script fees and execution unit fees
- Verifies the declared fee meets or exceeds minimum
-
Witness Validation
- Checks all required VKey witnesses are present
- Validates signature correctness
- Executes native scripts
- Checks for missing or extraneous witnesses
- Validates script witnesses
-
Collateral Validation
- Verifies collateral inputs are provided when Plutus scripts are present
- Checks collateral contains only ADA (no multi-assets)
- Validates collateral is not script-locked
- Verifies total collateral field matches sum of collateral inputs
- Validates collateral return output
-
Auxiliary Data Validation
- Verifies auxiliary data hash matches actual auxiliary data
- Checks metadata structure
-
Registration Validation (Certificates)
- Validates stake key registration and deregistration
- Checks stake pool registration and retirement
- Validates DRep registration and deregistration
- Verifies committee hot key authorization and cold key resignation
- Checks deposit and refund amounts
- Validates voting and proposal procedures
-
Output Validation
- Checks minimum ADA requirements for each output
- Validates output sizes don't exceed protocol limits
- Validates network IDs in output addresses
-
Transaction Limits Validation
- Checks transaction size doesn't exceed maximum
- Validates total execution units don't exceed transaction limits
- Checks reference script sizes
- Validates number of collateral inputs
Phase 2 executes Plutus scripts and validates their execution:
- Collects all transaction inputs (regular, reference, and collateral)
- Resolves UTXOs for script context
- Executes each redeemer with its associated Plutus script
- Validates execution budgets
- Captures script logs and execution results
- Checks that total execution units don't exceed declared amounts
import {
get_necessary_data_list_js,
validate_transaction_js
} from 'cquisitor-lib';
async function validateTransaction(txHex: string) {
try {
// Step 1: Get the list of required data
const necessaryDataJson = get_necessary_data_list_js(txHex);
const necessaryData = JSON.parse(necessaryDataJson);
// Step 2: Fetch the required data from your indexer/node
const utxos = await fetchUtxos(necessaryData.utxos);
const accounts = await fetchAccounts(necessaryData.accounts);
const pools = await fetchPools(necessaryData.pools);
// ... fetch other required data
// Step 3: Build the validation context
const validationContext = {
slot: await getCurrentSlot(),
networkType: "mainnet",
protocolParameters: await getProtocolParameters(),
utxoSet: utxos,
accountContexts: accounts,
poolContexts: pools,
drepContexts: [],
govActionContexts: [],
lastEnactedGovAction: [],
currentCommitteeMembers: [],
potentialCommitteeMembers: [],
treasuryValue: 0n
};
// Step 4: Validate the transaction
const resultJson = validate_transaction_js(
txHex,
JSON.stringify(validationContext)
);
const result = JSON.parse(resultJson);
// Step 5: Check the results
if (result.errors.length > 0) {
console.error('Transaction has validation errors:');
result.errors.forEach(err => {
console.error(`- ${err.error_message}`);
if (err.hint) {
console.error(` Hint: ${err.hint}`);
}
});
return false;
}
if (result.phase2_errors.length > 0) {
console.error('Transaction has script execution errors:');
result.phase2_errors.forEach(err => {
console.error(`- ${err.error_message}`);
});
return false;
}
if (result.warnings.length > 0) {
console.warn('Transaction has warnings:');
result.warnings.forEach(warn => {
console.warn(`- ${JSON.stringify(warn.warning)}`);
if (warn.hint) {
console.warn(` Hint: ${warn.hint}`);
}
});
}
if (result.phase2_warnings.length > 0) {
console.warn('Transaction has Phase 2 warnings:');
result.phase2_warnings.forEach(warn => {
console.warn(`- ${JSON.stringify(warn.warning)}`);
if (warn.hint) {
console.warn(` Hint: ${warn.hint}`);
}
});
}
// Log redeemer execution results
result.eval_redeemer_results.forEach(redeemer => {
console.log(`Redeemer ${redeemer.tag}[${redeemer.index}]:`);
console.log(` Success: ${redeemer.success}`);
console.log(` Provided ex units: ${JSON.stringify(redeemer.provided_ex_units)}`);
console.log(` Calculated ex units: ${JSON.stringify(redeemer.calculated_ex_units)}`);
if (redeemer.error) {
console.log(` Error: ${redeemer.error}`);
}
if (redeemer.logs.length > 0) {
console.log(` Logs: ${redeemer.logs.join(', ')}`);
}
});
console.log('Transaction is valid!');
return true;
} catch (error) {
console.error('Validation failed:', error);
return false;
}
}- Always call
get_necessary_data_list_jsfirst to determine what data you need to fetch - Provide accurate protocol parameters matching the current epoch
- Include all referenced data in the validation context
- Handle both errors and warnings - warnings might indicate sub-optimal transactions
- Log redeemer execution results for debugging script issues
- Validate transactions before submission to avoid rejection by the network
- Check Phase 2 errors separately from Phase 1 errors for better error handling