Skip to main content

truthlinked_sdk/
oracle.rs

1//! HTTP oracle interface for external data access.
2//!
3//! This module provides functions for making HTTP requests from smart contracts
4//! via the TruthLinked oracle system.
5//!
6//! # Example
7//!
8//! ```ignore
9//! use truthlinked_sdk::oracle::{http_get, OracleStatus};
10//!
11//! let response = http_get("https://api.example.com/data")?;
12//! match response.status {
13//!     OracleStatus::Ready => {
14//!         // Process response.body
15//!     }
16//!     OracleStatus::Pending => {
17//!         // Retry later
18//!     }
19//!     OracleStatus::Expired => {
20//!         // Request expired
21//!     }
22//! }
23//! ```
24
25extern crate alloc;
26
27use alloc::string::String;
28use alloc::vec;
29use alloc::vec::Vec;
30
31use crate::env;
32use crate::error::{Error, Result};
33
34/// Status of an oracle request.
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum OracleStatus {
37    /// Response is ready.
38    Ready,
39    /// Request is pending (retry later).
40    Pending,
41    /// Request has expired.
42    Expired,
43}
44
45/// Response from an oracle HTTP call.
46#[derive(Debug, Clone)]
47pub struct OracleResponse {
48    /// Status of the request.
49    pub status: OracleStatus,
50    /// Response body (empty if not ready).
51    pub body: Vec<u8>,
52}
53
54/// Makes an HTTP request via the oracle.
55///
56/// Returns `OracleResponse` with status and body.
57pub fn http_call(url: &str, method: &str, body: &[u8]) -> Result<OracleResponse> {
58    let mut out = vec![0u8; env::MAX_RETURN_DATA_SIZE];
59    match env::http_call_bytes(url.as_bytes(), method.as_bytes(), body, &mut out) {
60        Ok(len) => {
61            out.truncate(len.min(out.len()));
62            Ok(OracleResponse {
63                status: OracleStatus::Ready,
64                body: out,
65            })
66        }
67        Err(err) if err.code() == env::oracle_rc::PENDING => Ok(OracleResponse {
68            status: OracleStatus::Pending,
69            body: Vec::new(),
70        }),
71        Err(err) if err.code() == env::oracle_rc::EXPIRED => Ok(OracleResponse {
72            status: OracleStatus::Expired,
73            body: Vec::new(),
74        }),
75        Err(err) => Err(Error::new(err.code())),
76    }
77}
78
79/// Makes an HTTP GET request.
80pub fn http_get(url: &str) -> Result<OracleResponse> {
81    http_call(url, "GET", &[])
82}
83
84/// Makes an HTTP POST request.
85pub fn http_post(url: &str, body: &[u8]) -> Result<OracleResponse> {
86    http_call(url, "POST", body)
87}
88
89/// Converts the response body to a UTF-8 string.
90pub fn body_utf8(response: &OracleResponse) -> core::result::Result<String, core::str::Utf8Error> {
91    let s = core::str::from_utf8(&response.body)?;
92    Ok(String::from(s))
93}