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}