The Swift Package Index logo.Swift Package Index

Build Information

Successful build of SwiftOgmios, reference main (1fa70f), with Swift 6.3 for macOS (SPM) on 28 Sep 2026 16:20:00 UTC.

Swift 6 data race errors: 0

Build Command

env DEVELOPER_DIR=/Applications/Xcode-26.5.0.app xcrun swift build --arch arm64

Build Log

405 +                         }
406 +                     }
407 +                 }
408 +             }
409 +         }
410 +
411 +         // Check inputs for watched addresses (requires UTxO lookup)
412 +         // This would typically require maintaining a UTxO set
413 +
414 +         return false
415 +     }
416 + }
417 +
418 + // Usage in block processing
419 + private let transactionFilter = TransactionFilter(
420 +     addresses: ["addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer..."],
421 +     assets: ["3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e.546f6b656e41"]
422 + )
423 +
424 + private func processBlock(_ block: Block) async {
425 +     guard let transactions = block.body else { return }
426 +
427 +     let relevantTransactions = transactions.filter { transaction in
428 +         transactionFilter.isRelevant(transaction)
429 +     }
430 +
431 +     if !relevantTransactions.isEmpty {
432 +         print("Found \(relevantTransactions.count) relevant transactions in block \(block.header.blockHeight)")
433 +
434 +         for transaction in relevantTransactions {
435 +             await handleRelevantTransaction(transaction)
436 +         }
437 +     }
438 + }
439 + ```
440 |
441 | ### Building a Block Database
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ChainSynchronization.md:443:1-499:4
441 | ### Building a Block Database
442 |
443 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
444 + actor BlockDatabase {
445 +     private var blocks: [BlockHeight: Block] = [:]
446 +     private var transactions: [String: Transaction] = [:]
447 +     private var tipHeight: BlockHeight = 0
448 +
449 +     func addBlock(_ block: Block) {
450 +         blocks[block.header.blockHeight] = block
451 +         tipHeight = max(tipHeight, block.header.blockHeight)
452 +
453 +         // Index transactions
454 +         if let txs = block.body {
455 +             for tx in txs {
456 +                 transactions[tx.id] = tx
457 +             }
458 +         }
459 +     }
460 +
461 +     func rollbackTo(_ height: BlockHeight) {
462 +         // Remove blocks after the rollback point
463 +         let blocksToRemove = blocks.keys.filter { $0 > height }
464 +
465 +         for blockHeight in blocksToRemove {
466 +             if let block = blocks[blockHeight] {
467 +                 // Remove transactions from this block
468 +                 if let txs = block.body {
469 +                     for tx in txs {
470 +                         transactions.removeValue(forKey: tx.id)
471 +                     }
472 +                 }
473 +
474 +                 blocks.removeValue(forKey: blockHeight)
475 +             }
476 +         }
477 +
478 +         tipHeight = height
479 +     }
480 +
481 +     func getBlock(at height: BlockHeight) -> Block? {
482 +         return blocks[height]
483 +     }
484 +
485 +     func getTransaction(_ id: String) -> Transaction? {
486 +         return transactions[id]
487 +     }
488 +
489 +     func getTipHeight() -> BlockHeight {
490 +         return tipHeight
491 +     }
492 +
493 +     func getBlockRange(from: BlockHeight, to: BlockHeight) -> [Block] {
494 +         return (from...to).compactMap { height in
495 +             blocks[height]
496 +         }
497 +     }
498 + }
499 + ```
500 |
501 | ## Error Handling and Resilience
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ChainSynchronization.md:503:1-621:4
501 | ## Error Handling and Resilience
502 |
503 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
504 + actor ResilientChainSync {
505 +     private let client: OgmiosClient
506 +     private let database: BlockDatabase
507 +     private var isRunning = false
508 +     private let maxRetries = 3
509 +
510 +     init(client: OgmiosClient) {
511 +         self.client = client
512 +         self.database = BlockDatabase()
513 +     }
514 +
515 +     func startSync() async {
516 +         guard !isRunning else { return }
517 +         isRunning = true
518 +
519 +         var retryCount = 0
520 +
521 +         while isRunning && retryCount < maxRetries {
522 +             do {
523 +                 await performSync()
524 +                 retryCount = 0 // Reset on success
525 +             } catch {
526 +                 retryCount += 1
527 +                 print("Chain sync error (attempt \(retryCount)): \(error)")
528 +
529 +                 if retryCount < maxRetries {
530 +                     // Exponential backoff
531 +                     let delay = min(pow(2.0, Double(retryCount)), 60.0)
532 +                     try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
533 +                 } else {
534 +                     print("Max retries exceeded, stopping sync")
535 +                     isRunning = false
536 +                 }
537 +             }
538 +         }
539 +     }
540 +
541 +     private func performSync() async throws {
542 +         // Get current tip from database to resume sync
543 +         let currentTip = await database.getTipHeight()
544 +
545 +         // Find intersection point
546 +         let knownPoints = await buildIntersectionPoints(from: currentTip)
547 +         let intersection = try await client.chainSync.findIntersection.execute(
548 +             points: knownPoints,
549 +             id: .generateNextNanoId()
550 +         )
551 +
552 +         // Handle intersection result
553 +         switch intersection.result {
554 +         case .intersectionFound(let point):
555 +             print("Resuming sync from: \(point)")
556 +         case .intersectionNotFound:
557 +             print("No intersection found, starting from genesis")
558 +         }
559 +
560 +         // Stream blocks
561 +         while isRunning {
562 +             let blockResponse = try await client.chainSync.nextBlock.execute(
563 +                 id: .generateNextNanoId()
564 +             )
565 +
566 +             await handleBlockResponse(blockResponse.result)
567 +         }
568 +     }
569 +
570 +     private func buildIntersectionPoints(from tipHeight: BlockHeight) async -> [Point] {
571 +         // Build intersection points from recent blocks
572 +         var points: [Point] = []
573 +
574 +         // Add recent blocks for intersection finding
575 +         for height in stride(from: tipHeight, through: max(0, tipHeight - 100), by: -10) {
576 +             if let block = await database.getBlock(at: height) {
577 +                 let point = Point(slot: block.header.slot, id: block.header.hash)
578 +                 points.append(point)
579 +             }
580 +         }
581 +
582 +         return points
583 +     }
584 +
585 +     private func handleBlockResponse(_ result: NextBlockResult) async {
586 +         switch result.direction {
587 +         case .forward:
588 +             await handleForwardBlock(result.block)
589 +         case .backward:
590 +             await handleRollback(result.block)
591 +         }
592 +     }
593 +
594 +     private func handleForwardBlock(_ block: NextBlockResult.Block) async {
595 +         switch block {
596 +         case .block(let blockData):
597 +             await database.addBlock(blockData)
598 +             print("Added block: \(blockData.header.blockHeight)")
599 +
600 +         case .origin:
601 +             print("Reached origin")
602 +         }
603 +     }
604 +
605 +     private func handleRollback(_ point: NextBlockResult.Block) async {
606 +         switch point {
607 +         case .block(let blockData):
608 +             await database.rollbackTo(blockData.header.blockHeight)
609 +             print("Rolled back to block: \(blockData.header.blockHeight)")
610 +
611 +         case .origin:
612 +             await database.rollbackTo(0)
613 +             print("Rolled back to genesis")
614 +         }
615 +     }
616 +
617 +     func stop() {
618 +         isRunning = false
619 +     }
620 + }
621 + ```
622 |
623 | ## Performance Considerations
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ChainSynchronization.md:627:1-665:4
625 | ### Batch Processing
626 |
627 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
628 + actor BatchProcessor {
629 +     private var pendingBlocks: [Block] = []
630 +     private let batchSize = 10
631 +     private let processingQueue = DispatchQueue(label: "block-processing", qos: .utility)
632 +
633 +     func addBlock(_ block: Block) async {
634 +         pendingBlocks.append(block)
635 +
636 +         if pendingBlocks.count >= batchSize {
637 +             await processBatch()
638 +         }
639 +     }
640 +
641 +     func flush() async {
642 +         if !pendingBlocks.isEmpty {
643 +             await processBatch()
644 +         }
645 +     }
646 +
647 +     private func processBatch() async {
648 +         let batch = pendingBlocks
649 +         pendingBlocks.removeAll()
650 +
651 +         await withTaskGroup(of: Void.self) { group in
652 +             for block in batch {
653 +                 group.addTask {
654 +                     await self.processBlockConcurrently(block)
655 +                 }
656 +             }
657 +         }
658 +     }
659 +
660 +     private func processBlockConcurrently(_ block: Block) async {
661 +         // Heavy processing work
662 +         print("Processing block \(block.header.blockHeight) concurrently")
663 +     }
664 + }
665 + ```
666 |
667 | ### Memory Management
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ChainSynchronization.md:669:1-693:4
667 | ### Memory Management
668 |
669 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
670 + actor MemoryEfficientChainSync {
671 +     private let maxBlocksInMemory = 1000
672 +     private var blockHeights: [BlockHeight] = []
673 +     private weak var delegate: ChainSyncDelegate?
674 +
675 +     func addBlock(_ block: Block) async {
676 +         // Process immediately to avoid memory buildup
677 +         await delegate?.didReceiveBlock(block)
678 +
679 +         blockHeights.append(block.header.blockHeight)
680 +
681 +         // Cleanup old blocks if memory limit exceeded
682 +         if blockHeights.count > maxBlocksInMemory {
683 +             let oldestHeight = blockHeights.removeFirst()
684 +             await delegate?.shouldCleanupBlock(at: oldestHeight)
685 +         }
686 +     }
687 + }
688 +
689 + protocol ChainSyncDelegate: Actor {
690 +     func didReceiveBlock(_ block: Block) async
691 +     func shouldCleanupBlock(at height: BlockHeight) async
692 + }
693 + ```
694 |
695 | ## Testing Chain Sync
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ChainSynchronization.md:697:1-762:4
695 | ## Testing Chain Sync
696 |
697 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
698 + import XCTest
699 + @testable import SwiftOgmios
700 +
701 + class ChainSyncTests: XCTestCase {
702 +     func testBasicChainSync() async throws {
703 +         let mockClient = try await OgmiosClient(
704 +             httpOnly: false,
705 +             webSocketConnection: MockWebSocketConnection()
706 +         )
707 +
708 +         let manager = ChainSyncManager(client: mockClient)
709 +         var receivedBlocks: [Block] = []
710 +
711 +         let blockStream = await manager.createBlockStream()
712 +
713 +         // Collect first few results
714 +         var resultCount = 0
715 +         for try await result in blockStream {
716 +             switch result {
717 +             case .blockReceived(let blockResult):
718 +                 if case .block(let block) = blockResult.block {
719 +                     receivedBlocks.append(block)
720 +                 }
721 +
722 +             case .intersectionFound(_):
723 +                 break
724 +             }
725 +
726 +             resultCount += 1
727 +             if resultCount >= 5 { break }
728 +         }
729 +
730 +         XCTAssertGreaterThan(receivedBlocks.count, 0)
731 +     }
732 +
733 +     func testRollbackHandling() async throws {
734 +         let database = BlockDatabase()
735 +
736 +         // Add some blocks
737 +         let block1 = createMockBlock(height: 100)
738 +         let block2 = createMockBlock(height: 101)
739 +         let block3 = createMockBlock(height: 102)
740 +
741 +         await database.addBlock(block1)
742 +         await database.addBlock(block2)
743 +         await database.addBlock(block3)
744 +
745 +         XCTAssertEqual(await database.getTipHeight(), 102)
746 +
747 +         // Simulate rollback
748 +         await database.rollbackTo(100)
749 +
750 +         XCTAssertEqual(await database.getTipHeight(), 100)
751 +         XCTAssertNil(await database.getBlock(at: 101))
752 +         XCTAssertNil(await database.getBlock(at: 102))
753 +         XCTAssertNotNil(await database.getBlock(at: 100))
754 +     }
755 +
756 +     private func createMockBlock(height: BlockHeight) -> Block {
757 +         // Create mock block for testing
758 +         // Implementation depends on your Block structure
759 +         fatalError("Implement mock block creation")
760 +     }
761 + }
762 + ```
763 |
764 | ## Best Practices
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ChainSynchronization.md:776:3-776:55
774 | ## See Also
775 |
776 + - <doc:GettingStarted> - Basic setup and first queries
    |   ╰─suggestion: Remove extraneous content
777 | - <doc:ErrorHandling> - Handling chain sync errors and reconnections
778 | - <doc:AdvancedUsage> - Advanced concurrency patterns for chain sync
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ChainSynchronization.md:777:3-777:69
775 |
776 | - <doc:GettingStarted> - Basic setup and first queries
777 + - <doc:ErrorHandling> - Handling chain sync errors and reconnections
    |   ╰─suggestion: Remove extraneous content
778 | - <doc:AdvancedUsage> - Advanced concurrency patterns for chain sync
779 | - <doc:TransactionSubmission> - Submitting transactions after chain sync
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ChainSynchronization.md:778:3-778:69
776 | - <doc:GettingStarted> - Basic setup and first queries
777 | - <doc:ErrorHandling> - Handling chain sync errors and reconnections
778 + - <doc:AdvancedUsage> - Advanced concurrency patterns for chain sync
    |   ╰─suggestion: Remove extraneous content
779 | - <doc:TransactionSubmission> - Submitting transactions after chain sync
780 | - <doc:MempoolMonitoring> - Monitoring transactions in real-time
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ChainSynchronization.md:779:3-779:73
777 | - <doc:ErrorHandling> - Handling chain sync errors and reconnections
778 | - <doc:AdvancedUsage> - Advanced concurrency patterns for chain sync
779 + - <doc:TransactionSubmission> - Submitting transactions after chain sync
    |   ╰─suggestion: Remove extraneous content
780 | - <doc:MempoolMonitoring> - Monitoring transactions in real-time
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ChainSynchronization.md:780:3-780:65
778 | - <doc:AdvancedUsage> - Advanced concurrency patterns for chain sync
779 | - <doc:TransactionSubmission> - Submitting transactions after chain sync
780 + - <doc:MempoolMonitoring> - Monitoring transactions in real-time
    |   ╰─suggestion: Remove extraneous content
warning: Unknown option 'swift path' in code block.
  --> Tutorials/ErrorHandling.md:15:1-25:4
13 | ### OgmiosError Types
14 |
15 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
16 + public enum OgmiosError: LocalizedError, Sendable {
17 +     case httpError(String)
18 +     case websocketError(String)
19 +     case responseError(String)
20 +     case invalidResponse(String)
21 +     case timeoutError(String)
22 +     case invalidFormat(String)
23 +     case invalidMethodError(String)
24 + }
25 + ```
26 |
27 | #### Transport Errors
warning: Unknown option 'swift path' in code block.
  --> Tutorials/ErrorHandling.md:30:1-37:4
28 |
29 | **HTTP Errors**: Connection and HTTP-specific failures
30 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
31 + do {
32 +     let response = try await client.ledgerStateQuery.epoch.execute()
33 + } catch OgmiosError.httpError(let message) {
34 +     print("HTTP connection failed: \(message)")
35 +     // Handle: retry with backoff, switch to backup server, notify user
36 + }
37 + ```
38 |
39 | **WebSocket Errors**: WebSocket connection and communication failures
warning: Unknown option 'swift path' in code block.
  --> Tutorials/ErrorHandling.md:40:1-47:4
38 |
39 | **WebSocket Errors**: WebSocket connection and communication failures
40 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
41 + do {
42 +     let response = try await client.chainSync.nextBlock.execute()
43 + } catch OgmiosError.websocketError(let message) {
44 +     print("WebSocket error: \(message)")
45 +     // Handle: reconnect, fallback to HTTP, notify user of connection loss
46 + }
47 + ```
48 |
49 | #### Protocol Errors
warning: Unknown option 'swift path' in code block.
  --> Tutorials/ErrorHandling.md:52:1-62:4
50 |
51 | **Response Errors**: Ogmios server returned an error response
52 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
53 + do {
54 +     let response = try await client.ledgerStateQuery.constitution.execute()
55 + } catch OgmiosError.responseError(let message) {
56 +     print("Server error: \(message)")
57 +     // Parse error code for specific handling
58 +     if message.contains("2001") {
59 +         print("Era mismatch - query not available in current era")
60 +     }
61 + }
62 + ```
63 |
64 | **Invalid Response**: Malformed or unexpected response format
warning: Unknown option 'swift path' in code block.
  --> Tutorials/ErrorHandling.md:65:1-72:4
