1use alloy::{
2 primitives::{Address, FixedBytes, Log},
3 providers::Provider,
4 rpc::types::{Filter, TransactionReceipt},
5 signers::local::PrivateKeySigner,
6 sol_types::SolEvent,
7};
8use clients::{
9 arbiters::{ArbitersAddresses, ArbitersClient},
10 attestation::{AttestationAddresses, AttestationClient},
11 erc20::{Erc20Addresses, Erc20Client},
12 erc721::{Erc721Addresses, Erc721Client},
13 erc1155::{Erc1155Addresses, Erc1155Client},
14 string_obligation::{StringObligationAddresses, StringObligationClient},
15 token_bundle::{TokenBundleAddresses, TokenBundleClient},
16};
17use futures_util::StreamExt;
18use sol_types::EscrowClaimed;
19use types::{PublicProvider, WalletProvider};
20
21pub mod addresses;
22pub mod clients;
23pub mod contracts;
24pub mod fixtures;
25pub mod sol_types;
26pub mod types;
27pub mod utils;
28
29#[derive(Debug, Clone)]
32pub struct AddressConfig {
33 pub arbiters_addresses: Option<ArbitersAddresses>,
34 pub erc20_addresses: Option<Erc20Addresses>,
35 pub erc721_addresses: Option<Erc721Addresses>,
36 pub erc1155_addresses: Option<Erc1155Addresses>,
37 pub token_bundle_addresses: Option<TokenBundleAddresses>,
38 pub attestation_addresses: Option<AttestationAddresses>,
39 pub string_obligation_addresses: Option<StringObligationAddresses>,
40}
41
42#[derive(Clone)]
51pub struct AlkahestClient {
52 pub wallet_provider: WalletProvider,
53 pub public_provider: PublicProvider,
54 pub address: Address,
55
56 pub arbiters: ArbitersClient,
57 pub erc20: Erc20Client,
58 pub erc721: Erc721Client,
59 pub erc1155: Erc1155Client,
60 pub token_bundle: TokenBundleClient,
61 pub attestation: AttestationClient,
62 pub string_obligation: StringObligationClient,
63}
64
65impl AlkahestClient {
66 pub async fn new(
76 private_key: PrivateKeySigner,
77 rpc_url: impl ToString + Clone,
78 addresses: Option<AddressConfig>,
79 ) -> eyre::Result<Self> {
80 let wallet_provider =
81 utils::get_wallet_provider(private_key.clone(), rpc_url.clone()).await?;
82 let public_provider = utils::get_public_provider(rpc_url.clone()).await?;
83
84 macro_rules! make_client {
85 ($client:ident, $addresses:ident) => {
86 $client::new(
87 private_key.clone(),
88 rpc_url.clone(),
89 addresses.clone().and_then(|a| a.$addresses),
90 )
91 };
92 }
93
94 Ok(AlkahestClient {
95 wallet_provider: wallet_provider.clone(),
96 public_provider: public_provider.clone(),
97 address: private_key.address(),
98 arbiters: make_client!(ArbitersClient, arbiters_addresses).await?,
99 erc20: make_client!(Erc20Client, erc20_addresses).await?,
100 erc721: make_client!(Erc721Client, erc721_addresses).await?,
101 erc1155: make_client!(Erc1155Client, erc1155_addresses).await?,
102 token_bundle: make_client!(TokenBundleClient, token_bundle_addresses).await?,
103 attestation: make_client!(AttestationClient, attestation_addresses).await?,
104 string_obligation: make_client!(StringObligationClient, string_obligation_addresses)
105 .await?,
106 })
107 }
108
109 pub fn get_attested_event(
117 receipt: TransactionReceipt,
118 ) -> eyre::Result<Log<contracts::IEAS::Attested>> {
119 let attested_event = receipt
120 .inner
121 .logs()
122 .iter()
123 .filter(|log| log.topic0() == Some(&contracts::IEAS::Attested::SIGNATURE_HASH))
124 .collect::<Vec<_>>()
125 .first()
126 .map(|log| log.log_decode::<contracts::IEAS::Attested>())
127 .ok_or_else(|| eyre::eyre!("No Attested event found"))??;
128
129 Ok(attested_event.inner)
130 }
131
132 pub async fn wait_for_fulfillment(
146 &self,
147 contract_address: Address,
148 buy_attestation: FixedBytes<32>,
149 from_block: Option<u64>,
150 ) -> eyre::Result<Log<EscrowClaimed>> {
151 let filter = Filter::new()
152 .from_block(from_block.unwrap_or(0))
153 .address(contract_address)
154 .event_signature(EscrowClaimed::SIGNATURE_HASH)
155 .topic1(buy_attestation);
156
157 let logs = self.public_provider.get_logs(&filter).await?;
158 println!("initial logs: {:?}", logs);
159 if let Some(log) = logs
160 .iter()
161 .collect::<Vec<_>>()
162 .first()
163 .map(|log| log.log_decode::<EscrowClaimed>())
164 {
165 return Ok(log?.inner);
166 }
167
168 let sub = self.public_provider.subscribe_logs(&filter).await?;
169 let mut stream = sub.into_stream();
170
171 if let Some(log) = stream.next().await {
172 let log = log.log_decode::<EscrowClaimed>()?;
173 return Ok(log.inner);
174 }
175
176 Err(eyre::eyre!("No EscrowClaimed event found"))
177 }
178}