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::{DomainFormat, IotaNamesRegistration},
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)]
34pub(crate) enum AddressTransactionBlockRelationship {
35 Sign,
37 Recv,
39}
40
41#[Object]
44impl Address {
45 pub(crate) async fn address(&self) -> IotaAddress {
46 OwnerImpl::from(self).address().await
47 }
48
49 pub(crate) async fn objects(
51 &self,
52 ctx: &Context<'_>,
53 first: Option<u64>,
54 after: Option<object::Cursor>,
55 last: Option<u64>,
56 before: Option<object::Cursor>,
57 filter: Option<ObjectFilter>,
58 ) -> Result<Connection<String, MoveObject>> {
59 OwnerImpl::from(self)
60 .objects(ctx, first, after, last, before, filter)
61 .await
62 }
63
64 pub(crate) async fn balance(
67 &self,
68 ctx: &Context<'_>,
69 type_: Option<ExactTypeFilter>,
70 ) -> Result<Option<Balance>> {
71 OwnerImpl::from(self).balance(ctx, type_).await
72 }
73
74 pub(crate) async fn balances(
76 &self,
77 ctx: &Context<'_>,
78 first: Option<u64>,
79 after: Option<balance::Cursor>,
80 last: Option<u64>,
81 before: Option<balance::Cursor>,
82 ) -> Result<Connection<String, Balance>> {
83 OwnerImpl::from(self)
84 .balances(ctx, first, after, last, before)
85 .await
86 }
87
88 pub(crate) async fn coins(
93 &self,
94 ctx: &Context<'_>,
95 first: Option<u64>,
96 after: Option<object::Cursor>,
97 last: Option<u64>,
98 before: Option<object::Cursor>,
99 type_: Option<ExactTypeFilter>,
100 ) -> Result<Connection<String, Coin>> {
101 OwnerImpl::from(self)
102 .coins(ctx, first, after, last, before, type_)
103 .await
104 }
105
106 pub(crate) async fn staked_iotas(
108 &self,
109 ctx: &Context<'_>,
110 first: Option<u64>,
111 after: Option<object::Cursor>,
112 last: Option<u64>,
113 before: Option<object::Cursor>,
114 ) -> Result<Connection<String, StakedIota>> {
115 OwnerImpl::from(self)
116 .staked_iotas(ctx, first, after, last, before)
117 .await
118 }
119
120 pub(crate) async fn iota_names_default_name(
123 &self,
124 ctx: &Context<'_>,
125 format: Option<DomainFormat>,
126 ) -> Result<Option<String>> {
127 OwnerImpl::from(self)
128 .iota_names_default_name(ctx, format)
129 .await
130 }
131
132 pub(crate) async fn iota_names_registrations(
135 &self,
136 ctx: &Context<'_>,
137 first: Option<u64>,
138 after: Option<object::Cursor>,
139 last: Option<u64>,
140 before: Option<object::Cursor>,
141 ) -> Result<Connection<String, IotaNamesRegistration>> {
142 OwnerImpl::from(self)
143 .iota_names_registrations(ctx, first, after, last, before)
144 .await
145 }
146
147 async fn transaction_blocks(
175 &self,
176 ctx: &Context<'_>,
177 first: Option<u64>,
178 after: Option<transaction_block::Cursor>,
179 last: Option<u64>,
180 before: Option<transaction_block::Cursor>,
181 relation: Option<AddressTransactionBlockRelationship>,
182 filter: Option<TransactionBlockFilter>,
183 scan_limit: Option<u64>,
184 ) -> Result<ScanConnection<String, TransactionBlock>> {
185 use AddressTransactionBlockRelationship as R;
186 let page = Page::from_params(ctx.data_unchecked(), first, after, last, before)?;
187
188 let Some(filter) = filter.unwrap_or_default().intersect(match relation {
189 Some(R::Sign) | None => TransactionBlockFilter {
191 sign_address: Some(self.address),
192 ..Default::default()
193 },
194
195 Some(R::Recv) => TransactionBlockFilter {
196 recv_address: Some(self.address),
197 ..Default::default()
198 },
199 }) else {
200 return Ok(ScanConnection::new(false, false));
201 };
202
203 TransactionBlock::paginate(ctx, page, filter, self.checkpoint_viewed_at, scan_limit)
204 .await
205 .extend()
206 }
207}
208
209impl From<&Address> for OwnerImpl {
210 fn from(address: &Address) -> Self {
211 OwnerImpl {
212 address: address.address,
213 checkpoint_viewed_at: address.checkpoint_viewed_at,
214 }
215 }
216}