63 |
64 | **Invalid Response**: Malformed or unexpected response format
65 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
66 + do {
67 +     let response = try await client.ledgerStateQuery.tip.execute()
68 + } catch OgmiosError.invalidResponse(let message) {
69 +     print("Invalid response format: \(message)")
70 +     // Handle: log for debugging, retry, report to monitoring
71 + }
72 + ```
73 |
74 | #### Application Errors
warning: Unknown option 'swift path' in code block.
  --> Tutorials/ErrorHandling.md:77:1-84:4
75 |
76 | **Timeout Errors**: Operations that exceed time limits
77 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
78 + do {
79 +     try await client.mempoolMonitor.waitForEmptyMempool(timeoutSeconds: 30.0)
80 + } catch OgmiosError.timeoutError(let message) {
81 +     print("Operation timed out: \(message)")
82 +     // Handle: extend timeout, cancel operation, notify user
83 + }
84 + ```
85 |
86 | ## JSON-RPC Error Codes
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:111:1-145:4
109 | ### Error Code Detection
110 |
111 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
112 + extension OgmiosError {
113 +     var errorCode: Int? {
114 +         switch self {
115 +         case .responseError(let message):
116 +             // Extract error code from message
117 +             let codeRegex = try! NSRegularExpression(pattern: #"(\d{4})"#)
118 +             let range = NSRange(message.startIndex..<message.endIndex, in: message)
119 +
120 +             if let match = codeRegex.firstMatch(in: message, options: [], range: range) {
121 +                 let codeRange = Range(match.range(at: 1), in: message)!
122 +                 return Int(String(message[codeRange]))
123 +             }
124 +             return nil
125 +         default:
126 +             return nil
127 +         }
128 +     }
129 +
130 +     var isRetryable: Bool {
131 +         switch self {
132 +         case .httpError(_), .websocketError(_):
133 +             return true // Network errors are typically retryable
134 +         case .responseError(let message):
135 +             // Some response errors are retryable
136 +             guard let code = errorCode else { return false }
137 +             return code == 2003 // Acquired expired
138 +         case .timeoutError(_):
139 +             return true
140 +         default:
141 +             return false
142 +         }
143 +     }
144 + }
145 + ```
146 |
147 | ## Retry Strategies
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:151:1-178:4
149 | ### Basic Retry Pattern
150 |
151 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
152 + func withRetry<T>(
153 +     operation: @escaping () async throws -> T,
154 +     maxAttempts: Int = 3,
155 +     delay: TimeInterval = 1.0
156 + ) async throws -> T {
157 +     var lastError: Error?
158 +
159 +     for attempt in 1...maxAttempts {
160 +         do {
161 +             return try await operation()
162 +         } catch let error as OgmiosError where error.isRetryable && attempt < maxAttempts {
163 +             print("Attempt \(attempt) failed, retrying in \(delay)s: \(error.localizedDescription)")
164 +             lastError = error
165 +             try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
166 +         } catch {
167 +             throw error // Non-retryable error or final attempt
168 +         }
169 +     }
170 +
171 +     throw lastError ?? OgmiosError.responseError("Max attempts exceeded")
172 + }
173 +
174 + // Usage
175 + let epochResponse = try await withRetry {
176 +     return try await client.ledgerStateQuery.epoch.execute()
177 + }
178 + ```
179 |
180 | ### Exponential Backoff
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:182:1-207:4
180 | ### Exponential Backoff
181 |
182 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
183 + func withExponentialBackoff<T>(
184 +     operation: @escaping () async throws -> T,
185 +     maxAttempts: Int = 3,
186 +     baseDelay: TimeInterval = 1.0,
187 +     maxDelay: TimeInterval = 60.0
188 + ) async throws -> T {
189 +     var lastError: Error?
190 +
191 +     for attempt in 1...maxAttempts {
192 +         do {
193 +             return try await operation()
194 +         } catch let error as OgmiosError where error.isRetryable && attempt < maxAttempts {
195 +             let delay = min(baseDelay * pow(2.0, Double(attempt - 1)), maxDelay)
196 +             print("Attempt \(attempt) failed, retrying in \(String(format: "%.1f", delay))s")
197 +
198 +             lastError = error
199 +             try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
200 +         } catch {
201 +             throw error
202 +         }
203 +     }
204 +
205 +     throw lastError ?? OgmiosError.responseError("Max attempts exceeded")
206 + }
207 + ```
208 |
209 | ### Circuit Breaker Pattern
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:211:1-270:4
209 | ### Circuit Breaker Pattern
210 |
211 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
212 + actor CircuitBreaker {
213 +     enum State {
214 +         case closed    // Normal operation
215 +         case open      // Failing fast
216 +         case halfOpen  // Testing recovery
217 +     }
218 +
219 +     private var state: State = .closed
220 +     private var failureCount = 0
221 +     private var lastFailureTime: Date?
222 +     private let failureThreshold = 5
223 +     private let timeout: TimeInterval = 30.0
224 +
225 +     func execute<T>(_ operation: @escaping () async throws -> T) async throws -> T {
226 +         switch state {
227 +         case .open:
228 +             if let lastFailure = lastFailureTime,
229 +                Date().timeIntervalSince(lastFailure) > timeout {
230 +                 state = .halfOpen
231 +             } else {
232 +                 throw OgmiosError.responseError("Circuit breaker is open")
233 +             }
234 +
235 +         case .halfOpen, .closed:
236 +             break
237 +         }
238 +
239 +         do {
240 +             let result = try await operation()
241 +             await onSuccess()
242 +             return result
243 +         } catch {
244 +             await onFailure()
245 +             throw error
246 +         }
247 +     }
248 +
249 +     private func onSuccess() {
250 +         failureCount = 0
251 +         state = .closed
252 +     }
253 +
254 +     private func onFailure() {
255 +         failureCount += 1
256 +         lastFailureTime = Date()
257 +
258 +         if failureCount >= failureThreshold {
259 +             state = .open
260 +         }
261 +     }
262 + }
263 +
264 + // Usage
265 + let circuitBreaker = CircuitBreaker()
266 +
267 + let response = try await circuitBreaker.execute {
268 +     return try await client.ledgerStateQuery.epoch.execute()
269 + }
270 + ```
271 |
272 | ## Comprehensive Error Handling Service
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:274:1-402:4
272 | ## Comprehensive Error Handling Service
273 |
274 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
275 + @MainActor
276 + class OgmiosErrorHandler: ObservableObject {
277 +     @Published var connectionStatus: ConnectionStatus = .disconnected
278 +     @Published var lastError: OgmiosError?
279 +     @Published var errorHistory: [ErrorRecord] = []
280 +
281 +     enum ConnectionStatus {
282 +         case connected
283 +         case disconnected
284 +         case reconnecting
285 +         case failed
286 +     }
287 +
288 +     struct ErrorRecord {
289 +         let error: OgmiosError
290 +         let timestamp: Date
291 +         let operation: String
292 +     }
293 +
294 +     private let maxErrorHistory = 100
295 +
296 +     func handle(_ error: Error, operation: String) {
297 +         guard let ogmiosError = error as? OgmiosError else {
298 +             print("Non-Ogmios error: \(error)")
299 +             return
300 +         }
301 +
302 +         let record = ErrorRecord(
303 +             error: ogmiosError,
304 +             timestamp: Date(),
305 +             operation: operation
306 +         )
307 +
308 +         // Update published properties
309 +         lastError = ogmiosError
310 +         errorHistory.insert(record, at: 0)
311 +         if errorHistory.count > maxErrorHistory {
312 +             errorHistory.removeLast()
313 +         }
314 +
315 +         // Update connection status
316 +         updateConnectionStatus(from: ogmiosError)
317 +
318 +         // Log error with context
319 +         logError(record)
320 +
321 +         // Send to monitoring service (if configured)
322 +         reportToMonitoring(record)
323 +     }
324 +
325 +     private func updateConnectionStatus(from error: OgmiosError) {
326 +         switch error {
327 +         case .httpError(_), .websocketError(_):
328 +             connectionStatus = .failed
329 +         case .responseError(let message):
330 +             if let code = error.errorCode, code == 2003 {
331 +                 // Acquired expired - connection is fine, just need to retry
332 +                 connectionStatus = .connected
333 +             } else {
334 +                 connectionStatus = .connected // Server responded, connection is OK
335 +             }
336 +         case .timeoutError(_):
337 +             connectionStatus = .reconnecting
338 +         default:
339 +             connectionStatus = .connected
340 +         }
341 +     }
342 +
343 +     private func logError(_ record: ErrorRecord) {
344 +         let timestamp = DateFormatter.iso8601.string(from: record.timestamp)
345 +         print("[\(timestamp)] ERROR in \(record.operation): \(record.error.localizedDescription)")
346 +
347 +         // Add additional context based on error type
348 +         switch record.error {
349 +         case .responseError(let message):
350 +             if let code = record.error.errorCode {
351 +                 print("  Error code: \(code)")
352 +                 print("  Suggested action: \(suggestedAction(for: code))")
353 +             }
354 +         case .httpError(_), .websocketError(_):
355 +             print("  Suggested action: Check network connection and server availability")
356 +         case .timeoutError(_):
357 +             print("  Suggested action: Consider increasing timeout or optimizing query")
358 +         default:
359 +             break
360 +         }
361 +     }
362 +
363 +     private func suggestedAction(for errorCode: Int) -> String {
364 +         switch errorCode {
365 +         case 2001: return "Check current era and use compatible queries"
366 +         case 2002: return "Query not available in current era"
367 +         case 2003: return "Retry query to get fresh ledger snapshot"
368 +         case 3005: return "Rebuild transaction for current era"
369 +         case 3100, 3101: return "Check and fix transaction signatures"
370 +         case 3122: return "Increase transaction fee"
371 +         case 3123: return "Fix transaction input/output balance"
372 +         default: return "Check Ogmios documentation for error code \(errorCode)"
373 +         }
374 +     }
375 +
376 +     private func reportToMonitoring(_ record: ErrorRecord) {
377 +         // Implement monitoring service integration
378 +         // e.g., send to Sentry, DataDog, custom analytics
379 +     }
380 +
381 +     func clearErrorHistory() {
382 +         errorHistory.removeAll()
383 +         lastError = nil
384 +     }
385 +
386 +     func retry<T>(_ operation: @escaping () async throws -> T, operationName: String) async throws -> T {
387 +         do {
388 +             let result = try await withExponentialBackoff(operation: operation)
389 +
390 +             // Success - update connection status if it was failing
391 +             if connectionStatus == .failed || connectionStatus == .reconnecting {
392 +                 connectionStatus = .connected
393 +             }
394 +
395 +             return result
396 +         } catch {
397 +             handle(error, operation: operationName)
398 +             throw error
399 +         }
400 +     }
401 + }
402 + ```
403 |
404 | ## Error Handling in SwiftUI
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:406:1-527:4
404 | ## Error Handling in SwiftUI
405 |
406 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
407 + import SwiftUI
408 + import SwiftOgmios
409 +
410 + struct CardanoDataView: View {
411 +     @StateObject private var errorHandler = OgmiosErrorHandler()
412 +     @StateObject private var dataService = CardanoDataService()
413 +
414 +     @State private var currentEpoch: Int?
415 +     @State private var isLoading = false
416 +
417 +     var body: some View {
418 +         VStack {
419 +             // Connection status indicator
420 +             HStack {
421 +                 Circle()
422 +                     .fill(connectionStatusColor)
423 +                     .frame(width: 12, height: 12)
424 +                 Text(connectionStatusText)
425 +                     .font(.caption)
426 +                     .foregroundColor(.secondary)
427 +             }
428 +
429 +             // Main content
430 +             Group {
431 +                 if isLoading {
432 +                     ProgressView("Loading...")
433 +                 } else if let epoch = currentEpoch {
434 +                     VStack {
435 +                         Text("Current Epoch")
436 +                             .font(.headline)
437 +                         Text("\(epoch)")
438 +                             .font(.largeTitle)
439 +                             .bold()
440 +                     }
441 +                 } else {
442 +                     Text("No data available")
443 +                         .foregroundColor(.secondary)
444 +                 }
445 +             }
446 +
447 +             // Error display
448 +             if let lastError = errorHandler.lastError {
449 +                 ErrorBannerView(error: lastError) {
450 +                     Task { await loadData() }
451 +                 }
452 +             }
453 +
454 +             // Retry button
455 +             Button("Refresh") {
456 +                 Task { await loadData() }
457 +             }
458 +             .disabled(isLoading)
459 +         }
460 +         .task {
461 +             await loadData()
462 +         }
463 +         .environmentObject(errorHandler)
464 +     }
465 +
466 +     private var connectionStatusColor: Color {
467 +         switch errorHandler.connectionStatus {
468 +         case .connected: return .green
469 +         case .reconnecting: return .yellow
470 +         case .disconnected, .failed: return .red
471 +         }
472 +     }
473 +
474 +     private var connectionStatusText: String {
475 +         switch errorHandler.connectionStatus {
476 +         case .connected: return "Connected"
477 +         case .reconnecting: return "Reconnecting..."
478 +         case .disconnected: return "Disconnected"
479 +         case .failed: return "Connection Failed"
480 +         }
481 +     }
482 +
483 +     @MainActor
484 +     private func loadData() async {
485 +         isLoading = true
486 +         defer { isLoading = false }
487 +
488 +         do {
489 +             currentEpoch = try await errorHandler.retry({
490 +                 let response = try await dataService.client.ledgerStateQuery.epoch.execute()
491 +                 return response.result
492 +             }, operationName: "fetch-current-epoch")
493 +         } catch {
494 +             // Error already handled by errorHandler.retry
495 +             currentEpoch = nil
496 +         }
497 +     }
498 + }
499 +
500 + struct ErrorBannerView: View {
501 +     let error: OgmiosError
502 +     let onRetry: () -> Void
503 +
504 +     var body: some View {
505 +         HStack {
506 +             Image(systemName: "exclamationmark.triangle.fill")
507 +                 .foregroundColor(.red)
508 +
509 +             VStack(alignment: .leading, spacing: 4) {
510 +                 Text("Error")
511 +                     .font(.headline)
512 +                 Text(error.localizedDescription)
513 +                     .font(.caption)
514 +                     .foregroundColor(.secondary)
515 +             }
516 +
517 +             Spacer()
518 +
519 +             Button("Retry", action: onRetry)
520 +                 .buttonStyle(.bordered)
521 +         }
522 +         .padding()
523 +         .background(Color.red.opacity(0.1))
524 +         .cornerRadius(8)
525 +     }
526 + }
527 + ```
528 |
529 | ## Logging and Diagnostics
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:533:1-566:4
531 | ### Structured Logging
532 |
533 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
534 + import os.log
535 +
536 + extension OgmiosClient {
537 +     private static let logger = Logger(
538 +         subsystem: "com.yourapp.ogmios",
539 +         category: "client"
540 +     )
541 +
542 +     func logRequest(_ request: any JSONRPCRequest) {
543 +         Self.logger.debug("Sending request: \(request.method) (ID: \(request.id?.description ?? "none"))")
544 +     }
545 +
546 +     func logResponse<T>(_ response: T) where T: JSONRPCResponse {
547 +         Self.logger.debug("Received response: \(response.method) (ID: \(response.id?.description ?? "none"))")
548 +     }
549 +
550 +     func logError(_ error: OgmiosError, context: String) {
551 +         Self.logger.error("Error in \(context): \(error.localizedDescription)")
552 +
553 +         // Add error-specific details
554 +         switch error {
555 +         case .responseError(let message):
556 +             if let code = error.errorCode {
557 +                 Self.logger.error("Error code: \(code)")
558 +             }
559 +         case .httpError(let message), .websocketError(let message):
560 +             Self.logger.error("Transport error: \(message)")
561 +         default:
562 +             break
563 +         }
564 +     }
565 + }
566 + ```
567 |
568 | ### Diagnostic Information Collection
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:570:1-624:4
568 | ### Diagnostic Information Collection
569 |
570 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
571 + struct DiagnosticInfo: Codable {
572 +     let timestamp: Date
573 +     let clientVersion: String
574 +     let serverHealth: Health?
575 +     let connectionType: String
576 +     let lastError: String?
577 +     let errorHistory: [ErrorSummary]
578 +
579 +     struct ErrorSummary: Codable {
580 +         let error: String
581 +         let timestamp: Date
582 +         let operation: String
583 +     }
584 + }
585 +
586 + extension OgmiosErrorHandler {
587 +     func generateDiagnosticInfo(client: OgmiosClient) async -> DiagnosticInfo {
588 +         let serverHealth = try? await client.getServerHealth()
589 +
590 +         let errorSummaries = errorHistory.map { record in
591 +             DiagnosticInfo.ErrorSummary(
592 +                 error: record.error.localizedDescription,
593 +                 timestamp: record.timestamp,
594 +                 operation: record.operation
595 +             )
596 +         }
597 +
598 +         return DiagnosticInfo(
599 +             timestamp: Date(),
600 +             clientVersion: "1.0.0", // Your app version
601 +             serverHealth: serverHealth,
602 +             connectionType: client.isWebSocketTransport ? "WebSocket" : "HTTP",
603 +             lastError: lastError?.localizedDescription,
604 +             errorHistory: errorSummaries
605 +         )
606 +     }
607 +
608 +     func exportDiagnostics(client: OgmiosClient) async -> URL {
609 +         let diagnostics = await generateDiagnosticInfo(client: client)
610 +         let encoder = JSONEncoder()
611 +         encoder.dateEncodingStrategy = .iso8601
612 +         encoder.outputFormatting = .prettyPrinted
613 +
614 +         let data = try! encoder.encode(diagnostics)
615 +
616 +         let url = URL(fileURLWithPath: NSTemporaryDirectory())
617 +             .appendingPathComponent("ogmios-diagnostics-\(Date().timeIntervalSince1970)")
618 +             .appendingPathExtension("json")
619 +
620 +         try! data.write(to: url)
621 +         return url
622 +     }
623 + }
624 + ```
625 |
626 | ## Testing Error Scenarios
warning: Unknown option 'swift path' in code block.
   --> Tutorials/ErrorHandling.md:628:1-695:4
626 | ## Testing Error Scenarios
627 |
628 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
629 + import XCTest
630 + @testable import SwiftOgmios
631 +
632 + class ErrorHandlingTests: XCTestCase {
633 +     func testHTTPErrorHandling() async throws {
634 +         let mockConnection = MockHTTPConnection()
635 +         mockConnection.shouldFail = true
636 +         mockConnection.errorMessage = "Connection refused"
637 +
638 +         let client = try await OgmiosClient(
639 +             httpOnly: true,
640 +             httpConnection: mockConnection
641 +         )
642 +
643 +         do {
644 +             _ = try await client.ledgerStateQuery.epoch.execute()
645 +             XCTFail("Expected error")
646 +         } catch OgmiosError.httpError(let message) {
647 +             XCTAssertTrue(message.contains("Connection refused"))
648 +         }
649 +     }
650 +
651 +     func testRetryLogic() async throws {
652 +         let errorHandler = OgmiosErrorHandler()
653 +         var attemptCount = 0
654 +
655 +         do {
656 +             _ = try await errorHandler.retry({
657 +                 attemptCount += 1
658 +                 if attemptCount < 3 {
659 +                     throw OgmiosError.httpError("Temporary failure")
660 +                 }
661 +                 return "Success"
662 +             }, operationName: "test-operation")
663 +         } catch {
664 +             XCTFail("Should have succeeded after retry")
665 +         }
666 +
667 +         XCTAssertEqual(attemptCount, 3)
668 +     }
669 +
670 +     func testCircuitBreakerPattern() async throws {
671 +         let circuitBreaker = CircuitBreaker()
672 +
673 +         // Fail repeatedly to open circuit
674 +         for _ in 1...6 {
675 +             do {
676 +                 _ = try await circuitBreaker.execute {
677 +                     throw OgmiosError.responseError("Server error")
678 +                 }
679 +             } catch {
680 +                 // Expected
681 +             }
682 +         }
683 +
684 +         // Circuit should now be open
685 +         do {
686 +             _ = try await circuitBreaker.execute {
687 +                 return "Should not execute"
688 +             }
689 +             XCTFail("Circuit should be open")
690 +         } catch OgmiosError.responseError(let message) {
691 +             XCTAssertTrue(message.contains("Circuit breaker is open"))
692 +         }
693 +     }
694 + }
695 + ```
696 |
697 | ## Best Practices Summary
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ErrorHandling.md:710:3-710:55
708 | ## See Also
709 |
710 + - <doc:GettingStarted> - Basic setup and first queries
    |   ╰─suggestion: Remove extraneous content
711 | - <doc:TransportTypes> - Transport-specific error handling
712 | - <doc:AdvancedUsage> - Advanced error handling patterns
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ErrorHandling.md:711:3-711:59
709 |
710 | - <doc:GettingStarted> - Basic setup and first queries
711 + - <doc:TransportTypes> - Transport-specific error handling
    |   ╰─suggestion: Remove extraneous content
712 | - <doc:AdvancedUsage> - Advanced error handling patterns
713 | - <doc:LedgerStateQueries> - Query-specific error scenarios
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ErrorHandling.md:712:3-712:57
710 | - <doc:GettingStarted> - Basic setup and first queries
711 | - <doc:TransportTypes> - Transport-specific error handling
712 + - <doc:AdvancedUsage> - Advanced error handling patterns
    |   ╰─suggestion: Remove extraneous content
713 | - <doc:LedgerStateQueries> - Query-specific error scenarios
warning: Extraneous content found after a link in task group list item
   --> Tutorials/ErrorHandling.md:713:3-713:60
711 | - <doc:TransportTypes> - Transport-specific error handling
712 | - <doc:AdvancedUsage> - Advanced error handling patterns
713 + - <doc:LedgerStateQueries> - Query-specific error scenarios
    |   ╰─suggestion: Remove extraneous content
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:89:1-111:4
87  | Add SwiftOgmios as a dependency in your `Package.swift`:
88  |
89  + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
90  + // swift-tools-version: 6.1
91  + import PackageDescription
92  +
93  + let package = Package(
94  +     name: "MyCardanoApp",
95  +     platforms: [
96  +         .iOS(.v14),
97  +         .macOS(.v15)
98  +     ],
99  +     dependencies: [
100 +         .package(url: "https://github.com/Kingpin-Apps/swift-ogmios.git", from: "1.0.0")
101 +     ],
102 +     targets: [
103 +         .target(
104 +             name: "MyCardanoApp",
105 +             dependencies: [
106 +                 .product(name: "SwiftOgmios", package: "swift-ogmios")
107 +             ]
108 +         )
109 +     ]
110 + )
111 + ```
112 |
113 | ## Step 2: Import and Basic Setup
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:117:1-120:4
115 | Create a new Swift file and import SwiftOgmios:
116 |
117 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
118 + import SwiftOgmios
119 + import Foundation
120 + ```
121 |
122 | ## Step 3: Create Your First Client
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:126:1-145:4
124 | SwiftOgmios supports both HTTP and WebSocket transports. For simple queries, HTTP is often sufficient and easier to manage:
125 |
126 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
127 + import SwiftOgmios
128 +
129 + @main
130 + struct HelloOgmios {
131 +     static func main() async throws {
132 +         // Create an HTTP client (recommended for simple queries)
133 +         let client = try await OgmiosClient(
134 +             host: "localhost",    // Your Ogmios server host
135 +             port: 1337,          // Your Ogmios server port
136 +             secure: false,       // Use HTTP (set to true for HTTPS)
137 +             httpOnly: true       // Use HTTP transport
138 +         )
139 +
140 +         print("✅ Connected to Ogmios server!")
141 +
142 +         // Your queries will go here...
143 +     }
144 + }
145 + ```
146 |
147 | For real-time applications that need continuous data streaming, use WebSocket transport:
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:149:1-157:4
147 | For real-time applications that need continuous data streaming, use WebSocket transport:
148 |
149 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
150 + // Create a WebSocket client (recommended for real-time applications)
151 + let client = try await OgmiosClient(
152 +     host: "localhost",
153 +     port: 1337,
154 +     secure: false,       // Use WS (set to true for WSS)
155 +     httpOnly: false      // Use WebSocket transport
156 + )
157 + ```
158 |
159 | ## Step 4: Make Your First Query
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:163:1-183:4
161 | Let's query the current network tip to get basic information about the latest block:
162 |
163 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
164 + @main
165 + struct HelloOgmios {
166 +     static func main() async throws {
167 +         let client = try await OgmiosClient(httpOnly: true)
168 +
169 +         do {
170 +             // Query the current network tip
171 +             let tip = try await client.ledgerStateQuery.tip.result()
172 +
173 +             print("🎉 Success! Current blockchain tip:")
174 +             print("   Slot: \(tip.slot)")
175 +             print("   Block Hash: \(tip.id)")
176 +             print("   Height: \(tip.height)")
177 +
178 +         } catch {
179 +             print("❌ Error querying tip: \(error)")
180 +         }
181 +     }
182 + }
183 + ```
184 |
185 | Expected output:
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:198:1-228:4
196 | Now let's expand our example to query more information about the current state:
197 |
198 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
199 + @main
200 + struct HelloOgmios {
201 +     static func main() async throws {
202 +         let client = try await OgmiosClient(httpOnly: true)
203 +
204 +         do {
205 +             // Query current epoch
206 +             let epoch = try await client.ledgerStateQuery.epoch.result()
207 +             print("📅 Current epoch: \(epoch)")
208 +
209 +             // Query era summaries to understand blockchain eras
210 +             let eraSummaries = try await client.ledgerStateQuery.eraSummaries.result()
211 +             print("🗋  Available eras:")
212 +             for era in eraSummaries {
213 +                 let endEpoch = era.end?.epoch ?? "current"
214 +                 print("   \(era.start.epoch) - \(endEpoch)")
215 +             }
216 +
217 +             // Check server health
218 +             let health = try await client.getServerHealth()
219 +             print("🏥 Server status: \(health.connectionStatus)")
220 +             print("   Network: \(health.network)")
221 +             print("   Version: \(health.version)")
222 +
223 +         } catch {
224 +             print("❌ Error: \(error)")
225 +         }
226 +     }
227 + }
228 + ```
229 |
230 | ## Step 6: Error Handling Best Practices
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:234:1-262:4
232 | Always implement proper error handling when working with network operations:
233 |
234 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
235 + func queryTipWithErrorHandling() async throws {
236 +     let client = try await OgmiosClient(httpOnly: true)
237 +
238 +     do {
239 +         // Using .result() for cleaner code (recommended)
240 +         let tip = try await client.ledgerStateQuery.tip.result(
241 +             id: .generateNextNanoId() // Optional: provide custom request ID
242 +         )
243 +         print("Tip received: \(tip)")
244 +
245 +     } catch OgmiosError.httpError(let message) {
246 +         print("HTTP connection error: \(message)")
247 +         // Handle connection issues (retry, user notification, etc.)
248 +
249 +     } catch OgmiosError.responseError(let message) {
250 +         print("Ogmios server error: \(message)")
251 +         // Handle server-side errors
252 +
253 +     } catch OgmiosError.invalidResponse(let message) {
254 +         print("Invalid response format: \(message)")
255 +         // Handle malformed responses
256 +
257 +     } catch {
258 +         print("Unexpected error: \(error)")
259 +         // Handle any other errors
260 +     }
261 + }
262 + ```
263 |
264 | ## Platform-Specific Considerations
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:270:1-308:4
268 | For iOS apps, consider using SwiftOgmios in a background task or with proper lifecycle management:
269 |
270 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
271 + import SwiftUI
272 + import SwiftOgmios
273 +
274 + @MainActor
275 + class CardanoDataService: ObservableObject {
276 +     @Published var currentEpoch: Int?
277 +     @Published var isLoading = false
278 +
279 +     private var client: OgmiosClient?
280 +
281 +     func connect() async {
282 +         isLoading = true
283 +         do {
284 +             client = try await OgmiosClient(
285 +                 host: "your-server.com",
286 +                 port: 1337,
287 +                 secure: true,  // Use HTTPS for production
288 +                 httpOnly: true
289 +             )
290 +             await fetchCurrentEpoch()
291 +         } catch {
292 +             print("Failed to connect: \(error)")
293 +         }
294 +         isLoading = false
295 +     }
296 +
297 +     private func fetchCurrentEpoch() async {
298 +         guard let client = client else { return }
299 +
300 +         do {
301 +             let epoch = try await client.ledgerStateQuery.epoch.result()
302 +             currentEpoch = epoch
303 +         } catch {
304 +             print("Failed to fetch epoch: \(error)")
305 +         }
306 +     }
307 + }
308 + ```
309 |
310 | ### macOS Applications
warning: Unknown option 'swift path' in code block.
   --> Tutorials/GettingStarted.md:314:1-343:4
312 | For macOS apps, you have more flexibility with background processing:
313 |
314 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
315 + import AppKit
316 + import SwiftOgmios
317 +
318 + class CardanoWindowController: NSWindowController {
319 +     private var client: OgmiosClient?
320 +
321 +     override func windowDidLoad() {
322 +         super.windowDidLoad()
323 +
324 +         Task {
325 +             await setupOgmiosConnection()
326 +         }
327 +     }
328 +
329 +     private func setupOgmiosConnection() async {
330 +         do {
331 +             client = try await OgmiosClient(httpOnly: true)
332 +             // Start background monitoring
333 +             await startMonitoring()
334 +         } catch {
335 +             print("Connection failed: \(error)")
336 +         }
337 +     }
338 +
339 +     private func startMonitoring() async {
340 +         // Implement your monitoring logic here
341 +     }
342 + }
343 + ```
344 |
345 | ## Next Steps
warning: Unknown option 'swift path' in code block.
  --> Tutorials/LedgerStateQueries.md:15:1-27:4
13 | All ledger state queries follow a consistent pattern:
14 |
15 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
16 + import SwiftOgmios
17 +
18 + // Basic query without parameters
19 + let response = try await client.ledgerStateQuery.epoch.execute()
20 + print("Current epoch: \(response.result)")
21 +
22 + // Query with parameters and custom ID
23 + let utxoResponse = try await client.ledgerStateQuery.utxo.execute(
24 +     addresses: [Address("addr1...")],
25 +     id: .generateNextNanoId()
26 + )
27 + ```
28 |
29 | ## Era and Time Queries
warning: Unknown option 'swift path' in code block.
  --> Tutorials/LedgerStateQueries.md:35:1-41:4
33 | Get the current epoch number:
34 |
35 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
36 + let epochResponse = try await client.ledgerStateQuery.epoch.execute()
37 + let currentEpoch: Int = epochResponse.result
38 +
39 + print("Current epoch: \(currentEpoch)")
40 + // Output: Current epoch: 425
41 + ```
42 |
43 | **Use Cases**: Epoch-based calculations, reward distribution timing, protocol parameter change scheduling.
warning: Unknown option 'swift path' in code block.
  --> Tutorials/LedgerStateQueries.md:49:1-55:4
47 | Query when the current era started:
48 |
49 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
50 + let eraStartResponse = try await client.ledgerStateQuery.eraStart.execute()
51 + let startPoint = eraStartResponse.result
52 +
53 + print("Era started at slot: \(startPoint.slot)")
54 + print("Era started at epoch: \(startPoint.epoch)")
55 + ```
56 |
57 | **Use Cases**: Era transition analysis, historical data correlation.
warning: Unknown option 'swift path' in code block.
  --> Tutorials/LedgerStateQueries.md:63:1-71:4
61 | Get comprehensive information about all blockchain eras:
62 |
63 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
64 + let eraSummariesResponse = try await client.ledgerStateQuery.eraSummaries.execute()
65 +
66 + for era in eraSummariesResponse.result {
67 +     let endDescription = era.end?.epoch.map { String($0) } ?? "ongoing"
68 +     print("Era: \(era.start.epoch) to \(endDescription)")
69 +     print("  Parameters: \(era.parameters)")
70 + }
71 + ```
72 |
73 | **Use Cases**: Historical analysis, era transition planning, protocol evolution tracking.
warning: Unknown option 'swift path' in code block.
  --> Tutorials/LedgerStateQueries.md:81:1-89:4
79 | Query the current tip of the ledger:
80 |
81 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
82 + let tipResponse = try await client.ledgerStateQuery.tip.execute()
83 + let tip = tipResponse.result
84 +
85 + print("Ledger tip:")
86 + print("  Slot: \(tip.slot)")
87 + print("  Block ID: \(tip.id)")
88 + print("  Height: \(tip.height)")
89 + ```
90 |
91 | **Use Cases**: Synchronization status, latest block information, chain progress tracking.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:97:1-106:4
95  | Access current protocol parameters:
96  |
97  + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
98  + let paramsResponse = try await client.ledgerStateQuery.protocolParameters.execute()
99  + let params = paramsResponse.result
100 +
101 + print("Protocol parameters:")
102 + print("  Min fee A: \(params.minFeeCoefficient)")
103 + print("  Min fee B: \(params.minFeeConstant)")
104 + print("  Max block size: \(params.maxBlockHeaderSize)")
105 + print("  Max transaction size: \(params.maxTransactionSize)")
106 + ```
107 |
108 | **Use Cases**: Fee calculation, transaction size validation, smart contract development.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:114:1-128:4
112 | Check for pending protocol parameter updates:
113 |
114 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
115 + do {
116 +     let proposedResponse = try await client.ledgerStateQuery.proposedProtocolParameters.execute()
117 +     let proposedParams = proposedResponse.result
118 +
119 +     if let params = proposedParams {
120 +         print("Proposed parameter changes detected")
121 +         // Process proposed changes
122 +     } else {
123 +         print("No proposed parameter changes")
124 +     }
125 + } catch {
126 +     print("Error querying proposed parameters: \(error)")
127 + }
128 + ```
129 |
130 | **Performance Tip**: Cache protocol parameters and only refresh when epoch changes, as they typically remain stable.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:140:1-151:4
138 | #### Query Entire UTxO Set
139 |
140 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
141 + let allUtxoResponse = try await client.ledgerStateQuery.utxo.execute(
142 +     wholeUtxo: true,
143 +     id: .generateNextNanoId()
144 + )
145 +
146 + print("Total UTxOs: \(allUtxoResponse.result.count)")
147 + for utxo in allUtxoResponse.result.prefix(5) { // Show first 5
148 +     print("UTxO: \(utxo.transaction.id)#\(utxo.index)")
149 +     print("  Value: \(utxo.value.ada.lovelace) lovelace")
150 + }
151 + ```
152 |
153 | **⚠️ Warning**: Querying the entire UTxO set returns large amounts of data. Use with caution.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:157:1-181:4
155 | #### Query UTxOs by Addresses
156 |
157 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
158 + let addresses = [
159 +     Address("addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp"),
160 +     Address("addr1q8v42wjda8r6mpfj40d36znlgfdcqp7jtj03ah8skh6u8wnrqua2vw243tmjfjt0h5wsru6appuz8c0pfd75ur7myyeqsx9990")
161 + ]
162 +
163 + let addressUtxoResponse = try await client.ledgerStateQuery.utxo.execute(
164 +     addresses: addresses,
165 +     id: .generateNextNanoId()
166 + )
167 +
168 + for utxo in addressUtxoResponse.result {
169 +     print("Address: \(utxo.address.value)")
170 +     print("Value: \(utxo.value.ada.lovelace) lovelace")
171 +
172 +     // Check for native assets
173 +     if let assets = utxo.value.assets {
174 +         for (policyId, tokens) in assets {
175 +             for (assetName, quantity) in tokens {
176 +                 print("Asset: \(policyId).\(assetName) = \(quantity)")
177 +             }
178 +         }
179 +     }
180 + }
181 + ```
182 |
183 | #### Query UTxOs by Transaction Outputs
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:185:1-199:4
183 | #### Query UTxOs by Transaction Outputs
184 |
185 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
186 + let outputReferences = [
187 +     TransactionOutputReference(
188 +         transaction: TransactionOutputReference.TransactionReference(
189 +             id: "1234567890abcdef..."
190 +         ),
191 +         index: 0
192 +     )
193 + ]
194 +
195 + let refUtxoResponse = try await client.ledgerStateQuery.utxo.execute(
196 +     outputReferences: outputReferences,
197 +     id: .generateNextNanoId()
198 + )
199 + ```
200 |
201 | **Use Cases**: Wallet balance checking, transaction input validation, asset tracking.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:214:1-226:4
212 | Get current stake distribution across all pools:
213 |
214 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
215 + let stakeResponse = try await client.ledgerStateQuery.liveStakeDistribution.execute()
216 + let distribution = stakeResponse.result
217 +
218 + print("Stake distribution across \(distribution.value.count) pools")
219 +
220 + // Find top 10 pools by stake
221 + let sortedPools = distribution.value.sorted { $0.value.stake > $1.value.stake }
222 + for (index, (poolId, poolInfo)) in sortedPools.prefix(10).enumerated() {
223 +     let stakeAda = Double(poolInfo.stake) / 1_000_000 // Convert to ADA
224 +     print("\(index + 1). Pool \(poolId.value.prefix(8))...: \(String(format: "%.2f", stakeAda)) ADA")
225 + }
226 + ```
227 |
228 | ### Stake Pools
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:232:1-249:4
230 | Get detailed information about all registered stake pools:
231 |
232 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
233 + let poolsResponse = try await client.ledgerStateQuery.stakePools.execute()
234 + let pools = poolsResponse.result
235 +
236 + print("Total registered pools: \(pools.count)")
237 +
238 + for (poolId, pool) in pools.prefix(3) { // Show first 3 pools
239 +     print("\nPool ID: \(poolId.value)")
240 +     print("Cost: \(pool.cost) lovelace")
241 +     print("Margin: \(pool.margin)")
242 +     print("Pledge: \(pool.pledge) lovelace")
243 +
244 +     if let metadata = pool.metadata {
245 +         print("Metadata URL: \(metadata.url)")
246 +         print("Metadata Hash: \(metadata.hash)")
247 +     }
248 + }
249 + ```
250 |
251 | ### Stake Pool Performances
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:255:1-262:4
253 | Query performance metrics for stake pools:
254 |
255 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
256 + let performanceResponse = try await client.ledgerStateQuery.stakePoolsPerformances.execute()
257 + let performances = performanceResponse.result
258 +
259 + for (poolId, performance) in performances.prefix(5) {
260 +     print("Pool \(poolId.value.prefix(8))...: \(performance)")
261 + }
262 + ```
263 |
264 | ### Operational Certificates
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:268:1-273:4
266 | Get operational certificate information:
267 |
268 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
269 + let certResponse = try await client.ledgerStateQuery.operationalCertificates.execute()
270 + let certificates = certResponse.result
271 +
272 + print("Operational certificates: \(certificates.count)")
273 + ```
274 |
275 | **Use Cases**: Pool delegation decisions, performance analysis, pool operator monitoring.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:283:1-299:4
281 | Query the current constitution (Conway era):
282 |
283 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
284 + let constitutionResponse = try await client.ledgerStateQuery.constitution.execute()
285 +
286 + if let constitution = constitutionResponse.result {
287 +     print("Constitution found:")
288 +     if let anchor = constitution.anchor {
289 +         print("  URL: \(anchor.url)")
290 +         print("  Hash: \(anchor.dataHash)")
291 +     }
292 +
293 +     if let script = constitution.guardrails {
294 +         print("  Guardrails script: \(script)")
295 +     }
296 + } else {
297 +     print("No constitution defined")
298 + }
299 + ```
300 |
301 | ### Constitutional Committee
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:305:1-319:4
303 | Query constitutional committee state:
304 |
305 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
306 + let committeeResponse = try await client.ledgerStateQuery.constitutionalCommittee.execute()
307 +
308 + if let committee = committeeResponse.result {
309 +     print("Constitutional Committee:")
310 +     print("  Threshold: \(committee.threshold)")
311 +     print("  Members: \(committee.members.count)")
312 +
313 +     for (keyHash, epoch) in committee.members {
314 +         print("    Member \(keyHash): expires epoch \(epoch)")
315 +     }
316 + } else {
317 +     print("No constitutional committee")
318 + }
319 + ```
320 |
321 | ### Governance Proposals
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:325:1-336:4
323 | Query active governance proposals:
324 |
325 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
326 + let proposalsResponse = try await client.ledgerStateQuery.governanceProposals.execute()
327 +
328 + print("Active proposals: \(proposalsResponse.result.count)")
329 +
330 + for proposal in proposalsResponse.result.prefix(3) {
331 +     print("\nProposal ID: \(proposal.proposal.transaction.id)")
332 +     print("Index: \(proposal.proposal.index)")
333 +     print("Deposit: \(proposal.deposit) lovelace")
334 +     print("Return address: \(proposal.returnAddress.value)")
335 + }
336 + ```
337 |
338 | ### Delegate Representatives (DReps)
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:342:1-355:4
340 | Query registered delegate representatives:
341 |
342 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
343 + let drepsResponse = try await client.ledgerStateQuery.delegateRepresentatives.execute()
344 +
345 + print("Registered DReps: \(drepsResponse.result.count)")
346 +
347 + for drep in drepsResponse.result.prefix(5) {
348 +     print("\nDRep: \(drep.id)")
349 +     print("Type: \(drep.type)")
350 +
351 +     if let anchor = drep.anchor {
352 +         print("Metadata: \(anchor.url)")
353 +     }
354 + }
355 + ```
356 |
357 | **Use Cases**: Governance participation, voting decisions, proposal tracking.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:365:1-374:4
363 | Query treasury and reserves amounts:
364 |
365 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
366 + let treasuryResponse = try await client.ledgerStateQuery.treasuryAndReserves.execute()
367 + let treasury = treasuryResponse.result
368 +
369 + let treasuryAda = Double(treasury.treasury.ada.lovelace) / 1_000_000
370 + let reservesAda = Double(treasury.reserves.ada.lovelace) / 1_000_000
371 +
372 + print("Treasury: \(String(format: "%.2f", treasuryAda)) ADA")
373 + print("Reserves: \(String(format: "%.2f", reservesAda)) ADA")
374 + ```
375 |
376 | ### Projected Rewards
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:380:1-388:4
378 | Query projected rewards for stake pools:
379 |
380 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
381 + let rewardsResponse = try await client.ledgerStateQuery.projectedRewards.execute()
382 + let rewards = rewardsResponse.result
383 +
384 + for (stakeCredential, reward) in rewards.prefix(5) {
385 +     let rewardAda = Double(reward) / 1_000_000
386 +     print("Stake credential \(stakeCredential): \(String(format: "%.6f", rewardAda)) ADA")
387 + }
388 + ```
389 |
390 | ### Reward Account Summaries
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:394:1-406:4
392 | Query reward account information:
393 |
394 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
395 + let accountsResponse = try await client.ledgerStateQuery.rewardAccountSummaries.execute()
396 + let accounts = accountsResponse.result
397 +
398 + for (rewardAccount, summary) in accounts.prefix(3) {
399 +     print("\nReward account: \(rewardAccount)")
400 +     print("Available rewards: \(summary.rewards) lovelace")
401 +
402 +     if let delegation = summary.delegation {
403 +         print("Delegated to: \(delegation)")
404 +     }
405 + }
406 + ```
407 |
408 | **Use Cases**: Reward calculation, delegation analysis, economic modeling.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:416:1-439:4
414 | Export complete ledger state (use with caution):
415 |
416 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
417 + let tempURL = URL(fileURLWithPath: NSTemporaryDirectory())
418 +     .appendingPathComponent("ledger-dump-\(Date().timeIntervalSince1970)")
419 +     .appendingPathExtension("json")
420 +
421 + do {
422 +     let dumpResponse = try await client.ledgerStateQuery.dump.execute(
423 +         to: tempURL.path,
424 +         id: .generateNextNanoId()
425 +     )
426 +
427 +     print("Ledger state dumped to: \(tempURL.path)")
428 +     print("Dump result: \(dumpResponse.result)")
429 +
430 +     // Process the dump file
431 +     if FileManager.default.fileExists(atPath: tempURL.path) {
432 +         let fileSize = try FileManager.default.attributesOfItem(atPath: tempURL.path)[.size] as! Int64
433 +         print("Dump file size: \(fileSize) bytes")
434 +     }
435 +
436 + } catch {
437 +     print("Failed to dump ledger state: \(error)")
438 + }
439 + ```
440 |
441 | **⚠️ Warning**: Ledger state dumps can be very large (several GB). Use only for debugging or analysis purposes.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:447:1-453:4
445 | Query consensus nonces for randomness:
446 |
447 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
448 + let noncesResponse = try await client.ledgerStateQuery.nonces.execute()
449 + let nonces = noncesResponse.result
450 +
451 + print("Epoch nonce: \(nonces.epochNonce)")
452 + print("Extra entropy: \(nonces.extraEntropy)")
453 + ```
454 |
455 | **Use Cases**: Randomness verification, consensus debugging.
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:461:1-502:4
459 | ### Robust Error Handling
460 |
461 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
462 + func queryWithRetry<T>(
463 +     query: () async throws -> T,
464 +     maxRetries: Int = 3
465 + ) async throws -> T {
466 +     var lastError: Error?
467 +
468 +     for attempt in 1...maxRetries {
469 +         do {
470 +             return try await query()
471 +         } catch OgmiosError.responseError(let message) {
472 +             if message.contains("2001") { // Era mismatch
473 +                 print("Era mismatch - query not available in current era")
474 +                 throw OgmiosError.responseError("Query not available in current era")
475 +             } else if message.contains("2002") { // Unavailable in current era
476 +                 print("Query unavailable in current era")
477 +                 throw OgmiosError.responseError("Query unavailable in current era")
478 +             } else if attempt < maxRetries {
479 +                 print("Attempt \(attempt) failed, retrying...")
480 +                 lastError = OgmiosError.responseError(message)
481 +                 try await Task.sleep(nanoseconds: 1_000_000_000) // 1 second
482 +             } else {
483 +                 throw OgmiosError.responseError(message)
484 +             }
485 +         } catch {
486 +             throw error
487 +         }
488 +     }
489 +
490 +     throw lastError ?? OgmiosError.responseError("Max retries exceeded")
491 + }
492 +
493 + // Usage
494 + do {
495 +     let epoch = try await queryWithRetry {
496 +         return try await client.ledgerStateQuery.epoch.execute()
497 +     }
498 +     print("Current epoch: \(epoch.result)")
499 + } catch {
500 +     print("Failed to query epoch: \(error)")
501 + }
502 + ```
503 |
504 | ### Performance Optimization
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:508:1-533:4
506 | #### Batch Queries
507 |
508 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
509 + // Execute multiple queries concurrently
510 + async func fetchDashboardData() async throws -> (epoch: Int, tip: Point, pools: Int) {
511 +     async let epochTask = client.ledgerStateQuery.epoch.execute()
512 +     async let tipTask = client.ledgerStateQuery.tip.execute()
513 +     async let poolsTask = client.ledgerStateQuery.stakePools.execute()
514 +
515 +     let (epochResponse, tipResponse, poolsResponse) = try await (epochTask, tipTask, poolsTask)
516 +
517 +     return (
518 +         epoch: epochResponse.result,
519 +         tip: tipResponse.result,
520 +         pools: poolsResponse.result.count
521 +     )
522 + }
523 +
524 + // Usage
525 + do {
526 +     let dashboard = try await fetchDashboardData()
527 +     print("Epoch: \(dashboard.epoch)")
528 +     print("Tip: \(dashboard.tip.slot)")
529 +     print("Pools: \(dashboard.pools)")
530 + } catch {
531 +     print("Dashboard fetch failed: \(error)")
532 + }
533 + ```
534 |
535 | #### Caching Strategy
warning: Unknown option 'swift path' in code block.
   --> Tutorials/LedgerStateQueries.md:537:1-585:4
535 | #### Caching Strategy
536 |
537 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
538 + @MainActor
539 + class LedgerStateCache: ObservableObject {
540 +     @Published var currentEpoch: Int?
541 +     @Published var protocolParams: ProtocolParameters?
542 +     @Published var lastUpdated: Date?
543 +
544 +     private let client: OgmiosClient
545 +     private let cacheTimeout: TimeInterval = 300 // 5 minutes
546 +
547 +     init(client: OgmiosClient) {
548 +         self.client = client
549 +     }
550 +
551 +     func getProtocolParameters() async throws -> ProtocolParameters {
552 +         if let params = protocolParams,
553 +            let lastUpdated = lastUpdated,
554 +            Date().timeIntervalSince(lastUpdated) < cacheTimeout {
555 +             return params
556 +         }
557 +
558 +         let response = try await client.ledgerStateQuery.protocolParameters.execute()
559 +
560 +         await MainActor.run {
561 +             self.protocolParams = response.result
562 +             self.lastUpdated = Date()
563 +         }
564 +
565 +         return response.result
566 +     }
567 +
568 +     func getCurrentEpoch() async throws -> Int {
569 +         if let epoch = currentEpoch,
570 +            let lastUpdated = lastUpdated,
571 +            Date().timeIntervalSince(lastUpdated) < cacheTimeout {
572 +             return epoch
573 +         }
574 +
575 +         let response = try await client.ledgerStateQuery.epoch.execute()
576 +
577 +         await MainActor.run {
578 +             self.currentEpoch = response.result
579 +             self.lastUpdated = Date()
580 +         }
581 +
582 +         return response.result
583 +     }
584 + }
585 + ```
586 |
587 | ## Query Compatibility by Era
warning: Extraneous content found after a link in task group list item
   --> Tutorials/LedgerStateQueries.md:603:3-603:55
601 | ## See Also
602 |
603 + - <doc:GettingStarted> - Basic setup and first queries
    |   ╰─suggestion: Remove extraneous content
604 | - <doc:ErrorHandling> - Comprehensive error handling strategies
605 | - <doc:TransportTypes> - Optimizing query performance with transport selection
warning: Extraneous content found after a link in task group list item
   --> Tutorials/LedgerStateQueries.md:604:3-604:64
602 |
603 | - <doc:GettingStarted> - Basic setup and first queries
604 + - <doc:ErrorHandling> - Comprehensive error handling strategies
    |   ╰─suggestion: Remove extraneous content
605 | - <doc:TransportTypes> - Optimizing query performance with transport selection
606 | - <doc:AdvancedUsage> - Advanced query patterns and optimization techniques
warning: Extraneous content found after a link in task group list item
   --> Tutorials/LedgerStateQueries.md:605:3-605:79
603 | - <doc:GettingStarted> - Basic setup and first queries
604 | - <doc:ErrorHandling> - Comprehensive error handling strategies
605 + - <doc:TransportTypes> - Optimizing query performance with transport selection
    |   ╰─suggestion: Remove extraneous content
606 | - <doc:AdvancedUsage> - Advanced query patterns and optimization techniques
warning: Extraneous content found after a link in task group list item
   --> Tutorials/LedgerStateQueries.md:606:3-606:76
604 | - <doc:ErrorHandling> - Comprehensive error handling strategies
605 | - <doc:TransportTypes> - Optimizing query performance with transport selection
606 + - <doc:AdvancedUsage> - Advanced query patterns and optimization techniques
    |   ╰─suggestion: Remove extraneous content
warning: Unknown option 'swift path' in code block.
  --> Tutorials/MempoolMonitoring.md:23:1-46:4
21 | ### Basic Mempool Operations
22 |
23 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
24 + import SwiftOgmios
25 +
26 + // Create client (WebSocket recommended for continuous monitoring)
27 + let client = try await OgmiosClient(httpOnly: false)
28 +
29 + // Acquire mempool snapshot
30 + let snapshot = try await client.mempoolMonitor.acquireMempool.execute()
31 + print("Acquired mempool at slot: \(snapshot.result.slot)")
32 +
33 + // Check mempool size
34 + let sizeResponse = try await client.mempoolMonitor.sizeOfMempool.execute()
35 + print("Mempool size: \(sizeResponse.result.currentSize)/\(sizeResponse.result.capacity)")
36 +
37 + // Check if specific transaction exists
38 + let hasTransaction = try await client.mempoolMonitor.hasTransaction.execute(
39 +     transaction: TransactionId("abc123..."),
40 +     id: .generateNextNanoId()
41 + )
42 + print("Transaction in mempool: \(hasTransaction.result)")
43 +
44 + // Release mempool snapshot
45 + let _ = try await client.mempoolMonitor.releaseMempool.execute()
46 + ```
47 |
48 | ## Getting All Mempool Transactions
warning: Unknown option 'swift path' in code block.
  --> Tutorials/MempoolMonitoring.md:52:1-71:4
50 | SwiftOgmios provides a convenient helper method to retrieve all transactions from the mempool:
51 |
52 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
53 + do {
54 +     let transactions = try await client.mempoolMonitor.getMempoolTransactions()
55 +
56 +     print("Found \(transactions.count) transactions in mempool:")
57 +     for transaction in transactions {
58 +         switch transaction {
59 +         case .transaction(let tx):
60 +             print("  TX: \(tx.id)")
61 +             print("    Fee: \(tx.body.fee) lovelace")
62 +             print("    Inputs: \(tx.body.inputs.count)")
63 +             print("    Outputs: \(tx.body.outputs.count)")
64 +         case .noMoreTransactions:
65 +             break
66 +         }
67 +     }
68 + } catch {
69 +     print("Failed to get mempool transactions: \(error)")
70 + }
71 + ```
72 |
73 | ## Advanced Mempool Monitoring
warning: Unknown option 'swift path' in code block.
   --> Tutorials/MempoolMonitoring.md:77:1-145:4
75  | ### Real-Time Mempool Monitor
76  |
77  + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
78  + actor MempoolMonitor {
79  +     private let client: OgmiosClient
80  +     private var isMonitoring = false
81  +     private var monitoringTask: Task<Void, Never>?
82  +
83  +     init(client: OgmiosClient) {
84  +         self.client = client
85  +     }
86  +
87  +     func startMonitoring() async {
88  +         guard !isMonitoring else { return }
89  +         isMonitoring = true
90  +
91  +         monitoringTask = Task { [weak self] in
92  +             await self?.monitorLoop()
93  +         }
94  +     }
95  +
96  +     func stopMonitoring() {
97  +         isMonitoring = false
98  +         monitoringTask?.cancel()
99  +         monitoringTask = nil
100 +     }
101 +
102 +     private func monitorLoop() async {
103 +         while isMonitoring && !Task.isCancelled {
104 +             do {
105 +                 // Check mempool size
106 +                 let sizeResponse = try await client.mempoolMonitor.sizeOfMempool.execute()
107 +                 await handleSizeUpdate(sizeResponse.result)
108 +
109 +                 // Get current transactions
110 +                 let transactions = try await client.mempoolMonitor.getMempoolTransactions()
111 +                 await handleTransactionUpdate(transactions)
112 +
113 +                 // Wait before next check
114 +                 try await Task.sleep(nanoseconds: 30_000_000_000) // 30 seconds
115 +
116 +             } catch {
117 +                 print("Mempool monitoring error: \(error)")
118 +
119 +                 // Wait before retry
120 +                 try? await Task.sleep(nanoseconds: 10_000_000_000) // 10 seconds
121 +             }
122 +         }
123 +     }
124 +
125 +     private func handleSizeUpdate(_ size: SizeAndCapacity) async {
126 +         let utilization = Double(size.currentSize) / Double(size.capacity) * 100
127 +         print("Mempool utilization: \(String(format: "%.1f", utilization))% (\(size.currentSize)/\(size.capacity))")
128 +     }
129 +
130 +     private func handleTransactionUpdate(_ transactions: [NextTransactionResult]) async {
131 +         var txCount = 0
132 +         var totalFees: UInt64 = 0
133 +
134 +         for transaction in transactions {
135 +             if case .transaction(let tx) = transaction {
136 +                 txCount += 1
137 +                 totalFees += tx.body.fee
138 +             }
139 +         }
140 +
141 +         let avgFee = txCount > 0 ? totalFees / UInt64(txCount) : 0
142 +         print("Mempool stats: \(txCount) transactions, avg fee: \(avgFee) lovelace")
143 +     }
144 + }
145 + ```
146 |
147 | ### Transaction Filtering
warning: Unknown option 'swift path' in code block.
   --> Tutorials/MempoolMonitoring.md:151:1-228:4
149 | Create filters to monitor specific types of transactions:
150 |
151 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
152 + struct TransactionFilter {
153 +     let watchedAddresses: Set<String>
154 +     let watchedAssets: Set<String>
155 +     let minAmount: UInt64?
156 +     let maxAmount: UInt64?
157 +
158 +     init(
159 +         addresses: [String] = [],
160 +         assets: [String] = [],
161 +         minAmount: UInt64? = nil,
162 +         maxAmount: UInt64? = nil
163 +     ) {
164 +         self.watchedAddresses = Set(addresses)
165 +         self.watchedAssets = Set(assets)
166 +         self.minAmount = minAmount
167 +         self.maxAmount = maxAmount
168 +     }
169 +
170 +     func matches(_ transaction: Transaction) -> Bool {
171 +         // Check addresses
172 +         if !watchedAddresses.isEmpty {
173 +             let hasMatchingAddress = transaction.body.outputs.contains { output in
174 +                 watchedAddresses.contains(output.address.value)
175 +             }
176 +             if !hasMatchingAddress {
177 +                 return false
178 +             }
179 +         }
180 +
181 +         // Check assets
182 +         if !watchedAssets.isEmpty {
183 +             let hasMatchingAsset = transaction.body.outputs.contains { output in
184 +                 guard let assets = output.value.assets else { return false }
185 +
186 +                 return assets.contains { (policyId, tokens) in
187 +                     tokens.contains { (assetName, _) in
188 +                         let assetId = "\(policyId).\(assetName)"
189 +                         return watchedAssets.contains(assetId)
190 +                     }
191 +                 }
192 +             }
193 +             if !hasMatchingAsset {
194 +                 return false
195 +             }
196 +         }
197 +
198 +         // Check amount range
199 +         let totalOutput = transaction.body.outputs.reduce(0) { sum, output in
200 +             sum + output.value.ada.lovelace
201 +         }
202 +
203 +         if let minAmount = minAmount, totalOutput < minAmount {
204 +             return false
205 +         }
206 +
207 +         if let maxAmount = maxAmount, totalOutput > maxAmount {
208 +             return false
209 +         }
210 +
211 +         return true
212 +     }
213 + }
214 +
215 + // Usage
216 + let filter = TransactionFilter(
217 +     addresses: ["addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer..."],
218 +     minAmount: 1_000_000 // 1 ADA minimum
219 + )
220 +
221 + let allTransactions = try await client.mempoolMonitor.getMempoolTransactions()
222 + let filteredTransactions = allTransactions.compactMap { result -> Transaction? in
223 +     guard case .transaction(let tx) = result else { return nil }
224 +     return filter.matches(tx) ? tx : nil
225 + }
226 +
227 + print("Found \(filteredTransactions.count) matching transactions")
228 + ```
229 |
230 | ### Smart Mempool Observer
warning: Unknown option 'swift path' in code block.
   --> Tutorials/MempoolMonitoring.md:232:1-399:4
230 | ### Smart Mempool Observer
231 |
232 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
233 + @MainActor
234 + class SmartMempoolObserver: ObservableObject {
235 +     @Published var mempoolSize: SizeAndCapacity?
236 +     @Published var recentTransactions: [Transaction] = []
237 +     @Published var watchedTransactions: [String: TransactionStatus] = [:]
238 +     @Published var isMonitoring = false
239 +
240 +     private let client: OgmiosClient
241 +     private let filter: TransactionFilter
242 +     private var monitoringTask: Task<Void, Never>?
243 +     private var lastSnapshot: Set<String> = []
244 +
245 +     enum TransactionStatus {
246 +         case pending(since: Date)
247 +         case confirmed(at: Date)
248 +         case dropped(at: Date)
249 +     }
250 +
251 +     init(client: OgmiosClient, filter: TransactionFilter = TransactionFilter()) {
252 +         self.client = client
253 +         self.filter = filter
254 +     }
255 +
256 +     func startMonitoring() {
257 +         guard !isMonitoring else { return }
258 +         isMonitoring = true
259 +
260 +         monitoringTask = Task { [weak self] in
261 +             while !Task.isCancelled {
262 +                 await self?.performMonitoringCycle()
263 +
264 +                 // Wait before next cycle
265 +                 try? await Task.sleep(nanoseconds: 15_000_000_000) // 15 seconds
266 +             }
267 +         }
268 +     }
269 +
270 +     func stopMonitoring() {
271 +         isMonitoring = false
272 +         monitoringTask?.cancel()
273 +         monitoringTask = nil
274 +     }
275 +
276 +     func watchTransaction(_ transactionId: String) {
277 +         watchedTransactions[transactionId] = .pending(since: Date())
278 +     }
279 +
280 +     private func performMonitoringCycle() async {
281 +         do {
282 +             // Update mempool size
283 +             let sizeResponse = try await client.mempoolMonitor.sizeOfMempool.execute()
284 +             await MainActor.run {
285 +                 self.mempoolSize = sizeResponse.result
286 +             }
287 +
288 +             // Get current transactions
289 +             let allTransactions = try await client.mempoolMonitor.getMempoolTransactions()
290 +             let currentSnapshot = Set(allTransactions.compactMap { result in
291 +                 guard case .transaction(let tx) = result else { return nil }
292 +                 return tx.id
293 +             })
294 +
295 +             // Detect new transactions
296 +             let newTransactions = currentSnapshot.subtracting(lastSnapshot)
297 +             if !newTransactions.isEmpty {
298 +                 await handleNewTransactions(newTransactions, from: allTransactions)
299 +             }
300 +
301 +             // Detect dropped transactions
302 +             let droppedTransactions = lastSnapshot.subtracting(currentSnapshot)
303 +             if !droppedTransactions.isEmpty {
304 +                 await handleDroppedTransactions(droppedTransactions)
305 +             }
306 +
307 +             // Update watched transactions
308 +             await updateWatchedTransactions(currentSnapshot)
309 +
310 +             lastSnapshot = currentSnapshot
311 +
312 +         } catch {
313 +             print("Monitoring cycle error: \(error)")
314 +         }
315 +     }
316 +
317 +     private func handleNewTransactions(_ newTxIds: Set<String>, from allTransactions: [NextTransactionResult]) async {
318 +         let newTxs = allTransactions.compactMap { result -> Transaction? in
319 +             guard case .transaction(let tx) = result else { return nil }
320 +             return newTxIds.contains(tx.id) ? tx : nil
321 +         }
322 +
323 +         let filteredNewTxs = newTxs.filter { filter.matches($0) }
324 +
325 +         await MainActor.run {
326 +             // Add to recent transactions (keep last 20)
327 +             self.recentTransactions.insert(contentsOf: filteredNewTxs, at: 0)
328 +             if self.recentTransactions.count > 20 {
329 +                 self.recentTransactions = Array(self.recentTransactions.prefix(20))
330 +             }
331 +         }
332 +
333 +         // Notify about new transactions
334 +         for tx in filteredNewTxs {
335 +             print("New transaction: \(tx.id)")
336 +             await handleNewTransaction(tx)
337 +         }
338 +     }
339 +
340 +     private func handleDroppedTransactions(_ droppedTxIds: Set<String>) async {
341 +         await MainActor.run {
342 +             // Remove from recent transactions
343 +             self.recentTransactions.removeAll { tx in
344 +                 droppedTxIds.contains(tx.id)
345 +             }
346 +         }
347 +
348 +         for txId in droppedTxIds {
349 +             print("Transaction dropped from mempool: \(txId)")
350 +         }
351 +     }
352 +
353 +     private func updateWatchedTransactions(_ currentSnapshot: Set<String>) async {
354 +         await MainActor.run {
355 +             for (txId, status) in self.watchedTransactions {
356 +                 switch status {
357 +                 case .pending(_):
358 +                     if !currentSnapshot.contains(txId) {
359 +                         // Transaction left mempool - likely confirmed
360 +                         self.watchedTransactions[txId] = .confirmed(at: Date())
361 +                     }
362 +                 case .confirmed(_), .dropped(_):
363 +                     // Keep confirmed/dropped status
364 +                     break
365 +                 }
366 +             }
367 +         }
368 +     }
369 +
370 +     private func handleNewTransaction(_ transaction: Transaction) async {
371 +         // Analyze transaction
372 +         let totalOutput = transaction.body.outputs.reduce(0) { sum, output in
373 +             sum + output.value.ada.lovelace
374 +         }
375 +
376 +         print("  Fee: \(transaction.body.fee) lovelace")
377 +         print("  Total output: \(totalOutput) lovelace")
378 +         print("  Inputs: \(transaction.body.inputs.count)")
379 +         print("  Outputs: \(transaction.body.outputs.count)")
380 +
381 +         // Check for interesting patterns
382 +         if transaction.body.fee > 1_000_000 { // High fee (> 1 ADA)
383 +             print("  ⚠️ High fee transaction detected!")
384 +         }
385 +
386 +         if transaction.body.outputs.count > 100 {
387 +             print("  📊 Large transaction with many outputs")
388 +         }
389 +
390 +         // Check for native assets
391 +         let hasNativeAssets = transaction.body.outputs.contains { output in
392 +             output.value.assets != nil
393 +         }
394 +         if hasNativeAssets {
395 +             print("  🎨 Contains native assets")
396 +         }
397 +     }
398 + }
399 + ```
400 |
401 | ## Real-Time SwiftUI Integration
warning: Unknown option 'swift path' in code block.
   --> Tutorials/MempoolMonitoring.md:405:1-681:4
403 | ### Mempool Dashboard View
404 |
405 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
406 + import SwiftUI
407 +
408 + struct MempoolDashboardView: View {
409 +     @StateObject private var observer: SmartMempoolObserver
410 +     @State private var selectedFilter = FilterType.all
411 +     @State private var watchedTxId = ""
412 +
413 +     enum FilterType: String, CaseIterable {
414 +         case all = "All"
415 +         case highFee = "High Fee"
416 +         case largeAmount = "Large Amount"
417 +         case nativeAssets = "Native Assets"
418 +     }
419 +
420 +     init(client: OgmiosClient) {
421 +         self._observer = StateObject(wrappedValue: SmartMempoolObserver(client: client))
422 +     }
423 +
424 +     var body: some View {
425 +         NavigationView {
426 +             VStack(spacing: 20) {
427 +                 // Header with monitoring status
428 +                 headerView
429 +
430 +                 // Mempool stats
431 +                 if let size = observer.mempoolSize {
432 +                     mempoolStatsView(size)
433 +                 }
434 +
435 +                 // Transaction filter
436 +                 filterView
437 +
438 +                 // Recent transactions list
439 +                 transactionListView
440 +
441 +                 // Transaction watcher
442 +                 transactionWatcherView
443 +             }
444 +             .padding()
445 +             .navigationTitle("Mempool Monitor")
446 +             .onAppear {
447 +                 observer.startMonitoring()
448 +             }
449 +             .onDisappear {
450 +                 observer.stopMonitoring()
451 +             }
452 +         }
453 +     }
454 +
455 +     @ViewBuilder
456 +     private var headerView: some View {
457 +         HStack {
458 +             Circle()
459 +                 .fill(observer.isMonitoring ? Color.green : Color.red)
460 +                 .frame(width: 12, height: 12)
461 +
462 +             Text(observer.isMonitoring ? "Monitoring" : "Stopped")
463 +                 .font(.headline)
464 +
465 +             Spacer()
466 +
467 +             Button(observer.isMonitoring ? "Stop" : "Start") {
468 +                 if observer.isMonitoring {
469 +                     observer.stopMonitoring()
470 +                 } else {
471 +                     observer.startMonitoring()
472 +                 }
473 +             }
474 +             .buttonStyle(.bordered)
475 +         }
476 +     }
477 +
478 +     @ViewBuilder
479 +     private func mempoolStatsView(_ size: SizeAndCapacity) -> some View {
480 +         VStack(spacing: 8) {
481 +             HStack {
482 +                 Text("Mempool Size")
483 +                     .font(.caption)
484 +                     .foregroundColor(.secondary)
485 +                 Spacer()
486 +                 Text("\(size.currentSize) / \(size.capacity)")
487 +                     .font(.caption)
488 +                     .fontWeight(.semibold)
489 +             }
490 +
491 +             ProgressView(
492 +                 value: Double(size.currentSize),
493 +                 total: Double(size.capacity)
494 +             )
495 +
496 +             let utilization = Double(size.currentSize) / Double(size.capacity) * 100
497 +             Text("\(String(format: "%.1f", utilization))% full")
498 +                 .font(.caption2)
499 +                 .foregroundColor(.secondary)
500 +         }
501 +         .padding()
502 +         .background(Color.gray.opacity(0.1))
503 +         .cornerRadius(8)
504 +     }
505 +
506 +     @ViewBuilder
507 +     private var filterView: some View {
508 +         VStack {
509 +             Text("Filter Transactions")
510 +                 .font(.caption)
511 +                 .foregroundColor(.secondary)
512 +
513 +             Picker("Filter", selection: $selectedFilter) {
514 +                 ForEach(FilterType.allCases, id: \.self) { filter in
515 +                     Text(filter.rawValue).tag(filter)
516 +                 }
517 +             }
518 +             .pickerStyle(.segmented)
519 +         }
520 +     }
521 +
522 +     @ViewBuilder
523 +     private var transactionListView: some View {
524 +         VStack(alignment: .leading) {
525 +             Text("Recent Transactions")
526 +                 .font(.headline)
527 +
528 +             if observer.recentTransactions.isEmpty {
529 +                 Text("No transactions yet")
530 +                     .foregroundColor(.secondary)
531 +                     .frame(maxWidth: .infinity, alignment: .center)
532 +                     .padding()
533 +             } else {
534 +                 List(filteredTransactions, id: \.id) { transaction in
535 +                     TransactionRowView(transaction: transaction)
536 +                 }
537 +                 .listStyle(.plain)
538 +                 .frame(maxHeight: 300)
539 +             }
540 +         }
541 +     }
542 +
543 +     @ViewBuilder
544 +     private var transactionWatcherView: some View {
545 +         VStack(alignment: .leading) {
546 +             Text("Watch Transaction")
547 +                 .font(.headline)
548 +
549 +             HStack {
550 +                 TextField("Transaction ID", text: $watchedTxId)
551 +                     .textFieldStyle(.roundedBorder)
552 +
553 +                 Button("Watch") {
554 +                     observer.watchTransaction(watchedTxId)
555 +                     watchedTxId = ""
556 +                 }
557 +                 .disabled(watchedTxId.isEmpty)
558 +                 .buttonStyle(.borderedProminent)
559 +             }
560 +
561 +             // Watched transactions status
562 +             if !observer.watchedTransactions.isEmpty {
563 +                 ForEach(Array(observer.watchedTransactions.keys), id: \.self) { txId in
564 +                     if let status = observer.watchedTransactions[txId] {
565 +                         WatchedTransactionView(transactionId: txId, status: status)
566 +                     }
567 +                 }
568 +             }
569 +         }
570 +     }
571 +
572 +     private var filteredTransactions: [Transaction] {
573 +         observer.recentTransactions.filter { transaction in
574 +             switch selectedFilter {
575 +             case .all:
576 +                 return true
577 +             case .highFee:
578 +                 return transaction.body.fee > 1_000_000 // > 1 ADA
579 +             case .largeAmount:
580 +                 let totalOutput = transaction.body.outputs.reduce(0) { sum, output in
581 +                     sum + output.value.ada.lovelace
582 +                 }
583 +                 return totalOutput > 10_000_000 // > 10 ADA
584 +             case .nativeAssets:
585 +                 return transaction.body.outputs.contains { output in
586 +                     output.value.assets != nil
587 +                 }
588 +             }
589 +         }
590 +     }
591 + }
592 +
593 + struct TransactionRowView: View {
594 +     let transaction: Transaction
595 +
596 +     var body: some View {
597 +         VStack(alignment: .leading, spacing: 4) {
598 +             HStack {
599 +                 Text(transaction.id)
600 +                     .font(.system(.caption, design: .monospaced))
601 +                     .lineLimit(1)
602 +                     .truncationMode(.middle)
603 +
604 +                 Spacer()
605 +
606 +                 Text("\(transaction.body.fee) lovelace")
607 +                     .font(.caption2)
608 +                     .foregroundColor(.secondary)
609 +             }
610 +
611 +             HStack {
612 +                 Text("\(transaction.body.inputs.count) inputs")
613 +                 Text("•")
614 +                 Text("\(transaction.body.outputs.count) outputs")
615 +
616 +                 Spacer()
617 +
618 +                 if transaction.body.outputs.contains(where: { $0.value.assets != nil }) {
619 +                     Image(systemName: "paintbrush.fill")
620 +                         .foregroundColor(.purple)
621 +                         .font(.caption2)
622 +                 }
623 +             }
624 +             .font(.caption2)
625 +             .foregroundColor(.secondary)
626 +         }
627 +         .padding(.vertical, 2)
628 +     }
629 + }
630 +
631 + struct WatchedTransactionView: View {
632 +     let transactionId: String
633 +     let status: SmartMempoolObserver.TransactionStatus
634 +
635 +     var body: some View {
636 +         HStack {
637 +             statusIcon
638 +
639 +             VStack(alignment: .leading) {
640 +                 Text(transactionId)
641 +                     .font(.system(.caption, design: .monospaced))
642 +                     .lineLimit(1)
643 +                     .truncationMode(.middle)
644 +
645 +                 Text(statusText)
646 +                     .font(.caption2)
647 +                     .foregroundColor(.secondary)
648 +             }
649 +
650 +             Spacer()
651 +         }
652 +         .padding(.vertical, 2)
653 +     }
654 +
655 +     @ViewBuilder
656 +     private var statusIcon: some View {
657 +         switch status {
658 +         case .pending(_):
659 +             Image(systemName: "clock")
660 +                 .foregroundColor(.orange)
661 +         case .confirmed(_):
662 +             Image(systemName: "checkmark.circle.fill")
663 +                 .foregroundColor(.green)
664 +         case .dropped(_):
665 +             Image(systemName: "xmark.circle.fill")
666 +                 .foregroundColor(.red)
667 +         }
668 +     }
669 +
670 +     private var statusText: String {
671 +         switch status {
672 +         case .pending(let date):
673 +             return "Pending since \(date.formatted(.dateTime.hour().minute()))"
674 +         case .confirmed(let date):
675 +             return "Confirmed at \(date.formatted(.dateTime.hour().minute()))"
676 +         case .dropped(let date):
677 +             return "Dropped at \(date.formatted(.dateTime.hour().minute()))"
678 +         }
679 +     }
680 + }
681 + ```
682 |
683 | ## Performance Optimizations
warning: Unknown option 'swift path' in code block.
   --> Tutorials/MempoolMonitoring.md:687:1-770:4
685 | ### Efficient Mempool Polling
686 |
687 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
688 + actor EfficientMempoolMonitor {
689 +     private let client: OgmiosClient
690 +     private var lastKnownSize: Int = 0
691 +     private var pollInterval: TimeInterval = 30.0 // Start with 30 seconds
692 +     private let minPollInterval: TimeInterval = 5.0
693 +     private let maxPollInterval: TimeInterval = 120.0
694 +
695 +     init(client: OgmiosClient) {
696 +         self.client = client
697 +     }
698 +
699 +     func adaptiveMonitoring() async {
700 +         while !Task.isCancelled {
701 +             do {
702 +                 // Check mempool size first (lightweight operation)
703 +                 let sizeResponse = try await client.mempoolMonitor.sizeOfMempool.execute()
704 +                 let currentSize = sizeResponse.result.currentSize
705 +
706 +                 // Adapt polling interval based on activity
707 +                 if currentSize != lastKnownSize {
708 +                     // Activity detected - increase polling frequency
709 +                     pollInterval = max(pollInterval * 0.8, minPollInterval)
710 +
711 +                     // Full mempool scan on changes
712 +                     await performFullScan()
713 +                 } else {
714 +                     // No changes - decrease polling frequency
715 +                     pollInterval = min(pollInterval * 1.2, maxPollInterval)
716 +                 }
717 +
718 +                 lastKnownSize = currentSize
719 +
720 +                 print("Next poll in \(String(format: "%.1f", pollInterval)) seconds")
721 +                 try await Task.sleep(nanoseconds: UInt64(pollInterval * 1_000_000_000))
722 +
723 +             } catch {
724 +                 print("Adaptive monitoring error: \(error)")
725 +                 try await Task.sleep(nanoseconds: 10_000_000_000) // 10 seconds on error
726 +             }
727 +         }
728 +     }
729 +
730 +     private func performFullScan() async {
731 +         do {
732 +             let transactions = try await client.mempoolMonitor.getMempoolTransactions()
733 +             print("Full scan found \(transactions.count) transactions")
734 +
735 +             // Process interesting transactions
736 +             await analyzeTransactions(transactions)
737 +
738 +         } catch {
739 +             print("Full scan error: \(error)")
740 +         }
741 +     }
742 +
743 +     private func analyzeTransactions(_ transactions: [NextTransactionResult]) async {
744 +         var highFeeCount = 0
745 +         var nativeAssetCount = 0
746 +         var totalFees: UInt64 = 0
747 +
748 +         for result in transactions {
749 +             guard case .transaction(let tx) = result else { continue }
750 +
751 +             totalFees += tx.body.fee
752 +
753 +             if tx.body.fee > 1_000_000 { // > 1 ADA
754 +                 highFeeCount += 1
755 +             }
756 +
757 +             let hasAssets = tx.body.outputs.contains { output in
758 +                 output.value.assets != nil
759 +             }
760 +             if hasAssets {
761 +                 nativeAssetCount += 1
762 +             }
763 +         }
764 +
765 +         let avgFee = transactions.count > 0 ? totalFees / UInt64(transactions.count) : 0
766 +
767 +         print("Analysis: \(highFeeCount) high-fee, \(nativeAssetCount) with assets, avg fee: \(avgFee) lovelace")
768 +     }
769 + }
770 + ```
771 |
772 | ### Batch Transaction Processing
warning: Unknown option 'swift path' in code block.
   --> Tutorials/MempoolMonitoring.md:774:1-831:4
772 | ### Batch Transaction Processing
773 |
774 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
775 + actor BatchMempoolProcessor {
776 +     private let client: OgmiosClient
777 +     private let batchSize = 50
778 +     private var processingQueue: [Transaction] = []
779 +
780 +     init(client: OgmiosClient) {
781 +         self.client = client
782 +     }
783 +
784 +     func processMempoolInBatches() async {
785 +         do {
786 +             let allTransactions = try await client.mempoolMonitor.getMempoolTransactions()
787 +
788 +             let transactions = allTransactions.compactMap { result -> Transaction? in
789 +                 guard case .transaction(let tx) = result else { return nil }
790 +                 return tx
791 +             }
792 +
793 +             // Process in batches to avoid memory pressure
794 +             for batch in transactions.chunked(into: batchSize) {
795 +                 await processBatch(batch)
796 +
797 +                 // Small delay between batches to prevent overwhelming
798 +                 try await Task.sleep(nanoseconds: 100_000_000) // 0.1 seconds
799 +             }
800 +
801 +         } catch {
802 +             print("Batch processing error: \(error)")
803 +         }
804 +     }
805 +
806 +     private func processBatch(_ transactions: [Transaction]) async {
807 +         await withTaskGroup(of: Void.self) { group in
808 +             for transaction in transactions {
809 +                 group.addTask {
810 +                     await self.processTransaction(transaction)
811 +                 }
812 +             }
813 +         }
814 +     }
815 +
816 +     private func processTransaction(_ transaction: Transaction) async {
817 +         // Heavy processing work here
818 +         // e.g., database updates, notifications, analysis
819 +         print("Processing \(transaction.id)")
820 +     }
821 + }
822 +
823 + // Array extension for chunking
824 + extension Array {
825 +     func chunked(into size: Int) -> [[Element]] {
826 +         return stride(from: 0, to: count, by: size).map {
827 +             Array(self[$0..<Swift.min($0 + size, count)])
828 +         }
829 +     }
830 + }
831 + ```
832 |
833 | ## Testing Mempool Monitoring
warning: Unknown option 'swift path' in code block.
   --> Tutorials/MempoolMonitoring.md:835:1-922:4
833 | ## Testing Mempool Monitoring
834 |
835 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
836 + import XCTest
837 + @testable import SwiftOgmios
838 +
839 + class MempoolMonitoringTests: XCTestCase {
840 +     var client: OgmiosClient!
841 +     var observer: SmartMempoolObserver!
842 +
843 +     override func setUp() async throws {
844 +         client = try await OgmiosClient(
845 +             httpOnly: false,
846 +             webSocketConnection: MockWebSocketConnection()
847 +         )
848 +         observer = SmartMempoolObserver(client: client)
849 +     }
850 +
851 +     func testBasicMempoolOperations() async throws {
852 +         // Test acquiring mempool
853 +         let snapshot = try await client.mempoolMonitor.acquireMempool.execute()
854 +         XCTAssertNotNil(snapshot.result.slot)
855 +
856 +         // Test getting size
857 +         let size = try await client.mempoolMonitor.sizeOfMempool.execute()
858 +         XCTAssertGreaterThanOrEqual(size.result.currentSize, 0)
859 +         XCTAssertGreaterThan(size.result.capacity, 0)
860 +
861 +         // Test checking transaction existence
862 +         let hasTransaction = try await client.mempoolMonitor.hasTransaction.execute(
863 +             transaction: TransactionId("test-tx-id"),
864 +             id: .generateNextNanoId()
865 +         )
866 +         XCTAssertNotNil(hasTransaction.result)
867 +
868 +         // Test releasing mempool
869 +         let release = try await client.mempoolMonitor.releaseMempool.execute()
870 +         XCTAssertNotNil(release)
871 +     }
872 +
873 +     func testTransactionFilter() {
874 +         let filter = TransactionFilter(
875 +             addresses: ["addr1test123"],
876 +             minAmount: 1_000_000
877 +         )
878 +
879 +         // Create test transaction
880 +         let mockTransaction = createMockTransaction(
881 +             outputs: [
882 +                 createMockOutput(address: "addr1test123", amount: 2_000_000)
883 +             ]
884 +         )
885 +
886 +         XCTAssertTrue(filter.matches(mockTransaction))
887 +
888 +         // Test with different address
889 +         let mockTransaction2 = createMockTransaction(
890 +             outputs: [
891 +                 createMockOutput(address: "addr1different", amount: 2_000_000)
892 +             ]
893 +         )
894 +
895 +         XCTAssertFalse(filter.matches(mockTransaction2))
896 +     }
897 +
898 +     func testMempoolObserver() async throws {
899 +         // Start monitoring
900 +         await observer.startMonitoring()
901 +         XCTAssertTrue(observer.isMonitoring)
902 +
903 +         // Wait for some monitoring cycles
904 +         try await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
905 +
906 +         // Stop monitoring
907 +         await observer.stopMonitoring()
908 +         XCTAssertFalse(observer.isMonitoring)
909 +     }
910 +
911 +     private func createMockTransaction(outputs: [TransactionOutput]) -> Transaction {
912 +         // Create mock transaction for testing
913 +         // Implementation depends on your Transaction structure
914 +         fatalError("Implement mock transaction creation")
915 +     }
916 +
917 +     private func createMockOutput(address: String, amount: UInt64) -> TransactionOutput {
918 +         // Create mock transaction output
919 +         fatalError("Implement mock output creation")
920 +     }
921 + }
922 + ```
923 |
924 | ## Best Practices
warning: Extraneous content found after a link in task group list item
   --> Tutorials/MempoolMonitoring.md:946:3-946:58
944 | ## See Also
945 |
946 + - <doc:GettingStarted> - Basic setup and first operations
    |   ╰─suggestion: Remove extraneous content
947 | - <doc:TransactionSubmission> - Submitting transactions to monitor
948 | - <doc:ChainSynchronization> - Confirming mempool transactions in blocks
warning: Extraneous content found after a link in task group list item
   --> Tutorials/MempoolMonitoring.md:947:3-947:67
945 |
946 | - <doc:GettingStarted> - Basic setup and first operations
947 + - <doc:TransactionSubmission> - Submitting transactions to monitor
    |   ╰─suggestion: Remove extraneous content
948 | - <doc:ChainSynchronization> - Confirming mempool transactions in blocks
949 | - <doc:ErrorHandling> - Handling mempool monitoring errors
warning: Extraneous content found after a link in task group list item
   --> Tutorials/MempoolMonitoring.md:948:3-948:73
946 | - <doc:GettingStarted> - Basic setup and first operations
947 | - <doc:TransactionSubmission> - Submitting transactions to monitor
948 + - <doc:ChainSynchronization> - Confirming mempool transactions in blocks
    |   ╰─suggestion: Remove extraneous content
949 | - <doc:ErrorHandling> - Handling mempool monitoring errors
950 | - <doc:TransportTypes> - Optimizing connection types for monitoring
warning: Extraneous content found after a link in task group list item
   --> Tutorials/MempoolMonitoring.md:949:3-949:59
947 | - <doc:TransactionSubmission> - Submitting transactions to monitor
948 | - <doc:ChainSynchronization> - Confirming mempool transactions in blocks
949 + - <doc:ErrorHandling> - Handling mempool monitoring errors
    |   ╰─suggestion: Remove extraneous content
950 | - <doc:TransportTypes> - Optimizing connection types for monitoring
warning: Extraneous content found after a link in task group list item
   --> Tutorials/MempoolMonitoring.md:950:3-950:68
948 | - <doc:ChainSynchronization> - Confirming mempool transactions in blocks
949 | - <doc:ErrorHandling> - Handling mempool monitoring errors
950 + - <doc:TransportTypes> - Optimizing connection types for monitoring
    |   ╰─suggestion: Remove extraneous content
warning: Unknown option 'swift path' in code block.
  --> Tutorials/TransactionSubmission.md:23:1-44:4
21 | ### Simple Submission
22 |
23 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
24 + import SwiftOgmios
25 +
26 + // Create client (HTTP or WebSocket both work for submission)
27 + let client = try await OgmiosClient(httpOnly: true)
28 +
29 + // Your transaction CBOR bytes (from transaction builder)
30 + let transactionCBOR = Data(/* your transaction bytes */)
31 +
32 + do {
33 +     let response = try await client.transactionSubmission.submitTransaction.execute(
34 +         transaction: transactionCBOR,
35 +         id: .generateNextNanoId()
36 +     )
37 +
38 +     print("Transaction submitted successfully!")
39 +     print("Transaction ID: \(response.result)")
40 +
41 + } catch {
42 +     print("Transaction submission failed: \(error)")
43 + }
44 + ```
45 |
46 | ### Transaction Building Integration
warning: Unknown option 'swift path' in code block.
  --> Tutorials/TransactionSubmission.md:48:1-93:4
46 | ### Transaction Building Integration
47 |
48 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
49 + import SwiftCardanoTxBuilder // Assumed transaction builder library
50 +
51 + class TransactionService {
52 +     private let client: OgmiosClient
53 +     private let txBuilder: TransactionBuilder
54 +
55 +     init(client: OgmiosClient) {
56 +         self.client = client
57 +         self.txBuilder = TransactionBuilder()
58 +     }
59 +
60 +     func sendAda(
61 +         from senderKey: PrivateKey,
62 +         to recipientAddress: Address,
63 +         amount: Lovelace,
64 +         changeAddress: Address
65 +     ) async throws -> String {
66 +         // 1. Get protocol parameters for fee calculation
67 +         let protocolParams = try await client.ledgerStateQuery.protocolParameters.execute()
68 +
69 +         // 2. Get UTxOs for the sender
70 +         let utxoResponse = try await client.ledgerStateQuery.utxo.execute(
71 +             addresses: [senderKey.publicKey.address],
72 +             id: .generateNextNanoId()
73 +         )
74 +
75 +         // 3. Build transaction
76 +         let transaction = try txBuilder
77 +             .addInputs(from: utxoResponse.result)
78 +             .addOutput(address: recipientAddress, amount: amount)
79 +             .addOutput(address: changeAddress, amount: .calculateChange)
80 +             .calculateFee(using: protocolParams.result)
81 +             .sign(with: senderKey)
82 +             .build()
83 +
84 +         // 4. Submit transaction
85 +         let submitResponse = try await client.transactionSubmission.submitTransaction.execute(
86 +             transaction: transaction.toCBOR(),
87 +             id: .generateNextNanoId()
88 +         )
89 +
90 +         return submitResponse.result
91 +     }
92 + }
93 + ```
94 |
95 | ## Comprehensive Error Handling
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:101:1-174:4
99  | ### Error Code Mapping
100 |
101 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
102 + enum TransactionSubmissionError: Error, LocalizedError {
103 +     case eraMismatch
104 +     case invalidSignatures
105 +     case missingSignatures
106 +     case missingScripts
107 +     case feeTooSmall(required: UInt64, provided: UInt64)
108 +     case valueNotConserved
109 +     case unknownOutputReference
110 +     case transactionTooLarge(size: Int, limit: Int)
111 +     case networkError(String)
112 +     case unknownError(String)
113 +
114 +     var errorDescription: String? {
115 +         switch self {
116 +         case .eraMismatch:
117 +             return "Transaction not valid in current era"
118 +         case .invalidSignatures:
119 +             return "Transaction signatures are invalid"
120 +         case .missingSignatures:
121 +             return "Required signatures are missing"
122 +         case .missingScripts:
123 +             return "Required script witnesses are missing"
124 +         case .feeTooSmall(let required, let provided):
125 +             return "Fee too small: required \(required), provided \(provided)"
126 +         case .valueNotConserved:
127 +             return "Input and output values don't match"
128 +         case .unknownOutputReference:
129 +             return "Referenced UTxO not found"
130 +         case .transactionTooLarge(let size, let limit):
131 +             return "Transaction too large: \(size) bytes (limit: \(limit))"
132 +         case .networkError(let message):
133 +             return "Network error: \(message)"
134 +         case .unknownError(let message):
135 +             return "Unknown error: \(message)"
136 +         }
137 +     }
138 +
139 +     var recoveryStrategy: RecoveryStrategy {
140 +         switch self {
141 +         case .eraMismatch:
142 +             return .rebuildTransaction
143 +         case .invalidSignatures, .missingSignatures:
144 +             return .fixSignatures
145 +         case .missingScripts:
146 +             return .addScripts
147 +         case .feeTooSmall:
148 +             return .increaseFee
149 +         case .valueNotConserved:
150 +             return .fixBalance
151 +         case .unknownOutputReference:
152 +             return .refreshUtxos
153 +         case .transactionTooLarge:
154 +             return .optimizeTransaction
155 +         case .networkError:
156 +             return .retry
157 +         case .unknownError:
158 +             return .investigate
159 +         }
160 +     }
161 + }
162 +
163 + enum RecoveryStrategy {
164 +     case rebuildTransaction
165 +     case fixSignatures
166 +     case addScripts
167 +     case increaseFee
168 +     case fixBalance
169 +     case refreshUtxos
170 +     case optimizeTransaction
171 +     case retry
172 +     case investigate
173 + }
174 + ```
175 |
176 | ### Error Processing Function
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:178:1-238:4
176 | ### Error Processing Function
177 |
178 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
179 + extension TransactionService {
180 +     func processSubmissionError(_ error: Error) -> TransactionSubmissionError {
181 +         guard let ogmiosError = error as? OgmiosError,
182 +               case .responseError(let message) = ogmiosError else {
183 +             return .networkError(error.localizedDescription)
184 +         }
185 +
186 +         // Parse error code from message
187 +         let errorCode = extractErrorCode(from: message)
188 +
189 +         switch errorCode {
190 +         case 3005:
191 +             return .eraMismatch
192 +         case 3100:
193 +             return .invalidSignatures
194 +         case 3101:
195 +             return .missingSignatures
196 +         case 3102:
197 +             return .missingScripts
198 +         case 3122:
199 +             let (required, provided) = extractFeeInfo(from: message)
200 +             return .feeTooSmall(required: required, provided: provided)
201 +         case 3123:
202 +             return .valueNotConserved
203 +         case 3117:
204 +             return .unknownOutputReference
205 +         case 3119:
206 +             let (size, limit) = extractSizeInfo(from: message)
207 +             return .transactionTooLarge(size: size, limit: limit)
208 +         default:
209 +             return .unknownError(message)
210 +         }
211 +     }
212 +
213 +     private func extractErrorCode(from message: String) -> Int {
214 +         // Extract 4-digit error code from message
215 +         let pattern = #"(\d{4})"#
216 +         let regex = try! NSRegularExpression(pattern: pattern)
217 +         let range = NSRange(message.startIndex..<message.endIndex, in: message)
218 +
219 +         if let match = regex.firstMatch(in: message, options: [], range: range) {
220 +             let codeRange = Range(match.range(at: 1), in: message)!
221 +             return Int(String(message[codeRange])) ?? 0
222 +         }
223 +
224 +         return 0
225 +     }
226 +
227 +     private func extractFeeInfo(from message: String) -> (required: UInt64, provided: UInt64) {
228 +         // Parse fee information from error message
229 +         // Implementation depends on specific error message format
230 +         return (required: 0, provided: 0)
231 +     }
232 +
233 +     private func extractSizeInfo(from message: String) -> (size: Int, limit: Int) {
234 +         // Parse size information from error message
235 +         return (size: 0, limit: 0)
236 +     }
237 + }
238 + ```
239 |
240 | ## Retry Mechanisms with Backoff
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:244:1-322:4
242 | ### Intelligent Retry Strategy
243 |
244 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
245 + class ResilientTransactionSubmitter {
246 +     private let client: OgmiosClient
247 +     private let maxRetries: Int
248 +     private let baseDelay: TimeInterval
249 +
250 +     init(client: OgmiosClient, maxRetries: Int = 3, baseDelay: TimeInterval = 1.0) {
251 +         self.client = client
252 +         self.maxRetries = maxRetries
253 +         self.baseDelay = baseDelay
254 +     }
255 +
256 +     func submitWithRetry(
257 +         transaction: Data,
258 +         onRetry: ((TransactionSubmissionError, Int) -> Void)? = nil
259 +     ) async throws -> String {
260 +         var lastError: TransactionSubmissionError?
261 +
262 +         for attempt in 1...maxRetries {
263 +             do {
264 +                 let response = try await client.transactionSubmission.submitTransaction.execute(
265 +                     transaction: transaction,
266 +                     id: .generateNextNanoId()
267 +                 )
268 +
269 +                 return response.result
270 +
271 +             } catch {
272 +                 let submissionError = processSubmissionError(error)
273 +                 lastError = submissionError
274 +
275 +                 // Check if error is retryable
276 +                 if !submissionError.isRetryable || attempt == maxRetries {
277 +                     throw submissionError
278 +                 }
279 +
280 +                 // Notify caller of retry attempt
281 +                 onRetry?(submissionError, attempt)
282 +
283 +                 // Calculate delay with exponential backoff
284 +                 let delay = baseDelay * pow(2.0, Double(attempt - 1))
285 +                 try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
286 +             }
287 +         }
288 +
289 +         throw lastError ?? TransactionSubmissionError.unknownError("Max retries exceeded")
290 +     }
291 +
292 +     private func processSubmissionError(_ error: Error) -> TransactionSubmissionError {
293 +         // Implementation from previous example
294 +         return .networkError(error.localizedDescription)
295 +     }
296 + }
297 +
298 + extension TransactionSubmissionError {
299 +     var isRetryable: Bool {
300 +         switch self {
301 +         case .networkError:
302 +             return true
303 +         case .unknownOutputReference:
304 +             return true // UTxO might become available
305 +         case .feeTooSmall:
306 +             return false // Needs manual fix
307 +         case .invalidSignatures, .missingSignatures:
308 +             return false // Needs manual fix
309 +         case .valueNotConserved:
310 +             return false // Needs manual fix
311 +         case .transactionTooLarge:
312 +             return false // Needs optimization
313 +         case .eraMismatch:
314 +             return true // Era might change
315 +         case .missingScripts:
316 +             return false // Needs manual fix
317 +         case .unknownError:
318 +             return true // Might be temporary
319 +         }
320 +     }
321 + }
322 + ```
323 |
324 | ### Usage Example
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:326:1-365:4
324 | ### Usage Example
325 |
326 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
327 + let submitter = ResilientTransactionSubmitter(client: client)
328 +
329 + do {
330 +     let txId = try await submitter.submitWithRetry(
331 +         transaction: transactionCBOR
332 +     ) { error, attempt in
333 +         print("Attempt \(attempt) failed: \(error.localizedDescription)")
334 +
335 +         // Handle specific errors
336 +         switch error.recoveryStrategy {
337 +         case .retry:
338 +             print("  Retrying...")
339 +         case .increaseFee:
340 +             print("  Consider increasing the fee")
341 +         case .refreshUtxos:
342 +             print("  UTxO set might have changed, consider refreshing")
343 +         default:
344 +             print("  Manual intervention required")
345 +         }
346 +     }
347 +
348 +     print("Transaction submitted: \(txId)")
349 +
350 + } catch let error as TransactionSubmissionError {
351 +     print("Final submission error: \(error.localizedDescription)")
352 +
353 +     // Provide user guidance based on error type
354 +     switch error.recoveryStrategy {
355 +     case .increaseFee:
356 +         print("Please increase the transaction fee and try again")
357 +     case .fixBalance:
358 +         print("Please check transaction inputs and outputs")
359 +     case .fixSignatures:
360 +         print("Please verify transaction signatures")
361 +     default:
362 +         print("Please check transaction details and try again")
363 +     }
364 + }
365 + ```
366 |
367 | ## Transaction Confirmation Monitoring
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:371:1-438:4
369 | ### Basic Confirmation Check
370 |
371 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
372 + class TransactionMonitor {
373 +     private let client: OgmiosClient
374 +
375 +     init(client: OgmiosClient) {
376 +         self.client = client
377 +     }
378 +
379 +     func waitForConfirmation(
380 +         transactionId: String,
381 +         requiredConfirmations: Int = 1,
382 +         timeoutSeconds: TimeInterval = 300
383 +     ) async throws -> Bool {
384 +         let startTime = Date()
385 +
386 +         while Date().timeIntervalSince(startTime) < timeoutSeconds {
387 +             // Check if transaction exists in mempool
388 +             let mempoolResponse = try await client.mempoolMonitor.hasTransaction.execute(
389 +                 transaction: TransactionId(transactionId),
390 +                 id: .generateNextNanoId()
391 +             )
392 +
393 +             if mempoolResponse.result {
394 +                 print("Transaction \(transactionId) is in mempool")
395 +
396 +                 // Wait a bit and check again
397 +                 try await Task.sleep(nanoseconds: 10_000_000_000) // 10 seconds
398 +                 continue
399 +             }
400 +
401 +             // Transaction not in mempool, check if it's confirmed
402 +             let confirmations = try await getConfirmationCount(transactionId: transactionId)
403 +
404 +             if confirmations >= requiredConfirmations {
405 +                 print("Transaction \(transactionId) confirmed with \(confirmations) confirmations")
406 +                 return true
407 +             }
408 +
409 +             // Wait before next check
410 +             try await Task.sleep(nanoseconds: 20_000_000_000) // 20 seconds
411 +         }
412 +
413 +         throw TransactionMonitorError.timeout
414 +     }
415 +
416 +     private func getConfirmationCount(transactionId: String) async throws -> Int {
417 +         // Get current tip
418 +         let tipResponse = try await client.ledgerStateQuery.tip.execute()
419 +         let currentHeight = tipResponse.result.height
420 +
421 +         // Find transaction block (this is simplified - in practice you'd need to
422 +         // maintain a transaction index or use chain sync to track transactions)
423 +
424 +         // For this example, we'll assume the transaction was found at a specific height
425 +         // In a real implementation, you would:
426 +         // 1. Use chain sync to track transactions
427 +         // 2. Maintain a database of transaction locations
428 +         // 3. Or use external indexing services
429 +
430 +         return 0 // Placeholder - implement based on your transaction tracking strategy
431 +     }
432 + }
433 +
434 + enum TransactionMonitorError: Error {
435 +     case timeout
436 +     case notFound
437 + }
438 + ```
439 |
440 | ### Advanced Confirmation with Chain Sync
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:442:1-506:4
440 | ### Advanced Confirmation with Chain Sync
441 |
442 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
443 + actor TransactionTracker {
444 +     private var trackedTransactions: [String: TransactionStatus] = [:]
445 +     private let client: OgmiosClient
446 +
447 +     struct TransactionStatus {
448 +         let transactionId: String
449 +         var blockHeight: BlockHeight?
450 +         var confirmations: Int = 0
451 +         var isRolledBack = false
452 +         let submissionTime: Date
453 +     }
454 +
455 +     init(client: OgmiosClient) {
456 +         self.client = client
457 +     }
458 +
459 +     func trackTransaction(_ transactionId: String) {
460 +         trackedTransactions[transactionId] = TransactionStatus(
461 +             transactionId: transactionId,
462 +             submissionTime: Date()
463 +         )
464 +     }
465 +
466 +     func processBlock(_ block: Block, currentTip: BlockHeight) {
467 +         guard let transactions = block.body else { return }
468 +
469 +         // Check if any tracked transactions are in this block
470 +         for transaction in transactions {
471 +             if let status = trackedTransactions[transaction.id] {
472 +                 var updatedStatus = status
473 +                 updatedStatus.blockHeight = block.header.blockHeight
474 +                 updatedStatus.confirmations = Int(currentTip - block.header.blockHeight) + 1
475 +                 updatedStatus.isRolledBack = false
476 +
477 +                 trackedTransactions[transaction.id] = updatedStatus
478 +
479 +                 print("Transaction \(transaction.id) confirmed in block \(block.header.blockHeight)")
480 +             }
481 +         }
482 +     }
483 +
484 +     func handleRollback(to height: BlockHeight) {
485 +         // Mark transactions in rolled-back blocks
486 +         for (txId, var status) in trackedTransactions {
487 +             if let blockHeight = status.blockHeight, blockHeight > height {
488 +                 status.isRolledBack = true
489 +                 status.blockHeight = nil
490 +                 status.confirmations = 0
491 +                 trackedTransactions[txId] = status
492 +
493 +                 print("Transaction \(txId) rolled back")
494 +             }
495 +         }
496 +     }
497 +
498 +     func getStatus(for transactionId: String) -> TransactionStatus? {
499 +         return trackedTransactions[transactionId]
500 +     }
501 +
502 +     func removeTransaction(_ transactionId: String) {
503 +         trackedTransactions.removeValue(forKey: transactionId)
504 +     }
505 + }
506 + ```
507 |
508 | ## Transaction Evaluation
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:514:1-543:4
512 | ### Basic Transaction Evaluation
513 |
514 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
515 + func evaluateTransaction(
516 +     transaction: Data,
517 +     additionalUtxo: [TransactionInput: TransactionOutput] = [:]
518 + ) async throws -> EvaluationResult {
519 +     let response = try await client.transactionSubmission.evaluateTransaction.execute(
520 +         transaction: transaction,
521 +         additionalUtxo: additionalUtxo,
522 +         id: .generateNextNanoId()
523 +     )
524 +
525 +     return response.result
526 + }
527 +
528 + // Usage
529 + do {
530 +     let evaluation = try await evaluateTransaction(transaction: transactionCBOR)
531 +
532 +     print("Evaluation successful:")
533 +     for (redeemer, budget) in evaluation {
534 +         print("  Redeemer: \(redeemer)")
535 +         print("    CPU: \(budget.cpu) steps")
536 +         print("    Memory: \(budget.memory) units")
537 +     }
538 +
539 + } catch {
540 +     print("Evaluation failed: \(error)")
541 +     // Transaction would fail if submitted
542 + }
543 + ```
544 |
545 | ### Pre-Submission Validation
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:547:1-649:4
545 | ### Pre-Submission Validation
546 |
547 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
548 + class TransactionValidator {
549 +     private let client: OgmiosClient
550 +
551 +     init(client: OgmiosClient) {
552 +         self.client = client
553 +     }
554 +
555 +     func validateBeforeSubmission(transaction: Data) async throws -> ValidationResult {
556 +         var issues: [ValidationIssue] = []
557 +
558 +         // 1. Evaluate transaction execution
559 +         do {
560 +             let evaluation = try await client.transactionSubmission.evaluateTransaction.execute(
561 +                 transaction: transaction,
562 +                 additionalUtxo: [:],
563 +                 id: .generateNextNanoId()
564 +             )
565 +
566 +             // Check execution budgets
567 +             for (_, budget) in evaluation.result {
568 +                 if budget.cpu > 10_000_000 { // Example limit
569 +                     issues.append(.highCpuUsage(budget.cpu))
570 +                 }
571 +                 if budget.memory > 14_000_000 { // Example limit
572 +                     issues.append(.highMemoryUsage(budget.memory))
573 +                 }
574 +             }
575 +
576 +         } catch {
577 +             issues.append(.evaluationFailed(error.localizedDescription))
578 +         }
579 +
580 +         // 2. Check transaction size
581 +         if transaction.count > 16_384 { // 16KB limit example
582 +             issues.append(.transactionTooLarge(transaction.count))
583 +         }
584 +
585 +         // 3. Get protocol parameters and validate fee
586 +         do {
587 +             let protocolParams = try await client.ledgerStateQuery.protocolParameters.execute()
588 +             let minFee = calculateMinimumFee(for: transaction, using: protocolParams.result)
589 +
590 +             // Extract actual fee from transaction (implementation depends on transaction format)
591 +             let actualFee = extractFee(from: transaction)
592 +
593 +             if actualFee < minFee {
594 +                 issues.append(.feeTooLow(required: minFee, provided: actualFee))
595 +             }
596 +
597 +         } catch {
598 +             issues.append(.parameterCheckFailed(error.localizedDescription))
599 +         }
600 +
601 +         return ValidationResult(issues: issues, isValid: issues.isEmpty)
602 +     }
603 +
604 +     private func calculateMinimumFee(for transaction: Data, using params: ProtocolParameters) -> UInt64 {
605 +         // Implement fee calculation based on protocol parameters
606 +         // This is a simplified calculation - use proper fee calculation library
607 +         let baseFee = params.minFeeConstant
608 +         let sizeFee = UInt64(transaction.count) * params.minFeeCoefficient
609 +         return baseFee + sizeFee
610 +     }
611 +
612 +     private func extractFee(from transaction: Data) -> UInt64 {
613 +         // Extract fee from transaction CBOR
614 +         // Implementation depends on transaction format
615 +         return 0 // Placeholder
616 +     }
617 + }
618 +
619 + struct ValidationResult {
620 +     let issues: [ValidationIssue]
621 +     let isValid: Bool
622 + }
623 +
624 + enum ValidationIssue {
625 +     case highCpuUsage(UInt64)
626 +     case highMemoryUsage(UInt64)
627 +     case transactionTooLarge(Int)
628 +     case feeTooLow(required: UInt64, provided: UInt64)
629 +     case evaluationFailed(String)
630 +     case parameterCheckFailed(String)
631 +
632 +     var description: String {
633 +         switch self {
634 +         case .highCpuUsage(let cpu):
635 +             return "High CPU usage: \(cpu) steps"
636 +         case .highMemoryUsage(let memory):
637 +             return "High memory usage: \(memory) units"
638 +         case .transactionTooLarge(let size):
639 +             return "Transaction too large: \(size) bytes"
640 +         case .feeTooLow(let required, let provided):
641 +             return "Fee too low: \(provided) (required: \(required))"
642 +         case .evaluationFailed(let error):
643 +             return "Evaluation failed: \(error)"
644 +         case .parameterCheckFailed(let error):
645 +             return "Parameter check failed: \(error)"
646 +         }
647 +     }
648 + }
649 + ```
650 |
651 | ## Complete Transaction Workflow
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:655:1-760:4
653 | ### Production-Ready Transaction Service
654 |
655 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
656 + @MainActor
657 + class ProductionTransactionService: ObservableObject {
658 +     @Published var isSubmitting = false
659 +     @Published var submissionStatus: SubmissionStatus = .idle
660 +     @Published var lastTransactionId: String?
661 +     @Published var confirmationCount = 0
662 +
663 +     private let client: OgmiosClient
664 +     private let validator: TransactionValidator
665 +     private let submitter: ResilientTransactionSubmitter
666 +     private let monitor: TransactionMonitor
667 +     private let tracker: TransactionTracker
668 +
669 +     enum SubmissionStatus {
670 +         case idle
671 +         case validating
672 +         case submitting
673 +         case waitingConfirmation
674 +         case confirmed
675 +         case failed(String)
676 +         case rolledBack
677 +     }
678 +
679 +     init(client: OgmiosClient) {
680 +         self.client = client
681 +         self.validator = TransactionValidator(client: client)
682 +         self.submitter = ResilientTransactionSubmitter(client: client)
683 +         self.monitor = TransactionMonitor(client: client)
684 +         self.tracker = TransactionTracker(client: client)
685 +     }
686 +
687 +     func submitTransaction(
688 +         _ transaction: Data,
689 +         requiredConfirmations: Int = 1
690 +     ) async {
691 +         isSubmitting = true
692 +         submissionStatus = .validating
693 +
694 +         defer {
695 +             isSubmitting = false
696 +         }
697 +
698 +         do {
699 +             // 1. Validate transaction
700 +             let validation = try await validator.validateBeforeSubmission(transaction: transaction)
701 +
702 +             if !validation.isValid {
703 +                 let issues = validation.issues.map { $0.description }.joined(separator: ", ")
704 +                 submissionStatus = .failed("Validation failed: \(issues)")
705 +                 return
706 +             }
707 +
708 +             // 2. Submit transaction
709 +             submissionStatus = .submitting
710 +
711 +             let transactionId = try await submitter.submitWithRetry(
712 +                 transaction: transaction
713 +             ) { error, attempt in
714 +                 print("Submission attempt \(attempt) failed: \(error.localizedDescription)")
715 +             }
716 +
717 +             lastTransactionId = transactionId
718 +
719 +             // 3. Track transaction
720 +             await tracker.trackTransaction(transactionId)
721 +
722 +             // 4. Wait for confirmation
723 +             submissionStatus = .waitingConfirmation
724 +
725 +             let confirmed = try await monitor.waitForConfirmation(
726 +                 transactionId: transactionId,
727 +                 requiredConfirmations: requiredConfirmations
728 +             )
729 +
730 +             if confirmed {
731 +                 submissionStatus = .confirmed
732 +                 confirmationCount = requiredConfirmations
733 +             } else {
734 +                 submissionStatus = .failed("Confirmation timeout")
735 +             }
736 +
737 +         } catch let error as TransactionSubmissionError {
738 +             submissionStatus = .failed(error.localizedDescription)
739 +         } catch {
740 +             submissionStatus = .failed("Unknown error: \(error.localizedDescription)")
741 +         }
742 +     }
743 +
744 +     func checkTransactionStatus() async {
745 +         guard let txId = lastTransactionId else { return }
746 +
747 +         let status = await tracker.getStatus(for: txId)
748 +
749 +         if let status = status {
750 +             confirmationCount = status.confirmations
751 +
752 +             if status.isRolledBack {
753 +                 submissionStatus = .rolledBack
754 +             } else if status.confirmations > 0 {
755 +                 submissionStatus = .confirmed
756 +             }
757 +         }
758 +     }
759 + }
760 + ```
761 |
762 | ### SwiftUI Integration
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransactionSubmission.md:764:1-878:4
762 | ### SwiftUI Integration
763 |
764 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
765 + struct TransactionSubmissionView: View {
766 +     @StateObject private var transactionService: ProductionTransactionService
767 +     @State private var transactionData = Data()
768 +     @State private var showingDetails = false
769 +
770 +     init(client: OgmiosClient) {
771 +         self._transactionService = StateObject(wrappedValue: ProductionTransactionService(client: client))
772 +     }
773 +
774 +     var body: some View {
775 +         VStack(spacing: 20) {
776 +             // Status indicator
777 +             statusView
778 +
779 +             // Transaction ID
780 +             if let txId = transactionService.lastTransactionId {
781 +                 VStack {
782 +                     Text("Transaction ID")
783 +                         .font(.caption)
784 +                         .foregroundColor(.secondary)
785 +
786 +                     Text(txId)
787 +                         .font(.system(.caption, design: .monospaced))
788 +                         .lineLimit(1)
789 +                         .truncationMode(.middle)
790 +                 }
791 +             }
792 +
793 +             // Confirmation count
794 +             if transactionService.confirmationCount > 0 {
795 +                 HStack {
796 +                     Text("Confirmations:")
797 +                     Text("\(transactionService.confirmationCount)")
798 +                         .fontWeight(.semibold)
799 +                 }
800 +                 .font(.caption)
801 +             }
802 +
803 +             // Submit button
804 +             Button("Submit Transaction") {
805 +                 Task {
806 +                     await transactionService.submitTransaction(
807 +                         transactionData,
808 +                         requiredConfirmations: 3
809 +                     )
810 +                 }
811 +             }
812 +             .disabled(transactionService.isSubmitting || transactionData.isEmpty)
813 +             .buttonStyle(.borderedProminent)
814 +
815 +             // Details button
816 +             Button("View Details") {
817 +                 showingDetails = true
818 +             }
819 +             .buttonStyle(.bordered)
820 +         }
821 +         .padding()
822 +         .sheet(isPresented: $showingDetails) {
823 +             TransactionDetailsView(service: transactionService)
824 +         }
825 +         .task {
826 +             // Periodically check transaction status
827 +             while !Task.isCancelled {
828 +                 await transactionService.checkTransactionStatus()
829 +                 try? await Task.sleep(nanoseconds: 30_000_000_000) // 30 seconds
830 +             }
831 +         }
832 +     }
833 +
834 +     @ViewBuilder
835 +     private var statusView: some View {
836 +         HStack {
837 +             Circle()
838 +                 .fill(statusColor)
839 +                 .frame(width: 12, height: 12)
840 +
841 +             Text(statusText)
842 +                 .font(.headline)
843 +         }
844 +     }
845 +
846 +     private var statusColor: Color {
847 +         switch transactionService.submissionStatus {
848 +         case .idle:
849 +             return .gray
850 +         case .validating, .submitting, .waitingConfirmation:
851 +             return .orange
852 +         case .confirmed:
853 +             return .green
854 +         case .failed, .rolledBack:
855 +             return .red
856 +         }
857 +     }
858 +
859 +     private var statusText: String {
860 +         switch transactionService.submissionStatus {
861 +         case .idle:
862 +             return "Ready"
863 +         case .validating:
864 +             return "Validating..."
865 +         case .submitting:
866 +             return "Submitting..."
867 +         case .waitingConfirmation:
868 +             return "Waiting for Confirmation"
869 +         case .confirmed:
870 +             return "Confirmed"
871 +         case .failed(let error):
872 +             return "Failed: \(error)"
873 +         case .rolledBack:
874 +             return "Rolled Back"
875 +         }
876 +     }
877 + }
878 + ```
879 |
880 | ## Best Practices
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransactionSubmission.md:893:3-893:58
891 | ## See Also
892 |
893 + - <doc:GettingStarted> - Basic setup and first operations
    |   ╰─suggestion: Remove extraneous content
894 | - <doc:ErrorHandling> - Comprehensive error handling strategies
895 | - <doc:LedgerStateQueries> - Querying protocol parameters and UTxOs
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransactionSubmission.md:894:3-894:64
892 |
893 | - <doc:GettingStarted> - Basic setup and first operations
894 + - <doc:ErrorHandling> - Comprehensive error handling strategies
    |   ╰─suggestion: Remove extraneous content
895 | - <doc:LedgerStateQueries> - Querying protocol parameters and UTxOs
896 | - <doc:ChainSynchronization> - Monitoring transaction confirmations
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransactionSubmission.md:895:3-895:68
893 | - <doc:GettingStarted> - Basic setup and first operations
894 | - <doc:ErrorHandling> - Comprehensive error handling strategies
895 + - <doc:LedgerStateQueries> - Querying protocol parameters and UTxOs
    |   ╰─suggestion: Remove extraneous content
896 | - <doc:ChainSynchronization> - Monitoring transaction confirmations
897 | - <doc:MempoolMonitoring> - Tracking transactions in mempool
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransactionSubmission.md:896:3-896:68
894 | - <doc:ErrorHandling> - Comprehensive error handling strategies
895 | - <doc:LedgerStateQueries> - Querying protocol parameters and UTxOs
896 + - <doc:ChainSynchronization> - Monitoring transaction confirmations
    |   ╰─suggestion: Remove extraneous content
897 | - <doc:MempoolMonitoring> - Tracking transactions in mempool
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransactionSubmission.md:897:3-897:61
895 | - <doc:LedgerStateQueries> - Querying protocol parameters and UTxOs
896 | - <doc:ChainSynchronization> - Monitoring transaction confirmations
897 + - <doc:MempoolMonitoring> - Tracking transactions in mempool
    |   ╰─suggestion: Remove extraneous content
warning: Unknown option 'swift path' in code block.
  --> Tutorials/TransportTypes.md:37:1-54:4
35 | ### Basic HTTP Usage
36 |
37 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
38 + import SwiftOgmios
39 +
40 + // Create HTTP client
41 + let httpClient = try await OgmiosClient(
42 +     host: "localhost",
43 +     port: 1337,
44 +     secure: false,      // Use HTTP
45 +     httpOnly: true      // Force HTTP transport
46 + )
47 +
48 + // Perform simple queries
49 + let epochResponse = try await httpClient.ledgerStateQuery.epoch.execute()
50 + print("Current epoch: \(epochResponse.result)")
51 +
52 + // HTTP is automatically closed after each request
53 + // No need to manage persistent connections
54 + ```
55 |
56 | ### HTTPS for Production
warning: Unknown option 'swift path' in code block.
  --> Tutorials/TransportTypes.md:58:1-70:4
56 | ### HTTPS for Production
57 |
58 + ```swift path=null start=null
   | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
59 + // Production HTTPS client
60 + let httpsClient = try await OgmiosClient(
61 +     host: "your-ogmios-server.com",
62 +     port: 443,
63 +     secure: true,       // Use HTTPS
64 +     httpOnly: true      // Force HTTPS transport
65 + )
66 +
67 + // All communication is encrypted via TLS
68 + let tipResponse = try await httpsClient.ledgerStateQuery.tip.execute()
69 + print("Secure tip query: \(tipResponse.result)")
70 + ```
71 |
72 | ### HTTP Performance Optimization
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:74:1-116:4
72  | ### HTTP Performance Optimization
73  |
74  + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
75  + class OptimizedHTTPClient {
76  +     private let client: OgmiosClient
77  +     private let session: URLSession
78  +
79  +     init(host: String, port: Int, secure: Bool = true) async throws {
80  +         // Configure optimized URLSession
81  +         let config = URLSessionConfiguration.default
82  +         config.httpMaximumConnectionsPerHost = 6
83  +         config.timeoutIntervalForRequest = 30
84  +         config.timeoutIntervalForResource = 300
85  +         config.requestCachePolicy = .useProtocolCachePolicy
86  +
87  +         // Enable HTTP/2 and connection reuse
88  +         config.httpShouldUsePipelining = true
89  +         config.urlCache = URLCache(memoryCapacity: 4 * 1024 * 1024, // 4MB
90  +                                    diskCapacity: 20 * 1024 * 1024)    // 20MB
91  +
92  +         self.session = URLSession(configuration: config)
93  +         self.client = try await OgmiosClient(
94  +             host: host,
95  +             port: port,
96  +             secure: secure,
97  +             httpOnly: true,
98  +             configuration: config
99  +         )
100 +     }
101 +
102 +     func batchQueries() async throws {
103 +         // Execute multiple queries concurrently
104 +         async let epochTask = client.ledgerStateQuery.epoch.execute()
105 +         async let tipTask = client.ledgerStateQuery.tip.execute()
106 +         async let poolsTask = client.ledgerStateQuery.stakePools.execute()
107 +
108 +         let (epochResponse, tipResponse, poolsResponse) = try await (epochTask, tipTask, poolsTask)
109 +
110 +         print("Batch results:")
111 +         print("  Epoch: \(epochResponse.result)")
112 +         print("  Tip: \(tipResponse.result.slot)")
113 +         print("  Pools: \(poolsResponse.result.count)")
114 +     }
115 + }
116 + ```
117 |
118 | ## WebSocket Transport
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:131:1-149:4
129 | ### Basic WebSocket Usage
130 |
131 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
132 + // Create WebSocket client
133 + let wsClient = try await OgmiosClient(
134 +     host: "localhost",
135 +     port: 1337,
136 +     secure: false,      // Use WS
137 +     httpOnly: false     // Use WebSocket transport
138 + )
139 +
140 + // Connection remains open for multiple requests
141 + let epochResponse = try await wsClient.ledgerStateQuery.epoch.execute()
142 + let tipResponse = try await wsClient.ledgerStateQuery.tip.execute()
143 +
144 + // WebSocket connection is reused automatically
145 + print("Epoch: \(epochResponse.result)")
146 + print("Tip: \(tipResponse.result.slot)")
147 +
148 + // Remember to clean up when done (handled automatically by deinit)
149 + ```
150 |
151 | ### WSS for Production
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:153:1-163:4
151 | ### WSS for Production
152 |
153 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
154 + // Production WSS client with enhanced security
155 + let wssClient = try await OgmiosClient(
156 +     host: "secure-ogmios-server.com",
157 +     port: 443,
158 +     secure: true,       // Use WSS (WebSocket Secure)
159 +     httpOnly: false
160 + )
161 +
162 + // All WebSocket communication is encrypted via TLS
163 + ```
164 |
165 | ### WebSocket Connection Management
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:167:1-307:4
165 | ### WebSocket Connection Management
166 |
167 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
168 + actor WebSocketManager {
169 +     private var client: OgmiosClient?
170 +     private let config: ConnectionConfig
171 +     private var reconnectAttempts = 0
172 +     private let maxReconnectAttempts = 5
173 +     private var heartbeatTask: Task<Void, Never>?
174 +
175 +     struct ConnectionConfig {
176 +         let host: String
177 +         let port: Int
178 +         let secure: Bool
179 +         let heartbeatInterval: TimeInterval = 30.0
180 +         let reconnectDelay: TimeInterval = 5.0
181 +     }
182 +
183 +     init(config: ConnectionConfig) {
184 +         self.config = config
185 +     }
186 +
187 +     func connect() async throws {
188 +         guard client == nil else { return }
189 +
190 +         do {
191 +             client = try await OgmiosClient(
192 +                 host: config.host,
193 +                 port: config.port,
194 +                 secure: config.secure,
195 +                 httpOnly: false
196 +             )
197 +
198 +             reconnectAttempts = 0
199 +             startHeartbeat()
200 +             print("WebSocket connected successfully")
201 +
202 +         } catch {
203 +             print("Connection failed: \(error)")
204 +             await scheduleReconnect()
205 +             throw error
206 +         }
207 +     }
208 +
209 +     func disconnect() {
210 +         heartbeatTask?.cancel()
211 +         client = nil
212 +         print("WebSocket disconnected")
213 +     }
214 +
215 +     func execute<T>(_ operation: (OgmiosClient) async throws -> T) async throws -> T {
216 +         guard let client = client else {
217 +             throw TransportError.notConnected
218 +         }
219 +
220 +         do {
221 +             return try await operation(client)
222 +         } catch {
223 +             print("Operation failed: \(error)")
224 +
225 +             // Check if we need to reconnect
226 +             if shouldReconnectOnError(error) {
227 +                 await scheduleReconnect()
228 +             }
229 +
230 +             throw error
231 +         }
232 +     }
233 +
234 +     private func startHeartbeat() {
235 +         heartbeatTask = Task { [weak self] in
236 +             while !Task.isCancelled {
237 +                 do {
238 +                     try await Task.sleep(nanoseconds: UInt64(config.heartbeatInterval * 1_000_000_000))
239 +                     await self?.performHeartbeat()
240 +                 } catch {
241 +                     break
242 +                 }
243 +             }
244 +         }
245 +     }
246 +
247 +     private func performHeartbeat() async {
248 +         do {
249 +             _ = try await client?.ledgerStateQuery.tip.execute()
250 +         } catch {
251 +             print("Heartbeat failed: \(error)")
252 +             await scheduleReconnect()
253 +         }
254 +     }
255 +
256 +     private func scheduleReconnect() async {
257 +         guard reconnectAttempts < maxReconnectAttempts else {
258 +             print("Max reconnect attempts exceeded")
259 +             return
260 +         }
261 +
262 +         reconnectAttempts += 1
263 +         disconnect()
264 +
265 +         print("Reconnecting in \(config.reconnectDelay) seconds (attempt \(reconnectAttempts))")
266 +
267 +         try? await Task.sleep(nanoseconds: UInt64(config.reconnectDelay * 1_000_000_000))
268 +
269 +         do {
270 +             try await connect()
271 +         } catch {
272 +             print("Reconnect failed: \(error)")
273 +         }
274 +     }
275 +
276 +     private func shouldReconnectOnError(_ error: Error) -> Bool {
277 +         switch error {
278 +         case OgmiosError.websocketError(_),
279 +              OgmiosError.httpError(_):
280 +             return true
281 +         default:
282 +             return false
283 +         }
284 +     }
285 + }
286 +
287 + enum TransportError: Error {
288 +     case notConnected
289 +     case connectionLost
290 +     case reconnectFailed
291 + }
292 +
293 + // Usage
294 + let manager = WebSocketManager(config: WebSocketManager.ConnectionConfig(
295 +     host: "localhost",
296 +     port: 1337,
297 +     secure: false
298 + ))
299 +
300 + try await manager.connect()
301 +
302 + let epoch = try await manager.execute { client in
303 +     return try await client.ledgerStateQuery.epoch.execute()
304 + }
305 +
306 + print("Current epoch: \(epoch.result)")
307 + ```
308 |
309 | ## Security Considerations
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:313:1-369:4
311 | ### TLS Configuration
312 |
313 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
314 + class SecureTransportClient {
315 +     static func createSecureClient(
316 +         host: String,
317 +         port: Int,
318 +         certificatePinning: Bool = false
319 +     ) async throws -> OgmiosClient {
320 +
321 +         let config = URLSessionConfiguration.default
322 +
323 +         // Enhanced security settings
324 +         config.tlsMinimumSupportedProtocolVersion = .TLSv12
325 +         config.tlsMaximumSupportedProtocolVersion = .TLSv13
326 +
327 +         if certificatePinning {
328 +             // Implement certificate pinning for enhanced security
329 +             config.urlSessionDidReceiveChallenge = { session, challenge in
330 +                 return await handleCertificateChallenge(challenge)
331 +             }
332 +         }
333 +
334 +         // Disable insecure connections
335 +         config.httpShouldUsePipelining = false
336 +         config.httpCookieAcceptPolicy = .never
337 +
338 +         return try await OgmiosClient(
339 +             host: host,
340 +             port: port,
341 +             secure: true, // Always use TLS in production
342 +             httpOnly: false,
343 +             configuration: config
344 +         )
345 +     }
346 +
347 +     private static func handleCertificateChallenge(
348 +         _ challenge: URLAuthenticationChallenge
349 +     ) async -> (URLSession.AuthChallengeDisposition, URLCredential?) {
350 +
351 +         // Implement certificate pinning logic
352 +         guard let serverTrust = challenge.protectionSpace.serverTrust else {
353 +             return (.cancelAuthenticationChallenge, nil)
354 +         }
355 +
356 +         // Validate certificate against pinned certificates
357 +         // This is a simplified example - implement proper certificate validation
358 +         let credential = URLCredential(trust: serverTrust)
359 +         return (.useCredential, credential)
360 +     }
361 + }
362 +
363 + // Usage
364 + let secureClient = try await SecureTransportClient.createSecureClient(
365 +     host: "production-ogmios.example.com",
366 +     port: 443,
367 +     certificatePinning: true
368 + )
369 + ```
370 |
371 | ### Authentication and Authorization
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:373:1-425:4
371 | ### Authentication and Authorization
372 |
373 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
374 + class AuthenticatedOgmiosClient {
375 +     private let baseClient: OgmiosClient
376 +     private let apiKey: String
377 +
378 +     init(host: String, port: Int, apiKey: String) async throws {
379 +         self.apiKey = apiKey
380 +
381 +         let config = URLSessionConfiguration.default
382 +         config.httpAdditionalHeaders = [
383 +             "Authorization": "Bearer \(apiKey)",
384 +             "User-Agent": "SwiftOgmios/1.0.0",
385 +             "Accept": "application/json"
386 +         ]
387 +
388 +         self.baseClient = try await OgmiosClient(
389 +             host: host,
390 +             port: port,
391 +             secure: true,
392 +             httpOnly: true,
393 +             configuration: config
394 +         )
395 +     }
396 +
397 +     func authenticatedQuery<T: JSONRPCResponse>(
398 +         _ operation: (OgmiosClient) async throws -> T
399 +     ) async throws -> T {
400 +         do {
401 +             return try await operation(baseClient)
402 +         } catch OgmiosError.httpError(let message) where message.contains("401") {
403 +             throw AuthenticationError.invalidCredentials
404 +         } catch OgmiosError.httpError(let message) where message.contains("403") {
405 +             throw AuthenticationError.accessDenied
406 +         } catch {
407 +             throw error
408 +         }
409 +     }
410 + }
411 +
412 + enum AuthenticationError: Error, LocalizedError {
413 +     case invalidCredentials
414 +     case accessDenied
415 +
416 +     var errorDescription: String? {
417 +         switch self {
418 +         case .invalidCredentials:
419 +             return "Invalid API credentials"
420 +         case .accessDenied:
421 +             return "Access denied - insufficient permissions"
422 +         }
423 +     }
424 + }
425 + ```
426 |
427 | ## Mobile Optimization
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:431:1-558:4
429 | ### Battery-Efficient Patterns
430 |
431 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
432 + @MainActor
433 + class MobileOptimizedClient: ObservableObject {
434 +     @Published var connectionState: ConnectionState = .disconnected
435 +     @Published var isBackgroundMode = false
436 +
437 +     private var client: OgmiosClient?
438 +     private let config: MobileConfig
439 +     private var backgroundTask: UIBackgroundTaskIdentifier = .invalid
440 +
441 +     enum ConnectionState {
442 +         case disconnected
443 +         case connecting
444 +         case connected
445 +         case backgrounded
446 +     }
447 +
448 +     struct MobileConfig {
449 +         let useHTTPInBackground: Bool = true
450 +         let backgroundSyncInterval: TimeInterval = 300 // 5 minutes
451 +         let foregroundSyncInterval: TimeInterval = 30  // 30 seconds
452 +         let batteryOptimizationEnabled: Bool = true
453 +     }
454 +
455 +     init(config: MobileConfig = MobileConfig()) {
456 +         self.config = config
457 +         setupAppLifecycleObservers()
458 +     }
459 +
460 +     private func setupAppLifecycleObservers() {
461 +         NotificationCenter.default.addObserver(
462 +             self,
463 +             selector: #selector(appDidEnterBackground),
464 +             name: UIApplication.didEnterBackgroundNotification,
465 +             object: nil
466 +         )
467 +
468 +         NotificationCenter.default.addObserver(
469 +             self,
470 +             selector: #selector(appWillEnterForeground),
471 +             name: UIApplication.willEnterForegroundNotification,
472 +             object: nil
473 +         )
474 +     }
475 +
476 +     @objc private func appDidEnterBackground() {
477 +         isBackgroundMode = true
478 +
479 +         if config.useHTTPInBackground {
480 +             // Switch to HTTP for background mode
481 +             Task {
482 +                 await switchToBackgroundMode()
483 +             }
484 +         }
485 +     }
486 +
487 +     @objc private func appWillEnterForeground() {
488 +         isBackgroundMode = false
489 +         endBackgroundTask()
490 +
491 +         Task {
492 +             await switchToForegroundMode()
493 +         }
494 +     }
495 +
496 +     private func switchToBackgroundMode() async {
497 +         beginBackgroundTask()
498 +
499 +         // Close WebSocket connections to save battery
500 +         client = nil
501 +         connectionState = .backgrounded
502 +
503 +         // Create HTTP client for occasional background updates
504 +         do {
505 +             client = try await OgmiosClient(
506 +                 host: "your-server.com",
507 +                 port: 443,
508 +                 secure: true,
509 +                 httpOnly: true
510 +             )
511 +         } catch {
512 +             print("Failed to create background HTTP client: \(error)")
513 +         }
514 +     }
515 +
516 +     private func switchToForegroundMode() async {
517 +         connectionState = .connecting
518 +
519 +         do {
520 +             // Recreate WebSocket client for real-time updates
521 +             client = try await OgmiosClient(
522 +                 host: "your-server.com",
523 +                 port: 443,
524 +                 secure: true,
525 +                 httpOnly: false
526 +             )
527 +
528 +             connectionState = .connected
529 +         } catch {
530 +             print("Failed to create foreground WebSocket client: \(error)")
531 +             connectionState = .disconnected
532 +         }
533 +     }
534 +
535 +     private func beginBackgroundTask() {
536 +         backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
537 +             self?.endBackgroundTask()
538 +         }
539 +     }
540 +
541 +     private func endBackgroundTask() {
542 +         if backgroundTask != .invalid {
543 +             UIApplication.shared.endBackgroundTask(backgroundTask)
544 +             backgroundTask = .invalid
545 +         }
546 +     }
547 +
548 +     func performOptimizedQuery<T>(
549 +         _ operation: (OgmiosClient) async throws -> T
550 +     ) async throws -> T {
551 +         guard let client = client else {
552 +             throw TransportError.notConnected
553 +         }
554 +
555 +         return try await operation(client)
556 +     }
557 + }
558 + ```
559 |
560 | ### Network Change Handling
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:562:1-657:4
560 | ### Network Change Handling
561 |
562 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
563 + import Network
564 +
565 + class NetworkAwareClient: ObservableObject {
566 +     @Published var networkStatus: NetworkStatus = .unknown
567 +     @Published var connectionQuality: ConnectionQuality = .unknown
568 +
569 +     private let monitor = NWPathMonitor()
570 +     private let queue = DispatchQueue(label: "NetworkMonitor")
571 +     private var client: OgmiosClient?
572 +
573 +     enum NetworkStatus {
574 +         case unknown
575 +         case unavailable
576 +         case wifi
577 +         case cellular
578 +         case ethernet
579 +     }
580 +
581 +     enum ConnectionQuality {
582 +         case unknown
583 +         case poor
584 +         case moderate
585 +         case good
586 +         case excellent
587 +     }
588 +
589 +     init() {
590 +         startNetworkMonitoring()
591 +     }
592 +
593 +     private func startNetworkMonitoring() {
594 +         monitor.pathUpdateHandler = { [weak self] path in
595 +             Task { @MainActor in
596 +                 self?.handleNetworkChange(path)
597 +             }
598 +         }
599 +         monitor.start(queue: queue)
600 +     }
601 +
602 +     @MainActor
603 +     private func handleNetworkChange(_ path: NWPath) {
604 +         // Update network status
605 +         if path.status == .satisfied {
606 +             if path.usesInterfaceType(.wifi) {
607 +                 networkStatus = .wifi
608 +                 connectionQuality = .excellent
609 +             } else if path.usesInterfaceType(.cellular) {
610 +                 networkStatus = .cellular
611 +                 connectionQuality = assessCellularQuality(path)
612 +             } else if path.usesInterfaceType(.wiredEthernet) {
613 +                 networkStatus = .ethernet
614 +                 connectionQuality = .excellent
615 +             }
616 +         } else {
617 +             networkStatus = .unavailable
618 +             connectionQuality = .unknown
619 +         }
620 +
621 +         // Adapt transport based on network quality
622 +         Task {
623 +             await adaptTransportToNetwork()
624 +         }
625 +     }
626 +
627 +     private func assessCellularQuality(_ path: NWPath) -> ConnectionQuality {
628 +         // Simplified cellular quality assessment
629 +         if path.isExpensive {
630 +             return .moderate // Cellular data
631 +         }
632 +         return .good
633 +     }
634 +
635 +     private func adaptTransportToNetwork() async {
636 +         let shouldUseHTTP = networkStatus == .cellular || connectionQuality == .poor
637 +
638 +         do {
639 +             client = try await OgmiosClient(
640 +                 host: "your-server.com",
641 +                 port: 443,
642 +                 secure: true,
643 +                 httpOnly: shouldUseHTTP
644 +             )
645 +
646 +             print("Adapted transport: \(shouldUseHTTP ? "HTTP" : "WebSocket") for \(networkStatus)")
647 +
648 +         } catch {
649 +             print("Failed to adapt transport: \(error)")
650 +         }
651 +     }
652 +
653 +     deinit {
654 +         monitor.cancel()
655 +     }
656 + }
657 + ```
658 |
659 | ## Performance Benchmarking
warning: Unknown option 'swift path' in code block.
   --> Tutorials/TransportTypes.md:663:1-821:4
