diff --git a/sdks/python/pmxt/_exchanges.py b/sdks/python/pmxt/_exchanges.py index 2b1249c6..088863b8 100644 --- a/sdks/python/pmxt/_exchanges.py +++ b/sdks/python/pmxt/_exchanges.py @@ -593,6 +593,7 @@ def __init__( auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, wallet_address: Optional[str] = None, + api_base_url: Optional[str] = None, signer: Optional[object] = None, websocket: Optional[dict] = None, ) -> None: @@ -604,6 +605,10 @@ def __init__( auto_start_server: Automatically start server if not running (default: True) pmxt_api_key: Hosted PMXT API key (optional; enables hosted mode) wallet_address: Wallet address for hosted reads/writes (optional) + api_base_url: Base URL of the SuiBets exchange API itself (not the + sidecar — that is ``base_url``). Forwarded to the sidecar as the + ``baseUrl`` credential; falls back to the SUIBETS_BASE_URL env + var on the sidecar side when unset (optional) signer: Custom signer for hosted writes (optional) websocket: WebSocket transport configuration dict (optional) """ @@ -616,11 +621,14 @@ def __init__( signer=signer, websocket=websocket, ) + self.api_base_url = api_base_url def _get_credentials_dict(self) -> Optional[Dict[str, Any]]: creds = super()._get_credentials_dict() or {} if self.wallet_address: creds["walletAddress"] = self.wallet_address + if self.api_base_url: + creds["baseUrl"] = self.api_base_url return creds if creds else None diff --git a/sdks/python/pmxt/models.py b/sdks/python/pmxt/models.py index 96ad499c..9954e9b4 100644 --- a/sdks/python/pmxt/models.py +++ b/sdks/python/pmxt/models.py @@ -671,6 +671,7 @@ class PolymarketOptions(ExchangeOptions, total=False): class SuiBetsOptions(ExchangeOptions, total=False): """Constructor options for SuiBets clients.""" wallet_address: str + api_base_url: str class RouterOptions(TypedDict, total=False): diff --git a/sdks/python/tests/test_hosted_dispatch.py b/sdks/python/tests/test_hosted_dispatch.py index 85f9315a..7d0a0b4f 100644 --- a/sdks/python/tests/test_hosted_dispatch.py +++ b/sdks/python/tests/test_hosted_dispatch.py @@ -179,6 +179,25 @@ def test_suibets_constructor_accepts_wallet_address_for_hosted_mode() -> None: assert api._get_credentials_dict() == {"walletAddress": WALLET_ADDRESS} +def test_suibets_constructor_forwards_api_base_url_credential() -> None: + api = SuiBets( + wallet_address=WALLET_ADDRESS, + api_base_url="https://suibets.example", + auto_start_server=False, + ) + + assert api._get_credentials_dict() == { + "walletAddress": WALLET_ADDRESS, + "baseUrl": "https://suibets.example", + } + + +def test_suibets_api_base_url_alone_produces_credentials() -> None: + api = SuiBets(api_base_url="https://suibets.example", auto_start_server=False) + + assert api._get_credentials_dict() == {"baseUrl": "https://suibets.example"} + + # --------------------------------------------------------------------------- # # Read-method dispatch tests # --------------------------------------------------------------------------- # diff --git a/sdks/typescript/pmxt/client.ts b/sdks/typescript/pmxt/client.ts index 04ddc27f..48769b03 100644 --- a/sdks/typescript/pmxt/client.ts +++ b/sdks/typescript/pmxt/client.ts @@ -3648,6 +3648,14 @@ export interface SuiBetsOptions extends ExchangeOptions { * SUIBETS_WALLET_ADDRESS environment variable on the sidecar. */ walletAddress?: string; + + /** + * Base URL of the SuiBets exchange API itself (not the PMXT sidecar — + * use `baseUrl` for that). Forwarded to the sidecar as the `baseUrl` + * credential. Can also be set via the SUIBETS_BASE_URL environment + * variable on the sidecar. + */ + apiBaseUrl?: string; } /** @@ -3669,25 +3677,29 @@ export interface SuiBetsOptions extends ExchangeOptions { */ export class SuiBets extends Exchange { private readonly _walletAddress?: string; + private readonly _apiBaseUrl?: string; constructor(options: SuiBetsOptions = {}) { super("suibets", options); this._walletAddress = options.walletAddress; + this._apiBaseUrl = options.apiBaseUrl; } /** * Includes walletAddress in the credentials sent to the sidecar so - * that fetchPositions() can reach the /api/p2p/my endpoint. - * Falls back to SUIBETS_WALLET_ADDRESS env var on the sidecar side - * when walletAddress is not set here. + * that fetchPositions() can reach the /api/p2p/my endpoint, and + * apiBaseUrl as the `baseUrl` credential controlling the SuiBets + * exchange API origin. Each falls back to the corresponding sidecar + * env var (SUIBETS_WALLET_ADDRESS / SUIBETS_BASE_URL) when unset. */ protected override getCredentials(): ExchangeCredentials | undefined { const base = super.getCredentials(); - if (!this._walletAddress) return base; + if (!this._walletAddress && !this._apiBaseUrl) return base; return { ...(base ?? {}), - walletAddress: this._walletAddress, - } as ExchangeCredentials & { walletAddress: string }; + ...(this._walletAddress ? { walletAddress: this._walletAddress } : {}), + ...(this._apiBaseUrl ? { baseUrl: this._apiBaseUrl } : {}), + } as ExchangeCredentials; } } diff --git a/sdks/typescript/tests/exchange-credentials.test.ts b/sdks/typescript/tests/exchange-credentials.test.ts index ce8f9899..ca7bc6e1 100644 --- a/sdks/typescript/tests/exchange-credentials.test.ts +++ b/sdks/typescript/tests/exchange-credentials.test.ts @@ -1,4 +1,4 @@ -import { Exchange, ExchangeOptions } from "../pmxt/client"; +import { Exchange, ExchangeOptions, SuiBets } from "../pmxt/client"; class TestExchange extends Exchange { public exposedCredentials() { @@ -6,6 +6,12 @@ class TestExchange extends Exchange { } } +class TestSuiBets extends SuiBets { + public exposedCredentials() { + return this.getCredentials(); + } +} + describe("exchange credentials", () => { it("accepts and forwards apiSecret with sidecar credentials", () => { const options = { @@ -23,4 +29,28 @@ describe("exchange credentials", () => { privateKey: "private-key", }); }); + + it("SuiBets forwards apiBaseUrl as the baseUrl credential", () => { + const exchange = new TestSuiBets({ + walletAddress: "0x" + "ab".repeat(32), + apiBaseUrl: "https://suibets.example", + autoStartServer: false, + }); + + expect(exchange.exposedCredentials()).toMatchObject({ + walletAddress: "0x" + "ab".repeat(32), + baseUrl: "https://suibets.example", + }); + }); + + it("SuiBets apiBaseUrl alone produces credentials", () => { + const exchange = new TestSuiBets({ + apiBaseUrl: "https://suibets.example", + autoStartServer: false, + }); + + expect(exchange.exposedCredentials()).toMatchObject({ + baseUrl: "https://suibets.example", + }); + }); });