Skip to main content

strike_sdk/chain/
tokens.rs

1//! OutcomeToken (ERC-1155) balance and approval helpers.
2
3use alloy::primitives::{Address, U256};
4use alloy::providers::DynProvider;
5
6use crate::config::StrikeConfig;
7use crate::contracts::OutcomeToken;
8use crate::error::{Result, StrikeError};
9
10/// Client for outcome token operations.
11pub struct TokensClient<'a> {
12    provider: &'a DynProvider,
13    signer_addr: Option<Address>,
14    config: &'a StrikeConfig,
15}
16
17impl<'a> TokensClient<'a> {
18    pub(crate) fn new(
19        provider: &'a DynProvider,
20        signer_addr: Option<Address>,
21        config: &'a StrikeConfig,
22    ) -> Self {
23        Self {
24            provider,
25            signer_addr,
26            config,
27        }
28    }
29
30    fn ot(&self) -> OutcomeToken::OutcomeTokenInstance<&DynProvider> {
31        OutcomeToken::new(self.config.addresses.outcome_token, self.provider)
32    }
33
34    /// Get the YES token ID for a market.
35    pub async fn yes_token_id(&self, market_id: u64) -> Result<U256> {
36        self.ot()
37            .yesTokenId(U256::from(market_id))
38            .call()
39            .await
40            .map_err(|e| StrikeError::Contract(e.to_string()))
41    }
42
43    /// Get the NO token ID for a market.
44    pub async fn no_token_id(&self, market_id: u64) -> Result<U256> {
45        self.ot()
46            .noTokenId(U256::from(market_id))
47            .call()
48            .await
49            .map_err(|e| StrikeError::Contract(e.to_string()))
50    }
51
52    /// Get the ERC-1155 balance of `owner` for a specific token ID.
53    pub async fn balance_of(&self, owner: Address, token_id: U256) -> Result<U256> {
54        self.ot()
55            .balanceOf(owner, token_id)
56            .call()
57            .await
58            .map_err(|e| StrikeError::Contract(e.to_string()))
59    }
60
61    /// Check if `operator` is approved for all tokens owned by `owner`.
62    pub async fn is_approved_for_all(&self, owner: Address, operator: Address) -> Result<bool> {
63        self.ot()
64            .isApprovedForAll(owner, operator)
65            .call()
66            .await
67            .map_err(|e| StrikeError::Contract(e.to_string()))
68    }
69
70    /// Set approval for all tokens to an operator (e.g., the OrderBook for SellYes/SellNo).
71    pub async fn set_approval_for_all(&self, operator: Address, approved: bool) -> Result<()> {
72        self.signer_addr.ok_or(StrikeError::NoWallet)?;
73
74        let pending = self
75            .ot()
76            .setApprovalForAll(operator, approved)
77            .send()
78            .await
79            .map_err(|e| StrikeError::Contract(e.to_string()))?;
80        pending
81            .get_receipt()
82            .await
83            .map_err(|e| StrikeError::Contract(e.to_string()))?;
84        Ok(())
85    }
86}