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 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 let client = self.connect_client();
827 let resp = {
828 use super::unary;
829 unary::await_auth(
830 &self.ctx.factory,
831 "/chain.lifecycle.v1.LifecycleReadService/ListFlowsByTx",
832 req,
833 |req, opts| client.list_flows_by_tx_with_options(req, opts),
834 )
835 .await?
836 .into_owned()
837 };
838 Ok(flows_by_tx_list_from_proto(&resp))
839 }
840
841 pub async fn get_flow_by_tx(
842 &self,
843 req: crate::proto::chain::lifecycle::v1::ListFlowsByTxRequest,
844 ) -> crate::errors::Result<crate::models::LifecycleFlowSummary> {
845 use crate::codecs::decode::flow_from_get_by_tx_response;
846 let client = self.connect_client();
847 let resp = {
848 use super::unary;
849 unary::await_auth(
850 &self.ctx.factory,
851 "/chain.lifecycle.v1.LifecycleReadService/ListFlowsByTx",
852 req,
853 |req, opts| client.list_flows_by_tx_with_options(req, opts),
854 )
855 .await?
856 .into_owned()
857 };
858 flow_from_get_by_tx_response(&resp)
859 }
860
861 pub async fn subscribe_open_flows(
866 &self,
867 account_id: Option<&str>,
868 ) -> crate::errors::Result<
869 crate::realtime::TypedSubscription<crate::models::LifecycleFlowSummary>,
870 > {
871 if let Some(account) = account_id.filter(|s| !s.trim().is_empty()) {
872 let channel = format!("private:chain:lifecycle:flows:{account}:proto");
873 self.ctx
874 .realtime
875 .subscribe_proto(&channel, crate::codecs::decode::flow_summary_from_bytes)
876 .await
877 } else {
878 self.ctx
879 .realtime
880 .subscribe_proto(
881 "public:chain:lifecycle:flows:proto",
882 crate::codecs::decode::flow_summary_from_bytes,
883 )
884 .await
885 }
886 }
887
888 pub async fn subscribe_flow_detail(
890 &self,
891 flow_id: &str,
892 ) -> crate::errors::Result<
893 crate::realtime::TypedSubscription<crate::models::LifecycleFlowSummary>,
894 > {
895 let channel = format!("public:chain:lifecycle:flow:{flow_id}:proto");
896 self.ctx
897 .realtime
898 .subscribe_proto(&channel, crate::codecs::decode::flow_detail_from_bytes)
899 .await
900 }
901}
902
903impl GuardSignerService {
904 pub async fn get_status(
905 &self,
906 req: crate::proto::chain::guard::v1::GetGuardSignerStatusRequest,
907 ) -> crate::errors::Result<Option<crate::models::GuardSignerStatus>> {
908 use crate::codecs::decode::status_from_proto;
909 let client = self.connect_client();
910 let resp = {
911 use super::unary;
912 unary::await_auth(
913 &self.ctx.factory,
914 "/chain.guard.v1.GuardSignerService/GetGuardSignerStatus",
915 req,
916 |req, opts| client.get_guard_signer_status_with_options(req, opts),
917 )
918 .await?
919 .into_owned()
920 };
921 Ok(status_from_proto(&resp))
922 }
923
924 pub async fn create_wallet(
925 &self,
926 req: crate::proto::chain::guard::v1::CreateGuardSignerWalletRequest,
927 ) -> crate::errors::Result<crate::models::CreateGuardSignerWalletResult> {
928 use crate::codecs::decode::create_wallet_from_proto;
929 let client = self.connect_client();
930 let resp = {
931 use super::unary;
932 unary::await_auth(
933 &self.ctx.factory,
934 "/chain.guard.v1.GuardSignerService/CreateGuardSignerWallet",
935 req,
936 |req, opts| client.create_guard_signer_wallet_with_options(req, opts),
937 )
938 .await?
939 .into_owned()
940 };
941 Ok(create_wallet_from_proto(&resp))
942 }
943
944 pub async fn sign_protected_action(
945 &self,
946 req: crate::proto::chain::guard::v1::SignProtectedActionRequest,
947 ) -> crate::errors::Result<Option<crate::models::GuardApproval>> {
948 use crate::codecs::decode::sign_protected_action_from_proto;
949 let client = self.connect_client();
950 let resp = {
951 use super::unary;
952 unary::await_auth(
953 &self.ctx.factory,
954 "/chain.guard.v1.GuardSignerService/SignProtectedAction",
955 req,
956 |req, opts| client.sign_protected_action_with_options(req, opts),
957 )
958 .await?
959 .into_owned()
960 };
961 Ok(sign_protected_action_from_proto(&resp))
962 }
963
964 pub async fn batch_sign_protected_actions(
965 &self,
966 req: crate::proto::chain::guard::v1::BatchSignProtectedActionsRequest,
967 ) -> crate::errors::Result<crate::models::BatchSignProtectedActionsResult> {
968 use crate::codecs::decode::batch_sign_from_proto;
969 let client = self.connect_client();
970 let resp = {
971 use super::unary;
972 unary::await_auth(
973 &self.ctx.factory,
974 "/chain.guard.v1.GuardSignerService/BatchSignProtectedActions",
975 req,
976 |req, opts| client.batch_sign_protected_actions_with_options(req, opts),
977 )
978 .await?
979 .into_owned()
980 };
981 Ok(batch_sign_from_proto(&resp))
982 }
983
984 pub async fn rotate_wallet(
985 &self,
986 req: crate::proto::chain::guard::v1::RotateGuardSignerWalletRequest,
987 ) -> crate::errors::Result<crate::models::RotateGuardSignerWalletResult> {
988 use crate::codecs::decode::rotate_wallet_from_proto;
989 let client = self.connect_client();
990 let resp = {
991 use super::unary;
992 unary::await_auth(
993 &self.ctx.factory,
994 "/chain.guard.v1.GuardSignerService/RotateGuardSignerWallet",
995 req,
996 |req, opts| client.rotate_guard_signer_wallet_with_options(req, opts),
997 )
998 .await?
999 .into_owned()
1000 };
1001 Ok(rotate_wallet_from_proto(&resp))
1002 }
1003
1004 pub async fn export_wallet(
1005 &self,
1006 req: crate::proto::chain::guard::v1::ExportGuardSignerWalletRequest,
1007 ) -> crate::errors::Result<crate::models::ExportGuardSignerWalletResult> {
1008 use crate::codecs::decode::export_wallet_from_proto;
1009 let client = self.connect_client();
1010 let resp = {
1011 use super::unary;
1012 unary::await_auth(
1013 &self.ctx.factory,
1014 "/chain.guard.v1.GuardSignerService/ExportGuardSignerWallet",
1015 req,
1016 |req, opts| client.export_guard_signer_wallet_with_options(req, opts),
1017 )
1018 .await?
1019 .into_owned()
1020 };
1021 Ok(export_wallet_from_proto(&resp))
1022 }
1023}
1024
1025impl SocialVerificationService {
1026 pub async fn start(
1027 &self,
1028 provider: &str,
1029 method: &str,
1030 handle: &str,
1031 ) -> crate::errors::Result<crate::models::ApiData> {
1032 use crate::codecs::decode::api_data_from_proto;
1033 use crate::proto::auth::v1::StartSocialVerificationRequest;
1034 let req = StartSocialVerificationRequest {
1035 provider: social_provider_enum(provider).into(),
1036 method: social_method_enum(method).into(),
1037 handle: handle.to_owned(),
1038 ..Default::default()
1039 };
1040 let client = self.connect_client();
1041 let resp = {
1042 use super::unary;
1043 unary::await_auth(
1044 &self.ctx.factory,
1045 "/auth.v1.SocialVerificationService/StartSocialVerification",
1046 req,
1047 |req, opts| client.start_social_verification_with_options(req, opts),
1048 )
1049 .await?
1050 .into_owned()
1051 };
1052 Ok(api_data_from_proto(&resp))
1053 }
1054
1055 pub async fn mark_ready(
1056 &self,
1057 provider: &str,
1058 ) -> crate::errors::Result<crate::models::ApiData> {
1059 use crate::codecs::decode::api_data_from_proto;
1060 use crate::proto::auth::v1::SocialVerificationReadyRequest;
1061 let req = SocialVerificationReadyRequest {
1062 provider: social_provider_enum(provider).into(),
1063 ..Default::default()
1064 };
1065 let client = self.connect_client();
1066 let resp = {
1067 use super::unary;
1068 unary::await_auth(
1069 &self.ctx.factory,
1070 "/auth.v1.SocialVerificationService/SocialVerificationReady",
1071 req,
1072 |req, opts| client.social_verification_ready_with_options(req, opts),
1073 )
1074 .await?
1075 .into_owned()
1076 };
1077 Ok(api_data_from_proto(&resp))
1078 }
1079
1080 pub async fn get(&self, provider: &str) -> crate::errors::Result<crate::models::ApiData> {
1081 use crate::codecs::decode::api_data_from_proto;
1082 use crate::proto::auth::v1::GetSocialVerificationRequest;
1083 let req = GetSocialVerificationRequest {
1084 provider: social_provider_enum(provider).into(),
1085 ..Default::default()
1086 };
1087 let client = self.connect_client();
1088 let resp = {
1089 use super::unary;
1090 unary::await_auth(
1091 &self.ctx.factory,
1092 "/auth.v1.SocialVerificationService/GetSocialVerification",
1093 req,
1094 |req, opts| client.get_social_verification_with_options(req, opts),
1095 )
1096 .await?
1097 .into_owned()
1098 };
1099 Ok(api_data_from_proto(&resp))
1100 }
1101}
1102
1103fn social_provider_enum(v: &str) -> crate::proto::auth::v1::SocialProvider {
1104 use crate::proto::auth::v1::SocialProvider;
1105 match v.trim().to_ascii_lowercase().as_str() {
1106 "twitter" => SocialProvider::TWITTER,
1107 "discord" => SocialProvider::DISCORD,
1108 _ => SocialProvider::PROVIDER_UNSPECIFIED,
1109 }
1110}
1111
1112fn social_method_enum(v: &str) -> crate::proto::auth::v1::SocialVerificationMethod {
1113 use crate::proto::auth::v1::SocialVerificationMethod;
1114 match v.trim().to_ascii_lowercase().as_str() {
1115 "profile" => SocialVerificationMethod::METHOD_PROFILE,
1116 "channel" => SocialVerificationMethod::METHOD_CHANNEL,
1117 "dm" => SocialVerificationMethod::METHOD_DM,
1118 _ => SocialVerificationMethod::METHOD_UNSPECIFIED,
1119 }
1120}
1121
1122impl LayoutService {
1123 pub async fn get_layouts(
1124 &self,
1125 req: crate::proto::layout::v1::GetLayoutsRequest,
1126 ) -> crate::errors::Result<crate::models::ApiData> {
1127 use crate::codecs::decode::api_data_from_proto;
1128 let client = self.connect_client();
1129 let resp = {
1130 use super::unary;
1131 unary::await_auth(
1132 &self.ctx.factory,
1133 "/layout.v1.LayoutService/GetLayouts",
1134 req,
1135 |req, opts| client.get_layouts_with_options(req, opts),
1136 )
1137 .await?
1138 .into_owned()
1139 };
1140 Ok(api_data_from_proto(&resp))
1141 }
1142
1143 pub async fn get_layout(
1144 &self,
1145 req: crate::proto::layout::v1::GetLayoutRequest,
1146 ) -> crate::errors::Result<crate::models::ApiData> {
1147 use crate::codecs::decode::api_data_from_proto;
1148 let client = self.connect_client();
1149 let resp = {
1150 use super::unary;
1151 unary::await_auth(
1152 &self.ctx.factory,
1153 "/layout.v1.LayoutService/GetLayout",
1154 req,
1155 |req, opts| client.get_layout_with_options(req, opts),
1156 )
1157 .await?
1158 .into_owned()
1159 };
1160 Ok(api_data_from_proto(&resp))
1161 }
1162
1163 pub async fn upsert_layout(
1164 &self,
1165 req: crate::proto::layout::v1::UpsertLayoutRequest,
1166 ) -> crate::errors::Result<crate::models::ApiData> {
1167 use crate::codecs::decode::api_data_from_proto;
1168 let client = self.connect_client();
1169 let resp = {
1170 use super::unary;
1171 unary::await_auth(
1172 &self.ctx.factory,
1173 "/layout.v1.LayoutService/UpsertLayout",
1174 req,
1175 |req, opts| client.upsert_layout_with_options(req, opts),
1176 )
1177 .await?
1178 .into_owned()
1179 };
1180 Ok(api_data_from_proto(&resp))
1181 }
1182
1183 pub async fn delete_layout(
1184 &self,
1185 req: crate::proto::layout::v1::DeleteLayoutRequest,
1186 ) -> crate::errors::Result<crate::models::ApiData> {
1187 use crate::codecs::decode::api_data_from_proto;
1188 let client = self.connect_client();
1189 let resp = {
1190 use super::unary;
1191 unary::await_auth(
1192 &self.ctx.factory,
1193 "/layout.v1.LayoutService/DeleteLayout",
1194 req,
1195 |req, opts| client.delete_layout_with_options(req, opts),
1196 )
1197 .await?
1198 .into_owned()
1199 };
1200 Ok(api_data_from_proto(&resp))
1201 }
1202
1203 pub async fn resolve_layout_share_token(
1204 &self,
1205 req: crate::proto::layout::v1::ResolveLayoutShareTokenRequest,
1206 ) -> crate::errors::Result<crate::models::ApiData> {
1207 use crate::codecs::decode::api_data_from_proto;
1208 let client = self.connect_client();
1209 let resp = {
1210 use super::unary;
1211 unary::await_auth(
1212 &self.ctx.factory,
1213 "/layout.v1.LayoutService/ResolveLayoutShareToken",
1214 req,
1215 |req, opts| client.resolve_layout_share_token_with_options(req, opts),
1216 )
1217 .await?
1218 .into_owned()
1219 };
1220 Ok(api_data_from_proto(&resp))
1221 }
1222
1223 pub async fn create_layout_share_link(
1224 &self,
1225 req: crate::proto::layout::v1::CreateLayoutShareLinkRequest,
1226 ) -> crate::errors::Result<crate::models::ApiData> {
1227 use crate::codecs::decode::api_data_from_proto;
1228 let client = self.connect_client();
1229 let resp = {
1230 use super::unary;
1231 unary::await_auth(
1232 &self.ctx.factory,
1233 "/layout.v1.LayoutService/CreateLayoutShareLink",
1234 req,
1235 |req, opts| client.create_layout_share_link_with_options(req, opts),
1236 )
1237 .await?
1238 .into_owned()
1239 };
1240 Ok(api_data_from_proto(&resp))
1241 }
1242
1243 pub async fn revoke_layout_share_link(
1244 &self,
1245 req: crate::proto::layout::v1::RevokeLayoutShareLinkRequest,
1246 ) -> crate::errors::Result<crate::models::ApiData> {
1247 use crate::codecs::decode::api_data_from_proto;
1248 let client = self.connect_client();
1249 let resp = {
1250 use super::unary;
1251 unary::await_auth(
1252 &self.ctx.factory,
1253 "/layout.v1.LayoutService/RevokeLayoutShareLink",
1254 req,
1255 |req, opts| client.revoke_layout_share_link_with_options(req, opts),
1256 )
1257 .await?
1258 .into_owned()
1259 };
1260 Ok(api_data_from_proto(&resp))
1261 }
1262
1263 pub async fn list_owner_published_layouts(
1264 &self,
1265 req: crate::proto::layout::v1::ListOwnerPublishedLayoutsRequest,
1266 ) -> crate::errors::Result<crate::models::ApiData> {
1267 use crate::codecs::decode::api_data_from_proto;
1268 let client = self.connect_client();
1269 let resp = {
1270 use super::unary;
1271 unary::await_auth(
1272 &self.ctx.factory,
1273 "/layout.v1.LayoutService/ListOwnerPublishedLayouts",
1274 req,
1275 |req, opts| client.list_owner_published_layouts_with_options(req, opts),
1276 )
1277 .await?
1278 .into_owned()
1279 };
1280 Ok(api_data_from_proto(&resp))
1281 }
1282
1283 pub async fn publish_layout(
1284 &self,
1285 req: crate::proto::layout::v1::PublishLayoutRequest,
1286 ) -> crate::errors::Result<crate::models::ApiData> {
1287 use crate::codecs::decode::api_data_from_proto;
1288 let client = self.connect_client();
1289 let resp = {
1290 use super::unary;
1291 unary::await_auth(
1292 &self.ctx.factory,
1293 "/layout.v1.LayoutService/PublishLayout",
1294 req,
1295 |req, opts| client.publish_layout_with_options(req, opts),
1296 )
1297 .await?
1298 .into_owned()
1299 };
1300 Ok(api_data_from_proto(&resp))
1301 }
1302
1303 pub async fn unpublish_layout(
1304 &self,
1305 req: crate::proto::layout::v1::UnpublishLayoutRequest,
1306 ) -> crate::errors::Result<crate::models::ApiData> {
1307 use crate::codecs::decode::api_data_from_proto;
1308 let client = self.connect_client();
1309 let resp = {
1310 use super::unary;
1311 unary::await_auth(
1312 &self.ctx.factory,
1313 "/layout.v1.LayoutService/UnpublishLayout",
1314 req,
1315 |req, opts| client.unpublish_layout_with_options(req, opts),
1316 )
1317 .await?
1318 .into_owned()
1319 };
1320 Ok(api_data_from_proto(&resp))
1321 }
1322
1323 pub async fn list_layout_template_versions(
1324 &self,
1325 req: crate::proto::layout::v1::ListLayoutTemplateVersionsRequest,
1326 ) -> crate::errors::Result<crate::models::ApiData> {
1327 use crate::codecs::decode::api_data_from_proto;
1328 let client = self.connect_client();
1329 let resp = {
1330 use super::unary;
1331 unary::await_auth(
1332 &self.ctx.factory,
1333 "/layout.v1.LayoutService/ListLayoutTemplateVersions",
1334 req,
1335 |req, opts| client.list_layout_template_versions_with_options(req, opts),
1336 )
1337 .await?
1338 .into_owned()
1339 };
1340 Ok(api_data_from_proto(&resp))
1341 }
1342
1343 pub async fn get_layout_template_version(
1344 &self,
1345 req: crate::proto::layout::v1::GetLayoutTemplateVersionRequest,
1346 ) -> crate::errors::Result<crate::models::ApiData> {
1347 use crate::codecs::decode::api_data_from_proto;
1348 let client = self.connect_client();
1349 let resp = {
1350 use super::unary;
1351 unary::await_auth(
1352 &self.ctx.factory,
1353 "/layout.v1.LayoutService/GetLayoutTemplateVersion",
1354 req,
1355 |req, opts| client.get_layout_template_version_with_options(req, opts),
1356 )
1357 .await?
1358 .into_owned()
1359 };
1360 Ok(api_data_from_proto(&resp))
1361 }
1362
1363 pub async fn set_layout_template_subscription(
1364 &self,
1365 req: crate::proto::layout::v1::SetLayoutTemplateSubscriptionRequest,
1366 ) -> crate::errors::Result<crate::models::ApiData> {
1367 use crate::codecs::decode::api_data_from_proto;
1368 let client = self.connect_client();
1369 let resp = {
1370 use super::unary;
1371 unary::await_auth(
1372 &self.ctx.factory,
1373 "/layout.v1.LayoutService/SetLayoutTemplateSubscription",
1374 req,
1375 |req, opts| client.set_layout_template_subscription_with_options(req, opts),
1376 )
1377 .await?
1378 .into_owned()
1379 };
1380 Ok(api_data_from_proto(&resp))
1381 }
1382
1383 pub async fn delete_layout_template_subscription(
1384 &self,
1385 req: crate::proto::layout::v1::DeleteLayoutTemplateSubscriptionRequest,
1386 ) -> crate::errors::Result<crate::models::ApiData> {
1387 use crate::codecs::decode::api_data_from_proto;
1388 let client = self.connect_client();
1389 let resp = {
1390 use super::unary;
1391 unary::await_auth(
1392 &self.ctx.factory,
1393 "/layout.v1.LayoutService/DeleteLayoutTemplateSubscription",
1394 req,
1395 |req, opts| client.delete_layout_template_subscription_with_options(req, opts),
1396 )
1397 .await?
1398 .into_owned()
1399 };
1400 Ok(api_data_from_proto(&resp))
1401 }
1402
1403 pub async fn list_my_layout_template_subscriptions(
1404 &self,
1405 req: crate::proto::layout::v1::ListMyLayoutTemplateSubscriptionsRequest,
1406 ) -> crate::errors::Result<crate::models::ApiData> {
1407 use crate::codecs::decode::api_data_from_proto;
1408 let client = self.connect_client();
1409 let resp = {
1410 use super::unary;
1411 unary::await_auth(
1412 &self.ctx.factory,
1413 "/layout.v1.LayoutService/ListMyLayoutTemplateSubscriptions",
1414 req,
1415 |req, opts| client.list_my_layout_template_subscriptions_with_options(req, opts),
1416 )
1417 .await?
1418 .into_owned()
1419 };
1420 Ok(api_data_from_proto(&resp))
1421 }
1422}
1423
1424impl PolychartService {
1425 pub async fn get_market_layers(
1426 &self,
1427 req: crate::proto::polychart::v1::GetMarketLayersRequest,
1428 ) -> crate::errors::Result<crate::models::ApiData> {
1429 use crate::codecs::decode::api_data_from_proto;
1430 let client = self.connect_client();
1431 let resp = {
1432 use super::unary;
1433 unary::await_auth(
1434 &self.ctx.factory,
1435 "/polychart.v1.PolychartService/GetMarketLayers",
1436 req,
1437 |req, opts| client.get_market_layers_with_options(req, opts),
1438 )
1439 .await?
1440 .into_owned()
1441 };
1442 Ok(api_data_from_proto(&resp))
1443 }
1444
1445 pub async fn list_inbox_market_layers(
1446 &self,
1447 req: crate::proto::polychart::v1::ListInboxMarketLayersRequest,
1448 ) -> crate::errors::Result<crate::models::ApiData> {
1449 use crate::codecs::decode::api_data_from_proto;
1450 let client = self.connect_client();
1451 let resp = {
1452 use super::unary;
1453 unary::await_auth(
1454 &self.ctx.factory,
1455 "/polychart.v1.PolychartService/ListInboxMarketLayers",
1456 req,
1457 |req, opts| client.list_inbox_market_layers_with_options(req, opts),
1458 )
1459 .await?
1460 .into_owned()
1461 };
1462 Ok(api_data_from_proto(&resp))
1463 }
1464
1465 pub async fn get_layer_snapshot(
1466 &self,
1467 req: crate::proto::polychart::v1::GetLayerSnapshotRequest,
1468 ) -> crate::errors::Result<crate::models::ApiData> {
1469 use crate::codecs::decode::api_data_from_proto;
1470 let client = self.connect_client();
1471 let resp = {
1472 use super::unary;
1473 unary::await_auth(
1474 &self.ctx.factory,
1475 "/polychart.v1.PolychartService/GetLayerSnapshot",
1476 req,
1477 |req, opts| client.get_layer_snapshot_with_options(req, opts),
1478 )
1479 .await?
1480 .into_owned()
1481 };
1482 Ok(api_data_from_proto(&resp))
1483 }
1484
1485 pub async fn get_layer_subscribe_tokens(
1486 &self,
1487 req: crate::proto::polychart::v1::GetLayerSubscribeTokensRequest,
1488 ) -> crate::errors::Result<crate::models::ApiData> {
1489 use crate::codecs::decode::api_data_from_proto;
1490 let client = self.connect_client();
1491 let resp = {
1492 use super::unary;
1493 unary::await_auth(
1494 &self.ctx.factory,
1495 "/polychart.v1.PolychartService/GetLayerSubscribeTokens",
1496 req,
1497 |req, opts| client.get_layer_subscribe_tokens_with_options(req, opts),
1498 )
1499 .await?
1500 .into_owned()
1501 };
1502 Ok(api_data_from_proto(&resp))
1503 }
1504
1505 pub async fn resolve_layer_share_token(
1506 &self,
1507 req: crate::proto::polychart::v1::ResolveLayerShareTokenRequest,
1508 ) -> crate::errors::Result<crate::models::ApiData> {
1509 use crate::codecs::decode::api_data_from_proto;
1510 let client = self.connect_client();
1511 let resp = {
1512 use super::unary;
1513 unary::await_auth(
1514 &self.ctx.factory,
1515 "/polychart.v1.PolychartService/ResolveLayerShareToken",
1516 req,
1517 |req, opts| client.resolve_layer_share_token_with_options(req, opts),
1518 )
1519 .await?
1520 .into_owned()
1521 };
1522 Ok(api_data_from_proto(&resp))
1523 }
1524
1525 pub async fn create_layer_share_link(
1526 &self,
1527 req: crate::proto::polychart::v1::CreateLayerShareLinkRequest,
1528 ) -> crate::errors::Result<crate::models::ApiData> {
1529 use crate::codecs::decode::api_data_from_proto;
1530 let client = self.connect_client();
1531 let resp = {
1532 use super::unary;
1533 unary::await_auth(
1534 &self.ctx.factory,
1535 "/polychart.v1.PolychartService/CreateLayerShareLink",
1536 req,
1537 |req, opts| client.create_layer_share_link_with_options(req, opts),
1538 )
1539 .await?
1540 .into_owned()
1541 };
1542 Ok(api_data_from_proto(&resp))
1543 }
1544
1545 pub async fn revoke_layer_share_link(
1546 &self,
1547 req: crate::proto::polychart::v1::RevokeLayerShareLinkRequest,
1548 ) -> crate::errors::Result<crate::models::ApiData> {
1549 use crate::codecs::decode::api_data_from_proto;
1550 let client = self.connect_client();
1551 let resp = {
1552 use super::unary;
1553 unary::await_auth(
1554 &self.ctx.factory,
1555 "/polychart.v1.PolychartService/RevokeLayerShareLink",
1556 req,
1557 |req, opts| client.revoke_layer_share_link_with_options(req, opts),
1558 )
1559 .await?
1560 .into_owned()
1561 };
1562 Ok(api_data_from_proto(&resp))
1563 }
1564
1565 pub async fn list_owner_published_layers(
1566 &self,
1567 req: crate::proto::polychart::v1::ListOwnerPublishedLayersRequest,
1568 ) -> crate::errors::Result<crate::models::ApiData> {
1569 use crate::codecs::decode::api_data_from_proto;
1570 let client = self.connect_client();
1571 let resp = {
1572 use super::unary;
1573 unary::await_auth(
1574 &self.ctx.factory,
1575 "/polychart.v1.PolychartService/ListOwnerPublishedLayers",
1576 req,
1577 |req, opts| client.list_owner_published_layers_with_options(req, opts),
1578 )
1579 .await?
1580 .into_owned()
1581 };
1582 Ok(api_data_from_proto(&resp))
1583 }
1584
1585 pub async fn publish_layer(
1586 &self,
1587 req: crate::proto::polychart::v1::PublishLayerRequest,
1588 ) -> crate::errors::Result<crate::models::ApiData> {
1589 use crate::codecs::decode::api_data_from_proto;
1590 let client = self.connect_client();
1591 let resp = {
1592 use super::unary;
1593 unary::await_auth(
1594 &self.ctx.factory,
1595 "/polychart.v1.PolychartService/PublishLayer",
1596 req,
1597 |req, opts| client.publish_layer_with_options(req, opts),
1598 )
1599 .await?
1600 .into_owned()
1601 };
1602 Ok(api_data_from_proto(&resp))
1603 }
1604
1605 pub async fn unpublish_layer(
1606 &self,
1607 req: crate::proto::polychart::v1::UnpublishLayerRequest,
1608 ) -> crate::errors::Result<crate::models::ApiData> {
1609 use crate::codecs::decode::api_data_from_proto;
1610 let client = self.connect_client();
1611 let resp = {
1612 use super::unary;
1613 unary::await_auth(
1614 &self.ctx.factory,
1615 "/polychart.v1.PolychartService/UnpublishLayer",
1616 req,
1617 |req, opts| client.unpublish_layer_with_options(req, opts),
1618 )
1619 .await?
1620 .into_owned()
1621 };
1622 Ok(api_data_from_proto(&resp))
1623 }
1624
1625 pub async fn upsert_layer(
1626 &self,
1627 req: crate::proto::polychart::v1::UpsertLayerRequest,
1628 ) -> crate::errors::Result<crate::models::ApiData> {
1629 use crate::codecs::decode::api_data_from_proto;
1630 let client = self.connect_client();
1631 let resp = {
1632 use super::unary;
1633 unary::await_auth(
1634 &self.ctx.factory,
1635 "/polychart.v1.PolychartService/UpsertLayer",
1636 req,
1637 |req, opts| client.upsert_layer_with_options(req, opts),
1638 )
1639 .await?
1640 .into_owned()
1641 };
1642 Ok(api_data_from_proto(&resp))
1643 }
1644
1645 pub async fn delete_layer(
1646 &self,
1647 req: crate::proto::polychart::v1::DeleteLayerRequest,
1648 ) -> crate::errors::Result<crate::models::ApiData> {
1649 use crate::codecs::decode::api_data_from_proto;
1650 let client = self.connect_client();
1651 let resp = {
1652 use super::unary;
1653 unary::await_auth(
1654 &self.ctx.factory,
1655 "/polychart.v1.PolychartService/DeleteLayer",
1656 req,
1657 |req, opts| client.delete_layer_with_options(req, opts),
1658 )
1659 .await?
1660 .into_owned()
1661 };
1662 Ok(api_data_from_proto(&resp))
1663 }
1664
1665 pub async fn upsert_drawing(
1666 &self,
1667 req: crate::proto::polychart::v1::UpsertDrawingRequest,
1668 ) -> crate::errors::Result<crate::models::ApiData> {
1669 use crate::codecs::decode::api_data_from_proto;
1670 let client = self.connect_client();
1671 let resp = {
1672 use super::unary;
1673 unary::await_auth(
1674 &self.ctx.factory,
1675 "/polychart.v1.PolychartService/UpsertDrawing",
1676 req,
1677 |req, opts| client.upsert_drawing_with_options(req, opts),
1678 )
1679 .await?
1680 .into_owned()
1681 };
1682 Ok(api_data_from_proto(&resp))
1683 }
1684
1685 pub async fn delete_drawing(
1686 &self,
1687 req: crate::proto::polychart::v1::DeleteDrawingRequest,
1688 ) -> crate::errors::Result<crate::models::ApiData> {
1689 use crate::codecs::decode::api_data_from_proto;
1690 let client = self.connect_client();
1691 let resp = {
1692 use super::unary;
1693 unary::await_auth(
1694 &self.ctx.factory,
1695 "/polychart.v1.PolychartService/DeleteDrawing",
1696 req,
1697 |req, opts| client.delete_drawing_with_options(req, opts),
1698 )
1699 .await?
1700 .into_owned()
1701 };
1702 Ok(api_data_from_proto(&resp))
1703 }
1704
1705 pub async fn set_layer_subscriptions(
1706 &self,
1707 req: crate::proto::polychart::v1::SetLayerSubscriptionsRequest,
1708 ) -> crate::errors::Result<crate::models::ApiData> {
1709 use crate::codecs::decode::api_data_from_proto;
1710 let client = self.connect_client();
1711 let resp = {
1712 use super::unary;
1713 unary::await_auth(
1714 &self.ctx.factory,
1715 "/polychart.v1.PolychartService/SetLayerSubscriptions",
1716 req,
1717 |req, opts| client.set_layer_subscriptions_with_options(req, opts),
1718 )
1719 .await?
1720 .into_owned()
1721 };
1722 Ok(api_data_from_proto(&resp))
1723 }
1724}
1725
1726impl WhiteboardService {
1727 pub async fn create_board(
1728 &self,
1729 req: crate::proto::collab::v1::CreateBoardRequest,
1730 ) -> crate::errors::Result<crate::models::ApiData> {
1731 use crate::codecs::decode::api_data_from_proto;
1732 let client = self.connect_client();
1733 let resp = {
1734 use super::unary;
1735 unary::await_auth(
1736 &self.ctx.factory,
1737 "/collab.v1.WhiteboardService/CreateBoard",
1738 req,
1739 |req, opts| client.create_board_with_options(req, opts),
1740 )
1741 .await?
1742 .into_owned()
1743 };
1744 Ok(api_data_from_proto(&resp))
1745 }
1746
1747 pub async fn get_board(
1748 &self,
1749 req: crate::proto::collab::v1::GetBoardRequest,
1750 ) -> crate::errors::Result<crate::models::ApiData> {
1751 use crate::codecs::decode::api_data_from_proto;
1752 let client = self.connect_client();
1753 let resp = {
1754 use super::unary;
1755 unary::await_auth(
1756 &self.ctx.factory,
1757 "/collab.v1.WhiteboardService/GetBoard",
1758 req,
1759 |req, opts| client.get_board_with_options(req, opts),
1760 )
1761 .await?
1762 .into_owned()
1763 };
1764 Ok(api_data_from_proto(&resp))
1765 }
1766
1767 pub async fn list_boards(
1768 &self,
1769 req: crate::proto::collab::v1::ListBoardsRequest,
1770 ) -> crate::errors::Result<crate::models::ApiData> {
1771 use crate::codecs::decode::api_data_from_proto;
1772 let client = self.connect_client();
1773 let resp = {
1774 use super::unary;
1775 unary::await_auth(
1776 &self.ctx.factory,
1777 "/collab.v1.WhiteboardService/ListBoards",
1778 req,
1779 |req, opts| client.list_boards_with_options(req, opts),
1780 )
1781 .await?
1782 .into_owned()
1783 };
1784 Ok(api_data_from_proto(&resp))
1785 }
1786
1787 pub async fn update_board(
1788 &self,
1789 req: crate::proto::collab::v1::UpdateBoardRequest,
1790 ) -> crate::errors::Result<crate::models::ApiData> {
1791 use crate::codecs::decode::api_data_from_proto;
1792 let client = self.connect_client();
1793 let resp = {
1794 use super::unary;
1795 unary::await_auth(
1796 &self.ctx.factory,
1797 "/collab.v1.WhiteboardService/UpdateBoard",
1798 req,
1799 |req, opts| client.update_board_with_options(req, opts),
1800 )
1801 .await?
1802 .into_owned()
1803 };
1804 Ok(api_data_from_proto(&resp))
1805 }
1806
1807 pub async fn update_board_acl(
1808 &self,
1809 req: crate::proto::collab::v1::UpdateBoardAclRequest,
1810 ) -> crate::errors::Result<crate::models::ApiData> {
1811 use crate::codecs::decode::api_data_from_proto;
1812 let client = self.connect_client();
1813 let resp = {
1814 use super::unary;
1815 unary::await_auth(
1816 &self.ctx.factory,
1817 "/collab.v1.WhiteboardService/UpdateBoardAcl",
1818 req,
1819 |req, opts| client.update_board_acl_with_options(req, opts),
1820 )
1821 .await?
1822 .into_owned()
1823 };
1824 Ok(api_data_from_proto(&resp))
1825 }
1826
1827 pub async fn archive_board(
1828 &self,
1829 req: crate::proto::collab::v1::ArchiveBoardRequest,
1830 ) -> crate::errors::Result<crate::models::ApiData> {
1831 use crate::codecs::decode::api_data_from_proto;
1832 let client = self.connect_client();
1833 let resp = {
1834 use super::unary;
1835 unary::await_auth(
1836 &self.ctx.factory,
1837 "/collab.v1.WhiteboardService/ArchiveBoard",
1838 req,
1839 |req, opts| client.archive_board_with_options(req, opts),
1840 )
1841 .await?
1842 .into_owned()
1843 };
1844 Ok(api_data_from_proto(&resp))
1845 }
1846
1847 pub async fn mint_join_token(
1848 &self,
1849 req: crate::proto::collab::v1::MintJoinTokenRequest,
1850 ) -> crate::errors::Result<crate::models::ApiData> {
1851 use crate::codecs::decode::api_data_from_proto;
1852 let client = self.connect_client();
1853 let resp = {
1854 use super::unary;
1855 unary::await_auth(
1856 &self.ctx.factory,
1857 "/collab.v1.WhiteboardService/MintJoinToken",
1858 req,
1859 |req, opts| client.mint_join_token_with_options(req, opts),
1860 )
1861 .await?
1862 .into_owned()
1863 };
1864 Ok(api_data_from_proto(&resp))
1865 }
1866}
1867
1868#[cfg(test)]
1869mod tests {
1870 use super::internal_transfer_amount_e18;
1871 use crate::models::CreateInternalTransferParams;
1872 use crate::types::{AssetAmount, QuantityDomain};
1873
1874 #[test]
1875 fn internal_transfer_amount_is_always_exact_e18() {
1876 let amount =
1877 AssetAmount::from_scaled(125, Some(2), QuantityDomain::LedgerE18, Some(7)).unwrap();
1878 let wire = internal_transfer_amount_e18(&amount, Some(2), 7).unwrap();
1879 assert_eq!(
1880 (u128::from(wire.hi) << 64) | u128::from(wire.lo),
1881 1_250_000_000_000_000_000
1882 );
1883
1884 let inexact =
1885 AssetAmount::from_scaled(126, Some(19), QuantityDomain::LedgerE18, Some(7)).unwrap();
1886 assert!(internal_transfer_amount_e18(&inexact, Some(19), 7).is_err());
1887 }
1888
1889 #[test]
1890 fn internal_transfer_rejects_missing_amount_scale_before_transport() {
1891 let amount = AssetAmount::from_scaled(1, None, QuantityDomain::LedgerE18, Some(7)).unwrap();
1892 let err = internal_transfer_amount_e18(&amount, None, 7)
1893 .expect_err("missing scale must not silently mean e18");
1894 assert!(err.to_string().contains("amount scale is required"));
1895 }
1896
1897 #[tokio::test]
1898 async fn internal_transfer_requires_destination_before_transport() {
1899 let client = crate::Client::new(crate::Config {
1900 hydrate_catalogs: false,
1901 ..Default::default()
1902 })
1903 .unwrap();
1904 let params = CreateInternalTransferParams {
1905 asset_id: 7,
1906 quantity: AssetAmount::from_scaled(100, Some(18), QuantityDomain::LedgerE18, Some(7))
1907 .unwrap(),
1908 idempotency_key: "missing-destination".into(),
1909 subaccount_id: None,
1910 destination_account_id: None,
1911 destination_subaccount_id: None,
1912 destination_smart_account_address: None,
1913 quantity_scale: Some(18),
1914 };
1915
1916 let err = client
1917 .internal_transfers
1918 .create(params.clone())
1919 .await
1920 .unwrap_err();
1921 assert!(err.to_string().contains("requires exactly one"));
1922
1923 let multiple = CreateInternalTransferParams {
1924 destination_account_id: Some("2".into()),
1925 destination_subaccount_id: Some("3".into()),
1926 idempotency_key: "multiple-destinations".into(),
1927 ..params.clone()
1928 };
1929 let err = client
1930 .internal_transfers
1931 .create(multiple)
1932 .await
1933 .unwrap_err();
1934 assert!(err.to_string().contains("requires exactly one"));
1935
1936 let empty_key = CreateInternalTransferParams {
1937 destination_account_id: Some("2".into()),
1938 idempotency_key: " ".into(),
1939 ..params.clone()
1940 };
1941 let err = client
1942 .internal_transfers
1943 .create(empty_key)
1944 .await
1945 .unwrap_err();
1946 assert!(err.to_string().contains("non-empty idempotency_key"));
1947
1948 let whitespace_destination = CreateInternalTransferParams {
1949 destination_smart_account_address: Some(" ".into()),
1950 ..params
1951 };
1952 let err = client
1953 .internal_transfers
1954 .create(whitespace_destination)
1955 .await
1956 .unwrap_err();
1957 assert!(err.to_string().contains("requires exactly one"));
1958 }
1959}