661 | ### Transport Performance Comparison
662 |
663 + ```swift path=null start=null
    | ╰─suggestion: If 'swift path' is the language for this code block, then write 'swift path' as the first option.
664 + class TransportBenchmark {
665 +     struct BenchmarkResult {
666 +         let transportType: String
667 +         let operationsPerSecond: Double
668 +         let averageLatency: TimeInterval
669 +         let totalTime: TimeInterval
670 +         let successRate: Double
671 +     }
672 +
673 +     static func benchmarkTransports(
674 +         host: String,
675 +         port: Int,
676 +         operations: Int = 100
677 +     ) async throws -> [BenchmarkResult] {
678 +
679 +         var results: [BenchmarkResult] = []
680 +
681 +         // Benchmark HTTP
682 +         let httpResult = try await benchmarkHTTP(
683 +             host: host,
684 +             port: port,
685 +             operations: operations
686 +         )
687 +         results.append(httpResult)
688 +
689 +         // Benchmark WebSocket
690 +         let wsResult = try await benchmarkWebSocket(
691 +             host: host,
692 +             port: port,
693 +             operations: operations
694 +         )
695 +         results.append(wsResult)
696 +
697 +         return results
698 +     }
699 +
700 +     private static func benchmarkHTTP(
701 +         host: String,
702 +         port: Int,
703 +         operations: Int
704 +     ) async throws -> BenchmarkResult {
705 +
706 +         let client = try await OgmiosClient(
707 +             host: host,
708 +             port: port,
709 +             secure: false,
710 +             httpOnly: true
711 +         )
712 +
713 +         let startTime = Date()
714 +         var latencies: [TimeInterval] = []
715 +         var successes = 0
716 +
717 +         for _ in 0..<operations {
718 +             let operationStart = Date()
719 +
720 +             do {
721 +                 _ = try await client.ledgerStateQuery.tip.execute()
722 +                 let latency = Date().timeIntervalSince(operationStart)
723 +                 latencies.append(latency)
724 +                 successes += 1
725 +             } catch {
726 +                 print("HTTP operation failed: \(error)")
727 +             }
728 +         }
729 +
730 +         let totalTime = Date().timeIntervalSince(startTime)
731 +         let averageLatency = latencies.reduce(0, +) / Double(latencies.count)
732 +         let opsPerSecond = Double(successes) / totalTime
733 +         let successRate = Double(successes) / Double(operations)
734 +
735 +         return BenchmarkResult(
736 +             transportType: "HTTP",
737 +             operationsPerSecond: opsPerSecond,
738 +             averageLatency: averageLatency,
739 +             totalTime: totalTime,
740 +             successRate: successRate
741 +         )
742 +     }
743 +
744 +     private static func benchmarkWebSocket(
745 +         host: String,
746 +         port: Int,
747 +         operations: Int
748 +     ) async throws -> BenchmarkResult {
749 +
750 +         let client = try await OgmiosClient(
751 +             host: host,
752 +             port: port,
753 +             secure: false,
754 +             httpOnly: false
755 +         )
756 +
757 +         let startTime = Date()
758 +         var latencies: [TimeInterval] = []
759 +         var successes = 0
760 +
761 +         for _ in 0..<operations {
762 +             let operationStart = Date()
763 +
764 +             do {
765 +                 _ = try await client.ledgerStateQuery.tip.execute()
766 +                 let latency = Date().timeIntervalSince(operationStart)
767 +                 latencies.append(latency)
768 +                 successes += 1
769 +             } catch {
770 +                 print("WebSocket operation failed: \(error)")
771 +             }
772 +         }
773 +
774 +         let totalTime = Date().timeIntervalSince(startTime)
775 +         let averageLatency = latencies.reduce(0, +) / Double(latencies.count)
776 +         let opsPerSecond = Double(successes) / totalTime
777 +         let successRate = Double(successes) / Double(operations)
778 +
779 +         return BenchmarkResult(
780 +             transportType: "WebSocket",
781 +             operationsPerSecond: opsPerSecond,
782 +             averageLatency: averageLatency,
783 +             totalTime: totalTime,
784 +             successRate: successRate
785 +         )
786 +     }
787 +
788 +     static func printBenchmarkResults(_ results: [BenchmarkResult]) {
789 +         print("\n📊 Transport Benchmark Results:")
790 +         print("=" * 50)
791 +
792 +         for result in results {
793 +             print("\n\(result.transportType):")
794 +             print("  Operations/sec: \(String(format: "%.2f", result.operationsPerSecond))")
795 +             print("  Avg latency: \(String(format: "%.3f", result.averageLatency))s")
796 +             print("  Total time: \(String(format: "%.2f", result.totalTime))s")
797 +             print("  Success rate: \(String(format: "%.1f", result.successRate * 100))%")
798 +         }
799 +
800 +         if results.count >= 2 {
801 +             let httpResult = results.first { $0.transportType == "HTTP" }!
802 +             let wsResult = results.first { $0.transportType == "WebSocket" }!
803 +
804 +             let speedupFactor = wsResult.operationsPerSecond / httpResult.operationsPerSecond
805 +             let latencyImprovement = (httpResult.averageLatency - wsResult.averageLatency) / httpResult.averageLatency * 100
806 +
807 +             print("\n🚀 Performance Comparison:")
808 +             print("  WebSocket is \(String(format: "%.2f", speedupFactor))x faster")
809 +             print("  WebSocket has \(String(format: "%.1f", latencyImprovement))% lower latency")
810 +         }
811 +     }
812 + }
813 +
814 + // Usage
815 + let results = try await TransportBenchmark.benchmarkTransports(
816 +     host: "localhost",
817 +     port: 1337,
818 +     operations: 50
819 + )
820 + TransportBenchmark.printBenchmarkResults(results)
821 + ```
822 |
823 | ## Best Practices Summary
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransportTypes.md:863:3-863:61
861 | ## See Also
862 |
863 + - <doc:GettingStarted> - Basic setup and transport selection
    |   ╰─suggestion: Remove extraneous content
