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)]
105#[pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.polymarket")]
106#[derive(Debug, Clone)]
107pub struct PyPolymarketSessionKey {
108    inner: PolymarketSessionKey,
109}
110
111#[pymethods]
112#[pyo3_stub_gen::derive::gen_stub_pymethods]
113impl PyPolymarketSessionKey {
114    #[getter]
115    fn address(&self) -> &str {
116        &self.inner.address
117    }
118
119    #[getter]
120    fn scopes(&self) -> Vec<String> {
121        self.inner.scopes.clone()
122    }
123
124    #[getter]
125    fn valid_until(&self) -> u64 {
126        self.inner.valid_until
127    }
128
129    fn __repr__(&self) -> String {
130        format!("{:?}", self.inner)
131    }
132}
133
134#[pyclass(
135    module = "nautilus_trader.adapters.polymarket",
136    name = "PolymarketSessionKeyClient"
137)]
138#[pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.polymarket")]
139#[derive(Debug)]
140pub struct PyPolymarketSessionKeyClient {
141    inner: Arc<PolymarketSessionKeyClient>,
142}
143
144#[pymethods]
145#[pyo3_stub_gen::derive::gen_stub_pymethods]
146impl PyPolymarketSessionKeyClient {
147    #[new]
148    fn py_new(config: PyPolymarketSessionKeyClientConfig) -> PyResult<Self> {
149        Ok(Self {
150            inner: Arc::new(PolymarketSessionKeyClient::new(config.inner).map_err(to_pyvalue_err)?),
151        })
152    }
153
154    fn list_session_keys<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
155        let inner = self.inner.clone();
156        pyo3_async_runtimes::tokio::future_into_py(py, async move {
157            Ok(inner
158                .list_session_keys()
159                .await
160                .map_err(to_pyvalue_err)?
161                .into_iter()
162                .map(|inner| PyPolymarketSessionKey { inner })
163                .collect::<Vec<_>>())
164        })
165    }
166
167    fn authorize_session_key<'py>(
168        &self,
169        py: Python<'py>,
170        address: String,
171    ) -> PyResult<Bound<'py, PyAny>> {
172        let inner = self.inner.clone();
173        pyo3_async_runtimes::tokio::future_into_py(py, async move {
174            Ok(PyPolymarketSessionKey {
175                inner: inner
176                    .authorize_session_key(&address)
177                    .await
178                    .map_err(to_pyvalue_err)?,
179            })
180        })
181    }
182
183    fn revoke_session_key<'py>(
184        &self,
185        py: Python<'py>,
186        address: String,
187    ) -> PyResult<Bound<'py, PyAny>> {
188        let inner = self.inner.clone();
189        pyo3_async_runtimes::tokio::future_into_py(py, async move {
190            inner
191                .revoke_session_key(&address)
192                .await
193                .map_err(to_pyvalue_err)
194        })
195    }
196}