1#[cfg(feature = "rust")]
2use bon::Builder;
3#[cfg(feature = "node")]
4use napi_derive::napi;
5#[cfg(feature = "python")]
6use pyo3::{pyclass, pymethods};
7#[cfg(feature = "python")]
8use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods};
9use serde::{Deserialize, Deserializer, Serialize};
10
11fn deserialize_as_optional_json_string<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
12where
13 D: Deserializer<'de>,
14{
15 let value = Option::<serde_json::Value>::deserialize(deserializer)?;
16 match value {
17 None => Ok(None),
18 Some(v) => serde_json::to_string(&v)
19 .map(Some)
20 .map_err(serde::de::Error::custom),
21 }
22}
23
24#[cfg_attr(feature = "node", napi(string_enum))]
28#[cfg_attr(not(feature = "node"), derive(Clone))]
29#[derive(Debug, Serialize, Deserialize)]
30#[serde(rename_all = "camelCase")]
31pub enum WebhookTemplateId {
32 EvmWalletFilter,
33 EvmContractEvents,
34 EvmAbiFilter,
35 SolanaWalletFilter,
36 BitcoinWalletFilter,
37 XrplWalletFilter,
38 HyperliquidWalletEventsFilter,
39 StellarWalletTransactionsSourceAccountFilter,
40}
41
42impl WebhookTemplateId {
43 pub fn as_str(&self) -> &'static str {
44 match self {
45 WebhookTemplateId::EvmWalletFilter => "evmWalletFilter",
46 WebhookTemplateId::EvmContractEvents => "evmContractEvents",
47 WebhookTemplateId::EvmAbiFilter => "evmAbiFilter",
48 WebhookTemplateId::SolanaWalletFilter => "solanaWalletFilter",
49 WebhookTemplateId::BitcoinWalletFilter => "bitcoinWalletFilter",
50 WebhookTemplateId::XrplWalletFilter => "xrplWalletFilter",
51 WebhookTemplateId::HyperliquidWalletEventsFilter => "hyperliquidWalletEventsFilter",
52 WebhookTemplateId::StellarWalletTransactionsSourceAccountFilter => {
53 "stellarWalletTransactionsSourceAccountFilter"
54 }
55 }
56 }
57}
58
59#[cfg_attr(feature = "node", napi(string_enum))]
61#[cfg_attr(not(feature = "node"), derive(Clone))]
62#[derive(Debug, Serialize, Deserialize)]
63#[serde(rename_all = "lowercase")]
64pub enum WebhookStartFrom {
65 Last,
67 Latest,
69}
70
71#[cfg_attr(feature = "rust", derive(Builder))]
76#[cfg_attr(feature = "python", gen_stub_pyclass)]
77#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
78#[cfg_attr(feature = "node", napi(object))]
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct EvmWalletFilterTemplate {
81 pub wallets: Vec<String>,
83}
84
85#[cfg(feature = "python")]
86#[gen_stub_pymethods]
87#[pymethods]
88impl EvmWalletFilterTemplate {
89 #[new]
90 pub fn new(wallets: Vec<String>) -> Self {
91 Self { wallets }
92 }
93}
94
95#[cfg_attr(feature = "rust", derive(Builder))]
98#[cfg_attr(feature = "python", gen_stub_pyclass)]
99#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
100#[cfg_attr(feature = "node", napi(object))]
101#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(rename_all = "camelCase")]
103pub struct EvmContractEventsTemplate {
104 pub contracts: Vec<String>,
106 pub event_hashes: Vec<String>,
108}
109
110#[cfg(feature = "python")]
111#[gen_stub_pymethods]
112#[pymethods]
113impl EvmContractEventsTemplate {
114 #[new]
115 pub fn new(contracts: Vec<String>, event_hashes: Vec<String>) -> Self {
116 Self {
117 contracts,
118 event_hashes,
119 }
120 }
121}
122
123#[cfg_attr(feature = "rust", derive(Builder))]
126#[cfg_attr(feature = "python", gen_stub_pyclass)]
127#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
128#[cfg_attr(feature = "node", napi(object))]
129#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct EvmAbiFilterTemplate {
131 pub abi: String,
133 pub contracts: Vec<String>,
135}
136
137#[cfg(feature = "python")]
138#[gen_stub_pymethods]
139#[pymethods]
140impl EvmAbiFilterTemplate {
141 #[new]
142 pub fn new(abi: String, contracts: Vec<String>) -> Self {
143 Self { abi, contracts }
144 }
145}
146
147#[cfg_attr(feature = "rust", derive(Builder))]
150#[cfg_attr(feature = "python", gen_stub_pyclass)]
151#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
152#[cfg_attr(feature = "node", napi(object))]
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct SolanaWalletFilterTemplate {
155 pub accounts: Vec<String>,
157}
158
159#[cfg(feature = "python")]
160#[gen_stub_pymethods]
161#[pymethods]
162impl SolanaWalletFilterTemplate {
163 #[new]
164 pub fn new(accounts: Vec<String>) -> Self {
165 Self { accounts }
166 }
167}
168
169#[cfg_attr(feature = "rust", derive(Builder))]
171#[cfg_attr(feature = "python", gen_stub_pyclass)]
172#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
173#[cfg_attr(feature = "node", napi(object))]
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct BitcoinWalletFilterTemplate {
176 pub wallets: Vec<String>,
178}
179
180#[cfg(feature = "python")]
181#[gen_stub_pymethods]
182#[pymethods]
183impl BitcoinWalletFilterTemplate {
184 #[new]
185 pub fn new(wallets: Vec<String>) -> Self {
186 Self { wallets }
187 }
188}
189
190#[cfg_attr(feature = "rust", derive(Builder))]
192#[cfg_attr(feature = "python", gen_stub_pyclass)]
193#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
194#[cfg_attr(feature = "node", napi(object))]
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct XrplWalletFilterTemplate {
197 pub wallets: Vec<String>,
199}
200
201#[cfg(feature = "python")]
202#[gen_stub_pymethods]
203#[pymethods]
204impl XrplWalletFilterTemplate {
205 #[new]
206 pub fn new(wallets: Vec<String>) -> Self {
207 Self { wallets }
208 }
209}
210
211#[cfg_attr(feature = "rust", derive(Builder))]
213#[cfg_attr(feature = "python", gen_stub_pyclass)]
214#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
215#[cfg_attr(feature = "node", napi(object))]
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct HyperliquidWalletEventsFilterTemplate {
218 pub wallets: Vec<String>,
220}
221
222#[cfg(feature = "python")]
223#[gen_stub_pymethods]
224#[pymethods]
225impl HyperliquidWalletEventsFilterTemplate {
226 #[new]
227 pub fn new(wallets: Vec<String>) -> Self {
228 Self { wallets }
229 }
230}
231
232#[cfg_attr(feature = "rust", derive(Builder))]
235#[cfg_attr(feature = "python", gen_stub_pyclass)]
236#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
237#[cfg_attr(feature = "node", napi(object))]
238#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct StellarWalletTransactionsFilterTemplate {
240 pub wallets: Vec<String>,
242}
243
244#[cfg(feature = "python")]
245#[gen_stub_pymethods]
246#[pymethods]
247impl StellarWalletTransactionsFilterTemplate {
248 #[new]
249 pub fn new(wallets: Vec<String>) -> Self {
250 Self { wallets }
251 }
252}
253
254#[cfg_attr(feature = "rust", derive(Builder))]
265#[cfg_attr(feature = "python", gen_stub_pyclass)]
266#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
267#[cfg_attr(feature = "node", napi(object))]
268#[derive(Debug, Clone, Serialize, Deserialize)]
269#[serde(rename_all = "camelCase")]
270pub struct EvmWalletFilterByListTemplate {
271 pub wallets_list_name: String,
273}
274
275#[cfg(feature = "python")]
276#[gen_stub_pymethods]
277#[pymethods]
278impl EvmWalletFilterByListTemplate {
279 #[new]
280 pub fn new(wallets_list_name: String) -> Self {
281 Self { wallets_list_name }
282 }
283}
284
285#[cfg_attr(feature = "rust", derive(Builder))]
289#[cfg_attr(feature = "python", gen_stub_pyclass)]
290#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
291#[cfg_attr(feature = "node", napi(object))]
292#[derive(Debug, Clone, Serialize, Deserialize)]
293#[serde(rename_all = "camelCase")]
294pub struct EvmContractEventsByListTemplate {
295 pub contracts_list_name: String,
297 #[serde(skip_serializing_if = "Option::is_none")]
300 pub event_hashes_list_name: Option<String>,
301}
302
303#[cfg(feature = "python")]
304#[gen_stub_pymethods]
305#[pymethods]
306impl EvmContractEventsByListTemplate {
307 #[new]
308 #[pyo3(signature = (contracts_list_name, event_hashes_list_name=None))]
309 pub fn new(contracts_list_name: String, event_hashes_list_name: Option<String>) -> Self {
310 Self {
311 contracts_list_name,
312 event_hashes_list_name,
313 }
314 }
315}
316
317#[cfg_attr(feature = "rust", derive(Builder))]
322#[cfg_attr(feature = "python", gen_stub_pyclass)]
323#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
324#[cfg_attr(feature = "node", napi(object))]
325#[derive(Debug, Clone, Serialize, Deserialize)]
326#[serde(rename_all = "camelCase")]
327pub struct EvmAbiFilterByListTemplate {
328 pub abi_json: String,
330 #[serde(skip_serializing_if = "Option::is_none")]
333 pub contracts_list_name: Option<String>,
334}
335
336#[cfg(feature = "python")]
337#[gen_stub_pymethods]
338#[pymethods]
339impl EvmAbiFilterByListTemplate {
340 #[new]
341 #[pyo3(signature = (abi_json, contracts_list_name=None))]
342 pub fn new(abi_json: String, contracts_list_name: Option<String>) -> Self {
343 Self {
344 abi_json,
345 contracts_list_name,
346 }
347 }
348}
349
350#[cfg_attr(feature = "rust", derive(Builder))]
352#[cfg_attr(feature = "python", gen_stub_pyclass)]
353#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
354#[cfg_attr(feature = "node", napi(object))]
355#[derive(Debug, Clone, Serialize, Deserialize)]
356#[serde(rename_all = "camelCase")]
357pub struct SolanaWalletFilterByListTemplate {
358 pub accounts_list_name: String,
360}
361
362#[cfg(feature = "python")]
363#[gen_stub_pymethods]
364#[pymethods]
365impl SolanaWalletFilterByListTemplate {
366 #[new]
367 pub fn new(accounts_list_name: String) -> Self {
368 Self { accounts_list_name }
369 }
370}
371
372#[cfg_attr(feature = "rust", derive(Builder))]
374#[cfg_attr(feature = "python", gen_stub_pyclass)]
375#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
376#[cfg_attr(feature = "node", napi(object))]
377#[derive(Debug, Clone, Serialize, Deserialize)]
378#[serde(rename_all = "camelCase")]
379pub struct BitcoinWalletFilterByListTemplate {
380 pub wallets_list_name: String,
382}
383
384#[cfg(feature = "python")]
385#[gen_stub_pymethods]
386#[pymethods]
387impl BitcoinWalletFilterByListTemplate {
388 #[new]
389 pub fn new(wallets_list_name: String) -> Self {
390 Self { wallets_list_name }
391 }
392}
393
394#[cfg_attr(feature = "rust", derive(Builder))]
396#[cfg_attr(feature = "python", gen_stub_pyclass)]
397#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
398#[cfg_attr(feature = "node", napi(object))]
399#[derive(Debug, Clone, Serialize, Deserialize)]
400#[serde(rename_all = "camelCase")]
401pub struct XrplWalletFilterByListTemplate {
402 pub wallets_list_name: String,
404}
405
406#[cfg(feature = "python")]
407#[gen_stub_pymethods]
408#[pymethods]
409impl XrplWalletFilterByListTemplate {
410 #[new]
411 pub fn new(wallets_list_name: String) -> Self {
412 Self { wallets_list_name }
413 }
414}
415
416#[cfg_attr(feature = "rust", derive(Builder))]
418#[cfg_attr(feature = "python", gen_stub_pyclass)]
419#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
420#[cfg_attr(feature = "node", napi(object))]
421#[derive(Debug, Clone, Serialize, Deserialize)]
422#[serde(rename_all = "camelCase")]
423pub struct HyperliquidWalletEventsFilterByListTemplate {
424 pub wallets_list_name: String,
426}
427
428#[cfg(feature = "python")]
429#[gen_stub_pymethods]
430#[pymethods]
431impl HyperliquidWalletEventsFilterByListTemplate {
432 #[new]
433 pub fn new(wallets_list_name: String) -> Self {
434 Self { wallets_list_name }
435 }
436}
437
438#[cfg_attr(feature = "rust", derive(Builder))]
440#[cfg_attr(feature = "python", gen_stub_pyclass)]
441#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
442#[cfg_attr(feature = "node", napi(object))]
443#[derive(Debug, Clone, Serialize, Deserialize)]
444#[serde(rename_all = "camelCase")]
445pub struct StellarWalletTransactionsFilterByListTemplate {
446 pub wallets_list_name: String,
448}
449
450#[cfg(feature = "python")]
451#[gen_stub_pymethods]
452#[pymethods]
453impl StellarWalletTransactionsFilterByListTemplate {
454 #[new]
455 pub fn new(wallets_list_name: String) -> Self {
456 Self { wallets_list_name }
457 }
458}
459
460#[derive(Debug, Clone, Serialize, Deserialize)]
467#[serde(untagged)]
468pub enum EvmWalletFilterInput {
469 Inline(EvmWalletFilterTemplate),
470 ByList(EvmWalletFilterByListTemplate),
471}
472
473#[derive(Debug, Clone, Serialize, Deserialize)]
475#[serde(untagged)]
476pub enum EvmContractEventsInput {
477 Inline(EvmContractEventsTemplate),
478 ByList(EvmContractEventsByListTemplate),
479}
480
481#[derive(Debug, Clone, Serialize, Deserialize)]
483#[serde(untagged)]
484pub enum EvmAbiFilterInput {
485 Inline(EvmAbiFilterTemplate),
486 ByList(EvmAbiFilterByListTemplate),
487}
488
489#[derive(Debug, Clone, Serialize, Deserialize)]
491#[serde(untagged)]
492pub enum SolanaWalletFilterInput {
493 Inline(SolanaWalletFilterTemplate),
494 ByList(SolanaWalletFilterByListTemplate),
495}
496
497#[derive(Debug, Clone, Serialize, Deserialize)]
499#[serde(untagged)]
500pub enum BitcoinWalletFilterInput {
501 Inline(BitcoinWalletFilterTemplate),
502 ByList(BitcoinWalletFilterByListTemplate),
503}
504
505#[derive(Debug, Clone, Serialize, Deserialize)]
507#[serde(untagged)]
508pub enum XrplWalletFilterInput {
509 Inline(XrplWalletFilterTemplate),
510 ByList(XrplWalletFilterByListTemplate),
511}
512
513#[derive(Debug, Clone, Serialize, Deserialize)]
515#[serde(untagged)]
516pub enum HyperliquidWalletEventsFilterInput {
517 Inline(HyperliquidWalletEventsFilterTemplate),
518 ByList(HyperliquidWalletEventsFilterByListTemplate),
519}
520
521#[derive(Debug, Clone, Serialize, Deserialize)]
524#[serde(untagged)]
525pub enum StellarWalletTransactionsFilterInput {
526 Inline(StellarWalletTransactionsFilterTemplate),
527 ByList(StellarWalletTransactionsFilterByListTemplate),
528}
529
530#[derive(Debug, Clone, Serialize, Deserialize)]
542#[serde(tag = "templateId", content = "templateArgs", rename_all = "camelCase")]
543pub enum TemplateArgs {
544 EvmWalletFilter(EvmWalletFilterInput),
546 EvmContractEvents(EvmContractEventsInput),
548 EvmAbiFilter(EvmAbiFilterInput),
550 SolanaWalletFilter(SolanaWalletFilterInput),
552 BitcoinWalletFilter(BitcoinWalletFilterInput),
554 XrplWalletFilter(XrplWalletFilterInput),
556 HyperliquidWalletEventsFilter(HyperliquidWalletEventsFilterInput),
558 StellarWalletTransactionsSourceAccountFilter(StellarWalletTransactionsFilterInput),
560}
561
562impl TemplateArgs {
563 pub fn tag(&self) -> WebhookTemplateId {
564 match self {
565 Self::EvmWalletFilter(_) => WebhookTemplateId::EvmWalletFilter,
566 Self::EvmContractEvents(_) => WebhookTemplateId::EvmContractEvents,
567 Self::EvmAbiFilter(_) => WebhookTemplateId::EvmAbiFilter,
568 Self::SolanaWalletFilter(_) => WebhookTemplateId::SolanaWalletFilter,
569 Self::BitcoinWalletFilter(_) => WebhookTemplateId::BitcoinWalletFilter,
570 Self::XrplWalletFilter(_) => WebhookTemplateId::XrplWalletFilter,
571 Self::HyperliquidWalletEventsFilter(_) => {
572 WebhookTemplateId::HyperliquidWalletEventsFilter
573 }
574 Self::StellarWalletTransactionsSourceAccountFilter(_) => {
575 WebhookTemplateId::StellarWalletTransactionsSourceAccountFilter
576 }
577 }
578 }
579}
580
581#[cfg_attr(feature = "python", gen_stub_pyclass)]
585#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
586#[cfg_attr(feature = "node", napi(object))]
587#[derive(Debug, Clone, Serialize, Deserialize)]
588pub struct WebhookDestinationAttributes {
589 pub url: String,
591 #[serde(skip_serializing_if = "Option::is_none")]
593 pub security_token: Option<String>,
594 pub compression: String,
596}
597
598#[cfg(feature = "python")]
599#[gen_stub_pymethods]
600#[pymethods]
601impl WebhookDestinationAttributes {
602 #[new]
603 #[pyo3(signature = (url, compression, security_token=None))]
604 pub fn new(url: String, compression: String, security_token: Option<String>) -> Self {
605 Self {
606 url,
607 security_token,
608 compression,
609 }
610 }
611}
612
613#[cfg_attr(feature = "python", gen_stub_pyclass)]
617#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
618#[cfg_attr(feature = "node", napi(object))]
619#[cfg_attr(not(feature = "node"), derive(Clone))]
620#[derive(Debug, Default, Serialize, Deserialize)]
621pub struct GetWebhooksParams {
622 #[serde(skip_serializing_if = "Option::is_none")]
624 pub limit: Option<i64>,
625 #[serde(skip_serializing_if = "Option::is_none")]
627 pub offset: Option<i64>,
628}
629
630#[cfg(feature = "python")]
631#[gen_stub_pymethods]
632#[pymethods]
633impl GetWebhooksParams {
634 #[new]
635 #[pyo3(signature = (limit=None, offset=None))]
636 pub fn new(limit: Option<i64>, offset: Option<i64>) -> Self {
637 Self { limit, offset }
638 }
639}
640
641#[cfg_attr(feature = "python", gen_stub_pyclass)]
644#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
645#[cfg_attr(feature = "node", napi(object))]
646#[cfg_attr(not(feature = "node"), derive(Clone))]
647#[derive(Debug, Default, Serialize, Deserialize)]
648pub struct UpdateWebhookParams {
649 #[serde(skip_serializing_if = "Option::is_none")]
651 pub name: Option<String>,
652 #[serde(skip_serializing_if = "Option::is_none")]
654 pub notification_email: Option<String>,
655 #[serde(skip_serializing_if = "Option::is_none")]
657 pub destination_attributes: Option<WebhookDestinationAttributes>,
658}
659
660#[cfg(feature = "python")]
661#[gen_stub_pymethods]
662#[pymethods]
663impl UpdateWebhookParams {
664 #[new]
665 #[pyo3(signature = (name=None, notification_email=None, destination_attributes=None))]
666 pub fn new(
667 name: Option<String>,
668 notification_email: Option<String>,
669 destination_attributes: Option<WebhookDestinationAttributes>,
670 ) -> Self {
671 Self {
672 name,
673 notification_email,
674 destination_attributes,
675 }
676 }
677}
678
679#[cfg_attr(feature = "node", napi(object))]
681#[cfg_attr(not(feature = "node"), derive(Clone))]
682#[derive(Debug, Serialize, Deserialize)]
683#[serde(rename_all = "camelCase")]
684pub struct ActivateWebhookParams {
685 pub start_from: WebhookStartFrom,
687}
688
689#[cfg_attr(feature = "rust", derive(Builder))]
691#[derive(Debug, Clone, Serialize, Deserialize)]
692pub struct CreateWebhookFromTemplateParams {
693 pub name: String,
695 pub network: String,
697 #[serde(skip_serializing_if = "Option::is_none")]
699 pub notification_email: Option<String>,
700 pub destination_attributes: WebhookDestinationAttributes,
702 #[serde(flatten)]
705 pub template_args: TemplateArgs,
706}
707
708#[derive(Debug, Clone, Serialize, Deserialize)]
710pub struct UpdateWebhookTemplateParams {
711 #[serde(skip_serializing_if = "Option::is_none")]
713 pub name: Option<String>,
714 #[serde(skip_serializing_if = "Option::is_none")]
716 pub notification_email: Option<String>,
717 #[serde(skip_serializing_if = "Option::is_none")]
719 pub destination_attributes: Option<WebhookDestinationAttributes>,
720 #[serde(flatten)]
723 pub template_args: TemplateArgs,
724}
725
726#[cfg_attr(feature = "python", gen_stub_pyclass)]
730#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
731#[cfg_attr(feature = "node", napi(object))]
732#[derive(Debug, Clone, Serialize, Deserialize)]
733pub struct Webhook {
734 pub id: String,
736 pub name: String,
738 pub status: String,
740 pub network: String,
742 pub created_at: String,
744 #[serde(default, skip_serializing_if = "Option::is_none")]
746 pub updated_at: Option<String>,
747 #[serde(skip_serializing_if = "Option::is_none")]
749 pub template_id: Option<String>,
750 #[serde(skip_serializing_if = "Option::is_none")]
752 pub notification_email: Option<String>,
753 #[serde(
755 default,
756 skip_serializing_if = "Option::is_none",
757 deserialize_with = "deserialize_as_optional_json_string"
758 )]
759 pub destination_attributes: Option<String>,
760}
761
762#[cfg_attr(feature = "python", gen_stub_pyclass)]
764#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
765#[cfg_attr(feature = "node", napi(object))]
766#[derive(Debug, Clone, Serialize, Deserialize)]
767pub struct WebhookPageInfo {
768 pub limit: i64,
770 pub offset: i64,
772 pub total: i64,
774}
775
776#[cfg_attr(feature = "python", gen_stub_pyclass)]
778#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
779#[cfg_attr(feature = "node", napi(object))]
780#[derive(Debug, Clone, Serialize, Deserialize)]
781pub struct ListWebhooksResponse {
782 pub data: Vec<Webhook>,
784 #[serde(rename = "pageInfo")]
786 pub page_info: WebhookPageInfo,
787}
788
789#[cfg_attr(feature = "python", gen_stub_pyclass)]
791#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
792#[cfg_attr(feature = "node", napi(object))]
793#[derive(Debug, Clone, Serialize, Deserialize)]
794pub struct WebhookEnabledCountResponse {
795 pub total: i64,
797}
798
799#[cfg(test)]
800#[allow(clippy::unwrap_used)]
801mod template_args_tests {
802 use super::*;
803
804 #[test]
805 fn evm_wallet_filter_roundtrip() {
806 let args =
807 TemplateArgs::EvmWalletFilter(EvmWalletFilterInput::Inline(EvmWalletFilterTemplate {
808 wallets: vec!["0xabc".to_string()],
809 }));
810 let json = serde_json::to_string(&args).unwrap();
811 assert!(json.contains(r#""templateId":"evmWalletFilter""#));
812 assert!(json.contains(r#""wallets":["0xabc"]"#));
813 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
814 assert!(matches!(
815 parsed,
816 TemplateArgs::EvmWalletFilter(EvmWalletFilterInput::Inline(_))
817 ));
818 assert!(matches!(parsed.tag(), WebhookTemplateId::EvmWalletFilter));
819 }
820
821 #[test]
822 fn evm_wallet_filter_by_list_roundtrip() {
823 let args = TemplateArgs::EvmWalletFilter(EvmWalletFilterInput::ByList(
824 EvmWalletFilterByListTemplate {
825 wallets_list_name: "my_list".to_string(),
826 },
827 ));
828 let json = serde_json::to_string(&args).unwrap();
829 assert!(json.contains(r#""templateId":"evmWalletFilter""#));
830 assert!(json.contains(r#""walletsListName":"my_list""#));
831 assert!(!json.contains(r#""wallets":"#));
832 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
833 assert!(matches!(
834 parsed,
835 TemplateArgs::EvmWalletFilter(EvmWalletFilterInput::ByList(_))
836 ));
837 }
838
839 #[test]
840 fn evm_contract_events_roundtrip() {
841 let args = TemplateArgs::EvmContractEvents(EvmContractEventsInput::Inline(
842 EvmContractEventsTemplate {
843 contracts: vec!["0xdef".to_string()],
844 event_hashes: vec!["0x1234".to_string()],
845 },
846 ));
847 let json = serde_json::to_string(&args).unwrap();
848 assert!(json.contains(r#""templateId":"evmContractEvents""#));
849 assert!(json.contains(r#""eventHashes":["0x1234"]"#));
851 assert!(!json.contains("event_hashes"));
852 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
853 assert!(matches!(
854 parsed,
855 TemplateArgs::EvmContractEvents(EvmContractEventsInput::Inline(_))
856 ));
857 }
858
859 #[test]
860 fn evm_contract_events_by_list_roundtrip() {
861 let args = TemplateArgs::EvmContractEvents(EvmContractEventsInput::ByList(
863 EvmContractEventsByListTemplate {
864 contracts_list_name: "my_contracts".to_string(),
865 event_hashes_list_name: None,
866 },
867 ));
868 let json = serde_json::to_string(&args).unwrap();
869 assert!(json.contains(r#""contractsListName":"my_contracts""#));
870 assert!(!json.contains("eventHashesListName"));
871 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
872 assert!(matches!(
873 parsed,
874 TemplateArgs::EvmContractEvents(EvmContractEventsInput::ByList(_))
875 ));
876 }
877
878 #[test]
879 fn evm_abi_filter_roundtrip() {
880 let args = TemplateArgs::EvmAbiFilter(EvmAbiFilterInput::Inline(EvmAbiFilterTemplate {
881 abi: "[]".to_string(),
882 contracts: vec!["0xdef".to_string()],
883 }));
884 let json = serde_json::to_string(&args).unwrap();
885 assert!(json.contains(r#""templateId":"evmAbiFilter""#));
886 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
887 assert!(matches!(parsed, TemplateArgs::EvmAbiFilter(_)));
888 }
889
890 #[test]
891 fn evm_abi_filter_by_list_roundtrip() {
892 let args =
895 TemplateArgs::EvmAbiFilter(EvmAbiFilterInput::ByList(EvmAbiFilterByListTemplate {
896 abi_json: "[]".to_string(),
897 contracts_list_name: Some("my_contracts".to_string()),
898 }));
899 let json = serde_json::to_string(&args).unwrap();
900 assert!(json.contains(r#""abiJson":"[]""#));
901 assert!(json.contains(r#""contractsListName":"my_contracts""#));
902 assert!(!json.contains(r#""abi":"#));
903 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
904 assert!(matches!(
905 parsed,
906 TemplateArgs::EvmAbiFilter(EvmAbiFilterInput::ByList(_))
907 ));
908 }
909
910 #[test]
911 fn solana_wallet_filter_roundtrip() {
912 let args = TemplateArgs::SolanaWalletFilter(SolanaWalletFilterInput::Inline(
913 SolanaWalletFilterTemplate {
914 accounts: vec!["acc".to_string()],
915 },
916 ));
917 let json = serde_json::to_string(&args).unwrap();
918 assert!(json.contains(r#""templateId":"solanaWalletFilter""#));
919 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
920 assert!(matches!(parsed, TemplateArgs::SolanaWalletFilter(_)));
921 }
922
923 #[test]
924 fn solana_wallet_filter_by_list_roundtrip() {
925 let args = TemplateArgs::SolanaWalletFilter(SolanaWalletFilterInput::ByList(
926 SolanaWalletFilterByListTemplate {
927 accounts_list_name: "my_accounts".to_string(),
928 },
929 ));
930 let json = serde_json::to_string(&args).unwrap();
931 assert!(json.contains(r#""accountsListName":"my_accounts""#));
932 assert!(!json.contains(r#""accounts":"#));
933 }
934
935 #[test]
936 fn bitcoin_wallet_filter_roundtrip() {
937 let args = TemplateArgs::BitcoinWalletFilter(BitcoinWalletFilterInput::Inline(
938 BitcoinWalletFilterTemplate {
939 wallets: vec!["bc1".to_string()],
940 },
941 ));
942 let json = serde_json::to_string(&args).unwrap();
943 assert!(json.contains(r#""templateId":"bitcoinWalletFilter""#));
944 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
945 assert!(matches!(parsed, TemplateArgs::BitcoinWalletFilter(_)));
946 }
947
948 #[test]
949 fn bitcoin_wallet_filter_by_list_roundtrip() {
950 let args = TemplateArgs::BitcoinWalletFilter(BitcoinWalletFilterInput::ByList(
951 BitcoinWalletFilterByListTemplate {
952 wallets_list_name: "my_btc_list".to_string(),
953 },
954 ));
955 let json = serde_json::to_string(&args).unwrap();
956 assert!(json.contains(r#""walletsListName":"my_btc_list""#));
957 }
958
959 #[test]
960 fn xrpl_wallet_filter_roundtrip() {
961 let args = TemplateArgs::XrplWalletFilter(XrplWalletFilterInput::Inline(
962 XrplWalletFilterTemplate {
963 wallets: vec!["r1".to_string()],
964 },
965 ));
966 let json = serde_json::to_string(&args).unwrap();
967 assert!(json.contains(r#""templateId":"xrplWalletFilter""#));
968 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
969 assert!(matches!(parsed, TemplateArgs::XrplWalletFilter(_)));
970 }
971
972 #[test]
973 fn xrpl_wallet_filter_by_list_roundtrip() {
974 let args = TemplateArgs::XrplWalletFilter(XrplWalletFilterInput::ByList(
975 XrplWalletFilterByListTemplate {
976 wallets_list_name: "my_xrpl_list".to_string(),
977 },
978 ));
979 let json = serde_json::to_string(&args).unwrap();
980 assert!(json.contains(r#""walletsListName":"my_xrpl_list""#));
981 }
982
983 #[test]
984 fn hyperliquid_wallet_events_filter_roundtrip() {
985 let args = TemplateArgs::HyperliquidWalletEventsFilter(
986 HyperliquidWalletEventsFilterInput::Inline(HyperliquidWalletEventsFilterTemplate {
987 wallets: vec!["0xhl".to_string()],
988 }),
989 );
990 let json = serde_json::to_string(&args).unwrap();
991 assert!(json.contains(r#""templateId":"hyperliquidWalletEventsFilter""#));
992 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
993 assert!(matches!(
994 parsed,
995 TemplateArgs::HyperliquidWalletEventsFilter(_)
996 ));
997 }
998
999 #[test]
1000 fn hyperliquid_wallet_events_filter_by_list_roundtrip() {
1001 let args = TemplateArgs::HyperliquidWalletEventsFilter(
1002 HyperliquidWalletEventsFilterInput::ByList(
1003 HyperliquidWalletEventsFilterByListTemplate {
1004 wallets_list_name: "my_hl_list".to_string(),
1005 },
1006 ),
1007 );
1008 let json = serde_json::to_string(&args).unwrap();
1009 assert!(json.contains(r#""walletsListName":"my_hl_list""#));
1010 }
1011
1012 #[test]
1013 fn stellar_wallet_transactions_filter_roundtrip() {
1014 let args = TemplateArgs::StellarWalletTransactionsSourceAccountFilter(
1015 StellarWalletTransactionsFilterInput::Inline(StellarWalletTransactionsFilterTemplate {
1016 wallets: vec!["G...".to_string()],
1017 }),
1018 );
1019 let json = serde_json::to_string(&args).unwrap();
1020 assert!(json.contains(r#""templateId":"stellarWalletTransactionsSourceAccountFilter""#));
1021 let parsed: TemplateArgs = serde_json::from_str(&json).unwrap();
1022 assert!(matches!(
1023 parsed,
1024 TemplateArgs::StellarWalletTransactionsSourceAccountFilter(_)
1025 ));
1026 }
1027
1028 #[test]
1029 fn stellar_wallet_transactions_filter_by_list_roundtrip() {
1030 let args = TemplateArgs::StellarWalletTransactionsSourceAccountFilter(
1031 StellarWalletTransactionsFilterInput::ByList(
1032 StellarWalletTransactionsFilterByListTemplate {
1033 wallets_list_name: "my_stellar_list".to_string(),
1034 },
1035 ),
1036 );
1037 let json = serde_json::to_string(&args).unwrap();
1038 assert!(json.contains(r#""walletsListName":"my_stellar_list""#));
1039 }
1040
1041 #[test]
1042 fn create_params_flattens_template_args() {
1043 let params = CreateWebhookFromTemplateParams {
1044 name: "n".to_string(),
1045 network: "ethereum-mainnet".to_string(),
1046 notification_email: None,
1047 destination_attributes: WebhookDestinationAttributes {
1048 url: "https://x".to_string(),
1049 security_token: None,
1050 compression: "none".to_string(),
1051 },
1052 template_args: TemplateArgs::EvmWalletFilter(EvmWalletFilterInput::Inline(
1053 EvmWalletFilterTemplate {
1054 wallets: vec!["0xabc".to_string()],
1055 },
1056 )),
1057 };
1058 let json = serde_json::to_value(¶ms).unwrap();
1059 let obj = json.as_object().unwrap();
1060 assert_eq!(
1061 obj.get("templateId").and_then(|v| v.as_str()),
1062 Some("evmWalletFilter")
1063 );
1064 assert!(obj.get("templateArgs").unwrap().is_object());
1065 assert_eq!(obj["templateArgs"]["wallets"][0].as_str(), Some("0xabc"));
1066 }
1067}