864 | - <doc:ErrorHandling> - Transport-specific error handling strategies
865 | - <doc:ChainSynchronization> - WebSocket usage for real-time block streaming
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransportTypes.md:864:3-864:69
862 |
863 | - <doc:GettingStarted> - Basic setup and transport selection
864 + - <doc:ErrorHandling> - Transport-specific error handling strategies
    |   ╰─suggestion: Remove extraneous content
865 | - <doc:ChainSynchronization> - WebSocket usage for real-time block streaming
866 | - <doc:MempoolMonitoring> - Transport considerations for mempool monitoring
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransportTypes.md:865:3-865:77
863 | - <doc:GettingStarted> - Basic setup and transport selection
864 | - <doc:ErrorHandling> - Transport-specific error handling strategies
865 + - <doc:ChainSynchronization> - WebSocket usage for real-time block streaming
    |   ╰─suggestion: Remove extraneous content
866 | - <doc:MempoolMonitoring> - Transport considerations for mempool monitoring
867 | - <doc:AdvancedUsage> - Advanced transport patterns and optimization techniques
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransportTypes.md:866:3-866:76
864 | - <doc:ErrorHandling> - Transport-specific error handling strategies
865 | - <doc:ChainSynchronization> - WebSocket usage for real-time block streaming
866 + - <doc:MempoolMonitoring> - Transport considerations for mempool monitoring
    |   ╰─suggestion: Remove extraneous content
