Skip to main content

nautilus_polymarket/python/
session.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Thin Python bindings for owner-operated session administration.
17
18use std::sync::Arc;
19
20use nautilus_core::{python::to_pyvalue_err, string::secret::SecretString};
21use pyo3::prelude::*;
22
23use crate::session::{
24    PolymarketSessionKey, PolymarketSessionKeyClient, PolymarketSessionKeyClientConfig,
25};
26
27#[pyclass(
28    module = "nautilus_trader.adapters.polymarket",
29    name = "PolymarketSessionKeyClientConfig",
30    frozen,
31    from_py_object
32)]
33#[pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.polymarket")]
34#[derive(Debug, Clone)]
35pub struct PyPolymarketSessionKeyClientConfig {
36    inner: PolymarketSessionKeyClientConfig,
37}
38
39#[pymethods]
40#[pyo3_stub_gen::derive::gen_stub_pymethods]
41impl PyPolymarketSessionKeyClientConfig {
42    #[new]
43    #[expect(clippy::too_many_arguments)]
44    #[pyo3(signature = (private_key, api_key, api_secret, passphrase, builder_api_key, builder_api_secret, builder_passphrase, funder, base_url_http=None, base_url_relayer=None, proxy_url=None))]
45    fn py_new(
46        private_key: String,
47        api_key: String,
48        api_secret: String,
49        passphrase: String,
50        builder_api_key: String,
51        builder_api_secret: String,
52        builder_passphrase: String,
53        funder: String,
54        base_url_http: Option<String>,
55        base_url_relayer: Option<String>,
56        proxy_url: Option<String>,
57    ) -> Self {
58        Self {
59            inner: PolymarketSessionKeyClientConfig {
60                private_key: private_key.into(),
61                api_key: api_key.into(),
62                api_secret: api_secret.into(),
63                passphrase: passphrase.into(),
64                builder_api_key: builder_api_key.into(),
65                builder_api_secret: builder_api_secret.into(),
66                builder_passphrase: builder_passphrase.into(),
67                funder,
68                base_url_http,
69                base_url_relayer,
70                proxy_url: proxy_url.map(SecretString::from),
71            },
72        }
73    }
74
75    #[getter]
76    fn funder(&self) -> &str {
77        &self.inner.funder
78    }
79
80    #[getter]
81    fn base_url_http(&self) -> Option<&str> {
82        self.inner.base_url_http.as_deref()
83    }
84
85    #[getter]
86    fn base_url_relayer(&self) -> Option<&str> {
87        self.inner.base_url_relayer.as_deref()
88    }
89
90    #[getter]
91    fn has_proxy_url(&self) -> bool {
92        self.inner.proxy_url.is_some()
93    }
94
95    fn __repr__(&self) -> String {
96        format!("{:?}", self.inner)
97    }
98}
99
100#[pyclass(
101    module = "nautilus_trader.adapters.polymarket",
102    name = "PolymarketSessionKey",
103    frozen,
104    skip_from_py_object
105)]
106#[pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.polymarket")]
107#[derive(Debug, Clone)]
108pub struct PyPolymarketSessionKey {
109    inner: PolymarketSessionKey,
110}
111
112#[pymethods]
113#[pyo3_stub_gen::derive::gen_stub_pymethods]
114impl PyPolymarketSessionKey {
115    #[getter]
116    fn address(&self) -> &str {
117        &self.inner.address
118    }
119
120    #[getter]
121    fn scopes(&self) -> Vec<String> {
122        self.inner.scopes.clone()
123    }
124
125    #[getter]
126    fn valid_until(&self) -> u64 {
127        self.inner.valid_until
128    }
129
130    fn __repr__(&self) -> String {
131        format!("{:?}", self.inner)
132    }
133}
134
135#[pyclass(
136    module = "nautilus_trader.adapters.polymarket",
137    name = "PolymarketSessionKeyClient",
138    skip_from_py_object
139)]
140#[pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.polymarket")]
141#[derive(Debug)]
142pub struct PyPolymarketSessionKeyClient {
143    inner: Arc<PolymarketSessionKeyClient>,
144}
145
146#[pymethods]
147#[pyo3_stub_gen::derive::gen_stub_pymethods]
148impl PyPolymarketSessionKeyClient {
149    #[new]
150    fn py_new(config: PyPolymarketSessionKeyClientConfig) -> PyResult<Self> {
151        Ok(Self {
152            inner: Arc::new(PolymarketSessionKeyClient::new(config.inner).map_err(to_pyvalue_err)?),
153        })
154    }
155
156    fn list_session_keys<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
157        let inner = self.inner.clone();
158        pyo3_async_runtimes::tokio::future_into_py(py, async move {
159            Ok(inner
160                .list_session_keys()
161                .await
162                .map_err(to_pyvalue_err)?
163                .into_iter()
164                .map(|inner| PyPolymarketSessionKey { inner })
165                .collect::<Vec<_>>())
166        })
167    }
168
169    fn authorize_session_key<'py>(
170        &self,
171        py: Python<'py>,
172        address: String,
173    ) -> PyResult<Bound<'py, PyAny>> {
174        let inner = self.inner.clone();
175        pyo3_async_runtimes::tokio::future_into_py(py, async move {
176            Ok(PyPolymarketSessionKey {
177                inner: inner
178                    .authorize_session_key(&address)
179                    .await
180                    .map_err(to_pyvalue_err)?,
181            })
182        })
183    }
184
185    fn revoke_session_key<'py>(
186        &self,
187        py: Python<'py>,
188        address: String,
189    ) -> PyResult<Bound<'py, PyAny>> {
190        let inner = self.inner.clone();
191        pyo3_async_runtimes::tokio::future_into_py(py, async move {
192            inner
193                .revoke_session_key(&address)
194                .await
195                .map_err(to_pyvalue_err)
196        })
197    }
198}