Skip to main content

tx3_sdk/trp/
spec.rs

1//! Transaction Resolve Protocol (TRP) data types and structures.
2//!
3//! This module defines the request/response types used in the Transaction Resolve Protocol (TRP),
4//! a JSON-RPC based protocol for resolving, submitting, and tracking UTxO transactions.
5//!
6//! TRP provides a standardized interface for:
7//! - Resolving transaction templates into concrete blockchain transactions
8//! - Submitting signed transactions to the network
9//! - Monitoring transaction status and lifecycle
10//! - Querying pending and inflight transaction queues
11
12use serde::{Deserialize, Serialize};
13use std::collections::HashMap;
14
15use crate::core::{ArgMap, BytesEnvelope, EnvMap, TirEnvelope};
16
17/// Parameters for submitting a signed transaction to the network.
18///
19/// This structure wraps a signed transaction along with its cryptographic witnesses
20/// (signatures) for submission to the blockchain network via TRP.
21///
22/// # Fields
23///
24/// * `tx` - The signed transaction as a bytes envelope
25/// * `witnesses` - Vector of transaction witnesses (signatures)
26///
27/// # Example
28///
29/// ```ignore
30/// use tx3_sdk::trp::{SubmitParams, TxWitness, WitnessType};
31/// use tx3_sdk::core::BytesEnvelope;
32///
33/// let submit_params = SubmitParams {
34///     tx: BytesEnvelope {
35///         content: "84a40081825820...".to_string(),
36///         content_type: "application/cbor".to_string(),
37///     },
38///     witnesses: vec![TxWitness {
39///         key: BytesEnvelope { /* ... */ },
40///         signature: BytesEnvelope { /* ... */ },
41///         witness_type: WitnessType::VKey,
42///     }],
43/// };
44/// ```
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct SubmitParams {
47    /// The signed transaction bytes.
48    #[serde(rename = "tx")]
49    pub tx: BytesEnvelope,
50
51    /// Cryptographic witnesses (signatures) for the transaction.
52    #[serde(rename = "witnesses")]
53    pub witnesses: Vec<TxWitness>,
54}
55
56/// A resolved transaction envelope returned by the TRP resolver.
57///
58/// This structure contains a fully resolved UTxO transaction ready for signing
59/// and submission. The hash is computed from the transaction body.
60///
61/// # Fields
62///
63/// * `hash` - The transaction hash (hex-encoded)
64/// * `tx` - The CBOR-encoded transaction as a hex string
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct TxEnvelope {
67    /// The transaction hash (hex-encoded, 64 characters).
68    #[serde(rename = "hash")]
69    pub hash: String,
70
71    /// The CBOR-encoded transaction bytes as a hex string.
72    #[serde(rename = "tx")]
73    pub tx: String,
74}
75
76/// Response from a successful transaction submission.
77///
78/// After submitting a signed transaction, the TRP server returns this structure
79/// containing the transaction hash, which can be used to track the transaction status.
80///
81/// # Fields
82///
83/// * `hash` - The submitted transaction hash
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct SubmitResponse {
86    /// The transaction hash that was submitted.
87    #[serde(rename = "hash")]
88    pub hash: String,
89}
90
91/// A cryptographic witness (signature) for a transaction.
92///
93/// Witnesses provide the proof that a transaction has been authorized by the
94/// holder of a private key. Each witness includes the public key, signature,
95/// and the type of witness.
96///
97/// # Fields
98///
99/// * `key` - The public key bytes
100/// * `signature` - The cryptographic signature
101/// * `witness_type` - The type of witness (currently only VKey supported)
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct TxWitness {
104    /// The public key bytes.
105    #[serde(rename = "key")]
106    pub key: BytesEnvelope,
107
108    /// The cryptographic signature.
109    #[serde(rename = "signature")]
110    pub signature: BytesEnvelope,
111
112    /// The type of witness.
113    #[serde(rename = "type")]
114    pub witness_type: WitnessType,
115}
116
117/// Type of transaction witness.
118///
119/// Identifies the witness type for a transaction signature. Currently,
120/// only VKey (verification key) witnesses are supported.
121#[derive(Debug, Clone, Serialize, Deserialize)]
122#[serde(rename_all = "lowercase")]
123pub enum WitnessType {
124    /// Verification key witness (standard Ed25519 signature).
125    VKey,
126}
127
128/// A point on the blockchain identified by slot and block hash.
129///
130/// Chain points uniquely identify a specific block in a UTxO-based blockchain,
131/// used for tracking transaction confirmation and chain state.
132///
133/// # Fields
134///
135/// * `slot` - The slot number of the block
136/// * `block_hash` - The hash of the block
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct ChainPoint {
139    /// The slot number.
140    #[serde(rename = "slot")]
141    pub slot: u64,
142
143    /// The block hash (hex-encoded).
144    #[serde(rename = "blockHash")]
145    pub block_hash: String,
146}
147
148/// The lifecycle stage of a transaction.
149///
150/// Transactions progress through several stages from submission to finalization.
151/// This enum represents all possible stages in the transaction lifecycle.
152#[derive(Debug, Clone, Serialize, Deserialize)]
153#[serde(rename_all = "snake_case")]
154pub enum TxStage {
155    /// Transaction is pending and waiting to be processed.
156    Pending,
157
158    /// Transaction has been propagated to the network.
159    Propagated,
160
161    /// Transaction has been acknowledged by a node.
162    Acknowledged,
163
164    /// Transaction has been confirmed in a block.
165    Confirmed,
166
167    /// Transaction has reached finality (sufficient confirmations).
168    Finalized,
169
170    /// Transaction was dropped from the mempool.
171    Dropped,
172
173    /// Transaction was rolled back due to chain reorganization.
174    RolledBack,
175
176    /// Unknown or unrecognized stage.
177    Unknown,
178}
179
180/// Status information for a transaction.
181///
182/// Contains detailed status information including the current lifecycle stage,
183/// confirmation counts, and the chain point where the transaction was confirmed.
184///
185/// # Fields
186///
187/// * `stage` - Current lifecycle stage
188/// * `confirmations` - Number of confirmations received
189/// * `non_confirmations` - Number of non-confirmations (conflicting blocks)
190/// * `confirmed_at` - Chain point where first confirmed (if confirmed)
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct TxStatus {
193    /// Current lifecycle stage.
194    #[serde(rename = "stage")]
195    pub stage: TxStage,
196
197    /// Number of block confirmations.
198    #[serde(rename = "confirmations")]
199    pub confirmations: u64,
200
201    /// Number of blocks that didn't include the transaction.
202    #[serde(rename = "nonConfirmations")]
203    pub non_confirmations: u64,
204
205    /// Chain point where the transaction was first confirmed.
206    #[serde(rename = "confirmedAt", skip_serializing_if = "Option::is_none")]
207    pub confirmed_at: Option<ChainPoint>,
208}
209
210/// A map of transaction hashes to their statuses.
211///
212/// Returned by the `check_status` call to get status for multiple transactions.
213pub type TxStatusMap = HashMap<String, TxStatus>;
214
215/// Response from checking the status of transactions.
216///
217/// Contains the status map for all requested transactions.
218///
219/// # Fields
220///
221/// * `statuses` - Map of transaction hash to status
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct CheckStatusResponse {
224    /// Map of transaction hashes to their statuses.
225    #[serde(rename = "statuses")]
226    pub statuses: TxStatusMap,
227}
228
229/// A log entry for a transaction.
230///
231/// Represents a single entry in the transaction log, tracking the transaction's
232/// progress through various stages.
233///
234/// # Fields
235///
236/// * `hash` - Transaction hash
237/// * `stage` - Current stage
238/// * `payload` - Optional payload data
239/// * `confirmations` - Number of confirmations
240/// * `non_confirmations` - Number of non-confirmations
241/// * `confirmed_at` - Chain point of first confirmation
242#[derive(Debug, Clone, Serialize, Deserialize)]
243pub struct TxLog {
244    /// Transaction hash.
245    #[serde(rename = "hash")]
246    pub hash: String,
247
248    /// Current lifecycle stage.
249    #[serde(rename = "stage")]
250    pub stage: TxStage,
251
252    /// Optional payload data (CBOR-encoded).
253    #[serde(rename = "payload", skip_serializing_if = "Option::is_none")]
254    pub payload: Option<String>,
255
256    /// Number of confirmations.
257    #[serde(rename = "confirmations")]
258    pub confirmations: u64,
259
260    /// Number of non-confirmations.
261    #[serde(rename = "nonConfirmations")]
262    pub non_confirmations: u64,
263
264    /// Chain point of first confirmation.
265    #[serde(rename = "confirmedAt", skip_serializing_if = "Option::is_none")]
266    pub confirmed_at: Option<ChainPoint>,
267}
268
269/// Response from dumping transaction logs.
270///
271/// Returns a paginated list of transaction log entries and an optional
272/// cursor for retrieving the next page.
273///
274/// # Fields
275///
276/// * `entries` - Vector of log entries
277/// * `next_cursor` - Cursor for next page (if more entries exist)
278#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct DumpLogsResponse {
280    /// Transaction log entries.
281    #[serde(rename = "entries")]
282    pub entries: Vec<TxLog>,
283
284    /// Cursor for pagination (to fetch next page).
285    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
286    pub next_cursor: Option<u64>,
287}
288
289/// A pending transaction entry.
290///
291/// Represents a transaction that is pending in the mempool, waiting to be
292/// included in a block.
293///
294/// # Fields
295///
296/// * `hash` - Transaction hash
297/// * `payload` - Optional transaction payload
298#[derive(Debug, Clone, Serialize, Deserialize)]
299pub struct PendingTx {
300    /// Transaction hash.
301    #[serde(rename = "hash")]
302    pub hash: String,
303
304    /// Optional CBOR-encoded transaction payload.
305    #[serde(rename = "payload", skip_serializing_if = "Option::is_none")]
306    pub payload: Option<String>,
307}
308
309/// Response from peeking at pending transactions.
310///
311/// Returns pending transactions from the mempool.
312///
313/// # Fields
314///
315/// * `entries` - Vector of pending transactions
316/// * `has_more` - Whether more pending transactions exist
317#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct PeekPendingResponse {
319    /// Pending transaction entries.
320    #[serde(rename = "entries")]
321    pub entries: Vec<PendingTx>,
322
323    /// Whether more entries exist beyond this page.
324    #[serde(rename = "hasMore")]
325    pub has_more: bool,
326}
327
328/// An in-flight transaction entry.
329///
330/// Represents a transaction that has been submitted and is being tracked
331/// through its lifecycle stages.
332///
333/// # Fields
334///
335/// * `hash` - Transaction hash
336/// * `stage` - Current lifecycle stage
337/// * `confirmations` - Number of confirmations
338/// * `non_confirmations` - Number of non-confirmations
339/// * `confirmed_at` - Chain point of first confirmation
340/// * `payload` - Optional transaction payload
341#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct InflightTx {
343    /// Transaction hash.
344    #[serde(rename = "hash")]
345    pub hash: String,
346
347    /// Current lifecycle stage.
348    #[serde(rename = "stage")]
349    pub stage: TxStage,
350
351    /// Number of confirmations.
352    #[serde(rename = "confirmations")]
353    pub confirmations: u64,
354
355    /// Number of non-confirmations.
356    #[serde(rename = "nonConfirmations")]
357    pub non_confirmations: u64,
358
359    /// Chain point of first confirmation.
360    #[serde(rename = "confirmedAt", skip_serializing_if = "Option::is_none")]
361    pub confirmed_at: Option<ChainPoint>,
362
363    /// Optional CBOR-encoded transaction payload.
364    #[serde(rename = "payload", skip_serializing_if = "Option::is_none")]
365    pub payload: Option<String>,
366}
367
368/// Response from peeking at in-flight transactions.
369///
370/// Returns in-flight transactions being tracked by the TRP server.
371///
372/// # Fields
373///
374/// * `entries` - Vector of in-flight transactions
375/// * `has_more` - Whether more in-flight transactions exist
376#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct PeekInflightResponse {
378    /// In-flight transaction entries.
379    #[serde(rename = "entries")]
380    pub entries: Vec<InflightTx>,
381
382    /// Whether more entries exist beyond this page.
383    #[serde(rename = "hasMore")]
384    pub has_more: bool,
385}
386
387/// Parameters for resolving a transaction template into a concrete transaction.
388///
389/// This structure contains all the information needed to resolve a TIR-encoded transaction
390/// template into a concrete UTxO transaction, including the template itself, arguments,
391/// and optional environment variables.
392///
393/// # Fields
394///
395/// * `tir` - The Transaction Intermediate Representation envelope containing the template
396/// * `args` - Arguments to populate the template parameters
397/// * `env` - Optional environment variables for resolution context
398///
399/// # Example
400///
401/// ```ignore
402/// use tx3_sdk::trp::ResolveParams;
403/// use tx3_sdk::core::TirEnvelope;
404///
405/// let params = ResolveParams {
406///     tir: TirEnvelope {
407///         content: "a10081825820...".to_string(),
408///         encoding: tx3_sdk::core::TirEncoding::Hex,
409///         version: "v1beta0".to_string(),
410///     },
411///     args: serde_json::Map::new(),
412///     env: None,
413/// };
414/// ```
415#[derive(Debug, Clone, Serialize, Deserialize)]
416pub struct ResolveParams {
417    /// Arguments to populate the transaction template parameters.
418    #[serde(rename = "args")]
419    pub args: ArgMap,
420
421    /// The TIR envelope containing the transaction template.
422    #[serde(rename = "tir")]
423    pub tir: TirEnvelope,
424
425    /// Optional environment variables for transaction resolution.
426    #[serde(rename = "env", skip_serializing_if = "Option::is_none")]
427    pub env: Option<EnvMap>,
428}
429
430/// Diagnostic information about the search space for input resolution.
431///
432/// Provides details about the UTXO search space when an input cannot be resolved,
433/// helping debug why a particular input query failed.
434///
435/// # Fields
436///
437/// * `by_address_count` - Number of UTXOs found by address
438/// * `by_asset_class_count` - Number of UTXOs found by asset class
439/// * `by_ref_count` - Number of UTXOs found by reference
440/// * `matched` - List of matched UTXO references
441#[derive(Debug, Clone, Serialize, Deserialize)]
442pub struct SearchSpaceDiagnostic {
443    /// Count of UTXOs found by address query.
444    #[serde(rename = "byAddressCount", skip_serializing_if = "Option::is_none")]
445    pub by_address_count: Option<i64>,
446
447    /// Count of UTXOs found by asset class query.
448    #[serde(rename = "byAssetClassCount", skip_serializing_if = "Option::is_none")]
449    pub by_asset_class_count: Option<i64>,
450
451    /// Count of UTXOs found by reference query.
452    #[serde(rename = "byRefCount", skip_serializing_if = "Option::is_none")]
453    pub by_ref_count: Option<i64>,
454
455    /// List of matched UTXO references.
456    #[serde(rename = "matched")]
457    pub matched: Vec<String>,
458}
459
460/// Diagnostic information about an input query.
461///
462/// Contains the details of an input query that was attempted during
463/// transaction resolution.
464///
465/// # Fields
466///
467/// * `address` - The address being queried (if any)
468/// * `collateral` - Whether this is a collateral input
469/// * `min_amount` - Minimum amount requirements
470/// * `refs` - Specific UTXO references to include
471/// * `support_many` - Whether multiple UTXOs are supported
472#[derive(Debug, Clone, Serialize, Deserialize)]
473pub struct InputQueryDiagnostic {
474    /// The address being queried.
475    #[serde(rename = "address", skip_serializing_if = "Option::is_none")]
476    pub address: Option<String>,
477
478    /// Whether this is a collateral input.
479    #[serde(rename = "collateral")]
480    pub collateral: bool,
481
482    /// Minimum amount requirements by asset.
483    #[serde(rename = "minAmount")]
484    pub min_amount: std::collections::HashMap<String, String>,
485
486    /// Specific UTXO references to include.
487    #[serde(rename = "refs")]
488    pub refs: Vec<String>,
489
490    /// Whether multiple UTXOs are supported.
491    #[serde(rename = "supportMany")]
492    pub support_many: bool,
493}
494
495/// Diagnostic for unsupported TIR version.
496///
497/// Returned when the provided TIR version is not supported by the TRP server.
498///
499/// # Fields
500///
501/// * `expected` - The expected TIR version
502/// * `provided` - The version that was provided
503#[derive(Debug, Clone, Serialize, Deserialize)]
504pub struct UnsupportedTirDiagnostic {
505    /// The expected TIR version.
506    #[serde(rename = "expected")]
507    pub expected: String,
508
509    /// The TIR version that was provided.
510    #[serde(rename = "provided")]
511    pub provided: String,
512}
513
514/// Diagnostic for an unresolved input.
515///
516/// Provides detailed information about why a specific input could not be
517/// resolved during transaction construction.
518///
519/// # Fields
520///
521/// * `name` - The name of the unresolved input
522/// * `query` - The input query that was attempted
523/// * `search_space` - Information about the search space
524#[derive(Debug, Clone, Serialize, Deserialize)]
525pub struct InputNotResolvedDiagnostic {
526    /// The name of the input.
527    #[serde(rename = "name")]
528    pub name: String,
529
530    /// The input query details.
531    #[serde(rename = "query")]
532    pub query: InputQueryDiagnostic,
533
534    /// Search space diagnostic information.
535    #[serde(rename = "search_space")]
536    pub search_space: SearchSpaceDiagnostic,
537}
538
539/// Diagnostic for a missing transaction argument.
540///
541/// Returned when a required argument is not provided for a transaction
542/// template.
543///
544/// # Fields
545///
546/// * `key` - The name of the missing argument
547/// * `arg_type` - The expected type of the argument
548#[derive(Debug, Clone, Serialize, Deserialize)]
549pub struct MissingTxArgDiagnostic {
550    /// The name of the missing argument.
551    #[serde(rename = "key")]
552    pub key: String,
553
554    /// The expected type of the argument.
555    #[serde(rename = "type")]
556    pub arg_type: String,
557}
558
559/// Diagnostic for transaction script failure.
560///
561/// Contains log output from failed transaction script execution.
562///
563/// # Fields
564///
565/// * `logs` - Script execution log messages
566#[derive(Debug, Clone, Serialize, Deserialize)]
567pub struct TxScriptFailureDiagnostic {
568    /// Script execution log messages.
569    #[serde(rename = "logs")]
570    pub logs: Vec<String>,
571}