pub mod http_client;
pub mod resp;
pub mod types;
use crate::http_client::HttpClient;
use reqwest::{
Method,
header::{HeaderMap, HeaderValue},
};
use resp::{
AddressSummary, BalanceMulti, OkLinkBalanceDetail, OkLinkBalancePage, OkLinkResp, PublishTxInfo,
};
use serde_json::{Value, json};
use types::{InscriptionOk, OkApiUri, UtxoList};
#[derive(Debug)]
pub struct OkLinkClient {
client: HttpClient, chain: String, chain_id: u64, }
impl OkLinkClient {
pub fn new(base_url: String, api_key: String, chain: String, chain_id: u64) -> Self {
let mut headers = HeaderMap::new();
headers.insert("Ok-Access-Key", HeaderValue::from_str(&api_key).unwrap());
OkLinkClient {
client: HttpClient::new(base_url, Some(headers)),
chain,
chain_id,
}
}
pub async fn get_token_price_market_data(&self) -> anyhow::Result<Value> {
let response = self
.client
.request(
&format!(
"{}?chainId={}",
OkApiUri::TokenPriceMarketData.as_str(),
self.chain_id
),
Method::GET,
None,
true,
)
.await?;
Ok(response)
}
pub async fn get_address_summary_oklink(
&self,
address: &str,
) -> anyhow::Result<OkLinkResp<AddressSummary>> {
let response = self
.client
.request(
&format!(
"{}?chainShortName={}&address={}",
OkApiUri::AddressSummary.as_str(),
self.chain,
address
),
Method::GET,
None,
true,
)
.await?;
Ok(serde_json::from_value(response)?)
}
pub async fn get_address_balance_oklink_multi(
&self,
address: &str,
) -> anyhow::Result<OkLinkResp<BalanceMulti>> {
let response = self
.client
.request(
&format!(
"{}?chainShortName={}&address={}",
OkApiUri::BalanceMulti.as_str(),
self.chain,
address
),
Method::GET,
None,
true,
)
.await?;
Ok(serde_json::from_value(response)?)
}
pub async fn get_brc20_balance_oklink(
&self,
address: &str,
page: usize,
page_size: usize,
) -> anyhow::Result<OkLinkResp<OkLinkBalancePage>> {
let response = self
.client
.request(
&format!(
"{}?address={}&limit={}&page={}",
OkApiUri::BtcAddressBalanceList.as_str(),
address,
page_size,
page
),
Method::GET,
None,
true,
)
.await?;
Ok(serde_json::from_value(response)?)
}
pub async fn get_brc20_token_detail_oklink(
&self,
address: &str,
tick: &str,
page: usize,
page_size: usize,
) -> anyhow::Result<OkLinkResp<OkLinkBalanceDetail>> {
let response = self
.client
.request(
&format!(
"{}?address={}&token={}&page={}&limit={}",
OkApiUri::BtcAddressBalanceDetail.as_str(),
address,
tick,
page,
page_size
),
Method::GET,
None,
true,
)
.await?;
Ok(serde_json::from_value(response)?)
}
pub async fn address_inscription_list_oklink(
&self,
address: &str,
page: usize,
page_size: usize,
) -> anyhow::Result<Value> {
let response = self
.client
.request(
&format!(
"{}?chainShortName={}&protocolType=brc20&address={}&page={}&limit={}",
OkApiUri::InscriptionAddressInscriptionList.as_str(),
self.chain,
address,
page,
page_size
),
Method::GET,
None,
true,
)
.await?;
Ok(response)
}
pub async fn publish_tx(&self, signed_tx: &str) -> anyhow::Result<PublishTxInfo> {
let response = self
.client
.request(
OkApiUri::TransactionPublicshTx.as_str(),
Method::POST,
Some(&json!({
"chainShortName":self.chain,
"signedTx":signed_tx
})),
true,
)
.await?;
Ok(serde_json::from_value(response)?)
}
pub async fn get_btc_utxo_oklink(
&self,
address: &str,
cursor: usize,
size: usize,
) -> anyhow::Result<OkLinkResp<UtxoList>> {
let response = self
.client
.request(
&format!(
"{}?chainShortName={}&address={}&page={}&limit={}",
OkApiUri::AddressUtxo.as_str(),
self.chain,
address,
cursor,
size
),
Method::GET,
None,
true,
)
.await?;
Ok(serde_json::from_value(response)?)
}
pub async fn get_utxo_by_inscription_id_oklink(
&self,
inscription_id: &str,
inscription_number: &str,
) -> anyhow::Result<OkLinkResp<InscriptionOk>> {
let response = self
.client
.request(
&format!(
"{}?inscriptionId={}&inscriptionNumber={}",
OkApiUri::BtcTransactionList.as_str(),
inscription_id,
inscription_number
),
Method::GET,
None,
true,
)
.await?;
Ok(serde_json::from_value(response)?)
}
}
#[cfg(test)]
mod testx {
use super::*;
#[tokio::test]
async fn test_get_btc_utxo_oklink() {
dotenv::dotenv().ok();
println!("=============");
let api_key = std::env::var("OKLINK_API_KEY").expect("OKLINK_API_KEY must be set");
let client = OkLinkClient::new(
"https://www.oklink.com/api/v5/explorer".to_string(),
api_key,
"btc".to_string(),
1,
);
let resp = client
.get_btc_utxo_oklink("1BM1sAcrfV6d4zPKytzziu4McLQDsFC2Qc", 1, 100)
.await
.unwrap();
println!("{:#?}", resp.data);
}
}