867 | - <doc:AdvancedUsage> - Advanced transport patterns and optimization techniques
warning: Extraneous content found after a link in task group list item
   --> Tutorials/TransportTypes.md:867:3-867:80
865 | - <doc:ChainSynchronization> - WebSocket usage for real-time block streaming
866 | - <doc:MempoolMonitoring> - Transport considerations for mempool monitoring
867 + - <doc:AdvancedUsage> - Advanced transport patterns and optimization techniques
    |   ╰─suggestion: Remove extraneous content
Finished building documentation for 'SwiftOgmios' (4.59s)
Generated documentation archive at:
  /Users/admin/builder/spi-builder-workspace/.docs/kingpin-apps/swift-ogmios/main
Updating https://github.com/krzyzanowskim/CryptoSwift.git
Updating https://github.com/apple/swift-nio-extras.git
Updating https://github.com/apple/swift-atomics.git
Updating https://github.com/Kingpin-Apps/swift-cardano-core.git
Updating https://github.com/Kingpin-Apps/swift-nacl.git
Updating https://github.com/Kingpin-Apps/swift-mnemonic.git
Updating https://github.com/apple/swift-asn1.git
Updated https://github.com/apple/swift-nio-extras.git (0.62s)
Updated https://github.com/apple/swift-asn1.git (0.62s)
Updated https://github.com/Kingpin-Apps/swift-mnemonic.git (0.62s)
Updated https://github.com/Kingpin-Apps/swift-nacl.git (0.62s)
Updated https://github.com/Kingpin-Apps/swift-cardano-core.git (0.62s)
Updated https://github.com/apple/swift-atomics.git (0.62s)
Updated https://github.com/krzyzanowskim/CryptoSwift.git (0.63s)
Updating https://github.com/apple/swift-numerics
Updating https://github.com/Kingpin-Apps/swift-base58.git
Updating https://github.com/norio-nomura/Base32.git
Updating https://github.com/apple/swift-nio-ssl.git
Updating https://github.com/apple/swift-crypto.git
Updating https://github.com/Kingpin-Apps/swift-kes.git
Updating https://github.com/apple/swift-system.git
Updated https://github.com/apple/swift-system.git (0.60s)
Updating https://github.com/attaswift/BigInt.git
Updated https://github.com/apple/swift-numerics (0.93s)
Updated https://github.com/apple/swift-nio-ssl.git (0.93s)
Updated https://github.com/Kingpin-Apps/swift-kes.git (0.93s)
Updated https://github.com/norio-nomura/Base32.git (0.93s)
Updated https://github.com/apple/swift-crypto.git (0.93s)
Updated https://github.com/Kingpin-Apps/swift-base58.git (0.93s)
Updating https://github.com/Frizlab/swift-fraction-number.git
Updating https://github.com/apple/swift-http-types.git
Updating https://github.com/apple/swift-algorithms.git
Updating https://github.com/apple/swift-nio-transport-services.git
Updating https://github.com/apple/swift-nio-http2.git
Updating https://github.com/apple/swift-collections.git
Updated https://github.com/attaswift/BigInt.git (0.52s)
Updating https://github.com/SusanDoggie/Float16.git
Updated https://github.com/apple/swift-collections.git (0.63s)
Updated https://github.com/Frizlab/swift-fraction-number.git (0.63s)
Updated https://github.com/apple/swift-http-types.git (0.63s)
Updated https://github.com/apple/swift-algorithms.git (0.63s)
Updated https://github.com/apple/swift-nio-http2.git (0.63s)
Updated https://github.com/apple/swift-nio-transport-services.git (0.63s)
Updating https://github.com/vapor/websocket-kit.git
Updating https://github.com/Kingpin-Apps/swift-cbor-codable.git
Updating https://github.com/swift-server/swift-service-lifecycle.git
Updating https://github.com/mxcl/Version.git
Updating https://github.com/apple/swift-async-algorithms.git
Updating https://github.com/apple/swift-certificates.git
Updated https://github.com/SusanDoggie/Float16.git (0.53s)
Updating https://github.com/apple/swift-http-structured-headers.git
Updated https://github.com/vapor/websocket-kit.git (0.82s)
Updating https://github.com/apple/swift-log.git
Updated https://github.com/apple/swift-async-algorithms.git (0.86s)
Updated https://github.com/apple/swift-certificates.git (0.86s)
Updated https://github.com/swift-server/swift-service-lifecycle.git (0.86s)
Updated https://github.com/mxcl/Version.git (0.86s)
Updated https://github.com/Kingpin-Apps/swift-cbor-codable.git (0.86s)
Fetching https://github.com/swiftlang/swift-docc-plugin
Updating https://github.com/apple/swift-nio.git
Updated https://github.com/apple/swift-http-structured-headers.git (0.80s)
Updated https://github.com/apple/swift-log.git (0.61s)
Updated https://github.com/apple/swift-nio.git (0.89s)
[1/2345] Fetching swift-docc-plugin
Fetched https://github.com/swiftlang/swift-docc-plugin from cache (2.49s)
Computing version for https://github.com/vapor/websocket-kit.git
Computed https://github.com/vapor/websocket-kit.git at 2.16.2 (6.20s)
Computing version for https://github.com/Kingpin-Apps/swift-cardano-core.git
Computed https://github.com/Kingpin-Apps/swift-cardano-core.git at 0.5.3 (0.53s)
Computing version for https://github.com/apple/swift-atomics.git
Computed https://github.com/apple/swift-atomics.git at 1.3.1 (0.53s)
Computing version for https://github.com/apple/swift-nio-transport-services.git
Computed https://github.com/apple/swift-nio-transport-services.git at 1.28.0 (0.56s)
Computing version for https://github.com/apple/swift-nio-ssl.git
Computed https://github.com/apple/swift-nio-ssl.git at 2.37.5 (0.56s)
Computing version for https://github.com/apple/swift-nio-extras.git
Computed https://github.com/apple/swift-nio-extras.git at 1.35.1 (0.69s)
Computing version for https://github.com/apple/swift-nio.git
Computed https://github.com/apple/swift-nio.git at 2.103.0 (0.67s)
Computing version for https://github.com/mxcl/Version.git
Computed https://github.com/mxcl/Version.git at 2.2.1 (0.64s)
Computing version for https://github.com/krzyzanowskim/CryptoSwift.git
Computed https://github.com/krzyzanowskim/CryptoSwift.git at 1.10.0 (0.64s)
Computing version for https://github.com/Kingpin-Apps/swift-nacl.git
Computed https://github.com/Kingpin-Apps/swift-nacl.git at 1.0.3 (0.62s)
Computing version for https://github.com/Kingpin-Apps/swift-mnemonic.git
Computed https://github.com/Kingpin-Apps/swift-mnemonic.git at 0.2.5 (0.56s)
Computing version for https://github.com/Kingpin-Apps/swift-kes.git
Computed https://github.com/Kingpin-Apps/swift-kes.git at 1.0.2 (0.51s)
Computing version for https://github.com/Kingpin-Apps/swift-cbor-codable.git
Computed https://github.com/Kingpin-Apps/swift-cbor-codable.git at 0.3.3 (0.51s)
Computing version for https://github.com/Kingpin-Apps/swift-base58.git
Computed https://github.com/Kingpin-Apps/swift-base58.git at 0.1.5 (0.53s)
Computing version for https://github.com/Frizlab/swift-fraction-number.git
Computed https://github.com/Frizlab/swift-fraction-number.git at 0.2.0 (0.53s)
Computing version for https://github.com/attaswift/BigInt.git
Computed https://github.com/attaswift/BigInt.git at 6.0.1 (0.52s)
Computing version for https://github.com/apple/swift-log.git
Computed https://github.com/apple/swift-log.git at 1.15.1 (0.55s)
Computing version for https://github.com/apple/swift-crypto.git
Computed https://github.com/apple/swift-crypto.git at 4.5.2 (0.67s)
Computing version for https://github.com/apple/swift-async-algorithms.git
Computed https://github.com/apple/swift-async-algorithms.git at 1.1.5 (0.58s)
Computing version for https://github.com/swift-server/swift-service-lifecycle.git
Computed https://github.com/swift-server/swift-service-lifecycle.git at 2.12.0 (0.52s)
Computing version for https://github.com/apple/swift-asn1.git
Computed https://github.com/apple/swift-asn1.git at 1.7.3 (0.60s)
Computing version for https://github.com/apple/swift-certificates.git
Computed https://github.com/apple/swift-certificates.git at 1.20.0 (0.64s)
Computing version for https://github.com/apple/swift-algorithms.git
Computed https://github.com/apple/swift-algorithms.git at 1.2.1 (0.59s)
Computing version for https://github.com/apple/swift-http-structured-headers.git
Computed https://github.com/apple/swift-http-structured-headers.git at 1.7.0 (0.51s)
Computing version for https://github.com/apple/swift-http-types.git
Computed https://github.com/apple/swift-http-types.git at 1.8.0 (0.53s)
Computing version for https://github.com/apple/swift-nio-http2.git
Computed https://github.com/apple/swift-nio-http2.git at 1.46.0 (0.52s)
Computing version for https://github.com/apple/swift-system.git
Computed https://github.com/apple/swift-system.git at 1.8.1 (0.52s)
Computing version for https://github.com/apple/swift-collections.git
Computed https://github.com/apple/swift-collections.git at 1.6.0 (0.59s)
Computing version for https://github.com/norio-nomura/Base32.git
Computed https://github.com/norio-nomura/Base32.git at 0.9.0 (0.57s)
Computing version for https://github.com/SusanDoggie/Float16.git
Computed https://github.com/SusanDoggie/Float16.git at 1.1.1 (0.57s)
Computing version for https://github.com/apple/swift-numerics.git
Computed https://github.com/apple/swift-numerics.git at 1.1.1 (0.49s)
Computing version for https://github.com/swiftlang/swift-docc-plugin
Computed https://github.com/swiftlang/swift-docc-plugin at 1.5.0 (0.56s)
Fetching https://github.com/swiftlang/swift-docc-symbolkit
[1/3832] Fetching swift-docc-symbolkit
Fetched https://github.com/swiftlang/swift-docc-symbolkit from cache (1.42s)
Computing version for https://github.com/swiftlang/swift-docc-symbolkit
Computed https://github.com/swiftlang/swift-docc-symbolkit at 1.0.0 (2.06s)
Creating working copy for https://github.com/swiftlang/swift-docc-plugin
Working copy of https://github.com/swiftlang/swift-docc-plugin resolved at 1.5.0
Creating working copy for https://github.com/swiftlang/swift-docc-symbolkit
Working copy of https://github.com/swiftlang/swift-docc-symbolkit resolved at 1.0.0
Building for debugging...
[0/8] Write sources
[1/8] Write snippet-extract-tool-entitlement.plist
[1/8] Write sources
[4/8] Write swift-version-69A768CDF2A0BEE1.txt
[6/54] Compiling SymbolKit SemanticVersion.swift
[7/54] Compiling SymbolKit AccessControl.swift
[8/54] Compiling SymbolKit Availability.swift
[9/54] Compiling SymbolKit AvailabilityItem.swift
[10/54] Compiling SymbolKit Domain.swift
[11/54] Compiling SymbolKit DeclarationFragments.swift
[12/54] Compiling SymbolKit Fragment.swift
[13/54] Compiling SymbolKit FragmentKind.swift
[14/54] Compiling SymbolKit FunctionParameter.swift
[15/54] Compiling SymbolKit FunctionSignature.swift
[16/58] Compiling SymbolKit Mixin+Equals.swift
[17/58] Compiling SymbolKit Mixin+Hash.swift
[18/58] Compiling SymbolKit Mixin.swift
[19/58] Compiling SymbolKit LineList.swift
[20/58] Compiling SymbolKit Position.swift
[21/58] Emitting module SymbolKit
[22/58] Compiling SymbolKit Names.swift
[23/58] Compiling SymbolKit SPI.swift
[24/58] Compiling SymbolKit Snippet.swift
[25/58] Compiling SymbolKit Extension.swift
[26/58] Compiling SymbolKit SourceRange.swift
[27/58] Compiling SymbolKit Metadata.swift
[28/58] Compiling SymbolKit Module.swift
[29/58] Compiling SymbolKit OperatingSystem.swift
[30/58] Compiling SymbolKit Platform.swift
[31/58] Compiling SymbolKit GenericConstraint.swift
[32/58] Compiling SymbolKit GenericParameter.swift
[33/58] Compiling SymbolKit Generics.swift
[34/58] Compiling SymbolKit Namespace.swift
[35/58] Compiling SymbolKit Identifier.swift
[36/58] Compiling SymbolKit KindIdentifier.swift
[37/58] Compiling SymbolKit Location.swift
[38/58] Compiling SymbolKit Mutability.swift
[39/58] Compiling SymbolKit Symbol.swift
[40/58] Compiling SymbolKit SymbolKind.swift
[41/58] Compiling SymbolKit SymbolGraph.swift
[42/58] Compiling SymbolKit GraphCollector.swift
[43/58] Compiling SymbolKit Relationship.swift
[44/58] Compiling SymbolKit RelationshipKind.swift
[45/58] Compiling SymbolKit SourceOrigin.swift
[46/58] Compiling SymbolKit GenericConstraints.swift
[47/58] Compiling SymbolKit Swift.swift
[48/58] Compiling SymbolKit UnifiedSymbol+Encodable.swift
[49/58] Compiling SymbolKit UnifiedSymbol.swift
[50/58] Compiling SymbolKit UnifiedSymbolGraph+Encodable.swift
[51/58] Compiling SymbolKit UnifiedSymbolGraph.swift
[52/58] Compiling Snippets SnippetLanguage.swift
[53/58] Compiling Snippets Snippet.swift
[54/58] Compiling Snippets SnippetParser.swift
[55/58] Emitting module Snippets
[56/62] Emitting module snippet_extract
[57/62] Compiling snippet_extract SnippetBuildCommand.swift
[58/62] Compiling snippet_extract URL+Status.swift
[59/62] Compiling snippet_extract SymbolGraph+Snippet.swift
[59/62] Write Objects.LinkFileList
[60/62] Linking snippet-extract-tool
[61/62] Applying snippet-extract-tool
Build of product 'snippet-extract' complete! (6.84s)
Building for debugging...
[0/1] Write swift-version-69A768CDF2A0BEE1.txt
Build of target: 'SwiftOgmios' complete! (3.61s)
   16050
87	/Users/admin/builder/spi-builder-workspace/.docs/kingpin-apps/swift-ogmios/main
✅  Doc result (uploading) reported
========================================
SyncDocs
========================================
Doc archive source directory: $PWD/.docs/kingpin-apps/swift-ogmios/main
File count: 16050
Doc size:   87.0MB
Preparing doc bundle ...
Using presigned URL upload - AWS credentials not required
Uploading -kingpin-apps-swift-ogmios-main-504df51b.zip to presigned URL
Starting upload of 19791657 bytes...
Upload completed successfully
Done.