1#[cfg(feature = "rust")]
2use bon::Builder;
3#[cfg(feature = "node")]
4use napi_derive::napi;
5#[cfg(feature = "python")]
6use pyo3::{exceptions::PyValueError, pyclass, pymethods, PyResult};
7#[cfg(feature = "python")]
8use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods};
9use serde::{Deserialize, Deserializer, Serialize};
10
11use crate::errors::SdkError;
12
13fn deserialize_as_optional_json_string<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
14where
15 D: Deserializer<'de>,
16{
17 let value = Option::<serde_json::Value>::deserialize(deserializer)?;
18 match value {
19 None => Ok(None),
20 Some(v) => serde_json::to_string(&v)
21 .map(Some)
22 .map_err(serde::de::Error::custom),
23 }
24}
25
26#[cfg_attr(feature = "node", napi(string_enum))]
30#[cfg_attr(not(feature = "node"), derive(Clone))]
31#[derive(Debug, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub enum WebhookTemplateId {
34 EvmWalletFilter,
35 EvmContractEvents,
36 EvmAbiFilter,
37 SolanaWalletFilter,
38 BitcoinWalletFilter,
39 XrplWalletFilter,
40 HyperliquidWalletEventsFilter,
41 StellarWalletTransactionsSourceAccountFilter,
42}
43
44impl WebhookTemplateId {
45 pub fn as_str(&self) -> &'static str {
46 match self {
47 WebhookTemplateId::EvmWalletFilter => "evmWalletFilter",
48 WebhookTemplateId::EvmContractEvents => "evmContractEvents",
49 WebhookTemplateId::EvmAbiFilter => "evmAbiFilter",
50 WebhookTemplateId::SolanaWalletFilter => "solanaWalletFilter",
51 WebhookTemplateId::BitcoinWalletFilter => "bitcoinWalletFilter",
52 WebhookTemplateId::XrplWalletFilter => "xrplWalletFilter",
53 WebhookTemplateId::HyperliquidWalletEventsFilter => "hyperliquidWalletEventsFilter",
54 WebhookTemplateId::StellarWalletTransactionsSourceAccountFilter => {
55 "stellarWalletTransactionsSourceAccountFilter"
56 }
57 }
58 }
59}
60
61#[cfg_attr(feature = "node", napi(string_enum))]
63#[cfg_attr(not(feature = "node"), derive(Clone))]
64#[derive(Debug, Serialize, Deserialize)]
65#[serde(rename_all = "lowercase")]
66pub enum WebhookStartFrom {
67 Last,
69 Latest,
71}
72
73#[cfg_attr(feature = "rust", derive(Builder))]
78#[cfg_attr(feature = "python", gen_stub_pyclass)]
79#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
80#[cfg_attr(feature = "node", napi(object))]
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct EvmWalletFilterTemplate {
83 pub wallets: Vec<String>,
85}
86
87#[cfg(feature = "python")]
88#[gen_stub_pymethods]
89#[pymethods]
90impl EvmWalletFilterTemplate {
91 #[new]
92 pub fn new(wallets: Vec<String>) -> Self {
93 Self { wallets }
94 }
95}
96
97#[cfg_attr(feature = "rust", derive(Builder))]
100#[cfg_attr(feature = "python", gen_stub_pyclass)]
101#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
102#[cfg_attr(feature = "node", napi(object))]
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct EvmContractEventsTemplate {
105 pub contracts: Vec<String>,
107 #[serde(skip_serializing_if = "Option::is_none")]
109 pub event_hashes: Option<Vec<String>>,
110}
111
112#[cfg(feature = "python")]
113#[gen_stub_pymethods]
114#[pymethods]
115impl EvmContractEventsTemplate {
116 #[new]
117 #[pyo3(signature = (contracts, event_hashes=None))]
118 pub fn new(contracts: Vec<String>, event_hashes: Option<Vec<String>>) -> Self {
119 Self {
120 contracts,
121 event_hashes,
122 }
123 }
124}
125
126#[cfg_attr(feature = "rust", derive(Builder))]
129#[cfg_attr(feature = "python", gen_stub_pyclass)]
130#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
131#[cfg_attr(feature = "node", napi(object))]
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct EvmAbiFilterTemplate {
134 pub abi: String,
136 pub contracts: Vec<String>,
138}
139
140#[cfg(feature = "python")]
141#[gen_stub_pymethods]
142#[pymethods]
143impl EvmAbiFilterTemplate {
144 #[new]
145 pub fn new(abi: String, contracts: Vec<String>) -> Self {
146 Self { abi, contracts }
147 }
148}
149
150#[cfg_attr(feature = "rust", derive(Builder))]
153#[cfg_attr(feature = "python", gen_stub_pyclass)]
154#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
155#[cfg_attr(feature = "node", napi(object))]
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct SolanaWalletFilterTemplate {
158 pub accounts: Vec<String>,
160}
161
162#[cfg(feature = "python")]
163#[gen_stub_pymethods]
164#[pymethods]
165impl SolanaWalletFilterTemplate {
166 #[new]
167 pub fn new(accounts: Vec<String>) -> Self {
168 Self { accounts }
169 }
170}
171
172#[cfg_attr(feature = "rust", derive(Builder))]
174#[cfg_attr(feature = "python", gen_stub_pyclass)]
175#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
176#[cfg_attr(feature = "node", napi(object))]
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct BitcoinWalletFilterTemplate {
179 pub wallets: Vec<String>,
181}
182
183#[cfg(feature = "python")]
184#[gen_stub_pymethods]
185#[pymethods]
186impl BitcoinWalletFilterTemplate {
187 #[new]
188 pub fn new(wallets: Vec<String>) -> Self {
189 Self { wallets }
190 }
191}
192
193#[cfg_attr(feature = "rust", derive(Builder))]
195#[cfg_attr(feature = "python", gen_stub_pyclass)]
196#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
197#[cfg_attr(feature = "node", napi(object))]
198#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct XrplWalletFilterTemplate {
200 pub wallets: Vec<String>,
202}
203
204#[cfg(feature = "python")]
205#[gen_stub_pymethods]
206#[pymethods]
207impl XrplWalletFilterTemplate {
208 #[new]
209 pub fn new(wallets: Vec<String>) -> Self {
210 Self { wallets }
211 }
212}
213
214#[cfg_attr(feature = "rust", derive(Builder))]
216#[cfg_attr(feature = "python", gen_stub_pyclass)]
217#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
218#[cfg_attr(feature = "node", napi(object))]
219#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct HyperliquidWalletEventsFilterTemplate {
221 pub wallets: Vec<String>,
223}
224
225#[cfg(feature = "python")]
226#[gen_stub_pymethods]
227#[pymethods]
228impl HyperliquidWalletEventsFilterTemplate {
229 #[new]
230 pub fn new(wallets: Vec<String>) -> Self {
231 Self { wallets }
232 }
233}
234
235#[cfg_attr(feature = "rust", derive(Builder))]
238#[cfg_attr(feature = "python", gen_stub_pyclass)]
239#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
240#[cfg_attr(feature = "node", napi(object))]
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct StellarWalletTransactionsFilterTemplate {
243 pub wallets: Vec<String>,
245}
246
247#[cfg(feature = "python")]
248#[gen_stub_pymethods]
249#[pymethods]
250impl StellarWalletTransactionsFilterTemplate {
251 #[new]
252 pub fn new(wallets: Vec<String>) -> Self {
253 Self { wallets }
254 }
255}
256
257#[cfg_attr(feature = "python", gen_stub_pyclass)]
273#[cfg_attr(feature = "python", pyclass)]
274#[cfg_attr(feature = "node", napi(object))]
275#[derive(Debug, Clone, Serialize, Deserialize)]
276pub struct TemplateArgs {
277 pub template_id: WebhookTemplateId,
282 pub value: String,
286}
287
288impl Default for TemplateArgs {
292 fn default() -> Self {
293 Self {
294 template_id: WebhookTemplateId::EvmWalletFilter,
295 value: "null".to_string(),
296 }
297 }
298}
299
300impl TemplateArgs {
301 pub fn evm_wallet_filter(attrs: &EvmWalletFilterTemplate) -> Result<Self, SdkError> {
302 Ok(Self {
303 template_id: WebhookTemplateId::EvmWalletFilter,
304 value: serde_json::to_string(attrs).map_err(|e| SdkError::Config(e.to_string()))?,
305 })
306 }
307
308 pub fn evm_contract_events(attrs: &EvmContractEventsTemplate) -> Result<Self, SdkError> {
309 Ok(Self {
310 template_id: WebhookTemplateId::EvmContractEvents,
311 value: serde_json::to_string(attrs).map_err(|e| SdkError::Config(e.to_string()))?,
312 })
313 }
314
315 pub fn evm_abi_filter(attrs: &EvmAbiFilterTemplate) -> Result<Self, SdkError> {
316 Ok(Self {
317 template_id: WebhookTemplateId::EvmAbiFilter,
318 value: serde_json::to_string(attrs).map_err(|e| SdkError::Config(e.to_string()))?,
319 })
320 }
321
322 pub fn solana_wallet_filter(attrs: &SolanaWalletFilterTemplate) -> Result<Self, SdkError> {
323 Ok(Self {
324 template_id: WebhookTemplateId::SolanaWalletFilter,
325 value: serde_json::to_string(attrs).map_err(|e| SdkError::Config(e.to_string()))?,
326 })
327 }
328
329 pub fn bitcoin_wallet_filter(attrs: &BitcoinWalletFilterTemplate) -> Result<Self, SdkError> {
330 Ok(Self {
331 template_id: WebhookTemplateId::BitcoinWalletFilter,
332 value: serde_json::to_string(attrs).map_err(|e| SdkError::Config(e.to_string()))?,
333 })
334 }
335
336 pub fn xrpl_wallet_filter(attrs: &XrplWalletFilterTemplate) -> Result<Self, SdkError> {
337 Ok(Self {
338 template_id: WebhookTemplateId::XrplWalletFilter,
339 value: serde_json::to_string(attrs).map_err(|e| SdkError::Config(e.to_string()))?,
340 })
341 }
342
343 pub fn hyperliquid_wallet_events_filter(
344 attrs: &HyperliquidWalletEventsFilterTemplate,
345 ) -> Result<Self, SdkError> {
346 Ok(Self {
347 template_id: WebhookTemplateId::HyperliquidWalletEventsFilter,
348 value: serde_json::to_string(attrs).map_err(|e| SdkError::Config(e.to_string()))?,
349 })
350 }
351
352 pub fn stellar_wallet_transactions_filter(
353 attrs: &StellarWalletTransactionsFilterTemplate,
354 ) -> Result<Self, SdkError> {
355 Ok(Self {
356 template_id: WebhookTemplateId::StellarWalletTransactionsSourceAccountFilter,
357 value: serde_json::to_string(attrs).map_err(|e| SdkError::Config(e.to_string()))?,
358 })
359 }
360}
361
362#[cfg(feature = "python")]
363#[gen_stub_pymethods]
364#[pymethods]
365impl TemplateArgs {
366 #[staticmethod]
367 #[pyo3(name = "evm_wallet_filter")]
368 fn py_evm_wallet_filter(attrs: &EvmWalletFilterTemplate) -> PyResult<Self> {
369 Self::evm_wallet_filter(attrs).map_err(|e| PyValueError::new_err(e.to_string()))
370 }
371
372 #[staticmethod]
373 #[pyo3(name = "evm_contract_events")]
374 fn py_evm_contract_events(attrs: &EvmContractEventsTemplate) -> PyResult<Self> {
375 Self::evm_contract_events(attrs).map_err(|e| PyValueError::new_err(e.to_string()))
376 }
377
378 #[staticmethod]
379 #[pyo3(name = "evm_abi_filter")]
380 fn py_evm_abi_filter(attrs: &EvmAbiFilterTemplate) -> PyResult<Self> {
381 Self::evm_abi_filter(attrs).map_err(|e| PyValueError::new_err(e.to_string()))
382 }
383
384 #[staticmethod]
385 #[pyo3(name = "solana_wallet_filter")]
386 fn py_solana_wallet_filter(attrs: &SolanaWalletFilterTemplate) -> PyResult<Self> {
387 Self::solana_wallet_filter(attrs).map_err(|e| PyValueError::new_err(e.to_string()))
388 }
389
390 #[staticmethod]
391 #[pyo3(name = "bitcoin_wallet_filter")]
392 fn py_bitcoin_wallet_filter(attrs: &BitcoinWalletFilterTemplate) -> PyResult<Self> {
393 Self::bitcoin_wallet_filter(attrs).map_err(|e| PyValueError::new_err(e.to_string()))
394 }
395
396 #[staticmethod]
397 #[pyo3(name = "xrpl_wallet_filter")]
398 fn py_xrpl_wallet_filter(attrs: &XrplWalletFilterTemplate) -> PyResult<Self> {
399 Self::xrpl_wallet_filter(attrs).map_err(|e| PyValueError::new_err(e.to_string()))
400 }
401
402 #[staticmethod]
403 #[pyo3(name = "hyperliquid_wallet_events_filter")]
404 fn py_hyperliquid_wallet_events_filter(
405 attrs: &HyperliquidWalletEventsFilterTemplate,
406 ) -> PyResult<Self> {
407 Self::hyperliquid_wallet_events_filter(attrs)
408 .map_err(|e| PyValueError::new_err(e.to_string()))
409 }
410
411 #[staticmethod]
412 #[pyo3(name = "stellar_wallet_transactions_filter")]
413 fn py_stellar_wallet_transactions_filter(
414 attrs: &StellarWalletTransactionsFilterTemplate,
415 ) -> PyResult<Self> {
416 Self::stellar_wallet_transactions_filter(attrs)
417 .map_err(|e| PyValueError::new_err(e.to_string()))
418 }
419}
420
421#[cfg_attr(feature = "python", gen_stub_pyclass)]
425#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
426#[cfg_attr(feature = "node", napi(object))]
427#[derive(Debug, Clone, Serialize, Deserialize)]
428pub struct WebhookDestinationAttributes {
429 pub url: String,
431 #[serde(skip_serializing_if = "Option::is_none")]
433 pub security_token: Option<String>,
434 #[serde(skip_serializing_if = "Option::is_none")]
436 pub compression: Option<String>,
437}
438
439#[cfg(feature = "python")]
440#[gen_stub_pymethods]
441#[pymethods]
442impl WebhookDestinationAttributes {
443 #[new]
444 #[pyo3(signature = (url, security_token=None, compression=None))]
445 pub fn new(url: String, security_token: Option<String>, compression: Option<String>) -> Self {
446 Self {
447 url,
448 security_token,
449 compression,
450 }
451 }
452}
453
454#[cfg_attr(feature = "python", gen_stub_pyclass)]
458#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
459#[cfg_attr(feature = "node", napi(object))]
460#[cfg_attr(not(feature = "node"), derive(Clone))]
461#[derive(Debug, Default, Serialize, Deserialize)]
462pub struct GetWebhooksParams {
463 #[serde(skip_serializing_if = "Option::is_none")]
465 pub limit: Option<i64>,
466 #[serde(skip_serializing_if = "Option::is_none")]
468 pub offset: Option<i64>,
469}
470
471#[cfg(feature = "python")]
472#[gen_stub_pymethods]
473#[pymethods]
474impl GetWebhooksParams {
475 #[new]
476 #[pyo3(signature = (limit=None, offset=None))]
477 pub fn new(limit: Option<i64>, offset: Option<i64>) -> Self {
478 Self { limit, offset }
479 }
480}
481
482#[cfg_attr(feature = "python", gen_stub_pyclass)]
485#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
486#[cfg_attr(feature = "node", napi(object))]
487#[cfg_attr(not(feature = "node"), derive(Clone))]
488#[derive(Debug, Default, Serialize, Deserialize)]
489pub struct UpdateWebhookParams {
490 #[serde(skip_serializing_if = "Option::is_none")]
492 pub name: Option<String>,
493 #[serde(skip_serializing_if = "Option::is_none")]
495 pub notification_email: Option<String>,
496 #[serde(skip_serializing_if = "Option::is_none")]
498 pub destination_attributes: Option<WebhookDestinationAttributes>,
499}
500
501#[cfg(feature = "python")]
502#[gen_stub_pymethods]
503#[pymethods]
504impl UpdateWebhookParams {
505 #[new]
506 #[pyo3(signature = (name=None, notification_email=None, destination_attributes=None))]
507 pub fn new(
508 name: Option<String>,
509 notification_email: Option<String>,
510 destination_attributes: Option<WebhookDestinationAttributes>,
511 ) -> Self {
512 Self {
513 name,
514 notification_email,
515 destination_attributes,
516 }
517 }
518}
519
520#[cfg_attr(feature = "node", napi(object))]
522#[cfg_attr(not(feature = "node"), derive(Clone))]
523#[derive(Debug, Serialize, Deserialize)]
524#[serde(rename_all = "camelCase")]
525pub struct ActivateWebhookParams {
526 pub start_from: WebhookStartFrom,
528}
529
530#[cfg_attr(feature = "rust", derive(Builder))]
532#[cfg_attr(feature = "node", napi(object))]
533#[cfg_attr(not(feature = "node"), derive(Clone))]
534#[derive(Debug, Serialize, Deserialize)]
535pub struct CreateWebhookFromTemplateParams {
536 pub name: String,
538 pub network: String,
540 #[serde(skip_serializing_if = "Option::is_none")]
542 pub notification_email: Option<String>,
543 pub destination_attributes: WebhookDestinationAttributes,
545 #[serde(skip)]
549 pub template_args: TemplateArgs,
550}
551
552#[cfg_attr(feature = "python", gen_stub_pyclass)]
554#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
555#[cfg_attr(feature = "node", napi(object))]
556#[cfg_attr(not(feature = "node"), derive(Clone))]
557#[derive(Debug, Default, Serialize, Deserialize)]
558pub struct UpdateWebhookTemplateParams {
559 #[serde(skip_serializing_if = "Option::is_none")]
561 pub name: Option<String>,
562 #[serde(skip_serializing_if = "Option::is_none")]
564 pub notification_email: Option<String>,
565 #[serde(skip_serializing_if = "Option::is_none")]
567 pub destination_attributes: Option<WebhookDestinationAttributes>,
568 #[serde(skip)]
572 pub template_args: TemplateArgs,
573}
574
575#[cfg(feature = "python")]
576#[gen_stub_pymethods]
577#[pymethods]
578impl UpdateWebhookTemplateParams {
579 #[new]
580 #[pyo3(signature = (template_args, name=None, notification_email=None, destination_attributes=None))]
581 pub fn new(
582 template_args: TemplateArgs,
583 name: Option<String>,
584 notification_email: Option<String>,
585 destination_attributes: Option<WebhookDestinationAttributes>,
586 ) -> Self {
587 Self {
588 name,
589 notification_email,
590 destination_attributes,
591 template_args,
592 }
593 }
594}
595
596#[cfg_attr(feature = "python", gen_stub_pyclass)]
600#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
601#[cfg_attr(feature = "node", napi(object))]
602#[derive(Debug, Clone, Serialize, Deserialize)]
603pub struct Webhook {
604 pub id: String,
606 pub name: String,
608 pub status: String,
610 pub network: String,
612 pub created_at: String,
614 #[serde(default, skip_serializing_if = "Option::is_none")]
616 pub updated_at: Option<String>,
617 #[serde(skip_serializing_if = "Option::is_none")]
619 pub template_id: Option<String>,
620 #[serde(skip_serializing_if = "Option::is_none")]
622 pub notification_email: Option<String>,
623 #[serde(
625 default,
626 skip_serializing_if = "Option::is_none",
627 deserialize_with = "deserialize_as_optional_json_string"
628 )]
629 pub destination_attributes: Option<String>,
630}
631
632#[cfg_attr(feature = "python", gen_stub_pyclass)]
634#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
635#[cfg_attr(feature = "node", napi(object))]
636#[derive(Debug, Clone, Serialize, Deserialize)]
637pub struct ListWebhooksResponse {
638 pub data: Vec<Webhook>,
640}
641
642#[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#[derive(Debug, Clone, Serialize, Deserialize)]
647pub struct WebhookEnabledCountResponse {
648 pub total: i64,
650}