1use super::ServiceContext;
4
5macro_rules! thin_service {
6 ($name:ident, $client:ty) => {
7 #[derive(Clone)]
8 pub struct $name {
9 pub(crate) ctx: ServiceContext,
10 }
11 impl $name {
12 pub fn new(ctx: ServiceContext) -> Self {
13 Self { ctx }
14 }
15 pub(crate) fn connect_client(&self) -> $client {
16 <$client>::new(
17 self.ctx.factory.transport(),
18 self.ctx.factory.connect_config(),
19 )
20 }
21 }
22 };
23}
24
25macro_rules! realtime_only_service {
26 ($name:ident) => {
27 #[derive(Clone)]
28 pub struct $name {
29 pub(crate) ctx: ServiceContext,
30 }
31 impl $name {
32 pub fn new(ctx: ServiceContext) -> Self {
33 Self { ctx }
34 }
35 }
36 };
37}
38
39thin_service!(
40 ChainAnalyticsService,
41 crate::connect::chain::analytics::v1::ChainAnalyticsServiceClient<
42 crate::transport::SharedTransport,
43 >
44);
45thin_service!(
46 LifecycleService,
47 crate::connect::chain::lifecycle::v1::LifecycleReadServiceClient<
48 crate::transport::SharedTransport,
49 >
50);
51thin_service!(
52 HeatmapService,
53 crate::connect::marketdata::v1::HeatmapServiceClient<crate::transport::SharedTransport>
54);
55realtime_only_service!(PoliciesService);
56thin_service!(
57 SubAccountsService,
58 crate::connect::auth::v1::SubaccountServiceClient<crate::transport::SharedTransport>
59);
60thin_service!(
61 AddressBookService,
62 crate::connect::auth::v1::AddressBookServiceClient<crate::transport::SharedTransport>
63);
64thin_service!(
65 SocialVerificationService,
66 crate::connect::auth::v1::SocialVerificationServiceClient<crate::transport::SharedTransport>
67);
68thin_service!(
69 WhiteboardService,
70 crate::connect::collab::v1::WhiteboardServiceClient<crate::transport::SharedTransport>
71);
72thin_service!(
73 PolychartService,
74 crate::connect::polychart::v1::PolychartServiceClient<crate::transport::SharedTransport>
75);
76thin_service!(
77 LayoutService,
78 crate::connect::layout::v1::LayoutServiceClient<crate::transport::SharedTransport>
79);
80thin_service!(
81 GuardSignerService,
82 crate::connect::chain::guard::v1::GuardSignerServiceClient<crate::transport::SharedTransport>
83);
84thin_service!(
85 InternalTransfersService,
86 crate::connect::transfer::v1::InternalTransferServiceClient<crate::transport::SharedTransport>
87);
88thin_service!(
89 TransfersService,
90 crate::connect::ledger::read::v1::LedgerReadServiceClient<crate::transport::SharedTransport>
91);
92
93impl HeatmapService {
94 pub async fn get(
96 &self,
97 symbol: &str,
98 interval: &str,
99 depth: u32,
100 limit: u32,
101 quantity_mode: &str,
102 ) -> crate::errors::Result<crate::models::ApiData> {
103 use crate::codecs::decode::api_data_from_proto;
104 use crate::codecs::heatmap::{
105 heatmap_depth_for_levels, resolve_heatmap_interval, resolve_heatmap_quantity_mode,
106 };
107 use crate::errors::Error;
108 use crate::proto::marketdata::v1::{GetOrderbookHeatmapRequest, HeatmapTimeRange};
109 use buffa_types::google::protobuf::Timestamp;
110 use std::time::{SystemTime, UNIX_EPOCH};
111
112 let symbol_id = self
113 .ctx
114 .catalogs
115 .symbol_id_for_symbol(symbol)
116 .ok_or_else(|| {
117 Error::validation(format!(
118 "unknown symbol {symbol}; call hydrate_catalogs / get_spot_config first"
119 ))
120 })?;
121 let interval_enum = resolve_heatmap_interval(interval)?;
122 let qty_mode = resolve_heatmap_quantity_mode(quantity_mode)?;
123 let now = SystemTime::now()
124 .duration_since(UNIX_EPOCH)
125 .unwrap_or_default();
126 let end = Timestamp {
127 seconds: now.as_secs() as i64,
128 nanos: now.subsec_nanos() as i32,
129 ..Default::default()
130 };
131 let start = Timestamp {
132 seconds: end.seconds.saturating_sub(300),
133 nanos: end.nanos,
134 ..Default::default()
135 };
136 let req = GetOrderbookHeatmapRequest {
137 symbol_id,
138 interval: interval_enum.into(),
139 depth: heatmap_depth_for_levels(depth).into(),
140 time_range: HeatmapTimeRange {
141 start_time: start.into(),
142 end_time: end.into(),
143 ..Default::default()
144 }
145 .into(),
146 limit: if limit == 0 { 100 } else { limit },
147 quantity_mode: qty_mode.into(),
148 ..Default::default()
149 };
150 let client = self.connect_client();
151 let resp = super::unary::await_public(client.get_orderbook_heatmap(req))
152 .await?
153 .into_owned();
154 Ok(api_data_from_proto(&resp))
155 }
156
157 pub async fn subscribe_live(
159 &self,
160 symbol: &str,
161 interval: &str,
162 ) -> crate::errors::Result<crate::realtime::TypedSubscription<crate::models::ApiData>> {
163 use crate::codecs::heatmap::heatmap_interval_channel_name;
164 use crate::errors::Error;
165 let symbol_id = self
166 .ctx
167 .catalogs
168 .symbol_id_for_symbol(symbol)
169 .ok_or_else(|| {
170 Error::validation(format!(
171 "unknown symbol {symbol}; call hydrate_catalogs / get_spot_config first"
172 ))
173 })?;
174 crate::codecs::heatmap::resolve_heatmap_interval(interval)?;
176 let interval_name = heatmap_interval_channel_name(interval);
177 let channel = format!("public:spot:market:heatmap:{interval_name}:{symbol_id}:proto");
178 self.ctx
179 .realtime
180 .subscribe_proto(
181 &channel,
182 crate::codecs::decode::heatmap_live_bucket_from_bytes,
183 )
184 .await
185 }
186}
187
188fn internal_transfer_amount_e18(
189 quantity: &crate::types::AssetAmount,
190 quantity_scale: Option<u32>,
191 asset_id: u32,
192) -> crate::errors::Result<crate::proto::polyester::r#type::v1::U128> {
193 use crate::codecs::scalars::{LEDGER_SCALE, i128_to_u128};
194 use crate::types::{QuantityDomain, resolve_asset_amount_scaled_with_input_scale};
195
196 let scaled = resolve_asset_amount_scaled_with_input_scale(
197 quantity,
198 quantity_scale,
199 LEDGER_SCALE,
200 QuantityDomain::LedgerE18,
201 Some(asset_id),
202 )?;
203 i128_to_u128(scaled)
204}
205
206impl InternalTransfersService {
207 pub async fn create(
209 &self,
210 params: crate::models::CreateInternalTransferParams,
211 ) -> crate::errors::Result<crate::models::InternalTransferResult> {
212 use super::scope;
213 use super::unary;
214 use crate::codecs::decode::internal_transfer_from_proto;
215 use crate::codecs::scalars::id_to_u64;
216 use crate::errors::Error;
217 use crate::proto::transfer::v1::{
218 CreateInternalTransferRequest, create_internal_transfer_request::Destination,
219 };
220
221 let has_account = params
222 .destination_account_id
223 .as_ref()
224 .is_some_and(|s| !s.trim().is_empty());
225 let has_sub = params
226 .destination_subaccount_id
227 .as_ref()
228 .is_some_and(|s| !s.trim().is_empty());
229 let has_smart = params
230 .destination_smart_account_address
231 .as_ref()
232 .is_some_and(|s| !s.trim().is_empty());
233 if usize::from(has_account) + usize::from(has_sub) + usize::from(has_smart) != 1 {
234 return Err(Error::validation(
235 "create requires exactly one of destination_account_id, destination_subaccount_id, or destination_smart_account_address",
236 ));
237 }
238 if params.idempotency_key.trim().is_empty() {
239 return Err(Error::validation(
240 "create requires a non-empty idempotency_key reused across retries",
241 ));
242 }
243
244 let amount_e18 =
245 internal_transfer_amount_e18(¶ms.quantity, params.quantity_scale, params.asset_id)?;
246 let mut req = CreateInternalTransferRequest {
247 asset_id: params.asset_id,
248 idempotency_key: params.idempotency_key,
249 subaccount_id: scope::optional_subaccount(&self.ctx, params.subaccount_id)?
250 .unwrap_or(0),
251 ..Default::default()
252 };
253 *req.amount_e18.get_or_insert_default() = amount_e18;
254 if has_account {
255 req.destination = Some(Destination::DestinationAccountId(id_to_u64(
256 params.destination_account_id.as_deref().unwrap(),
257 "destination_account_id",
258 )?));
259 } else if has_sub {
260 req.destination = Some(Destination::DestinationSubaccountId(id_to_u64(
261 params.destination_subaccount_id.as_deref().unwrap(),
262 "destination_subaccount_id",
263 )?));
264 } else {
265 req.destination = Some(Destination::DestinationSmartAccountAddress(
266 params.destination_smart_account_address.unwrap_or_default(),
267 ));
268 }
269
270 let client = self.connect_client();
271 let resp = unary::await_auth(
272 &self.ctx.factory,
273 "/transfer.v1.InternalTransferService/CreateInternalTransfer",
274 req,
275 |req, opts| client.create_internal_transfer_with_options(req, opts),
276 )
277 .await?
278 .into_owned();
279 internal_transfer_from_proto(&resp)
280 }
281}
282
283impl PoliciesService {
284 pub async fn subscribe(
286 &self,
287 account_id: Option<&str>,
288 ) -> crate::errors::Result<crate::realtime::TypedSubscription<crate::models::SubaccountPolicy>>
289 {
290 self.subscribe_subaccount_policies(account_id).await
291 }
292
293 pub async fn subscribe_subaccount_policies(
295 &self,
296 account_id: Option<&str>,
297 ) -> crate::errors::Result<crate::realtime::TypedSubscription<crate::models::SubaccountPolicy>>
298 {
299 let account = super::scope::resolve_account_id(&self.ctx, account_id)?;
300 let channel = format!("private:auth:subaccount-policies:{account}:proto");
301 self.ctx
302 .realtime
303 .subscribe_proto(
304 &channel,
305 crate::codecs::decode::subaccount_policy_from_bytes,
306 )
307 .await
308 }
309
310 pub async fn subscribe_api_policies(
312 &self,
313 account_id: Option<&str>,
314 ) -> crate::errors::Result<crate::realtime::TypedSubscription<crate::models::ApiPolicy>> {
315 let account = super::scope::resolve_account_id(&self.ctx, account_id)?;
316 let channel = format!("private:auth:api-policies:{account}:proto");
317 self.ctx
318 .realtime
319 .subscribe_proto(&channel, crate::codecs::decode::api_policy_from_bytes)
320 .await
321 }
322}
323
324#[derive(Debug, Clone, Default)]
325pub struct GetSubaccountOpts {
326 pub include_api_keys: bool,
327 pub include_members: bool,
328 pub include_invites: bool,
329 pub include_policy: bool,
330 pub include_balances: bool,
331 pub invites_direction: String,
332}
333
334impl SubAccountsService {
335 pub async fn subscribe(
337 &self,
338 account_id: Option<&str>,
339 ) -> crate::errors::Result<crate::realtime::TypedSubscription<crate::models::SubAccount>> {
340 let account = super::scope::resolve_account_id(&self.ctx, account_id)?;
341 let channel = format!("private:auth:subaccounts:{account}:proto");
342 self.ctx
343 .realtime
344 .subscribe_proto(&channel, crate::codecs::decode::subaccount_from_bytes)
345 .await
346 }
347
348 pub async fn subscribe_api_keys(
350 &self,
351 account_id: Option<&str>,
352 ) -> crate::errors::Result<crate::realtime::TypedSubscription<crate::models::ApiKeySummary>>
353 {
354 let account = super::scope::resolve_account_id(&self.ctx, account_id)?;
355 let channel = format!("private:auth:api-keys:{account}:proto");
356 self.ctx
357 .realtime
358 .subscribe_proto(&channel, crate::codecs::decode::api_key_from_bytes)
359 .await
360 }
361
362 pub async fn list(
363 &self,
364 req: crate::proto::auth::v1::ListSubaccountsRequest,
365 ) -> crate::errors::Result<crate::models::SubAccountsList> {
366 use crate::codecs::decode::subaccounts_list_from_proto;
367 let client = self.connect_client();
368 let resp = {
369 use super::unary;
370 unary::await_auth(
371 &self.ctx.factory,
372 "/auth.v1.SubaccountService/ListSubaccounts",
373 req,
374 |req, opts| client.list_subaccounts_with_options(req, opts),
375 )
376 .await?
377 .into_owned()
378 };
379 Ok(subaccounts_list_from_proto(&resp))
380 }
381
382 pub async fn get(
383 &self,
384 subaccount_id: u64,
385 opts: GetSubaccountOpts,
386 ) -> crate::errors::Result<crate::models::GetSubaccountResult> {
387 use crate::codecs::decode::get_subaccount_from_proto;
388 use crate::proto::auth::v1::GetSubaccountRequest;
389 let req = GetSubaccountRequest {
390 subaccount_id,
391 include_api_keys: opts.include_api_keys,
392 include_members: opts.include_members,
393 include_invites: opts.include_invites,
394 include_policy: opts.include_policy,
395 include_balances: opts.include_balances,
396 invites_direction: opts.invites_direction,
397 ..Default::default()
398 };
399 let client = crate::connect::auth::v1::SubaccountViewServiceClient::new(
400 self.ctx.factory.transport(),
401 self.ctx.factory.connect_config(),
402 );
403 let resp = {
404 use super::unary;
405 unary::await_auth(
406 &self.ctx.factory,
407 "/auth.v1.SubaccountViewService/GetSubaccount",
408 req,
409 |req, opts| client.get_subaccount_with_options(req, opts),
410 )
411 .await?
412 .into_owned()
413 };
414 Ok(get_subaccount_from_proto(&resp))
415 }
416
417 pub async fn list_members(
418 &self,
419 req: crate::proto::auth::v1::ListSubaccountMembersRequest,
420 ) -> crate::errors::Result<crate::models::SubAccountMembersList> {
421 use crate::codecs::decode::subaccount_members_list_from_proto;
422 let client = self.connect_client();
423 let resp = {
424 use super::unary;
425 unary::await_auth(
426 &self.ctx.factory,
427 "/auth.v1.SubaccountService/ListSubaccountMembers",
428 req,
429 |req, opts| client.list_subaccount_members_with_options(req, opts),
430 )
431 .await?
432 .into_owned()
433 };
434 Ok(subaccount_members_list_from_proto(&resp))
435 }
436
437 pub async fn list_invites(
438 &self,
439 req: crate::proto::auth::v1::ListSubaccountInvitesRequest,
440 ) -> crate::errors::Result<crate::models::SubAccountInvitesList> {
441 use crate::codecs::decode::subaccount_invites_list_from_proto;
442 let client = self.connect_client();
443 let resp = {
444 use super::unary;
445 unary::await_auth(
446 &self.ctx.factory,
447 "/auth.v1.SubaccountService/ListSubaccountInvites",
448 req,
449 |req, opts| client.list_subaccount_invites_with_options(req, opts),
450 )
451 .await?
452 .into_owned()
453 };
454 Ok(subaccount_invites_list_from_proto(&resp))
455 }
456
457 pub async fn list_activity(
458 &self,
459 req: crate::proto::auth::v1::ListSubaccountEventsRequest,
460 ) -> crate::errors::Result<crate::models::SubAccountActivityList> {
461 use crate::codecs::decode::subaccount_activity_list_from_proto;
462 let client = crate::connect::auth::v1::SubaccountViewServiceClient::new(
463 self.ctx.factory.transport(),
464 self.ctx.factory.connect_config(),
465 );
466 let resp = {
467 use super::unary;
468 unary::await_auth(
469 &self.ctx.factory,
470 "/auth.v1.SubaccountViewService/ListSubaccountActivity",
471 req,
472 |req, opts| client.list_subaccount_activity_with_options(req, opts),
473 )
474 .await?
475 .into_owned()
476 };
477 Ok(subaccount_activity_list_from_proto(&resp))
478 }
479}
480
481impl AddressBookService {
482 pub async fn subscribe(
484 &self,
485 account_id: Option<&str>,
486 ) -> crate::errors::Result<
487 crate::realtime::TypedSubscription<crate::models::AddressBookViewInvalidation>,
488 > {
489 let account = super::scope::resolve_account_id(&self.ctx, account_id)?;
490 let channel = format!("private:auth:address-books:{account}:proto");
491 self.ctx
492 .realtime
493 .subscribe_proto(
494 &channel,
495 crate::codecs::decode::address_book_invalidation_from_bytes,
496 )
497 .await
498 }
499
500 pub async fn subscribe_view_invalidations(
502 &self,
503 root_account_public_id: Option<&str>,
504 ) -> crate::errors::Result<
505 crate::realtime::TypedSubscription<crate::models::AddressBookViewInvalidation>,
506 > {
507 self.subscribe(root_account_public_id).await
508 }
509
510 pub async fn list_books(
511 &self,
512 req: crate::proto::auth::v1::ListAddressBooksRequest,
513 ) -> crate::errors::Result<crate::models::AddressBooksList> {
514 use crate::codecs::decode::list_books_from_proto;
515 let client = self.connect_client();
516 let resp = {
517 use super::unary;
518 unary::await_auth(
519 &self.ctx.factory,
520 "/auth.v1.AddressBookService/ListAddressBooks",
521 req,
522 |req, opts| client.list_address_books_with_options(req, opts),
523 )
524 .await?
525 .into_owned()
526 };
527 Ok(list_books_from_proto(&resp))
528 }
529
530 pub async fn list_entries(
531 &self,
532 req: crate::proto::auth::v1::ListAddressBookEntriesRequest,
533 ) -> crate::errors::Result<crate::models::AddressBookEntriesList> {
534 use crate::codecs::decode::list_entries_from_proto;
535 let client = self.connect_client();
536 let resp = {
537 use super::unary;
538 unary::await_auth(
539 &self.ctx.factory,
540 "/auth.v1.AddressBookService/ListAddressBookEntries",
541 req,
542 |req, opts| client.list_address_book_entries_with_options(req, opts),
543 )
544 .await?
545 .into_owned()
546 };
547 Ok(list_entries_from_proto(&resp))
548 }
549
550 pub async fn list_transfer_counterparties(
551 &self,
552 req: crate::proto::auth::v1::ListTransferCounterpartiesRequest,
553 ) -> crate::errors::Result<crate::models::ApiData> {
554 use crate::codecs::decode::api_data_from_proto;
555 let client = self.connect_client();
556 let resp = {
557 use super::unary;
558 unary::await_auth(
559 &self.ctx.factory,
560 "/auth.v1.AddressBookService/ListTransferCounterparties",
561 req,
562 |req, opts| client.list_transfer_counterparties_with_options(req, opts),
563 )
564 .await?
565 .into_owned()
566 };
567 Ok(api_data_from_proto(&resp))
568 }
569
570 pub async fn list_transfer_destinations(
571 &self,
572 req: crate::proto::auth::v1::ListTransferDestinationsRequest,
573 ) -> crate::errors::Result<crate::models::ApiData> {
574 use crate::codecs::decode::api_data_from_proto;
575 let client = self.connect_client();
576 let resp = {
577 use super::unary;
578 unary::await_auth(
579 &self.ctx.factory,
580 "/auth.v1.AddressBookService/ListTransferDestinations",
581 req,
582 |req, opts| client.list_transfer_destinations_with_options(req, opts),
583 )
584 .await?
585 .into_owned()
586 };
587 Ok(api_data_from_proto(&resp))
588 }
589
590 pub async fn list_internal_transfer_whitelist_entries(
591 &self,
592 req: crate::proto::auth::v1::ListInternalTransferWhitelistEntriesRequest,
593 ) -> crate::errors::Result<crate::models::ApiData> {
594 use crate::codecs::decode::api_data_from_proto;
595 let client = self.connect_client();
596 let resp = {
597 use super::unary;
598 unary::await_auth(
599 &self.ctx.factory,
600 "/auth.v1.AddressBookService/ListInternalTransferWhitelistEntries",
601 req,
602 |req, opts| client.list_internal_transfer_whitelist_entries_with_options(req, opts),
603 )
604 .await?
605 .into_owned()
606 };
607 Ok(api_data_from_proto(&resp))
608 }
609
610 pub async fn get_withdraw_whitelist_view(
611 &self,
612 req: crate::proto::auth::v1::GetWithdrawWhitelistViewRequest,
613 ) -> crate::errors::Result<crate::models::ApiData> {
614 use crate::codecs::decode::api_data_from_proto;
615 let client = self.connect_client();
616 let resp = {
617 use super::unary;
618 unary::await_auth(
619 &self.ctx.factory,
620 "/auth.v1.AddressBookService/GetWithdrawWhitelistView",
621 req,
622 |req, opts| client.get_withdraw_whitelist_view_with_options(req, opts),
623 )
624 .await?
625 .into_owned()
626 };
627 Ok(api_data_from_proto(&resp))
628 }
629
630 pub async fn get_view(
631 &self,
632 req: crate::proto::auth::v1::GetAddressBookViewRequest,
633 ) -> crate::errors::Result<crate::models::ApiData> {
634 use crate::codecs::decode::api_data_from_proto;
635 let client = self.connect_client();
636 let resp = {
637 use super::unary;
638 unary::await_auth(
639 &self.ctx.factory,
640 "/auth.v1.AddressBookService/GetAddressBookView",
641 req,
642 |req, opts| client.get_address_book_view_with_options(req, opts),
643 )
644 .await?
645 .into_owned()
646 };
647 Ok(api_data_from_proto(&resp))
648 }
649}
650
651impl TransfersService {
652 pub async fn list(
653 &self,
654 req: crate::proto::ledger::read::v1::ListTransfersRequest,
655 ) -> crate::errors::Result<crate::models::TransfersList> {
656 use crate::codecs::decode::transfers_list_from_proto;
657 let client = self.connect_client();
658 let resp = {
659 use super::unary;
660 unary::await_auth(
661 &self.ctx.factory,
662 "/ledger.read.v1.LedgerReadService/ListTransfers",
663 req,
664 |req, opts| client.list_transfers_with_options(req, opts),
665 )
666 .await?
667 .into_owned()
668 };
669 Ok(transfers_list_from_proto(&resp))
670 }
671
672 pub async fn subscribe(
674 &self,
675 account_id: Option<&str>,
676 ) -> crate::errors::Result<crate::realtime::TypedSubscription<crate::models::LedgerTransfer>>
677 {
678 let account = super::scope::resolve_account_id(&self.ctx, account_id)?;
679 let channel = format!("private:ledger:transfers:{account}:proto");
680 self.ctx
681 .realtime
682 .subscribe_proto(&channel, crate::codecs::decode::ledger_transfer_from_bytes)
683 .await
684 }
685}
686
687impl ChainAnalyticsService {
688 pub async fn get_zipped_asset_supply(
689 &self,
690 zipped_asset_id: u32,
691 range_key: &str,
692 bucket: &str,
693 start_ts_sec: u32,
694 end_ts_sec: u32,
695 ) -> crate::errors::Result<crate::models::ApiData> {
696 use crate::codecs::analytics::resolve_analytics_range;
697 use crate::codecs::decode::api_data_from_proto;
698 use crate::proto::chain::analytics::v1::GetZippedAssetSupplyRequest;
699 let req = GetZippedAssetSupplyRequest {
700 zipped_asset_id,
701 range: resolve_analytics_range(range_key)?.into(),
702 bucket: bucket.to_owned(),
703 start_ts_sec,
704 end_ts_sec,
705 ..Default::default()
706 };
707 let client = self.connect_client();
708 let resp = super::unary::await_public(client.get_zipped_asset_supply(req))
709 .await?
710 .into_owned();
711 Ok(api_data_from_proto(&resp))
712 }
713
714 pub async fn get_zipped_asset_supply_group(
715 &self,
716 group_id: &str,
717 range_key: &str,
718 bucket: &str,
719 start_ts_sec: u32,
720 end_ts_sec: u32,
721 ) -> crate::errors::Result<crate::models::ApiData> {
722 use crate::codecs::analytics::resolve_analytics_range;
723 use crate::codecs::decode::api_data_from_proto;
724 use crate::proto::chain::analytics::v1::GetZippedAssetSupplyGroupRequest;
725 let req = GetZippedAssetSupplyGroupRequest {
726 group_id: group_id.to_owned(),
727 range: resolve_analytics_range(range_key)?.into(),
728 bucket: bucket.to_owned(),
729 start_ts_sec,
730 end_ts_sec,
731 ..Default::default()
732 };
733 let client = self.connect_client();
734 let resp = super::unary::await_public(client.get_zipped_asset_supply_group(req))
735 .await?
736 .into_owned();
737 Ok(api_data_from_proto(&resp))
738 }
739
740 pub async fn get_unified_asset_balances(
741 &self,
742 asset_id: u32,
743 range_key: &str,
744 bucket: &str,
745 start_ts_sec: u32,
746 end_ts_sec: u32,
747 ) -> crate::errors::Result<crate::models::ApiData> {
748 use crate::codecs::analytics::resolve_analytics_range;
749 use crate::codecs::decode::api_data_from_proto;
750 use crate::errors::Error;
751 use crate::proto::chain::analytics::v1::GetUnifiedAssetBalancesRequest;
752 if asset_id == 0 {
753 return Err(Error::validation("asset_id must be positive"));
754 }
755 let req = GetUnifiedAssetBalancesRequest {
756 asset_id,
757 range: resolve_analytics_range(range_key)?.into(),
758 bucket: bucket.to_owned(),
759 start_ts_sec,
760 end_ts_sec,
761 ..Default::default()
762 };
763 let client = self.connect_client();
764 let resp = super::unary::await_public(client.get_unified_asset_balances(req))
765 .await?
766 .into_owned();
767 Ok(api_data_from_proto(&resp))
768 }
769}
770
771impl LifecycleService {
772 pub async fn list_flows(
773 &self,
774 req: crate::proto::chain::lifecycle::v1::ListFlowsRequest,
775 ) -> crate::errors::Result<crate::models::LifecycleFlowsList> {
776 use crate::codecs::decode::flows_list_from_proto;
777 let client = self.connect_client();
778 let resp = {
779 use super::unary;
780 unary::await_auth(
781 &self.ctx.factory,
782 "/chain.lifecycle.v1.LifecycleReadService/ListFlows",
783 req,
784 |req, opts| client.list_flows_with_options(req, opts),
785 )
786 .await?
787 .into_owned()
788 };
789 Ok(flows_list_from_proto(&resp))
790 }
791
792 pub async fn get_flow(
793 &self,
794 flow_id: &str,
795 ) -> crate::errors::Result<crate::models::LifecycleFlowSummary> {
796 use crate::codecs::decode::flow_from_get_response;
797 use crate::errors::Error;
798 use crate::proto::chain::lifecycle::v1::GetFlowByIdRequest;
799 if flow_id.trim().is_empty() {
800 return Err(Error::validation("flow_id or intent_id is required"));
801 }
802 let req = GetFlowByIdRequest {
803 flow_id: flow_id.to_owned(),
804 ..Default::default()
805 };
806 let client = self.connect_client();
807 let resp = {
808 use super::unary;
809 unary::await_auth(
810 &self.ctx.factory,
811 "/chain.lifecycle.v1.LifecycleReadService/GetFlowById",
812 req,
813 |req, opts| client.get_flow_by_id_with_options(req, opts),
814 )
815 .await?
816 .into_owned()
817 };
818 flow_from_get_response(&resp)
819 }
820
821 pub async fn list_flows_by_tx(
822 &self,
823 mut req: crate::proto::chain::lifecycle::v1::ListFlowsByTxRequest,
824 ) -> crate::errors::Result<crate::models::LifecycleFlowsList> {
825 use crate::codecs::decode::flows_by_tx_list_from_proto;
826 if req.limit == 0 {
827 req.limit = 50;
828 }
829 let client = self.connect_client();
830 let resp = {
831 use super::unary;
832 unary::await_auth(
833 &self.ctx.factory,
834 "/chain.lifecycle.v1.LifecycleReadService/ListFlowsByTx",
835 req,
836 |req, opts| client.list_flows_by_tx_with_options(req, opts),
837 )
838 .await?
839 .into_owned()
840 };
841 Ok(flows_by_tx_list_from_proto(&resp))
842 }
843
844 pub async fn get_flow_by_tx(
849 &self,
850 mut req: crate::proto::chain::lifecycle::v1::ListFlowsByTxRequest,
851 ) -> crate::errors::Result<crate::models::LifecycleFlowsList> {
852 use crate::codecs::decode::flow_from_get_by_tx_response;
853 if req.limit == 0 {
854 req.limit = 50;
855 }
856 let client = self.connect_client();
857 let resp = {
858 use super::unary;
859 unary::await_auth(
860 &self.ctx.factory,
861 "/chain.lifecycle.v1.LifecycleReadService/ListFlowsByTx",
862 req,
863 |req, opts| client.list_flows_by_tx_with_options(req, opts),
864 )
865 .await?
866 .into_owned()
867 };
868 Ok(flow_from_get_by_tx_response(&resp))
869 }
870
871 pub async fn subscribe_open_flows(
876 &self,
877 account_id: Option<&str>,
878 ) -> crate::errors::Result<
879 crate::realtime::TypedSubscription<crate::models::LifecycleFlowSummary>,
880 > {
881 if let Some(account) = account_id.filter(|s| !s.trim().is_empty()) {
882 let channel = format!("private:chain:lifecycle:flows:{account}:proto");
883 self.ctx
884 .realtime
885 .subscribe_proto(&channel, crate::codecs::decode::flow_summary_from_bytes)
886 .await
887 } else {
888 self.ctx
889 .realtime
890 .subscribe_proto(
891 "public:chain:lifecycle:flows:proto",
892 crate::codecs::decode::flow_summary_from_bytes,
893 )
894 .await
895 }
896 }
897
898 pub async fn subscribe_flow_detail(
900 &self,
901 flow_id: &str,
902 ) -> crate::errors::Result<
903 crate::realtime::TypedSubscription<crate::models::LifecycleFlowSummary>,
904 > {
905 let channel = format!("public:chain:lifecycle:flow:{flow_id}:proto");
906 self.ctx
907 .realtime
908 .subscribe_proto(&channel, crate::codecs::decode::flow_detail_from_bytes)
909 .await
910 }
911}
912
913impl GuardSignerService {
914 pub async fn get_status(
915 &self,
916 req: crate::proto::chain::guard::v1::GetGuardSignerStatusRequest,
917 ) -> crate::errors::Result<Option<crate::models::GuardSignerStatus>> {
918 use crate::codecs::decode::status_from_proto;
919 let client = self.connect_client();
920 let resp = {
921 use super::unary;
922 unary::await_auth(
923 &self.ctx.factory,
924 "/chain.guard.v1.GuardSignerService/GetGuardSignerStatus",
925 req,
926 |req, opts| client.get_guard_signer_status_with_options(req, opts),
927 )
928 .await?
929 .into_owned()
930 };
931 Ok(status_from_proto(&resp))
932 }
933
934 pub async fn create_wallet(
935 &self,
936 req: crate::proto::chain::guard::v1::CreateGuardSignerWalletRequest,
937 ) -> crate::errors::Result<crate::models::CreateGuardSignerWalletResult> {
938 use crate::codecs::decode::create_wallet_from_proto;
939 let client = self.connect_client();
940 let resp = {
941 use super::unary;
942 unary::await_auth(
943 &self.ctx.factory,
944 "/chain.guard.v1.GuardSignerService/CreateGuardSignerWallet",
945 req,
946 |req, opts| client.create_guard_signer_wallet_with_options(req, opts),
947 )
948 .await?
949 .into_owned()
950 };
951 Ok(create_wallet_from_proto(&resp))
952 }
953
954 pub async fn sign_protected_action(
955 &self,
956 req: crate::proto::chain::guard::v1::SignProtectedActionRequest,
957 ) -> crate::errors::Result<Option<crate::models::GuardApproval>> {
958 use crate::codecs::decode::sign_protected_action_from_proto;
959 let client = self.connect_client();
960 let resp = {
961 use super::unary;
962 unary::await_auth(
963 &self.ctx.factory,
964 "/chain.guard.v1.GuardSignerService/SignProtectedAction",
965 req,
966 |req, opts| client.sign_protected_action_with_options(req, opts),
967 )
968 .await?
969 .into_owned()
970 };
971 Ok(sign_protected_action_from_proto(&resp))
972 }
973
974 pub async fn batch_sign_protected_actions(
975 &self,
976 req: crate::proto::chain::guard::v1::BatchSignProtectedActionsRequest,
977 ) -> crate::errors::Result<crate::models::BatchSignProtectedActionsResult> {
978 use crate::codecs::decode::batch_sign_from_proto;
979 let client = self.connect_client();
980 let resp = {
981 use super::unary;
982 unary::await_auth(
983 &self.ctx.factory,
984 "/chain.guard.v1.GuardSignerService/BatchSignProtectedActions",
985 req,
986 |req, opts| client.batch_sign_protected_actions_with_options(req, opts),
987 )
988 .await?
989 .into_owned()
990 };
991 Ok(batch_sign_from_proto(&resp))
992 }
993
994 pub async fn rotate_wallet(
995 &self,
996 req: crate::proto::chain::guard::v1::RotateGuardSignerWalletRequest,
997 ) -> crate::errors::Result<crate::models::RotateGuardSignerWalletResult> {
998 use crate::codecs::decode::rotate_wallet_from_proto;
999 let client = self.connect_client();
1000 let resp = {
1001 use super::unary;
1002 unary::await_auth(
1003 &self.ctx.factory,
1004 "/chain.guard.v1.GuardSignerService/RotateGuardSignerWallet",
1005 req,
1006 |req, opts| client.rotate_guard_signer_wallet_with_options(req, opts),
1007 )
1008 .await?
1009 .into_owned()
1010 };
1011 Ok(rotate_wallet_from_proto(&resp))
1012 }
1013
1014 pub async fn export_wallet(
1015 &self,
1016 req: crate::proto::chain::guard::v1::ExportGuardSignerWalletRequest,
1017 ) -> crate::errors::Result<crate::models::ExportGuardSignerWalletResult> {
1018 use crate::codecs::decode::export_wallet_from_proto;
1019 let client = self.connect_client();
1020 let resp = {
1021 use super::unary;
1022 unary::await_auth(
1023 &self.ctx.factory,
1024 "/chain.guard.v1.GuardSignerService/ExportGuardSignerWallet",
1025 req,
1026 |req, opts| client.export_guard_signer_wallet_with_options(req, opts),
1027 )
1028 .await?
1029 .into_owned()
1030 };
1031 Ok(export_wallet_from_proto(&resp))
1032 }
1033}
1034
1035impl SocialVerificationService {
1036 pub async fn start(
1037 &self,
1038 provider: &str,
1039 method: &str,
1040 handle: &str,
1041 ) -> crate::errors::Result<crate::models::ApiData> {
1042 use crate::codecs::decode::api_data_from_proto;
1043 use crate::proto::auth::v1::StartSocialVerificationRequest;
1044 let req = StartSocialVerificationRequest {
1045 provider: social_provider_enum(provider).into(),
1046 method: social_method_enum(method).into(),
1047 handle: handle.to_owned(),
1048 ..Default::default()
1049 };
1050 let client = self.connect_client();
1051 let resp = {
1052 use super::unary;
1053 unary::await_auth(
1054 &self.ctx.factory,
1055 "/auth.v1.SocialVerificationService/StartSocialVerification",
1056 req,
1057 |req, opts| client.start_social_verification_with_options(req, opts),
1058 )
1059 .await?
1060 .into_owned()
1061 };
1062 Ok(api_data_from_proto(&resp))
1063 }
1064
1065 pub async fn mark_ready(
1066 &self,
1067 provider: &str,
1068 ) -> crate::errors::Result<crate::models::ApiData> {
1069 use crate::codecs::decode::api_data_from_proto;
1070 use crate::proto::auth::v1::SocialVerificationReadyRequest;
1071 let req = SocialVerificationReadyRequest {
1072 provider: social_provider_enum(provider).into(),
1073 ..Default::default()
1074 };
1075 let client = self.connect_client();
1076 let resp = {
1077 use super::unary;
1078 unary::await_auth(
1079 &self.ctx.factory,
1080 "/auth.v1.SocialVerificationService/SocialVerificationReady",
1081 req,
1082 |req, opts| client.social_verification_ready_with_options(req, opts),
1083 )
1084 .await?
1085 .into_owned()
1086 };
1087 Ok(api_data_from_proto(&resp))
1088 }
1089
1090 pub async fn get(&self, provider: &str) -> crate::errors::Result<crate::models::ApiData> {
1091 use crate::codecs::decode::api_data_from_proto;
1092 use crate::proto::auth::v1::GetSocialVerificationRequest;
1093 let req = GetSocialVerificationRequest {
1094 provider: social_provider_enum(provider).into(),
1095 ..Default::default()
1096 };
1097 let client = self.connect_client();
1098 let resp = {
1099 use super::unary;
1100 unary::await_auth(
1101 &self.ctx.factory,
1102 "/auth.v1.SocialVerificationService/GetSocialVerification",
1103 req,
1104 |req, opts| client.get_social_verification_with_options(req, opts),
1105 )
1106 .await?
1107 .into_owned()
1108 };
1109 Ok(api_data_from_proto(&resp))
1110 }
1111}
1112
1113fn social_provider_enum(v: &str) -> crate::proto::auth::v1::SocialProvider {
1114 use crate::proto::auth::v1::SocialProvider;
1115 match v.trim().to_ascii_lowercase().as_str() {
1116 "twitter" => SocialProvider::TWITTER,
1117 "discord" => SocialProvider::DISCORD,
1118 _ => SocialProvider::PROVIDER_UNSPECIFIED,
1119 }
1120}
1121
1122fn social_method_enum(v: &str) -> crate::proto::auth::v1::SocialVerificationMethod {
1123 use crate::proto::auth::v1::SocialVerificationMethod;
1124 match v.trim().to_ascii_lowercase().as_str() {
1125 "profile" => SocialVerificationMethod::METHOD_PROFILE,
1126 "channel" => SocialVerificationMethod::METHOD_CHANNEL,
1127 "dm" => SocialVerificationMethod::METHOD_DM,
1128 _ => SocialVerificationMethod::METHOD_UNSPECIFIED,
1129 }
1130}
1131
1132impl LayoutService {
1133 pub async fn get_layouts(
1134 &self,
1135 req: crate::proto::layout::v1::GetLayoutsRequest,
1136 ) -> crate::errors::Result<crate::models::ApiData> {
1137 use crate::codecs::decode::api_data_from_proto;
1138 let client = self.connect_client();
1139 let resp = {
1140 use super::unary;
1141 unary::await_auth(
1142 &self.ctx.factory,
1143 "/layout.v1.LayoutService/GetLayouts",
1144 req,
1145 |req, opts| client.get_layouts_with_options(req, opts),
1146 )
1147 .await?
1148 .into_owned()
1149 };
1150 Ok(api_data_from_proto(&resp))
1151 }
1152
1153 pub async fn get_layout(
1154 &self,
1155 req: crate::proto::layout::v1::GetLayoutRequest,
1156 ) -> crate::errors::Result<crate::models::ApiData> {
1157 use crate::codecs::decode::api_data_from_proto;
1158 let client = self.connect_client();
1159 let resp = {
1160 use super::unary;
1161 unary::await_auth(
1162 &self.ctx.factory,
1163 "/layout.v1.LayoutService/GetLayout",
1164 req,
1165 |req, opts| client.get_layout_with_options(req, opts),
1166 )
1167 .await?
1168 .into_owned()
1169 };
1170 Ok(api_data_from_proto(&resp))
1171 }
1172
1173 pub async fn upsert_layout(
1174 &self,
1175 req: crate::proto::layout::v1::UpsertLayoutRequest,
1176 ) -> crate::errors::Result<crate::models::ApiData> {
1177 use crate::codecs::decode::api_data_from_proto;
1178 let client = self.connect_client();
1179 let resp = {
1180 use super::unary;
1181 unary::await_auth(
1182 &self.ctx.factory,
1183 "/layout.v1.LayoutService/UpsertLayout",
1184 req,
1185 |req, opts| client.upsert_layout_with_options(req, opts),
1186 )
1187 .await?
1188 .into_owned()
1189 };
1190 Ok(api_data_from_proto(&resp))
1191 }
1192
1193 pub async fn delete_layout(
1194 &self,
1195 req: crate::proto::layout::v1::DeleteLayoutRequest,
1196 ) -> crate::errors::Result<crate::models::ApiData> {
1197 use crate::codecs::decode::api_data_from_proto;
1198 let client = self.connect_client();
1199 let resp = {
1200 use super::unary;
1201 unary::await_auth(
1202 &self.ctx.factory,
1203 "/layout.v1.LayoutService/DeleteLayout",
1204 req,
1205 |req, opts| client.delete_layout_with_options(req, opts),
1206 )
1207 .await?
1208 .into_owned()
1209 };
1210 Ok(api_data_from_proto(&resp))
1211 }
1212
1213 pub async fn resolve_layout_share_token(
1214 &self,
1215 req: crate::proto::layout::v1::ResolveLayoutShareTokenRequest,
1216 ) -> crate::errors::Result<crate::models::ApiData> {
1217 use crate::codecs::decode::api_data_from_proto;
1218 let client = self.connect_client();
1219 let resp = {
1220 use super::unary;
1221 unary::await_auth(
1222 &self.ctx.factory,
1223 "/layout.v1.LayoutService/ResolveLayoutShareToken",
1224 req,
1225 |req, opts| client.resolve_layout_share_token_with_options(req, opts),
1226 )
1227 .await?
1228 .into_owned()
1229 };
1230 Ok(api_data_from_proto(&resp))
1231 }
1232
1233 pub async fn create_layout_share_link(
1234 &self,
1235 req: crate::proto::layout::v1::CreateLayoutShareLinkRequest,
1236 ) -> crate::errors::Result<crate::models::ApiData> {
1237 use crate::codecs::decode::api_data_from_proto;
1238 let client = self.connect_client();
1239 let resp = {
1240 use super::unary;
1241 unary::await_auth(
1242 &self.ctx.factory,
1243 "/layout.v1.LayoutService/CreateLayoutShareLink",
1244 req,
1245 |req, opts| client.create_layout_share_link_with_options(req, opts),
1246 )
1247 .await?
1248 .into_owned()
1249 };
1250 Ok(api_data_from_proto(&resp))
1251 }
1252
1253 pub async fn revoke_layout_share_link(
1254 &self,
1255 req: crate::proto::layout::v1::RevokeLayoutShareLinkRequest,
1256 ) -> crate::errors::Result<crate::models::ApiData> {
1257 use crate::codecs::decode::api_data_from_proto;
1258 let client = self.connect_client();
1259 let resp = {
1260 use super::unary;
1261 unary::await_auth(
1262 &self.ctx.factory,
1263 "/layout.v1.LayoutService/RevokeLayoutShareLink",
1264 req,
1265 |req, opts| client.revoke_layout_share_link_with_options(req, opts),
1266 )
1267 .await?
1268 .into_owned()
1269 };
1270 Ok(api_data_from_proto(&resp))
1271 }
1272
1273 pub async fn list_owner_published_layouts(
1274 &self,
1275 req: crate::proto::layout::v1::ListOwnerPublishedLayoutsRequest,
1276 ) -> crate::errors::Result<crate::models::ApiData> {
1277 use crate::codecs::decode::api_data_from_proto;
1278 let client = self.connect_client();
1279 let resp = {
1280 use super::unary;
1281 unary::await_auth(
1282 &self.ctx.factory,
1283 "/layout.v1.LayoutService/ListOwnerPublishedLayouts",
1284 req,
1285 |req, opts| client.list_owner_published_layouts_with_options(req, opts),
1286 )
1287 .await?
1288 .into_owned()
1289 };
1290 Ok(api_data_from_proto(&resp))
1291 }
1292
1293 pub async fn publish_layout(
1294 &self,
1295 req: crate::proto::layout::v1::PublishLayoutRequest,
1296 ) -> crate::errors::Result<crate::models::ApiData> {
1297 use crate::codecs::decode::api_data_from_proto;
1298 let client = self.connect_client();
1299 let resp = {
1300 use super::unary;
1301 unary::await_auth(
1302 &self.ctx.factory,
1303 "/layout.v1.LayoutService/PublishLayout",
1304 req,
1305 |req, opts| client.publish_layout_with_options(req, opts),
1306 )
1307 .await?
1308 .into_owned()
1309 };
1310 Ok(api_data_from_proto(&resp))
1311 }
1312
1313 pub async fn unpublish_layout(
1314 &self,
1315 req: crate::proto::layout::v1::UnpublishLayoutRequest,
1316 ) -> crate::errors::Result<crate::models::ApiData> {
1317 use crate::codecs::decode::api_data_from_proto;
1318 let client = self.connect_client();
1319 let resp = {
1320 use super::unary;
1321 unary::await_auth(
1322 &self.ctx.factory,
1323 "/layout.v1.LayoutService/UnpublishLayout",
1324 req,
1325 |req, opts| client.unpublish_layout_with_options(req, opts),
1326 )
1327 .await?
1328 .into_owned()
1329 };
1330 Ok(api_data_from_proto(&resp))
1331 }
1332
1333 pub async fn list_layout_template_versions(
1334 &self,
1335 req: crate::proto::layout::v1::ListLayoutTemplateVersionsRequest,
1336 ) -> crate::errors::Result<crate::models::ApiData> {
1337 use crate::codecs::decode::api_data_from_proto;
1338 let client = self.connect_client();
1339 let resp = {
1340 use super::unary;
1341 unary::await_auth(
1342 &self.ctx.factory,
1343 "/layout.v1.LayoutService/ListLayoutTemplateVersions",
1344 req,
1345 |req, opts| client.list_layout_template_versions_with_options(req, opts),
1346 )
1347 .await?
1348 .into_owned()
1349 };
1350 Ok(api_data_from_proto(&resp))
1351 }
1352
1353 pub async fn get_layout_template_version(
1354 &self,
1355 req: crate::proto::layout::v1::GetLayoutTemplateVersionRequest,
1356 ) -> crate::errors::Result<crate::models::ApiData> {
1357 use crate::codecs::decode::api_data_from_proto;
1358 let client = self.connect_client();
1359 let resp = {
1360 use super::unary;
1361 unary::await_auth(
1362 &self.ctx.factory,
1363 "/layout.v1.LayoutService/GetLayoutTemplateVersion",
1364 req,
1365 |req, opts| client.get_layout_template_version_with_options(req, opts),
1366 )
1367 .await?
1368 .into_owned()
1369 };
1370 Ok(api_data_from_proto(&resp))
1371 }
1372
1373 pub async fn set_layout_template_subscription(
1374 &self,
1375 req: crate::proto::layout::v1::SetLayoutTemplateSubscriptionRequest,
1376 ) -> crate::errors::Result<crate::models::ApiData> {
1377 use crate::codecs::decode::api_data_from_proto;
1378 let client = self.connect_client();
1379 let resp = {
1380 use super::unary;
1381 unary::await_auth(
1382 &self.ctx.factory,
1383 "/layout.v1.LayoutService/SetLayoutTemplateSubscription",
1384 req,
1385 |req, opts| client.set_layout_template_subscription_with_options(req, opts),
1386 )
1387 .await?
1388 .into_owned()
1389 };
1390 Ok(api_data_from_proto(&resp))
1391 }
1392
1393 pub async fn delete_layout_template_subscription(
1394 &self,
1395 req: crate::proto::layout::v1::DeleteLayoutTemplateSubscriptionRequest,
1396 ) -> crate::errors::Result<crate::models::ApiData> {
1397 use crate::codecs::decode::api_data_from_proto;
1398 let client = self.connect_client();
1399 let resp = {
1400 use super::unary;
1401 unary::await_auth(
1402 &self.ctx.factory,
1403 "/layout.v1.LayoutService/DeleteLayoutTemplateSubscription",
1404 req,
1405 |req, opts| client.delete_layout_template_subscription_with_options(req, opts),
1406 )
1407 .await?
1408 .into_owned()
1409 };
1410 Ok(api_data_from_proto(&resp))
1411 }
1412
1413 pub async fn list_my_layout_template_subscriptions(
1414 &self,
1415 req: crate::proto::layout::v1::ListMyLayoutTemplateSubscriptionsRequest,
1416 ) -> crate::errors::Result<crate::models::ApiData> {
1417 use crate::codecs::decode::api_data_from_proto;
1418 let client = self.connect_client();
1419 let resp = {
1420 use super::unary;
1421 unary::await_auth(
1422 &self.ctx.factory,
1423 "/layout.v1.LayoutService/ListMyLayoutTemplateSubscriptions",
1424 req,
1425 |req, opts| client.list_my_layout_template_subscriptions_with_options(req, opts),
1426 )
1427 .await?
1428 .into_owned()
1429 };
1430 Ok(api_data_from_proto(&resp))
1431 }
1432}
1433
1434impl PolychartService {
1435 pub async fn get_market_layers(
1436 &self,
1437 req: crate::proto::polychart::v1::GetMarketLayersRequest,
1438 ) -> crate::errors::Result<crate::models::ApiData> {
1439 use crate::codecs::decode::api_data_from_proto;
1440 let client = self.connect_client();
1441 let resp = {
1442 use super::unary;
1443 unary::await_auth(
1444 &self.ctx.factory,
1445 "/polychart.v1.PolychartService/GetMarketLayers",
1446 req,
1447 |req, opts| client.get_market_layers_with_options(req, opts),
1448 )
1449 .await?
1450 .into_owned()
1451 };
1452 Ok(api_data_from_proto(&resp))
1453 }
1454
1455 pub async fn list_inbox_market_layers(
1456 &self,
1457 req: crate::proto::polychart::v1::ListInboxMarketLayersRequest,
1458 ) -> crate::errors::Result<crate::models::ApiData> {
1459 use crate::codecs::decode::api_data_from_proto;
1460 let client = self.connect_client();
1461 let resp = {
1462 use super::unary;
1463 unary::await_auth(
1464 &self.ctx.factory,
1465 "/polychart.v1.PolychartService/ListInboxMarketLayers",
1466 req,
1467 |req, opts| client.list_inbox_market_layers_with_options(req, opts),
1468 )
1469 .await?
1470 .into_owned()
1471 };
1472 Ok(api_data_from_proto(&resp))
1473 }
1474
1475 pub async fn get_layer_snapshot(
1476 &self,
1477 req: crate::proto::polychart::v1::GetLayerSnapshotRequest,
1478 ) -> crate::errors::Result<crate::models::ApiData> {
1479 use crate::codecs::decode::api_data_from_proto;
1480 let client = self.connect_client();
1481 let resp = {
1482 use super::unary;
1483 unary::await_auth(
1484 &self.ctx.factory,
1485 "/polychart.v1.PolychartService/GetLayerSnapshot",
1486 req,
1487 |req, opts| client.get_layer_snapshot_with_options(req, opts),
1488 )
1489 .await?
1490 .into_owned()
1491 };
1492 Ok(api_data_from_proto(&resp))
1493 }
1494
1495 pub async fn get_layer_subscribe_tokens(
1496 &self,
1497 req: crate::proto::polychart::v1::GetLayerSubscribeTokensRequest,
1498 ) -> crate::errors::Result<crate::models::ApiData> {
1499 use crate::codecs::decode::api_data_from_proto;
1500 let client = self.connect_client();
1501 let resp = {
1502 use super::unary;
1503 unary::await_auth(
1504 &self.ctx.factory,
1505 "/polychart.v1.PolychartService/GetLayerSubscribeTokens",
1506 req,
1507 |req, opts| client.get_layer_subscribe_tokens_with_options(req, opts),
1508 )
1509 .await?
1510 .into_owned()
1511 };
1512 Ok(api_data_from_proto(&resp))
1513 }
1514
1515 pub async fn resolve_layer_share_token(
1516 &self,
1517 req: crate::proto::polychart::v1::ResolveLayerShareTokenRequest,
1518 ) -> crate::errors::Result<crate::models::ApiData> {
1519 use crate::codecs::decode::api_data_from_proto;
1520 let client = self.connect_client();
1521 let resp = {
1522 use super::unary;
1523 unary::await_auth(
1524 &self.ctx.factory,
1525 "/polychart.v1.PolychartService/ResolveLayerShareToken",
1526 req,
1527 |req, opts| client.resolve_layer_share_token_with_options(req, opts),
1528 )
1529 .await?
1530 .into_owned()
1531 };
1532 Ok(api_data_from_proto(&resp))
1533 }
1534
1535 pub async fn create_layer_share_link(
1536 &self,
1537 req: crate::proto::polychart::v1::CreateLayerShareLinkRequest,
1538 ) -> crate::errors::Result<crate::models::ApiData> {
1539 use crate::codecs::decode::api_data_from_proto;
1540 let client = self.connect_client();
1541 let resp = {
1542 use super::unary;
1543 unary::await_auth(
1544 &self.ctx.factory,
1545 "/polychart.v1.PolychartService/CreateLayerShareLink",
1546 req,
1547 |req, opts| client.create_layer_share_link_with_options(req, opts),
1548 )
1549 .await?
1550 .into_owned()
1551 };
1552 Ok(api_data_from_proto(&resp))
1553 }
1554
1555 pub async fn revoke_layer_share_link(
1556 &self,
1557 req: crate::proto::polychart::v1::RevokeLayerShareLinkRequest,
1558 ) -> crate::errors::Result<crate::models::ApiData> {
1559 use crate::codecs::decode::api_data_from_proto;
1560 let client = self.connect_client();
1561 let resp = {
1562 use super::unary;
1563 unary::await_auth(
1564 &self.ctx.factory,
1565 "/polychart.v1.PolychartService/RevokeLayerShareLink",
1566 req,
1567 |req, opts| client.revoke_layer_share_link_with_options(req, opts),
1568 )
1569 .await?
1570 .into_owned()
1571 };
1572 Ok(api_data_from_proto(&resp))
1573 }
1574
1575 pub async fn list_owner_published_layers(
1576 &self,
1577 req: crate::proto::polychart::v1::ListOwnerPublishedLayersRequest,
1578 ) -> crate::errors::Result<crate::models::ApiData> {
1579 use crate::codecs::decode::api_data_from_proto;
1580 let client = self.connect_client();
1581 let resp = {
1582 use super::unary;
1583 unary::await_auth(
1584 &self.ctx.factory,
1585 "/polychart.v1.PolychartService/ListOwnerPublishedLayers",
1586 req,
1587 |req, opts| client.list_owner_published_layers_with_options(req, opts),
1588 )
1589 .await?
1590 .into_owned()
1591 };
1592 Ok(api_data_from_proto(&resp))
1593 }
1594
1595 pub async fn publish_layer(
1596 &self,
1597 req: crate::proto::polychart::v1::PublishLayerRequest,
1598 ) -> crate::errors::Result<crate::models::ApiData> {
1599 use crate::codecs::decode::api_data_from_proto;
1600 let client = self.connect_client();
1601 let resp = {
1602 use super::unary;
1603 unary::await_auth(
1604 &self.ctx.factory,
1605 "/polychart.v1.PolychartService/PublishLayer",
1606 req,
1607 |req, opts| client.publish_layer_with_options(req, opts),
1608 )
1609 .await?
1610 .into_owned()
1611 };
1612 Ok(api_data_from_proto(&resp))
1613 }
1614
1615 pub async fn unpublish_layer(
1616 &self,
1617 req: crate::proto::polychart::v1::UnpublishLayerRequest,
1618 ) -> crate::errors::Result<crate::models::ApiData> {
1619 use crate::codecs::decode::api_data_from_proto;
1620 let client = self.connect_client();
1621 let resp = {
1622 use super::unary;
1623 unary::await_auth(
1624 &self.ctx.factory,
1625 "/polychart.v1.PolychartService/UnpublishLayer",
1626 req,
1627 |req, opts| client.unpublish_layer_with_options(req, opts),
1628 )
1629 .await?
1630 .into_owned()
1631 };
1632 Ok(api_data_from_proto(&resp))
1633 }
1634
1635 pub async fn upsert_layer(
1636 &self,
1637 req: crate::proto::polychart::v1::UpsertLayerRequest,
1638 ) -> crate::errors::Result<crate::models::ApiData> {
1639 use crate::codecs::decode::api_data_from_proto;
1640 let client = self.connect_client();
1641 let resp = {
1642 use super::unary;
1643 unary::await_auth(
1644 &self.ctx.factory,
1645 "/polychart.v1.PolychartService/UpsertLayer",
1646 req,
1647 |req, opts| client.upsert_layer_with_options(req, opts),
1648 )
1649 .await?
1650 .into_owned()
1651 };
1652 Ok(api_data_from_proto(&resp))
1653 }
1654
1655 pub async fn delete_layer(
1656 &self,
1657 req: crate::proto::polychart::v1::DeleteLayerRequest,
1658 ) -> crate::errors::Result<crate::models::ApiData> {
1659 use crate::codecs::decode::api_data_from_proto;
1660 let client = self.connect_client();
1661 let resp = {
1662 use super::unary;
1663 unary::await_auth(
1664 &self.ctx.factory,
1665 "/polychart.v1.PolychartService/DeleteLayer",
1666 req,
1667 |req, opts| client.delete_layer_with_options(req, opts),
1668 )
1669 .await?
1670 .into_owned()
1671 };
1672 Ok(api_data_from_proto(&resp))
1673 }
1674
1675 pub async fn upsert_drawing(
1676 &self,
1677 req: crate::proto::polychart::v1::UpsertDrawingRequest,
1678 ) -> crate::errors::Result<crate::models::ApiData> {
1679 use crate::codecs::decode::api_data_from_proto;
1680 let client = self.connect_client();
1681 let resp = {
1682 use super::unary;
1683 unary::await_auth(
1684 &self.ctx.factory,
1685 "/polychart.v1.PolychartService/UpsertDrawing",
1686 req,
1687 |req, opts| client.upsert_drawing_with_options(req, opts),
1688 )
1689 .await?
1690 .into_owned()
1691 };
1692 Ok(api_data_from_proto(&resp))
1693 }
1694
1695 pub async fn delete_drawing(
1696 &self,
1697 req: crate::proto::polychart::v1::DeleteDrawingRequest,
1698 ) -> crate::errors::Result<crate::models::ApiData> {
1699 use crate::codecs::decode::api_data_from_proto;
1700 let client = self.connect_client();
1701 let resp = {
1702 use super::unary;
1703 unary::await_auth(
1704 &self.ctx.factory,
1705 "/polychart.v1.PolychartService/DeleteDrawing",
1706 req,
1707 |req, opts| client.delete_drawing_with_options(req, opts),
1708 )
1709 .await?
1710 .into_owned()
1711 };
1712 Ok(api_data_from_proto(&resp))
1713 }
1714
1715 pub async fn set_layer_subscriptions(
1716 &self,
1717 req: crate::proto::polychart::v1::SetLayerSubscriptionsRequest,
1718 ) -> crate::errors::Result<crate::models::ApiData> {
1719 use crate::codecs::decode::api_data_from_proto;
1720 let client = self.connect_client();
1721 let resp = {
1722 use super::unary;
1723 unary::await_auth(
1724 &self.ctx.factory,
1725 "/polychart.v1.PolychartService/SetLayerSubscriptions",
1726 req,
1727 |req, opts| client.set_layer_subscriptions_with_options(req, opts),
1728 )
1729 .await?
1730 .into_owned()
1731 };
1732 Ok(api_data_from_proto(&resp))
1733 }
1734}
1735
1736impl WhiteboardService {
1737 pub async fn create_board(
1738 &self,
1739 req: crate::proto::collab::v1::CreateBoardRequest,
1740 ) -> crate::errors::Result<crate::models::ApiData> {
1741 use crate::codecs::decode::api_data_from_proto;
1742 let client = self.connect_client();
1743 let resp = {
1744 use super::unary;
1745 unary::await_auth(
1746 &self.ctx.factory,
1747 "/collab.v1.WhiteboardService/CreateBoard",
1748 req,
1749 |req, opts| client.create_board_with_options(req, opts),
1750 )
1751 .await?
1752 .into_owned()
1753 };
1754 Ok(api_data_from_proto(&resp))
1755 }
1756
1757 pub async fn get_board(
1758 &self,
1759 req: crate::proto::collab::v1::GetBoardRequest,
1760 ) -> crate::errors::Result<crate::models::ApiData> {
1761 use crate::codecs::decode::api_data_from_proto;
1762 let client = self.connect_client();
1763 let resp = {
1764 use super::unary;
1765 unary::await_auth(
1766 &self.ctx.factory,
1767 "/collab.v1.WhiteboardService/GetBoard",
1768 req,
1769 |req, opts| client.get_board_with_options(req, opts),
1770 )
1771 .await?
1772 .into_owned()
1773 };
1774 Ok(api_data_from_proto(&resp))
1775 }
1776
1777 pub async fn list_boards(
1778 &self,
1779 req: crate::proto::collab::v1::ListBoardsRequest,
1780 ) -> crate::errors::Result<crate::models::ApiData> {
1781 use crate::codecs::decode::api_data_from_proto;
1782 let client = self.connect_client();
1783 let resp = {
1784 use super::unary;
1785 unary::await_auth(
1786 &self.ctx.factory,
1787 "/collab.v1.WhiteboardService/ListBoards",
1788 req,
1789 |req, opts| client.list_boards_with_options(req, opts),
1790 )
1791 .await?
1792 .into_owned()
1793 };
1794 Ok(api_data_from_proto(&resp))
1795 }
1796
1797 pub async fn update_board(
1798 &self,
1799 req: crate::proto::collab::v1::UpdateBoardRequest,
1800 ) -> crate::errors::Result<crate::models::ApiData> {
1801 use crate::codecs::decode::api_data_from_proto;
1802 let client = self.connect_client();
1803 let resp = {
1804 use super::unary;
1805 unary::await_auth(
1806 &self.ctx.factory,
1807 "/collab.v1.WhiteboardService/UpdateBoard",
1808 req,
1809 |req, opts| client.update_board_with_options(req, opts),
1810 )
1811 .await?
1812 .into_owned()
1813 };
1814 Ok(api_data_from_proto(&resp))
1815 }
1816
1817 pub async fn update_board_acl(
1818 &self,
1819 req: crate::proto::collab::v1::UpdateBoardAclRequest,
1820 ) -> crate::errors::Result<crate::models::ApiData> {
1821 use crate::codecs::decode::api_data_from_proto;
1822 let client = self.connect_client();
1823 let resp = {
1824 use super::unary;
1825 unary::await_auth(
1826 &self.ctx.factory,
1827 "/collab.v1.WhiteboardService/UpdateBoardAcl",
1828 req,
1829 |req, opts| client.update_board_acl_with_options(req, opts),
1830 )
1831 .await?
1832 .into_owned()
1833 };
1834 Ok(api_data_from_proto(&resp))
1835 }
1836
1837 pub async fn archive_board(
1838 &self,
1839 req: crate::proto::collab::v1::ArchiveBoardRequest,
1840 ) -> crate::errors::Result<crate::models::ApiData> {
1841 use crate::codecs::decode::api_data_from_proto;
1842 let client = self.connect_client();
1843 let resp = {
1844 use super::unary;
1845 unary::await_auth(
1846 &self.ctx.factory,
1847 "/collab.v1.WhiteboardService/ArchiveBoard",
1848 req,
1849 |req, opts| client.archive_board_with_options(req, opts),
1850 )
1851 .await?
1852 .into_owned()
1853 };
1854 Ok(api_data_from_proto(&resp))
1855 }
1856
1857 pub async fn mint_join_token(
1858 &self,
1859 req: crate::proto::collab::v1::MintJoinTokenRequest,
1860 ) -> crate::errors::Result<crate::models::ApiData> {
1861 use crate::codecs::decode::api_data_from_proto;
1862 let client = self.connect_client();
1863 let resp = {
1864 use super::unary;
1865 unary::await_auth(
1866 &self.ctx.factory,
1867 "/collab.v1.WhiteboardService/MintJoinToken",
1868 req,
1869 |req, opts| client.mint_join_token_with_options(req, opts),
1870 )
1871 .await?
1872 .into_owned()
1873 };
1874 Ok(api_data_from_proto(&resp))
1875 }
1876}
1877
1878#[cfg(test)]
1879mod tests {
1880 use super::internal_transfer_amount_e18;
1881 use crate::models::CreateInternalTransferParams;
1882 use crate::types::{AssetAmount, QuantityDomain};
1883
1884 #[test]
1885 fn internal_transfer_amount_is_always_exact_e18() {
1886 let amount =
1887 AssetAmount::from_scaled(125, Some(2), QuantityDomain::LedgerE18, Some(7)).unwrap();
1888 let wire = internal_transfer_amount_e18(&amount, Some(2), 7).unwrap();
1889 assert_eq!(
1890 (u128::from(wire.hi) << 64) | u128::from(wire.lo),
1891 1_250_000_000_000_000_000
1892 );
1893
1894 let inexact =
1895 AssetAmount::from_scaled(126, Some(19), QuantityDomain::LedgerE18, Some(7)).unwrap();
1896 assert!(internal_transfer_amount_e18(&inexact, Some(19), 7).is_err());
1897 }
1898
1899 #[test]
1900 fn internal_transfer_rejects_missing_amount_scale_before_transport() {
1901 let amount = AssetAmount::from_scaled(1, None, QuantityDomain::LedgerE18, Some(7)).unwrap();
1902 let err = internal_transfer_amount_e18(&amount, None, 7)
1903 .expect_err("missing scale must not silently mean e18");
1904 assert!(err.to_string().contains("amount scale is required"));
1905 }
1906
1907 #[tokio::test]
1908 async fn internal_transfer_requires_destination_before_transport() {
1909 let client = crate::Client::new(crate::Config {
1910 hydrate_catalogs: false,
1911 ..Default::default()
1912 })
1913 .unwrap();
1914 let params = CreateInternalTransferParams {
1915 asset_id: 7,
1916 quantity: AssetAmount::from_scaled(100, Some(18), QuantityDomain::LedgerE18, Some(7))
1917 .unwrap(),
1918 idempotency_key: "missing-destination".into(),
1919 subaccount_id: None,
1920 destination_account_id: None,
1921 destination_subaccount_id: None,
1922 destination_smart_account_address: None,
1923 quantity_scale: Some(18),
1924 };
1925
1926 let err = client
1927 .internal_transfers
1928 .create(params.clone())
1929 .await
1930 .unwrap_err();
1931 assert!(err.to_string().contains("requires exactly one"));
1932
1933 let multiple = CreateInternalTransferParams {
1934 destination_account_id: Some("2".into()),
1935 destination_subaccount_id: Some("3".into()),
1936 idempotency_key: "multiple-destinations".into(),
1937 ..params.clone()
1938 };
1939 let err = client
1940 .internal_transfers
1941 .create(multiple)
1942 .await
1943 .unwrap_err();
1944 assert!(err.to_string().contains("requires exactly one"));
1945
1946 let empty_key = CreateInternalTransferParams {
1947 destination_account_id: Some("2".into()),
1948 idempotency_key: " ".into(),
1949 ..params.clone()
1950 };
1951 let err = client
1952 .internal_transfers
1953 .create(empty_key)
1954 .await
1955 .unwrap_err();
1956 assert!(err.to_string().contains("non-empty idempotency_key"));
1957
1958 let whitespace_destination = CreateInternalTransferParams {
1959 destination_smart_account_address: Some(" ".into()),
1960 ..params
1961 };
1962 let err = client
1963 .internal_transfers
1964 .create(whitespace_destination)
1965 .await
1966 .unwrap_err();
1967 assert!(err.to_string().contains("requires exactly one"));
1968 }
1969}