1use async_graphql::{connection::Connection, *};
6
7use crate::{
8 connection::ScanConnection,
9 types::{
10 balance::{self, Balance},
11 coin::Coin,
12 cursor::Page,
13 iota_address::IotaAddress,
14 iota_names_registration::{NameFormat, NameRegistration},
15 move_object::MoveObject,
16 object::{self, ObjectFilter},
17 owner::OwnerImpl,
18 stake::StakedIota,
19 transaction_block::{self, TransactionBlock, TransactionBlockFilter},
20 type_filter::ExactTypeFilter,
21 },
22};
23
24#[derive(Clone, Debug, PartialEq, Eq, Copy)]
25pub(crate) struct Address {
26 pub address: IotaAddress,
27 pub checkpoint_viewed_at: u64,
29}
30
31#[derive(Enum, Copy, Clone, Eq, PartialEq)]
33pub(crate) enum AddressTransactionBlockRelationship {
34 #[graphql(
41 deprecation = "Misleading semantics. Use `SENT` instead. This will be removed with the 1.24.0 release."
42 )]
43 Sign,
44 Sent,
46 Recv,
48}
49
50#[Object]
53impl Address {
54 pub(crate) async fn address(&self) -> IotaAddress {
55 OwnerImpl::from(self).address().await
56 }
57
58 pub(crate) async fn objects(
60 &self,
61 ctx: &Context<'_>,
62 first: Option<u64>,
63 after: Option<object::Cursor>,
64 last: Option<u64>,
65 before: Option<object::Cursor>,
66 filter: Option<ObjectFilter>,
67 ) -> Result<Connection<String, MoveObject>> {
68 OwnerImpl::from(self)
69 .objects(ctx, first, after, last, before, filter)
70 .await
71 }
72
73 pub(crate) async fn balance(
76 &self,
77 ctx: &Context<'_>,
78 type_: Option<ExactTypeFilter>,
79 ) -> Result<Option<Balance>> {
80 OwnerImpl::from(self).balance(ctx, type_).await
81 }
82
83 pub(crate) async fn balances(
85 &self,
86 ctx: &Context<'_>,
87 first: Option<u64>,
88 after: Option<balance::Cursor>,
89 last: Option<u64>,
90 before: Option<balance::Cursor>,
91 ) -> Result<Connection<String, Balance>> {
92 OwnerImpl::from(self)
93 .balances(ctx, first, after, last, before)
94 .await
95 }
96
97 pub(crate) async fn coins(
102 &self,
103 ctx: &Context<'_>,
104 first: Option<u64>,
105 after: Option<object::Cursor>,
106 last: Option<u64>,
107 before: Option<object::Cursor>,
108 type_: Option<ExactTypeFilter>,
109 ) -> Result<Connection<String, Coin>> {
110 OwnerImpl::from(self)
111 .coins(ctx, first, after, last, before, type_)
112 .await
113 }
114
115 pub(crate) async fn staked_iotas(
117 &self,
118 ctx: &Context<'_>,
119 first: Option<u64>,
120 after: Option<object::Cursor>,
121 last: Option<u64>,
122 before: Option<object::Cursor>,
123 ) -> Result<Connection<String, StakedIota>> {
124 OwnerImpl::from(self)
125 .staked_iotas(ctx, first, after, last, before)
126 .await
127 }
128
129 pub(crate) async fn iota_names_default_name(
132 &self,
133 ctx: &Context<'_>,
134 format: Option<NameFormat>,
135 ) -> Result<Option<String>> {
136 OwnerImpl::from(self)
137 .iota_names_default_name(ctx, format)
138 .await
139 }
140
141 pub(crate) async fn iota_names_registrations(
144 &self,
145 ctx: &Context<'_>,
146 first: Option<u64>,
147 after: Option<object::Cursor>,
148 last: Option<u64>,
149 before: Option<object::Cursor>,
150 ) -> Result<Connection<String, NameRegistration>> {
151 OwnerImpl::from(self)
152 .iota_names_registrations(ctx, first, after, last, before)
153 .await
154 }
155
156 async fn transaction_blocks(
184 &self,
185 ctx: &Context<'_>,
186 first: Option<u64>,
187 after: Option<transaction_block::Cursor>,
188 last: Option<u64>,
189 before: Option<transaction_block::Cursor>,
190 relation: Option<AddressTransactionBlockRelationship>,
191 filter: Option<TransactionBlockFilter>,
192 scan_limit: Option<u64>,
193 ) -> Result<ScanConnection<String, TransactionBlock>> {
194 use AddressTransactionBlockRelationship as R;
195 let page = Page::from_params(ctx.data_unchecked(), first, after, last, before)?;
196
197 let Some(filter) = filter.unwrap_or_default().intersect(match relation {
198 Some(R::Sign) | Some(R::Sent) | None => TransactionBlockFilter {
200 sent_address: Some(self.address),
201 ..Default::default()
202 },
203
204 Some(R::Recv) => TransactionBlockFilter {
205 recv_address: Some(self.address),
206 ..Default::default()
207 },
208 }) else {
209 return Ok(ScanConnection::new(false, false));
210 };
211
212 TransactionBlock::paginate(ctx, page, filter, self.checkpoint_viewed_at, scan_limit)
213 .await
214 .extend()
215 }
216}
217
218impl From<&Address> for OwnerImpl {
219 fn from(address: &Address) -> Self {
220 OwnerImpl {
221 address: address.address,
222 checkpoint_viewed_at: address.checkpoint_viewed_at,
223 }
224 }
225}