pmxt-core 2.37.8 → 2.37.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BaseExchange.d.ts +1 -0
- package/dist/exchanges/kalshi/api.d.ts +1 -1
- package/dist/exchanges/kalshi/api.js +1 -1
- package/dist/exchanges/limitless/api.d.ts +1 -1
- package/dist/exchanges/limitless/api.js +1 -1
- package/dist/exchanges/limitless/auth.d.ts +15 -20
- package/dist/exchanges/limitless/auth.js +33 -28
- package/dist/exchanges/limitless/client.d.ts +51 -7
- package/dist/exchanges/limitless/client.js +196 -37
- package/dist/exchanges/limitless/index.js +27 -3
- package/dist/exchanges/myriad/api.d.ts +1 -1
- package/dist/exchanges/myriad/api.js +1 -1
- package/dist/exchanges/opinion/api.d.ts +1 -1
- package/dist/exchanges/opinion/api.js +1 -1
- package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
- package/dist/exchanges/polymarket/api-clob.js +1 -1
- package/dist/exchanges/polymarket/api-data.d.ts +1 -1
- package/dist/exchanges/polymarket/api-data.js +1 -1
- package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
- package/dist/exchanges/polymarket/api-gamma.js +1 -1
- package/dist/exchanges/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/server/openapi.yaml +5 -0
- package/dist/types.d.ts +1 -0
- package/package.json +4 -4
package/dist/BaseExchange.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/kalshi/Kalshi.yaml
|
|
3
|
-
* Generated at: 2026-05-
|
|
3
|
+
* Generated at: 2026-05-07T05:14:50.177Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const kalshiApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.kalshiApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/kalshi/Kalshi.yaml
|
|
6
|
-
* Generated at: 2026-05-
|
|
6
|
+
* Generated at: 2026-05-07T05:14:50.177Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.kalshiApiSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/limitless/Limitless.yaml
|
|
3
|
-
* Generated at: 2026-05-
|
|
3
|
+
* Generated at: 2026-05-07T05:14:50.217Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const limitlessApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.limitlessApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/limitless/Limitless.yaml
|
|
6
|
-
* Generated at: 2026-05-
|
|
6
|
+
* Generated at: 2026-05-07T05:14:50.217Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.limitlessApiSpec = {
|
|
@@ -1,40 +1,35 @@
|
|
|
1
1
|
import { HttpClient } from '@limitless-exchange/sdk';
|
|
2
2
|
import { Wallet } from 'ethers';
|
|
3
3
|
import { ExchangeCredentials } from '../../BaseExchange';
|
|
4
|
+
export interface HMACCredentials {
|
|
5
|
+
tokenId: string;
|
|
6
|
+
secret: string;
|
|
7
|
+
}
|
|
4
8
|
/**
|
|
5
|
-
* Manages Limitless authentication
|
|
6
|
-
*
|
|
9
|
+
* Manages Limitless authentication.
|
|
10
|
+
*
|
|
11
|
+
* Supports two modes:
|
|
12
|
+
* 1. API key + private key (individual signer — EIP-712 order signing)
|
|
13
|
+
* 2. HMAC credentials (partner/delegated signing — no private key needed)
|
|
7
14
|
*/
|
|
8
15
|
export declare class LimitlessAuth {
|
|
9
16
|
private credentials;
|
|
10
17
|
private signer?;
|
|
11
18
|
private httpClient?;
|
|
12
19
|
private apiKey?;
|
|
20
|
+
private hmacCreds?;
|
|
13
21
|
constructor(credentials: ExchangeCredentials);
|
|
14
|
-
/**
|
|
15
|
-
* Get the API key being used for authentication.
|
|
16
|
-
*/
|
|
17
22
|
getApiKey(): string;
|
|
18
23
|
/**
|
|
19
|
-
* Get or create the HTTP client
|
|
20
|
-
*
|
|
24
|
+
* Get or create the HTTP client.
|
|
25
|
+
* Uses HMAC auth when credentials are available (delegated signing),
|
|
26
|
+
* otherwise falls back to the legacy X-API-Key header.
|
|
21
27
|
*/
|
|
22
28
|
getHttpClient(): HttpClient;
|
|
23
|
-
/**
|
|
24
|
-
* Get the signer (wallet) for signing orders.
|
|
25
|
-
* Required for placing orders via EIP-712 signatures.
|
|
26
|
-
*/
|
|
27
29
|
getSigner(): Wallet;
|
|
28
|
-
/**
|
|
29
|
-
* Get the signer's address.
|
|
30
|
-
*/
|
|
31
30
|
getAddress(): string;
|
|
32
|
-
/**
|
|
33
|
-
* Check if the auth has a signer available.
|
|
34
|
-
*/
|
|
35
31
|
hasSigner(): boolean;
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
*/
|
|
32
|
+
/** True when HMAC credentials are present and no private key — delegated signing mode. */
|
|
33
|
+
isDelegatedSigning(): boolean;
|
|
39
34
|
reset(): void;
|
|
40
35
|
}
|
|
@@ -5,81 +5,86 @@ const sdk_1 = require("@limitless-exchange/sdk");
|
|
|
5
5
|
const ethers_1 = require("ethers");
|
|
6
6
|
const LIMITLESS_HOST = 'https://api.limitless.exchange';
|
|
7
7
|
/**
|
|
8
|
-
* Manages Limitless authentication
|
|
9
|
-
*
|
|
8
|
+
* Manages Limitless authentication.
|
|
9
|
+
*
|
|
10
|
+
* Supports two modes:
|
|
11
|
+
* 1. API key + private key (individual signer — EIP-712 order signing)
|
|
12
|
+
* 2. HMAC credentials (partner/delegated signing — no private key needed)
|
|
10
13
|
*/
|
|
11
14
|
class LimitlessAuth {
|
|
12
15
|
credentials;
|
|
13
16
|
signer;
|
|
14
17
|
httpClient;
|
|
15
18
|
apiKey;
|
|
19
|
+
hmacCreds;
|
|
16
20
|
constructor(credentials) {
|
|
17
21
|
this.credentials = credentials;
|
|
18
|
-
//
|
|
19
|
-
//
|
|
22
|
+
// HMAC credentials for delegated signing (partner mode).
|
|
23
|
+
// apiSecret is the base64-encoded HMAC secret from the Limitless dashboard.
|
|
24
|
+
if (credentials.apiKey && credentials.apiSecret) {
|
|
25
|
+
this.hmacCreds = {
|
|
26
|
+
tokenId: credentials.apiKey,
|
|
27
|
+
secret: credentials.apiSecret,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// API key for legacy X-API-Key header auth.
|
|
20
31
|
this.apiKey = credentials.apiKey || process.env.LIMITLESS_API_KEY;
|
|
21
|
-
if (!this.apiKey) {
|
|
32
|
+
if (!this.apiKey && !this.hmacCreds) {
|
|
22
33
|
throw new Error('Limitless requires an API key. Set LIMITLESS_API_KEY environment variable or provide apiKey in credentials.');
|
|
23
34
|
}
|
|
24
|
-
// Initialize signer if private key is provided (needed for order signing)
|
|
35
|
+
// Initialize signer if private key is provided (needed for EIP-712 order signing).
|
|
25
36
|
if (credentials.privateKey) {
|
|
26
37
|
let privateKey = credentials.privateKey;
|
|
27
|
-
// Fix for common .env issue where newlines are escaped
|
|
28
38
|
if (privateKey.includes('\\n')) {
|
|
29
39
|
privateKey = privateKey.replace(/\\n/g, '\n');
|
|
30
40
|
}
|
|
31
41
|
this.signer = new ethers_1.Wallet(privateKey);
|
|
32
42
|
}
|
|
33
43
|
}
|
|
34
|
-
/**
|
|
35
|
-
* Get the API key being used for authentication.
|
|
36
|
-
*/
|
|
37
44
|
getApiKey() {
|
|
38
45
|
return this.apiKey;
|
|
39
46
|
}
|
|
40
47
|
/**
|
|
41
|
-
* Get or create the HTTP client
|
|
42
|
-
*
|
|
48
|
+
* Get or create the HTTP client.
|
|
49
|
+
* Uses HMAC auth when credentials are available (delegated signing),
|
|
50
|
+
* otherwise falls back to the legacy X-API-Key header.
|
|
43
51
|
*/
|
|
44
52
|
getHttpClient() {
|
|
45
53
|
if (this.httpClient) {
|
|
46
54
|
return this.httpClient;
|
|
47
55
|
}
|
|
48
|
-
|
|
56
|
+
const config = {
|
|
49
57
|
baseURL: LIMITLESS_HOST,
|
|
50
|
-
apiKey: this.apiKey,
|
|
51
58
|
timeout: 30000,
|
|
52
|
-
}
|
|
59
|
+
};
|
|
60
|
+
if (this.hmacCreds) {
|
|
61
|
+
config.hmacCredentials = this.hmacCreds;
|
|
62
|
+
}
|
|
63
|
+
else if (this.apiKey) {
|
|
64
|
+
config.apiKey = this.apiKey;
|
|
65
|
+
}
|
|
66
|
+
this.httpClient = new sdk_1.HttpClient(config);
|
|
53
67
|
return this.httpClient;
|
|
54
68
|
}
|
|
55
|
-
/**
|
|
56
|
-
* Get the signer (wallet) for signing orders.
|
|
57
|
-
* Required for placing orders via EIP-712 signatures.
|
|
58
|
-
*/
|
|
59
69
|
getSigner() {
|
|
60
70
|
if (!this.signer) {
|
|
61
71
|
throw new Error('Wallet signer not available. Provide privateKey in credentials to sign orders.');
|
|
62
72
|
}
|
|
63
73
|
return this.signer;
|
|
64
74
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Get the signer's address.
|
|
67
|
-
*/
|
|
68
75
|
getAddress() {
|
|
69
76
|
if (!this.signer) {
|
|
70
77
|
throw new Error('Signer not initialized. Provide privateKey in credentials.');
|
|
71
78
|
}
|
|
72
79
|
return this.signer.address;
|
|
73
80
|
}
|
|
74
|
-
/**
|
|
75
|
-
* Check if the auth has a signer available.
|
|
76
|
-
*/
|
|
77
81
|
hasSigner() {
|
|
78
82
|
return !!this.signer;
|
|
79
83
|
}
|
|
80
|
-
/**
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
/** True when HMAC credentials are present and no private key — delegated signing mode. */
|
|
85
|
+
isDelegatedSigning() {
|
|
86
|
+
return !!this.hmacCreds && !this.signer;
|
|
87
|
+
}
|
|
83
88
|
reset() {
|
|
84
89
|
this.httpClient = undefined;
|
|
85
90
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HttpClient, OrderClient, MarketFetcher } from '@limitless-exchange/sdk';
|
|
2
|
+
import { Wallet } from 'ethers';
|
|
2
3
|
export interface LimitlessOrderParams {
|
|
3
4
|
marketSlug: string;
|
|
4
5
|
outcomeId: string;
|
|
@@ -6,28 +7,71 @@ export interface LimitlessOrderParams {
|
|
|
6
7
|
price: number;
|
|
7
8
|
amount: number;
|
|
8
9
|
type?: 'limit' | 'market';
|
|
10
|
+
onBehalfOf?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface LimitlessClientConfig {
|
|
13
|
+
httpClient: HttpClient;
|
|
14
|
+
wallet?: Wallet;
|
|
15
|
+
isDelegated?: boolean;
|
|
16
|
+
/** Wallet address for profile lookup in delegated mode. */
|
|
17
|
+
walletAddress?: string;
|
|
9
18
|
}
|
|
10
19
|
/**
|
|
11
20
|
* Wrapper client for Limitless Exchange using the official SDK.
|
|
12
|
-
*
|
|
21
|
+
*
|
|
22
|
+
* Two modes:
|
|
23
|
+
* - Individual: wallet + OrderClient (EIP-712 signing)
|
|
24
|
+
* - Delegated: no wallet, DelegatedOrderService (HMAC auth, server signs)
|
|
13
25
|
*/
|
|
14
26
|
export declare class LimitlessClient {
|
|
15
27
|
private httpClient;
|
|
16
|
-
private orderClient
|
|
28
|
+
private orderClient?;
|
|
17
29
|
private marketFetcher;
|
|
18
|
-
private signer
|
|
30
|
+
private signer?;
|
|
31
|
+
private readonly isDelegated;
|
|
32
|
+
private walletAddress?;
|
|
33
|
+
private cachedProfileId?;
|
|
19
34
|
private marketCache;
|
|
35
|
+
/** @deprecated Use the config-object constructor instead. */
|
|
20
36
|
constructor(privateKey: string, apiKey: string);
|
|
37
|
+
constructor(config: LimitlessClientConfig);
|
|
21
38
|
/**
|
|
22
39
|
* Get market details by slug.
|
|
23
40
|
* Results are cached to reduce API calls.
|
|
24
41
|
*/
|
|
25
42
|
getMarket(slug: string): Promise<any>;
|
|
26
43
|
/**
|
|
27
|
-
* Create
|
|
28
|
-
*
|
|
44
|
+
* Create an order.
|
|
45
|
+
*
|
|
46
|
+
* - Individual mode: EIP-712 signed via OrderClient (requires private key).
|
|
47
|
+
* - Delegated mode: unsigned order via DelegatedOrderService (HMAC auth).
|
|
48
|
+
*/
|
|
49
|
+
createOrder(params: LimitlessOrderParams): Promise<{
|
|
50
|
+
order: any;
|
|
51
|
+
id: any;
|
|
52
|
+
} | import("@limitless-exchange/sdk").OrderResponse>;
|
|
53
|
+
/**
|
|
54
|
+
* Create an order for a smart wallet account.
|
|
55
|
+
* maker = smart wallet address, signer = EOA address (our private key).
|
|
56
|
+
*/
|
|
57
|
+
private createSmartWalletOrder;
|
|
58
|
+
/**
|
|
59
|
+
* Build and submit an unsigned order via the delegated signing flow.
|
|
60
|
+
* The Limitless server signs on behalf of the partner account.
|
|
61
|
+
* No private key required — uses HMAC-authenticated HTTP.
|
|
62
|
+
*/
|
|
63
|
+
/**
|
|
64
|
+
* Resolve the Limitless profile ID for this account.
|
|
65
|
+
* Fetched once from the public profile endpoint, then cached.
|
|
66
|
+
*/
|
|
67
|
+
private cachedProfile?;
|
|
68
|
+
private resolveProfile;
|
|
69
|
+
private resolveProfileId;
|
|
70
|
+
/**
|
|
71
|
+
* Build and submit an unsigned order via the delegated signing flow.
|
|
72
|
+
* The Limitless server signs on behalf of the account.
|
|
29
73
|
*/
|
|
30
|
-
|
|
74
|
+
private createDelegatedOrder;
|
|
31
75
|
/**
|
|
32
76
|
* Cancel a specific order by ID.
|
|
33
77
|
*/
|
|
@@ -57,7 +101,7 @@ export declare class LimitlessClient {
|
|
|
57
101
|
/**
|
|
58
102
|
* Get the underlying OrderClient for advanced order operations.
|
|
59
103
|
*/
|
|
60
|
-
getOrderClient(): OrderClient;
|
|
104
|
+
getOrderClient(): OrderClient | undefined;
|
|
61
105
|
/**
|
|
62
106
|
* Get the underlying MarketFetcher for advanced market queries.
|
|
63
107
|
*/
|
|
@@ -6,33 +6,66 @@ const ethers_1 = require("ethers");
|
|
|
6
6
|
const LIMITLESS_API_URL = 'https://api.limitless.exchange';
|
|
7
7
|
/**
|
|
8
8
|
* Wrapper client for Limitless Exchange using the official SDK.
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
|
+
* Two modes:
|
|
11
|
+
* - Individual: wallet + OrderClient (EIP-712 signing)
|
|
12
|
+
* - Delegated: no wallet, DelegatedOrderService (HMAC auth, server signs)
|
|
10
13
|
*/
|
|
11
14
|
class LimitlessClient {
|
|
12
15
|
httpClient;
|
|
13
16
|
orderClient;
|
|
14
17
|
marketFetcher;
|
|
15
18
|
signer;
|
|
19
|
+
isDelegated;
|
|
20
|
+
walletAddress;
|
|
21
|
+
cachedProfileId;
|
|
16
22
|
marketCache = {};
|
|
17
|
-
constructor(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
privateKey =
|
|
23
|
+
constructor(configOrKey, apiKey) {
|
|
24
|
+
if (typeof configOrKey === 'string') {
|
|
25
|
+
// Legacy positional constructor: (privateKey, apiKey)
|
|
26
|
+
let privateKey = configOrKey;
|
|
27
|
+
if (privateKey.includes('\\n')) {
|
|
28
|
+
privateKey = privateKey.replace(/\\n/g, '\n');
|
|
29
|
+
}
|
|
30
|
+
this.signer = new ethers_1.Wallet(privateKey);
|
|
31
|
+
this.isDelegated = false;
|
|
32
|
+
this.httpClient = new sdk_1.HttpClient({
|
|
33
|
+
baseURL: LIMITLESS_API_URL,
|
|
34
|
+
apiKey: apiKey,
|
|
35
|
+
timeout: 30000,
|
|
36
|
+
});
|
|
37
|
+
// ethers v5/v6 compat: SDK expects wallet.signTypedData (v6)
|
|
38
|
+
const wallet = this.signer;
|
|
39
|
+
if (!wallet.signTypedData && wallet._signTypedData) {
|
|
40
|
+
wallet.signTypedData = wallet._signTypedData;
|
|
41
|
+
}
|
|
42
|
+
this.orderClient = new sdk_1.OrderClient({
|
|
43
|
+
httpClient: this.httpClient,
|
|
44
|
+
wallet: wallet,
|
|
45
|
+
});
|
|
46
|
+
this.marketFetcher = new sdk_1.MarketFetcher(this.httpClient);
|
|
47
|
+
return;
|
|
21
48
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.httpClient =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
timeout: 30000,
|
|
28
|
-
});
|
|
29
|
-
// Initialize SDK clients
|
|
30
|
-
// Note: SDK uses ethers v6, we use v5, so we cast to any
|
|
31
|
-
this.orderClient = new sdk_1.OrderClient({
|
|
32
|
-
httpClient: this.httpClient,
|
|
33
|
-
wallet: this.signer,
|
|
34
|
-
});
|
|
49
|
+
// New config-object constructor
|
|
50
|
+
const config = configOrKey;
|
|
51
|
+
this.httpClient = config.httpClient;
|
|
52
|
+
this.isDelegated = config.isDelegated ?? false;
|
|
53
|
+
this.walletAddress = config.walletAddress;
|
|
35
54
|
this.marketFetcher = new sdk_1.MarketFetcher(this.httpClient);
|
|
55
|
+
if (!this.isDelegated && config.wallet) {
|
|
56
|
+
this.signer = config.wallet;
|
|
57
|
+
const wallet = this.signer;
|
|
58
|
+
if (!wallet.signTypedData && wallet._signTypedData) {
|
|
59
|
+
wallet.signTypedData = wallet._signTypedData;
|
|
60
|
+
}
|
|
61
|
+
this.orderClient = new sdk_1.OrderClient({
|
|
62
|
+
httpClient: this.httpClient,
|
|
63
|
+
wallet: wallet,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// In delegated mode without a wallet, createOrder uses a direct
|
|
67
|
+
// HTTP POST with an unsigned order payload (no SDK DelegatedOrderService
|
|
68
|
+
// required — compatible with all SDK versions).
|
|
36
69
|
}
|
|
37
70
|
/**
|
|
38
71
|
* Get market details by slug.
|
|
@@ -50,33 +83,159 @@ class LimitlessClient {
|
|
|
50
83
|
return market;
|
|
51
84
|
}
|
|
52
85
|
/**
|
|
53
|
-
* Create
|
|
54
|
-
*
|
|
86
|
+
* Create an order.
|
|
87
|
+
*
|
|
88
|
+
* - Individual mode: EIP-712 signed via OrderClient (requires private key).
|
|
89
|
+
* - Delegated mode: unsigned order via DelegatedOrderService (HMAC auth).
|
|
55
90
|
*/
|
|
56
91
|
async createOrder(params) {
|
|
57
92
|
const market = await this.getMarket(params.marketSlug);
|
|
58
93
|
if (!market.venue || !market.venue.exchange) {
|
|
59
94
|
throw new Error(`Market ${params.marketSlug} has no venue exchange address`);
|
|
60
95
|
}
|
|
61
|
-
// Map BUY/SELL to SDK's Side enum
|
|
62
96
|
const side = params.side === 'BUY' ? sdk_1.Side.BUY : sdk_1.Side.SELL;
|
|
63
|
-
// Determine order type - default to GTC (limit orders)
|
|
64
|
-
// FOK (Fill-or-Kill) can be used for market orders
|
|
65
97
|
const orderType = params.type === 'market' ? sdk_1.OrderType.FOK : sdk_1.OrderType.GTC;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
98
|
+
if (this.isDelegated) {
|
|
99
|
+
return this.createDelegatedOrder(params, side, orderType);
|
|
100
|
+
}
|
|
101
|
+
if (!this.signer) {
|
|
102
|
+
throw new Error('No signer available. Provide a privateKey or use delegated signing.');
|
|
103
|
+
}
|
|
104
|
+
// For smart wallets: maker = smartWallet address, signer = EOA address.
|
|
105
|
+
// For EOA wallets: maker = signer = wallet address.
|
|
106
|
+
// The walletAddress credential indicates a smart wallet.
|
|
107
|
+
const signerAddress = this.signer.address;
|
|
108
|
+
const makerAddress = this.walletAddress ?? signerAddress;
|
|
109
|
+
const isSmartWallet = makerAddress.toLowerCase() !== signerAddress.toLowerCase();
|
|
110
|
+
if (!isSmartWallet && this.orderClient) {
|
|
111
|
+
// Standard EOA flow — use the SDK's OrderClient directly.
|
|
112
|
+
return this.orderClient.createOrder({
|
|
113
|
+
tokenId: params.outcomeId,
|
|
114
|
+
price: params.price,
|
|
115
|
+
size: params.amount,
|
|
116
|
+
side,
|
|
117
|
+
orderType,
|
|
118
|
+
marketSlug: params.marketSlug,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// Smart wallet flow: build the order with maker=smartWallet, signer=EOA,
|
|
122
|
+
// sign with the EOA key, and submit.
|
|
123
|
+
return this.createSmartWalletOrder(params, side, orderType, market, makerAddress, signerAddress);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create an order for a smart wallet account.
|
|
127
|
+
* maker = smart wallet address, signer = EOA address (our private key).
|
|
128
|
+
*/
|
|
129
|
+
async createSmartWalletOrder(params, side, orderType, market, makerAddress, signerAddress) {
|
|
130
|
+
if (!this.walletAddress) {
|
|
131
|
+
throw new Error('Smart wallet flow requires walletAddress in credentials.');
|
|
132
|
+
}
|
|
133
|
+
if (!this.signer) {
|
|
134
|
+
throw new Error('Smart wallet flow requires a privateKey for signing.');
|
|
135
|
+
}
|
|
136
|
+
const profile = await this.resolveProfile();
|
|
137
|
+
const feeRateBps = profile.feeRateBps ?? 100;
|
|
138
|
+
// Build unsigned order with maker = smart wallet address.
|
|
139
|
+
const builder = new sdk_1.OrderBuilder(makerAddress, feeRateBps);
|
|
140
|
+
const orderArgs = orderType === sdk_1.OrderType.FOK
|
|
141
|
+
? { tokenId: params.outcomeId, makerAmount: params.price * params.amount, side }
|
|
142
|
+
: { tokenId: params.outcomeId, price: params.price, size: params.amount, side };
|
|
143
|
+
const unsignedOrder = builder.buildOrder(orderArgs);
|
|
144
|
+
// Override signer to the EOA (different from maker for smart wallets).
|
|
145
|
+
unsignedOrder.signer = signerAddress;
|
|
146
|
+
// ethers v5/v6 compat shim — SDK expects signTypedData (v6).
|
|
147
|
+
const wallet = this.signer;
|
|
148
|
+
if (!wallet.signTypedData && wallet._signTypedData) {
|
|
149
|
+
wallet.signTypedData = wallet._signTypedData;
|
|
150
|
+
}
|
|
151
|
+
// Sign with the EOA private key.
|
|
152
|
+
const orderSigner = new sdk_1.OrderSigner(wallet);
|
|
153
|
+
const signature = await orderSigner.signOrder(unsignedOrder, {
|
|
154
|
+
chainId: 8453,
|
|
155
|
+
contractAddress: market.venue.exchange,
|
|
78
156
|
});
|
|
79
|
-
|
|
157
|
+
// Submit with ownerId (required by Limitless API).
|
|
158
|
+
const payload = {
|
|
159
|
+
order: { ...unsignedOrder, signature },
|
|
160
|
+
orderType: orderType === sdk_1.OrderType.FOK ? 'FOK' : 'GTC',
|
|
161
|
+
marketSlug: params.marketSlug,
|
|
162
|
+
ownerId: profile.id,
|
|
163
|
+
};
|
|
164
|
+
const response = await this.httpClient.post('/orders', payload);
|
|
165
|
+
return {
|
|
166
|
+
order: response,
|
|
167
|
+
id: response?.order?.id ?? 'unknown',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Build and submit an unsigned order via the delegated signing flow.
|
|
172
|
+
* The Limitless server signs on behalf of the partner account.
|
|
173
|
+
* No private key required — uses HMAC-authenticated HTTP.
|
|
174
|
+
*/
|
|
175
|
+
/**
|
|
176
|
+
* Resolve the Limitless profile ID for this account.
|
|
177
|
+
* Fetched once from the public profile endpoint, then cached.
|
|
178
|
+
*/
|
|
179
|
+
cachedProfile;
|
|
180
|
+
async resolveProfile() {
|
|
181
|
+
if (this.cachedProfile)
|
|
182
|
+
return this.cachedProfile;
|
|
183
|
+
const addr = this.walletAddress ?? this.signer?.address;
|
|
184
|
+
if (!addr) {
|
|
185
|
+
throw new Error('No wallet address available for profile lookup.');
|
|
186
|
+
}
|
|
187
|
+
const profile = await this.httpClient.get(`/profiles/public/${addr}`);
|
|
188
|
+
const id = profile?.id;
|
|
189
|
+
if (!id || !Number.isFinite(id)) {
|
|
190
|
+
throw new Error(`Could not resolve Limitless profile ID for ${addr}`);
|
|
191
|
+
}
|
|
192
|
+
this.cachedProfile = {
|
|
193
|
+
id,
|
|
194
|
+
feeRateBps: profile?.rank?.feeRateBps ?? 100,
|
|
195
|
+
};
|
|
196
|
+
return this.cachedProfile;
|
|
197
|
+
}
|
|
198
|
+
async resolveProfileId() {
|
|
199
|
+
return (await this.resolveProfile()).id;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Build and submit an unsigned order via the delegated signing flow.
|
|
203
|
+
* The Limitless server signs on behalf of the account.
|
|
204
|
+
*/
|
|
205
|
+
async createDelegatedOrder(params, side, orderType) {
|
|
206
|
+
const profileId = params.onBehalfOf ?? await this.resolveProfileId();
|
|
207
|
+
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
208
|
+
const USDC_DECIMALS = 6;
|
|
209
|
+
const price = Math.round(params.price * 1_000_000) / 1_000_000;
|
|
210
|
+
const size = params.amount;
|
|
211
|
+
const makerAmount = Math.round(price * size * Math.pow(10, USDC_DECIMALS));
|
|
212
|
+
const takerAmount = Math.round(size * Math.pow(10, USDC_DECIMALS));
|
|
213
|
+
const payload = {
|
|
214
|
+
order: {
|
|
215
|
+
salt: Date.now() * 1000 + Math.floor(Math.random() * 1000),
|
|
216
|
+
maker: ZERO_ADDRESS,
|
|
217
|
+
signer: ZERO_ADDRESS,
|
|
218
|
+
taker: ZERO_ADDRESS,
|
|
219
|
+
tokenId: params.outcomeId,
|
|
220
|
+
makerAmount: side === sdk_1.Side.BUY ? makerAmount : takerAmount,
|
|
221
|
+
takerAmount: side === sdk_1.Side.BUY ? takerAmount : makerAmount,
|
|
222
|
+
expiration: '0',
|
|
223
|
+
nonce: 0,
|
|
224
|
+
feeRateBps: 100,
|
|
225
|
+
side: side === sdk_1.Side.BUY ? 0 : 1,
|
|
226
|
+
signatureType: 0,
|
|
227
|
+
price,
|
|
228
|
+
},
|
|
229
|
+
orderType: orderType === sdk_1.OrderType.FOK ? 'FOK' : 'GTC',
|
|
230
|
+
marketSlug: params.marketSlug,
|
|
231
|
+
ownerId: profileId,
|
|
232
|
+
onBehalfOf: profileId,
|
|
233
|
+
};
|
|
234
|
+
const response = await this.httpClient.post('/orders', payload);
|
|
235
|
+
return {
|
|
236
|
+
order: response,
|
|
237
|
+
id: response?.order?.id ?? 'unknown',
|
|
238
|
+
};
|
|
80
239
|
}
|
|
81
240
|
/**
|
|
82
241
|
* Cancel a specific order by ID.
|
|
@@ -109,7 +268,7 @@ class LimitlessClient {
|
|
|
109
268
|
* Get the signer's wallet address.
|
|
110
269
|
*/
|
|
111
270
|
getAddress() {
|
|
112
|
-
return this.signer
|
|
271
|
+
return this.signer?.address ?? '';
|
|
113
272
|
}
|
|
114
273
|
/**
|
|
115
274
|
* Get the underlying HTTP client for direct API access.
|
|
@@ -53,10 +53,33 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
53
53
|
if (credentials?.apiKey || credentials?.privateKey) {
|
|
54
54
|
try {
|
|
55
55
|
this.auth = new auth_1.LimitlessAuth(credentials);
|
|
56
|
-
// Initialize client only if we have both privateKey and apiKey
|
|
57
56
|
if (credentials.privateKey) {
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
// Signing mode: use the private key for EIP-712 signatures.
|
|
58
|
+
// When apiSecret is also present, use HMAC-authenticated HTTP
|
|
59
|
+
// (new-style tokens); otherwise legacy X-API-Key header.
|
|
60
|
+
if (credentials.apiSecret) {
|
|
61
|
+
let pk = credentials.privateKey;
|
|
62
|
+
if (!pk.startsWith('0x'))
|
|
63
|
+
pk = '0x' + pk;
|
|
64
|
+
const wallet = new (require('ethers').Wallet)(pk);
|
|
65
|
+
this.client = new client_1.LimitlessClient({
|
|
66
|
+
httpClient: this.auth.getHttpClient(),
|
|
67
|
+
wallet,
|
|
68
|
+
walletAddress: credentials.walletAddress,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const apiKey = this.auth.getApiKey();
|
|
73
|
+
this.client = new client_1.LimitlessClient(credentials.privateKey, apiKey);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (this.auth.isDelegatedSigning()) {
|
|
77
|
+
// Delegated mode: HMAC auth, no private key, server signs
|
|
78
|
+
this.client = new client_1.LimitlessClient({
|
|
79
|
+
httpClient: this.auth.getHttpClient(),
|
|
80
|
+
isDelegated: true,
|
|
81
|
+
walletAddress: credentials.walletAddress,
|
|
82
|
+
});
|
|
60
83
|
}
|
|
61
84
|
}
|
|
62
85
|
catch (error) {
|
|
@@ -197,6 +220,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
197
220
|
price: price,
|
|
198
221
|
amount: params.amount,
|
|
199
222
|
type: params.type,
|
|
223
|
+
onBehalfOf: params.onBehalfOf,
|
|
200
224
|
});
|
|
201
225
|
// Map response to Order object
|
|
202
226
|
// The SDK returns OrderResponse with order.id
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/myriad/myriad.yaml
|
|
3
|
-
* Generated at: 2026-05-
|
|
3
|
+
* Generated at: 2026-05-07T05:14:50.228Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const myriadApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.myriadApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/myriad/myriad.yaml
|
|
6
|
-
* Generated at: 2026-05-
|
|
6
|
+
* Generated at: 2026-05-07T05:14:50.228Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.myriadApiSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/opinion/opinion-openapi.yaml
|
|
3
|
-
* Generated at: 2026-05-
|
|
3
|
+
* Generated at: 2026-05-07T05:14:50.231Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const opinionApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.opinionApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/opinion/opinion-openapi.yaml
|
|
6
|
-
* Generated at: 2026-05-
|
|
6
|
+
* Generated at: 2026-05-07T05:14:50.231Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.opinionApiSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketClobAPI.yaml
|
|
3
|
-
* Generated at: 2026-05-
|
|
3
|
+
* Generated at: 2026-05-07T05:14:50.184Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const polymarketClobSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.polymarketClobSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketClobAPI.yaml
|
|
6
|
-
* Generated at: 2026-05-
|
|
6
|
+
* Generated at: 2026-05-07T05:14:50.184Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.polymarketClobSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/Polymarket_Data_API.yaml
|
|
3
|
-
* Generated at: 2026-05-
|
|
3
|
+
* Generated at: 2026-05-07T05:14:50.199Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const polymarketDataSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.polymarketDataSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/Polymarket_Data_API.yaml
|
|
6
|
-
* Generated at: 2026-05-
|
|
6
|
+
* Generated at: 2026-05-07T05:14:50.199Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.polymarketDataSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketGammaAPI.yaml
|
|
3
|
-
* Generated at: 2026-05-
|
|
3
|
+
* Generated at: 2026-05-07T05:14:50.197Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const polymarketGammaSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.polymarketGammaSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketGammaAPI.yaml
|
|
6
|
-
* Generated at: 2026-05-
|
|
6
|
+
* Generated at: 2026-05-07T05:14:50.197Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.polymarketGammaSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/probable/probable.yaml
|
|
3
|
-
* Generated at: 2026-05-
|
|
3
|
+
* Generated at: 2026-05-07T05:14:50.222Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const probableApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.probableApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/probable/probable.yaml
|
|
6
|
-
* Generated at: 2026-05-
|
|
6
|
+
* Generated at: 2026-05-07T05:14:50.222Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.probableApiSpec = {
|
package/dist/server/openapi.yaml
CHANGED
|
@@ -2843,6 +2843,9 @@ components:
|
|
|
2843
2843
|
negRisk:
|
|
2844
2844
|
type: boolean
|
|
2845
2845
|
description: Optional override to skip neg-risk lookup (Polymarket)
|
|
2846
|
+
onBehalfOf:
|
|
2847
|
+
type: number
|
|
2848
|
+
description: 'Limitless delegated signing: profile ID to trade on behalf of'
|
|
2846
2849
|
required:
|
|
2847
2850
|
- marketId
|
|
2848
2851
|
- outcomeId
|
|
@@ -3381,6 +3384,8 @@ components:
|
|
|
3381
3384
|
funderAddress:
|
|
3382
3385
|
type: string
|
|
3383
3386
|
description: The address funding the trades (defaults to signer address)
|
|
3387
|
+
walletAddress:
|
|
3388
|
+
type: string
|
|
3384
3389
|
x-sdk-constructors:
|
|
3385
3390
|
polymarket:
|
|
3386
3391
|
className: Polymarket
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmxt-core",
|
|
3
|
-
"version": "2.37.
|
|
3
|
+
"version": "2.37.9",
|
|
4
4
|
"description": "pmxt is a unified prediction market data API. The ccxt for prediction markets.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"test": "jest -c jest.config.js",
|
|
30
30
|
"server": "tsx watch src/server/index.ts",
|
|
31
31
|
"server:prod": "node dist/server/index.js",
|
|
32
|
-
"generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.37.
|
|
33
|
-
"generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.37.
|
|
32
|
+
"generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.37.9,library=urllib3",
|
|
33
|
+
"generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.37.9,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.js",
|
|
34
34
|
"fetch:openapi": "node scripts/fetch-openapi-specs.js",
|
|
35
35
|
"extract:jsdoc": "node ../scripts/extract-jsdoc.js",
|
|
36
36
|
"generate:docs": "npm run extract:jsdoc && node ../scripts/generate-api-docs.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"type": "commonjs",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@limitless-exchange/sdk": "^1.0.
|
|
48
|
+
"@limitless-exchange/sdk": "^1.0.5",
|
|
49
49
|
"@opinion-labs/opinion-clob-sdk": "^0.6.0",
|
|
50
50
|
"@polymarket/clob-client-v2": "^1.0.0",
|
|
51
51
|
"@prob/clob": "0.5.0",
|