Skip to main content

conxian_core/
lib.rs

1pub mod lightning;
2pub mod musig2;
3pub mod persistence;
4pub mod settlement;
5pub mod trust_policy;
6use async_trait::async_trait;
7pub use lightning::*;
8use serde::{Deserialize, Serialize};
9pub use settlement::*;
10use std::sync::{Arc, RwLock};
11use thiserror::Error;
12use tracing::info;
13pub use trust_policy::*;
14
15/// Current version of the Conxian Gateway core library.
16pub const VERSION: &str = env!("CARGO_PKG_VERSION");
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct BlockInfo {
20    pub hash: String,
21    pub height: u64,
22    pub timestamp: u64,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct TransactionInfo {
27    pub txid: String,
28    pub confirmations: u32,
29    pub block_hash: Option<String>,
30    pub block_height: Option<u64>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
34#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
35pub enum FeeBumpStrategy {
36    Rbf,
37    Cpfp,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
41#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
42pub enum MempoolTxStatus {
43    #[default]
44    Pending,
45    Stuck,
46    BumpBroadcasted,
47    GuardrailRejected,
48    Confirmed,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, Default)]
52pub struct TrackedMempoolTx {
53    pub txid: String,
54    pub first_seen_at: u64,
55    pub last_evaluated_at: Option<u64>,
56    pub last_bump_at: Option<u64>,
57    pub bump_attempts: u32,
58    pub current_fee_rate_sat_vb: u64,
59    pub target_fee_rate_sat_vb: Option<u64>,
60    pub replaceable: bool,
61    pub cpfp_eligible: bool,
62    #[serde(default)]
63    pub status: MempoolTxStatus,
64    pub last_bump_strategy: Option<FeeBumpStrategy>,
65    pub last_error: Option<String>,
66    pub replacement_txid: Option<String>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize, Default)]
70pub struct ChainState {
71    pub height: u64,
72    pub status: String,
73    pub last_updated: u64,
74    pub last_sync_time: u64,
75    pub best_block_hash: String,
76    pub network: String,
77    /// Research enhancement: Nakamoto-specific fields
78    pub epoch: Option<String>,
79    pub mode: Option<String>,
80    pub burn_block_height: Option<u64>,
81}
82
83#[derive(Debug, Default, Clone, Serialize, Deserialize)]
84pub struct Metrics {
85    pub health_requests: u64,
86    pub state_requests: u64,
87    pub metrics_requests: u64,
88    pub verification_requests: u64,
89    pub verification_success: u64,
90    pub verification_failure: u64,
91    pub total_requests: u64,
92    pub trust_policy_allow: u64,
93    pub trust_policy_block: u64,
94    /// Research enhancement: Treasury metrics
95    pub treasury_balance_stx: f64,
96    pub treasury_balance_btc: u64,
97    pub last_treasury_update: u64,
98    /// Industry Enhancement: TAM Capture Metrics
99    pub sbtc_liquidity: f64,
100    pub syi_index: f64,
101    /// G-B2: Multi-currency FX rates (relative to USD)
102    pub fx_rmb_usd: f64,
103    pub fx_rub_usd: f64,
104    pub fx_inr_usd: f64,
105    pub fx_aed_usd: f64,
106    /// CON-230: Bounty Payout Activation
107    pub bounty_payouts_enabled: bool,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize, Default)]
111pub struct GatewayState {
112    pub bitcoin: ChainState,
113    pub stacks: ChainState,
114    pub metrics: Metrics,
115    pub wallets: SystemWallets,
116    pub handoff_state: HandoffState,
117    pub start_time: u64,
118}
119
120impl GatewayState {
121    pub fn new() -> Self {
122        Self {
123            bitcoin: ChainState::default(),
124            stacks: ChainState::default(),
125            metrics: Metrics::default(),
126            wallets: SystemWallets::default(),
127            handoff_state: HandoffState::default(),
128            start_time: std::time::SystemTime::now()
129                .duration_since(std::time::UNIX_EPOCH)
130                .unwrap()
131                .as_secs(),
132        }
133    }
134}
135
136pub type ConxianResult<T> = Result<T, ConxianError>;
137
138#[derive(Error, Debug)]
139pub enum ConxianError {
140    #[error("Bitcoin error: {0}")]
141    Bitcoin(String),
142    #[error("Stacks error: {0}")]
143    Stacks(String),
144    #[error("API error: {0}")]
145    Api(String),
146    #[error("Compliance error: {0}")]
147    Compliance(String),
148    #[error("Internal error: {0}")]
149    Internal(String),
150    #[error("Security/Verification error: {0}")]
151    Security(String),
152    #[error("IO error: {0}")]
153    Io(String),
154    #[error("Persistence error: {0}")]
155    Persistence(String),
156    #[error("Machine identity error: {0}")]
157    MachineIdentity(String),
158}
159
160/// Shared global state wrapped for thread-safe access.
161pub type SharedState = Arc<RwLock<GatewayState>>;
162
163/// Represents a cryptographic attestation from a Conxius Wallet Secure Enclave.
164#[derive(Debug, Serialize, Deserialize, Clone)]
165pub struct Attestation {
166    pub device_id: String,
167    pub signature: String, // Hex encoded
168    pub payload: String,
169    pub public_key: String, // Hex encoded
170}
171
172/// Research enhancement: Schnorr signature support for Taproot-compatible attestations.
173#[derive(Debug, Serialize, Deserialize, Clone)]
174pub struct SchnorrAttestation {
175    pub device_id: String,
176    pub signature: String, // 64-byte Schnorr signature in hex
177    pub payload: String,
178    pub x_only_public_key: String, // 32-byte X-only public key in hex
179}
180
181/// ZKML proof mapping to Guardian Attestations for off-chain models.
182#[derive(Debug, Serialize, Deserialize, Clone)]
183pub struct ZkmlProof {
184    pub device_id: String,
185    #[serde(default)]
186    pub image_id: String,
187    #[serde(default)]
188    pub receipt: String,
189    pub receipt_hash: String,
190    pub public_inputs: String,
191    pub journal: String,
192}
193
194/// Industry Enhancement: BitVM Attestation for trustless state verification.
195#[derive(Debug, Serialize, Deserialize, Clone)]
196pub struct BitVmAttestation {
197    pub prover_id: String,
198    pub commitment_hash: String,
199    pub state_root: String,
200    #[serde(default)]
201    pub proof_hash: String,
202    #[serde(default)]
203    pub verifier_address: String,
204}
205
206/// Unified request for attestation verification.
207#[derive(Debug, Serialize, Deserialize, Clone)]
208#[serde(tag = "type", content = "data")]
209pub enum AttestationRequest {
210    Ecdsa(Attestation),
211    Schnorr(SchnorrAttestation),
212    Zkml(ZkmlProof),
213    BitVm(BitVmAttestation),
214    Cbtc(CbtcAttestation),
215}
216
217// ── CBTC Non-Custodial Verification (G-C1) ───────────────────────────
218
219/// G-C1: CBTC (wrapped Bitcoin on Canton Network via BitSafe) attestation.
220/// Verifies that CBTC tokens on Canton are provably backed by Bitcoin reserves
221/// without joining the FROST signer set or taking custody.
222#[derive(Debug, Serialize, Deserialize, Clone)]
223pub struct CbtcAttestation {
224    /// Canton domain where CBTC contract lives
225    pub canton_domain: String,
226    /// Daml contract ID for the CBTC token
227    pub contract_id: String,
228    /// Amount of CBTC (in satoshis) claimed to be backed
229    pub amount_sats: u64,
230    /// Bitcoin UTXO(s) backing this CBTC — txid:vout format
231    pub bitcoin_utxos: Vec<String>,
232    /// FROST threshold signature attesting to Bitcoin reserve
233    #[serde(default)]
234    pub frost_attestation: Option<String>,
235    /// Block height at which the attestation was produced
236    pub attested_at_height: u64,
237    /// Signer quorum metadata (threshold, total signers)
238    #[serde(default)]
239    pub quorum: Option<CbtcQuorum>,
240}
241
242/// G-C1: FROST signer quorum metadata for CBTC attestation verification.
243#[derive(Debug, Serialize, Deserialize, Clone)]
244pub struct CbtcQuorum {
245    /// Number of signers that produced the attestation
246    pub signers_present: u16,
247    /// Total signers in the FROST set
248    pub signers_total: u16,
249    /// Aggregated public key of the FROST signer set
250    pub aggregate_key: String,
251}
252
253/// G-C1: CBTC verification request sent to the UCV-1 universal verifier.
254#[derive(Debug, Serialize, Deserialize, Clone)]
255pub struct CbtcVerificationRequest {
256    /// The CBTC attestation to verify
257    pub attestation: CbtcAttestation,
258    /// If true, also verify Bitcoin UTXO inclusion proofs (requires Bitcoin RPC)
259    #[serde(default)]
260    pub verify_utxo_proofs: bool,
261}
262
263/// G-C1: CBTC verification response from UCV-1.
264#[derive(Debug, Serialize, Deserialize, Clone)]
265pub struct CbtcVerificationResponse {
266    /// Whether the CBTC attestation passed all verification checks
267    pub verified: bool,
268    /// Contract ID that was verified
269    pub contract_id: String,
270    /// Amount verified (sats)
271    pub amount_sats: u64,
272    /// Number of UTXOs confirmed as backing
273    pub utxos_verified: u32,
274    /// Quorum ratio (signers_present / signers_total) — None if no quorum info
275    pub quorum_ratio: Option<f64>,
276    /// Verification timestamp (Unix)
277    pub verified_at: u64,
278    /// Detailed verification results per check
279    #[serde(default)]
280    pub checks: Vec<CbtcVerificationCheck>,
281}
282
283/// G-C1: Individual verification check result.
284#[derive(Debug, Serialize, Deserialize, Clone)]
285pub struct CbtcVerificationCheck {
286    /// Check name
287    pub check: String,
288    /// Whether this check passed
289    pub passed: bool,
290    /// Human-readable detail
291    #[serde(default)]
292    pub detail: Option<String>,
293}
294
295// ── Canton State Translation (G-C4) ──────────────────────────────────
296
297/// G-C4: Universal Contract Reference — a unified identifier that can reference
298/// a contract on any supported ledger (Canton Daml, Bitcoin UTXO, Stacks Clarity).
299/// This is the core abstraction for cross-ledger state translation.
300#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
301pub struct UniversalContractRef {
302    /// Ledger family: "canton", "bitcoin", "stacks", "liquid", "rgb"
303    pub ledger: String,
304    /// Ledger-native contract identifier (Daml ContractId, Bitcoin OutPoint, etc.)
305    pub contract_id: String,
306    /// Optional domain/subnet qualifier (Canton domain, Stacks chain tip, etc.)
307    #[serde(default)]
308    pub domain: Option<String>,
309}
310
311/// G-C4: Canton domain reference for state observation.
312#[derive(Debug, Serialize, Deserialize, Clone)]
313pub struct CantonDomainRef {
314    /// Canton domain name (e.g., "global", "canton://global")
315    pub domain_name: String,
316    /// Canton synchronizer endpoint (for observer connection)
317    #[serde(default)]
318    pub synchronizer_endpoint: Option<String>,
319    /// Whether the domain is publicly observable
320    #[serde(default)]
321    pub public_observer: bool,
322}
323
324/// G-C4: Canton state translation request — translate a Daml Active Contract
325/// into a Universal Contract Reference suitable for Bitcoin anchoring.
326#[derive(Debug, Serialize, Deserialize, Clone)]
327pub struct CantonStateTranslationRequest {
328    /// Canton domain where the contract lives
329    pub domain: CantonDomainRef,
330    /// Daml contract ID to translate
331    pub daml_contract_id: String,
332    /// Daml template name (for type-aware translation)
333    #[serde(default)]
334    pub template_name: Option<String>,
335    /// Target ledger for the translated reference
336    pub target_ledger: String,
337}
338
339/// G-C4: Canton state translation response.
340#[derive(Debug, Serialize, Deserialize, Clone)]
341pub struct CantonStateTranslationResponse {
342    /// The translated universal contract reference
343    pub contract_ref: UniversalContractRef,
344    /// Source ledger
345    pub source_ledger: String,
346    /// Target ledger
347    pub target_ledger: String,
348    /// Whether translation succeeded with full fidelity
349    pub translation_complete: bool,
350    /// Fields that could not be mapped (if any)
351    #[serde(default)]
352    pub unmapped_fields: Vec<String>,
353    /// Translation timestamp
354    pub translated_at: u64,
355}
356
357// ── Chainlink CCIP Canton Connector (G-C5) ───────────────────────────
358
359/// G-C5: Chainlink CCIP message route through Conxian's compliance ZKC pipeline.
360/// Conxian does not participate in CCIP consensus — it routes messages through
361/// sanctions screening and jurisdictional compliance.
362#[derive(Debug, Serialize, Deserialize, Clone)]
363pub struct CcipMessageRoute {
364    /// Source chain identifier (e.g., "canton", "ethereum", "arbitrum")
365    pub source_chain: String,
366    /// Destination chain identifier
367    pub destination_chain: String,
368    /// CCIP message ID for traceability
369    pub message_id: String,
370    /// Message payload (CCIP-encoded)
371    pub payload: String,
372    /// Whether this message requires sanctions screening
373    #[serde(default)]
374    pub requires_screening: bool,
375}
376
377/// G-C5: CCIP route request — submit a CCIP message for compliance routing.
378#[derive(Debug, Serialize, Deserialize, Clone)]
379pub struct CcipRouteRequest {
380    /// The CCIP message to route
381    pub message: CcipMessageRoute,
382    /// If true, apply elevated compliance scrutiny
383    #[serde(default)]
384    pub elevated_scrutiny: bool,
385}
386
387/// G-C5: CCIP route response — result of compliance routing.
388#[derive(Debug, Serialize, Deserialize, Clone)]
389pub struct CcipRouteResponse {
390    /// Whether the message passed compliance screening
391    pub approved: bool,
392    /// Message ID (echo)
393    pub message_id: String,
394    /// Sanctions risk classification applied
395    pub risk_level: SanctionsRisk,
396    /// Reason for rejection (if not approved)
397    #[serde(default)]
398    pub rejection_reason: Option<String>,
399    /// Compliance audit trail reference
400    #[serde(default)]
401    pub audit_ref: Option<String>,
402    /// Timestamp of routing decision
403    pub routed_at: u64,
404}
405
406// ── Machine RWA Revenue Verification (G-C6) ──────────────────────────
407
408/// G-C6: Machine RWA revenue attestation — a machine reports its revenue
409/// for verification by Conxian Gateway. Machines hold keys; Conxian verifies.
410#[derive(Debug, Serialize, Deserialize, Clone)]
411pub struct MachineRwaRevenue {
412    /// Machine that generated the revenue
413    pub machine_identity: MachineIdentity,
414    /// Revenue period start (Unix timestamp)
415    pub period_start: u64,
416    /// Revenue period end (Unix timestamp)
417    pub period_end: u64,
418    /// Total revenue in smallest currency unit (sats, wei-equivalent, etc.)
419    pub total_revenue_minor: u64,
420    /// Revenue currency code
421    pub currency: String,
422    /// Revenue source breakdown
423    #[serde(default)]
424    pub revenue_sources: Vec<RevenueSource>,
425    /// Proof-of-revenue attestation (signed by machine device key)
426    #[serde(default)]
427    pub attestation_signature: Option<String>,
428}
429
430/// G-C6: Breakdown of revenue by source.
431#[derive(Debug, Serialize, Deserialize, Clone)]
432pub struct RevenueSource {
433    /// Service type that generated this revenue
434    pub service_type: MachineService,
435    /// Revenue from this source (minor units)
436    pub amount_minor: u64,
437    /// Number of service events delivered
438    #[serde(default)]
439    pub event_count: u64,
440    /// Arbitrary metadata (kWh, GB-hours, km driven, etc.)
441    #[serde(default)]
442    pub metadata: Option<serde_json::Value>,
443}
444
445/// G-C6: Machine RWA revenue verification request.
446#[derive(Debug, Serialize, Deserialize, Clone)]
447pub struct MachineRwaVerificationRequest {
448    /// The revenue attestation to verify
449    pub revenue: MachineRwaRevenue,
450    /// If true, require device-key signature verification
451    #[serde(default)]
452    pub verify_signature: bool,
453    /// RWA token contract to verify against (optional)
454    #[serde(default)]
455    pub rwa_token_contract: Option<String>,
456}
457
458/// G-C6: Machine RWA revenue verification response.
459#[derive(Debug, Serialize, Deserialize, Clone)]
460pub struct MachineRwaVerificationResponse {
461    /// Whether the revenue attestation is verified
462    pub verified: bool,
463    /// Machine identity (echo)
464    pub machine_did: Option<String>,
465    /// Total verified revenue
466    pub verified_revenue_minor: u64,
467    /// Currency
468    pub currency: String,
469    /// Revenue period
470    pub period_start: u64,
471    pub period_end: u64,
472    /// Number of revenue sources verified
473    pub sources_verified: u32,
474    /// Distribution recommendation: percentage to token holders
475    #[serde(default)]
476    pub holder_distribution_bps: Option<u16>,
477    /// Verification timestamp
478    pub verified_at: u64,
479    /// Detailed verification checks
480    #[serde(default)]
481    pub checks: Vec<RevenueVerificationCheck>,
482}
483
484/// G-C6: Individual revenue verification check.
485#[derive(Debug, Serialize, Deserialize, Clone)]
486pub struct RevenueVerificationCheck {
487    pub check: String,
488    pub passed: bool,
489    #[serde(default)]
490    pub detail: Option<String>,
491}
492
493#[derive(Debug, Serialize, Deserialize, Clone)]
494pub struct JobCardSettlementRequest {
495    pub job_card: ConxianJobCard,
496    pub bitvm_attestation: BitVmAttestation,
497}
498
499/// Discrete Log Contract (DLC) bond definition (CON-72).
500#[derive(Debug, Serialize, Deserialize, Clone)]
501pub struct DlcBond {
502    pub bond_id: String,
503    pub amount_btc: u64,
504    pub interest_rate: f64,
505    pub maturity_date: u64,
506    pub sovereign_alignment: bool,
507}
508
509/// Industry Enhancement: Discrete Log Contract (DLC) Orchestrator (CON-62).
510pub trait DlcOrchestrator: Send + Sync {
511    fn create_dlc_bond(&self, bond: &DlcBond) -> ConxianResult<String>;
512    fn settle_coupon(&self, bond_id: &str, amount_sbtc: u64) -> ConxianResult<bool>;
513}
514
515/// Concrete implementation of Discrete Log Contract (DLC) Orchestrator for Bitcoin bonds (CON-72).
516pub struct DlcManager {
517    pub oracle_pubkey: String,
518}
519
520impl DlcManager {
521    pub fn new(oracle_pubkey: String) -> Self {
522        Self { oracle_pubkey }
523    }
524}
525
526impl DlcOrchestrator for DlcManager {
527    fn create_dlc_bond(&self, bond: &DlcBond) -> ConxianResult<String> {
528        info!("Creating DLC-backed Bitcoin bond: {} sBTC", bond.amount_btc);
529        let bond_id = format!("dlc-bond-{}", uuid::Uuid::new_v4());
530        Ok(bond_id)
531    }
532
533    fn settle_coupon(&self, bond_id: &str, amount_sbtc: u64) -> ConxianResult<bool> {
534        info!(
535            "Settling coupon for DLC bond {}: {} satoshis",
536            bond_id, amount_sbtc
537        );
538        Ok(!bond_id.is_empty())
539    }
540}
541
542/// CON-66: Identity resolution request for ENS, BNS, and World ID.
543#[derive(Debug, Serialize, Deserialize, Clone)]
544pub struct IdentityResolutionRequest {
545    pub identifier: String,
546    pub provider: String, // "ens", "bns", "worldid", or "web3bio",
547    pub signature: Option<String>,
548}
549
550/// CON-66: Identity resolution response.
551#[derive(Debug, Serialize, Deserialize, Clone)]
552pub struct IdentityResolutionResponse {
553    pub address: String,
554    pub provider: String,
555    pub verified: bool,
556    pub metadata: Option<serde_json::Value>,
557}
558
559// ── Machine Identity (G-C2) ──────────────────────────────────────────
560
561/// Classification of autonomous machine types in the Machine Economy (DePIN).
562#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
563#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
564pub enum MachineType {
565    ElectricVehicle,
566    EvCharger,
567    Drone,
568    Robot,
569    Sensor,
570    ComputeNode,
571    StorageNode,
572    Camera,
573    DeliveryVehicle,
574    EnergyMeter,
575    Other,
576}
577
578/// Sovereign machine identity for DePIN / Machine Economy participants.
579/// Machines hold their own keys; Conxian routes and verifies, never custodies.
580#[derive(Debug, Serialize, Deserialize, Clone)]
581pub struct MachineIdentity {
582    /// peaq decentralized identifier (did:peaq:<address>)
583    pub peaq_did: Option<String>,
584    /// DIMO vehicle identity (for connected vehicles)
585    pub dimo_vehicle_id: Option<String>,
586    /// Schnorr x-only public key (Taproot-ready, BIP-340)
587    pub device_key: String,
588    /// Manufacturer or DePIN-network attestation proof
589    #[serde(default)]
590    pub attestation_proof: Option<String>,
591    /// Classification of the machine
592    pub machine_type: MachineType,
593    /// Human-readable machine label (e.g., "Tesla Model 3 — Vienna Fleet #42")
594    #[serde(default)]
595    pub label: Option<String>,
596}
597
598/// G-C2: Machine identity resolution request — extends existing CON-66 identity stack
599/// to support autonomous machine participants.
600#[derive(Debug, Serialize, Deserialize, Clone)]
601pub struct MachineIdentityResolutionRequest {
602    /// Machine DID or device public key to resolve
603    pub identifier: String,
604    /// Provider: "peaq", "dimo", "device_key"
605    pub provider: String,
606    /// BIP-322 or Schnorr proof-of-possession signature (optional)
607    #[serde(default)]
608    pub signature: Option<String>,
609    /// Schnorr x-only public key for signature verification (required for peaq/dimo if signature is provided)
610    #[serde(default)]
611    pub device_key: Option<String>,
612    /// If set, the resolution targets a specific machine identity variant
613    #[serde(default)]
614    pub machine_type_hint: Option<MachineType>,
615}
616
617/// G-C2: Machine identity resolution response.
618#[derive(Debug, Serialize, Deserialize, Clone)]
619pub struct MachineIdentityResolutionResponse {
620    /// Resolved machine identity with all known attributes
621    pub identity: MachineIdentity,
622    /// Provider that served the resolution
623    pub provider: String,
624    /// Whether the device key attestation was verified
625    pub verified: bool,
626    /// Arbitrary provider-supplied metadata
627    #[serde(default)]
628    pub metadata: Option<serde_json::Value>,
629}
630
631/// Industry Enhancement: Workload Identity Federation (WIF) token request.
632#[derive(Debug, Serialize, Deserialize, Clone)]
633pub struct GcpTokenRequest {
634    pub audience: String,
635    #[serde(default)]
636    pub grant_type: String,
637    #[serde(default)]
638    pub requested_token_type: String,
639    #[serde(default)]
640    pub scope: String,
641    pub subject_token: String,
642    #[serde(default)]
643    pub subject_token_type: String,
644}
645
646/// Persistent data that needs to be saved across restarts.
647#[derive(Debug, Serialize, Deserialize, Clone, Default)]
648pub struct PersistentState {
649    pub bitcoin_height: u64,
650    pub stacks_height: u64,
651    #[serde(default)]
652    pub mempool_pending_txs: Vec<TrackedMempoolTx>,
653}
654
655/// Trait for persistence of gateway state.
656pub trait Persistence: Send + Sync {
657    fn save(&self, state: &PersistentState) -> ConxianResult<()>;
658    fn load(&self) -> ConxianResult<PersistentState>;
659}
660
661/// CON-423: SAB-owned system wallets for BOS operations.
662#[derive(Debug, Serialize, Deserialize, Clone)]
663pub struct SystemWallets {
664    pub bootstrap: String,
665    pub treasury: String,
666    pub payout: String,
667    pub deployment: String,
668    pub emergency: String,
669    pub dao_handoff: String,
670    pub protocol_owned: String,
671    pub reserve_fund: String,
672    pub labs_ops: String,
673    pub contributor_claims: String,
674    pub founder_vault: String,
675}
676
677impl Default for SystemWallets {
678    fn default() -> Self {
679        Self {
680            bootstrap: "SPSZXAKV7DWTDZN2601WR31BM51BD3YTQWE97VRM".to_string(),
681            treasury: "SP12JZZSBY0S3FJH7WJT2787YTYT8Y6725F7T8E62".to_string(),
682            payout: "SP2JZZSBY0S3FJH7WJT2787YTYT8Y6725F7T8E62".to_string(),
683            deployment: "SP3JZZSBY0S3FJH7WJT2787YTYT8Y6725F7T8E62".to_string(),
684            emergency: "SP000000000000000000002Q6VF78".to_string(),
685            dao_handoff: "SP1P74G56Z5SNC6B2H70MBN8D6X1XW19C52R0P95".to_string(),
686            protocol_owned: "SP2JZZSBY0S3FJH7WJT2787YTYT8Y6725F7T8E62".to_string(),
687            reserve_fund: "SP3JZZSBY0S3FJH7WJT2787YTYT8Y6725F7T8E62".to_string(),
688            labs_ops: "SP2KZZSBY0S3FJH7WJT2787YTYT8Y6725F7T8E62".to_string(),
689            contributor_claims: "SP3KZZSBY0S3FJH7WJT2787YTYT8Y6725F7T8E62".to_string(),
690            founder_vault: "SP4KZZSBY0S3FJH7WJT2787YTYT8Y6725F7T8E62".to_string(),
691        }
692    }
693}
694
695/// Request for an ALEX swap operation.
696#[derive(Debug, Clone, Serialize, Deserialize)]
697pub struct AlexSwapRequest {
698    pub token_x: String,
699    pub token_y: String,
700    pub factor: u64,
701    pub amount: u128,
702    pub min_dy: Option<u128>,
703}
704
705/// CON-78: Offline-First POS Receipt.
706#[derive(Debug, Serialize, Deserialize, Clone)]
707pub struct OfflineReceipt {
708    pub receipt_id: String,
709    pub tx_hash: String,
710    pub amount_sbtc: u64,
711    pub timestamp: u64,
712    pub device_id: String,
713    pub tee_signature: String, // TEE-signed commitment
714    pub passkey_attestation: AttestationRequest,
715    pub status: OfflineReceiptStatus,
716}
717
718#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
719#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
720pub enum OfflineReceiptStatus {
721    Pending,
722    Gossiped,
723    Broadcasted,
724    Reconciled,
725}
726
727/// CON-78: Local encrypted queue for offline transactions.
728pub trait OfflineQueue: Send + Sync {
729    fn enqueue(&self, receipt: &OfflineReceipt) -> ConxianResult<()>;
730    fn dequeue_pending(&self) -> ConxianResult<Vec<OfflineReceipt>>;
731    fn mark_broadcasted(&self, receipt_id: &str) -> ConxianResult<()>;
732    /// Claims a webhook replay key for a bounded TTL window.
733    ///
734    /// Returns `true` when this caller successfully claimed the key (first
735    /// delivery in-window), and `false` when an unexpired claim already exists.
736    fn claim_replay_key(&self, replay_key: &str, ttl_seconds: u64) -> ConxianResult<bool>;
737}
738
739/// CON-73: [ATS-v12.0] Conxian Job Card Schema (CJCS) v2.0 JSON-LD
740#[derive(Debug, Serialize, Deserialize, Clone)]
741pub struct ConxianJobCard {
742    #[serde(rename = "@context", default)]
743    pub context: String,
744    #[serde(rename = "@type")]
745    pub r#type: String,
746    #[serde(default)]
747    pub work_intent: WorkIntent,
748}
749
750#[derive(Debug, Serialize, Deserialize, Clone, Default)]
751pub struct WorkIntent {
752    pub sender_address: String,
753    pub receiver_address: String,
754    pub amount_sbtc: u64,
755    pub town_name: Option<String>,
756    pub country_code: Option<String>,
757}
758
759#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
760pub enum RolloutMode {
761    Disabled,
762    Shadow,
763    Active,
764}
765
766#[derive(Debug, Serialize, Deserialize, Clone)]
767pub struct RgbAdapterConfig {
768    pub mode: RolloutMode,
769    pub node_url: String,
770}
771
772#[derive(Debug, Serialize, Deserialize, Clone)]
773pub struct ContractState {
774    pub contract_id: String,
775    pub schema_id: String,
776    pub state_data: serde_json::Value,
777}
778
779#[async_trait]
780pub trait RgbAdapter: Send + Sync {
781    async fn lookup_contract(&self, contract_id: &str) -> ConxianResult<Option<ContractState>>;
782    async fn verify_transition(&self, transition_id: &str) -> ConxianResult<bool>;
783}
784pub trait PersistentStateTrait: Send + Sync {
785    fn save(&self, state: &GatewayState) -> ConxianResult<()>;
786    fn load(&self) -> ConxianResult<GatewayState>;
787}
788
789/// CON-482: Handoff sequence state
790#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default)]
791pub enum HandoffState {
792    #[default]
793    BootstrapActive,
794    SabAuditInProgress,
795    DaoProposalActive,
796    HandoffComplete,
797}
798
799impl SystemWallets {
800    pub fn get_payout_destination(&self, state: HandoffState) -> &str {
801        match state {
802            HandoffState::BootstrapActive => &self.bootstrap,
803            _ => &self.payout,
804        }
805    }
806
807    pub fn get_treasury_destination(&self, state: HandoffState) -> &str {
808        match state {
809            HandoffState::BootstrapActive => &self.bootstrap,
810            _ => &self.treasury,
811        }
812    }
813}
814
815#[async_trait]
816#[async_trait]
817#[async_trait]
818pub trait ChainAdapter: Send + Sync {
819    async fn get_latest_height(&self) -> ConxianResult<u64>;
820    async fn get_chain_identity(&self) -> String;
821    async fn prepare_unsigned_transaction(
822        &self,
823        tx_details: serde_json::Value,
824    ) -> ConxianResult<serde_json::Value>;
825    async fn verify_state_proof(&self, proof_metadata: serde_json::Value) -> ConxianResult<bool>;
826}
827
828#[async_trait]
829#[allow(async_fn_in_trait)]
830pub trait Bip322Verifier: Send + Sync {
831    fn verify_message(&self, address: &str, message: &str, signature: &str) -> ConxianResult<bool>;
832}
833
834#[async_trait]
835#[allow(async_fn_in_trait)]
836pub trait SimulatedStacksRpcTrait: Send + Sync {
837    async fn call_read_only(
838        &self,
839        contract: &str,
840        function: &str,
841        args: Vec<serde_json::Value>,
842    ) -> ConxianResult<serde_json::Value>;
843}
844
845/// CON-775: Release approval request.
846#[derive(Debug, Serialize, Deserialize, Clone)]
847pub struct ReleaseApprovalRequest {
848    pub release_id: String,
849    pub artifact_hash: String,
850    pub environment: String,
851    pub requester: String,
852}
853
854/// CON-775: Release decision submission.
855#[derive(Debug, Serialize, Deserialize, Clone)]
856pub struct ReleaseDecisionRequest {
857    pub release_id: String,
858    pub decision: String, // "approved" or "rejected"
859    pub approver: String,
860    pub reason: Option<String>,
861}
862
863/// CON-775: Governance decision submission.
864#[derive(Debug, Serialize, Deserialize, Clone)]
865pub struct GovernanceDecisionRequest {
866    pub proposal_id: String,
867    pub decision: String, // "approved", "rejected", or "abstain"
868    pub voter: String,
869    pub signature: String, // TEE or EOC signature
870}
871
872/// CON-775: Unified admin response.
873#[derive(Debug, Serialize, Deserialize, Clone)]
874pub struct AdminActionResponse {
875    pub action_id: String,
876    pub status: String,
877    pub audit_event_id: String,
878    pub message: String,
879}
880
881/// CON-771: Shared domain schema for Governance Actions.
882#[derive(Debug, Serialize, Deserialize, Clone)]
883pub struct GovernanceAction {
884    pub action_id: String,
885    pub proposal_id: String,
886    pub action_type: String, // e.g., "parameter_change", "treasury_allocation"
887    pub payload: serde_json::Value,
888    pub status: String,
889    pub enacted_at: Option<u64>,
890}
891
892/// CON-771: Shared domain schema for Treasury Events.
893#[derive(Debug, Serialize, Deserialize, Clone)]
894pub struct TreasuryEvent {
895    pub event_id: String,
896    pub asset: String,
897    pub amount: u128,
898    pub direction: String, // "inflow" or "outflow"
899    pub reason: String,
900    pub timestamp: u64,
901    pub reference_id: Option<String>,
902}
903
904/// CON-771: Shared domain schema for Audit Events.
905#[derive(Debug, Serialize, Deserialize, Clone)]
906pub struct AuditEvent {
907    pub event_id: String,
908    pub domain: String, // "release", "governance", "treasury", "identity"
909    pub actor: String,
910    pub action: String,
911    pub outcome: String,
912    pub timestamp: u64,
913    pub metadata: serde_json::Value,
914}