strike_sdk/chain/
redeem.rs1use alloy::primitives::{Address, Bytes, U256};
4use alloy::providers::DynProvider;
5use alloy::rpc::types::TransactionRequest;
6use alloy::sol_types::SolCall;
7use std::sync::Arc;
8use tokio::sync::Mutex;
9use tracing::info;
10
11use crate::chain::send_tx;
12use crate::config::StrikeConfig;
13use crate::contracts::{OutcomeToken, RedemptionContract};
14use crate::error::{Result, StrikeError};
15use crate::nonce::NonceSender;
16
17pub struct RedeemClient<'a> {
19 provider: &'a DynProvider,
20 signer_addr: Option<Address>,
21 config: &'a StrikeConfig,
22 nonce_sender: Option<Arc<Mutex<NonceSender>>>,
23}
24
25impl<'a> RedeemClient<'a> {
26 pub(crate) fn new(
27 provider: &'a DynProvider,
28 signer_addr: Option<Address>,
29 config: &'a StrikeConfig,
30 nonce_sender: Option<Arc<Mutex<NonceSender>>>,
31 ) -> Self {
32 Self {
33 provider,
34 signer_addr,
35 config,
36 nonce_sender,
37 }
38 }
39
40 fn require_wallet(&self) -> Result<Address> {
41 self.signer_addr.ok_or(StrikeError::NoWallet)
42 }
43
44 pub async fn redeem(&self, market_id: u64, amount: U256) -> Result<()> {
49 self.require_wallet()?;
50
51 info!(market_id, amount = %amount, "redeeming outcome tokens");
52
53 let calldata = RedemptionContract::redeemCall {
54 factoryMarketId: U256::from(market_id),
55 amount,
56 }
57 .abi_encode();
58
59 let mut tx = TransactionRequest::default()
60 .to(self.config.addresses.redemption)
61 .input(Bytes::from(calldata).into());
62 tx.gas = Some(300_000);
63
64 let pending = send_tx(self.provider, &self.nonce_sender, tx).await?;
65 let receipt = pending
66 .get_receipt()
67 .await
68 .map_err(|e| StrikeError::Contract(e.to_string()))?;
69
70 info!(market_id, tx = %receipt.transaction_hash, gas_used = receipt.gas_used, "redemption confirmed");
71 Ok(())
72 }
73
74 pub async fn balances(&self, market_id: u64, owner: Address) -> Result<(U256, U256)> {
76 let ot = OutcomeToken::new(self.config.addresses.outcome_token, self.provider);
77 let mid = U256::from(market_id);
78
79 let yes_id = ot
80 .yesTokenId(mid)
81 .call()
82 .await
83 .map_err(|e| StrikeError::Contract(e.to_string()))?;
84 let no_id = ot
85 .noTokenId(mid)
86 .call()
87 .await
88 .map_err(|e| StrikeError::Contract(e.to_string()))?;
89
90 let yes_bal = ot
91 .balanceOf(owner, yes_id)
92 .call()
93 .await
94 .map_err(|e| StrikeError::Contract(e.to_string()))?;
95 let no_bal = ot
96 .balanceOf(owner, no_id)
97 .call()
98 .await
99 .map_err(|e| StrikeError::Contract(e.to_string()))?;
100
101 Ok((yes_bal, no_bal))
102 }
103}