@jsnw/kalshi-client 0.0.1 → 0.2.0
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/index.cjs +271 -13
- package/dist/index.d.cts +567 -121
- package/dist/index.d.mts +567 -121
- package/dist/index.mjs +252 -14
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,7 @@ let zod = require("zod");
|
|
|
4
4
|
let uuid = require("uuid");
|
|
5
5
|
let ws = require("ws");
|
|
6
6
|
let node_timers_promises = require("node:timers/promises");
|
|
7
|
+
let _jsnw_api_client = require("@jsnw/api-client");
|
|
7
8
|
//#region src/request-signer.ts
|
|
8
9
|
var RequestSigner = class {
|
|
9
10
|
privkey;
|
|
@@ -78,8 +79,39 @@ const primitives$fixedPointSchema = zod.z.string().regex(/^\d{1,14}\.\d{2,8}$/);
|
|
|
78
79
|
const primitives$orderSideSchema = zod.z.enum(["yes", "no"]);
|
|
79
80
|
const primitives$bookSideSchema = zod.z.enum(["bid", "ask"]);
|
|
80
81
|
const primitives$orderActionSchema = zod.z.enum(["buy", "sell"]);
|
|
82
|
+
const primitives$rateLimitBucketMetaSchema = zod.z.object({
|
|
83
|
+
refill_rate: zod.z.number(),
|
|
84
|
+
bucket_capacity: zod.z.number()
|
|
85
|
+
});
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/schemas/http.ts
|
|
88
|
+
const http$errorMessageSchema = zod.z.object({
|
|
89
|
+
code: zod.z.number(),
|
|
90
|
+
message: zod.z.string().optional(),
|
|
91
|
+
details: zod.z.any().optional(),
|
|
92
|
+
service: zod.z.any().optional()
|
|
93
|
+
});
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/schemas/account.ts
|
|
96
|
+
const account$accountTierSchema = zod.z.enum([
|
|
97
|
+
"basic",
|
|
98
|
+
"advanced",
|
|
99
|
+
"expert",
|
|
100
|
+
"premier",
|
|
101
|
+
"paragon",
|
|
102
|
+
"prime",
|
|
103
|
+
"prestige"
|
|
104
|
+
]);
|
|
105
|
+
const account$subaccountSchema = zod.z.number().min(0).max(63).default(0);
|
|
106
|
+
const account$accountGrantSchema = zod.z.object({
|
|
107
|
+
exchange_instance: zod.z.enum(["event_contract", "margined"]),
|
|
108
|
+
level: account$accountTierSchema,
|
|
109
|
+
source: zod.z.enum(["volume", "manual"]),
|
|
110
|
+
expires_ts: zod.z.number().nullable().default(null)
|
|
111
|
+
});
|
|
81
112
|
//#endregion
|
|
82
113
|
//#region src/schemas/orders.ts
|
|
114
|
+
const orders$clientOrderIdSchema = zod.z.string().nullable().optional();
|
|
83
115
|
const orders$orderStatusSchema = zod.z.enum([
|
|
84
116
|
"resting",
|
|
85
117
|
"canceled",
|
|
@@ -87,17 +119,22 @@ const orders$orderStatusSchema = zod.z.enum([
|
|
|
87
119
|
]);
|
|
88
120
|
const orders$orderTypeSchema = zod.z.enum(["limit", "market"]);
|
|
89
121
|
const orders$selfTradePreventionTypeSchema = zod.z.enum(["taker_at_cross", "maker"]);
|
|
122
|
+
const orders$timeInForceSchema = zod.z.enum([
|
|
123
|
+
"fill_or_kill",
|
|
124
|
+
"good_till_canceled",
|
|
125
|
+
"immediate_or_cancel"
|
|
126
|
+
]);
|
|
90
127
|
const orders$orderDetailedSchema = zod.z.object({
|
|
91
128
|
order_id: zod.z.uuid(),
|
|
92
129
|
user_id: zod.z.uuid(),
|
|
93
|
-
|
|
94
|
-
order_group_id: zod.z.
|
|
130
|
+
client_order_id: orders$clientOrderIdSchema,
|
|
131
|
+
order_group_id: zod.z.string().nullable().optional(),
|
|
132
|
+
subaccount_number: account$subaccountSchema,
|
|
95
133
|
exchange_index: zod.z.number().min(0).default(0),
|
|
96
|
-
client_order_id: zod.z.string(),
|
|
97
134
|
ticker: zod.z.string(),
|
|
135
|
+
type: orders$orderTypeSchema,
|
|
98
136
|
outcome_side: primitives$orderSideSchema,
|
|
99
137
|
book_side: primitives$bookSideSchema,
|
|
100
|
-
type: orders$orderTypeSchema,
|
|
101
138
|
status: orders$orderStatusSchema,
|
|
102
139
|
yes_price_dollars: primitives$fixedPointSchema,
|
|
103
140
|
no_price_dollars: primitives$fixedPointSchema,
|
|
@@ -108,11 +145,11 @@ const orders$orderDetailedSchema = zod.z.object({
|
|
|
108
145
|
maker_fill_cost_dollars: primitives$fixedPointSchema,
|
|
109
146
|
taker_fees_dollars: primitives$fixedPointSchema,
|
|
110
147
|
maker_fees_dollars: primitives$fixedPointSchema,
|
|
111
|
-
self_trade_prevention_type: orders$selfTradePreventionTypeSchema
|
|
148
|
+
self_trade_prevention_type: orders$selfTradePreventionTypeSchema,
|
|
112
149
|
cancel_order_on_pause: zod.z.boolean(),
|
|
113
150
|
created_time: zod.z.iso.datetime(),
|
|
114
|
-
|
|
115
|
-
|
|
151
|
+
last_update_time: zod.z.iso.datetime().nullable().optional(),
|
|
152
|
+
expiration_time: zod.z.iso.datetime().nullable().optional()
|
|
116
153
|
});
|
|
117
154
|
const orders$orderWsSchema = orders$orderDetailedSchema.omit({
|
|
118
155
|
exchange_index: true,
|
|
@@ -125,12 +162,32 @@ const orders$orderWsSchema = orders$orderDetailedSchema.omit({
|
|
|
125
162
|
last_updated_ts_ms: zod.z.number().positive().optional(),
|
|
126
163
|
expiration_ts_ms: zod.z.number().positive().optional()
|
|
127
164
|
});
|
|
165
|
+
const orders$createOrderDtoSchema = zod.z.object({
|
|
166
|
+
client_order_id: zod.z.string().optional(),
|
|
167
|
+
order_group_id: zod.z.string().optional(),
|
|
168
|
+
exchange_index: zod.z.number().min(0).default(0),
|
|
169
|
+
ticker: zod.z.string(),
|
|
170
|
+
side: primitives$bookSideSchema,
|
|
171
|
+
count: primitives$fixedPointSchema,
|
|
172
|
+
subaccount: account$subaccountSchema,
|
|
173
|
+
price: primitives$fixedPointSchema,
|
|
174
|
+
post_only: zod.z.boolean().default(false),
|
|
175
|
+
reduce_only: zod.z.boolean().default(false),
|
|
176
|
+
cancel_order_on_pause: zod.z.boolean(),
|
|
177
|
+
self_trade_prevention_type: orders$selfTradePreventionTypeSchema,
|
|
178
|
+
time_in_force: orders$timeInForceSchema,
|
|
179
|
+
expiration_time: zod.z.number().optional()
|
|
180
|
+
});
|
|
128
181
|
//#endregion
|
|
129
182
|
//#region src/consts.ts
|
|
130
183
|
const KALSHI_WS_URL = {
|
|
131
184
|
"development": "wss://external-api-ws.demo.kalshi.co",
|
|
132
185
|
"production": "wss://external-api-ws.kalshi.com"
|
|
133
186
|
};
|
|
187
|
+
const KALSHI_API_URL = {
|
|
188
|
+
"development": "https://external-api.demo.kalshi.co",
|
|
189
|
+
"production": "https://external-api.kalshi.com"
|
|
190
|
+
};
|
|
134
191
|
//#endregion
|
|
135
192
|
//#region src/typed-emitter.ts
|
|
136
193
|
var TypedEmitter = class {
|
|
@@ -502,6 +559,8 @@ var WsKalshiError = class extends Error {
|
|
|
502
559
|
this.code = code;
|
|
503
560
|
}
|
|
504
561
|
};
|
|
562
|
+
var WsClosedError = class extends Error {};
|
|
563
|
+
var WsClosedByUserError = class extends Error {};
|
|
505
564
|
//#endregion
|
|
506
565
|
//#region src/ws/ws-client.ts
|
|
507
566
|
var WsClient = class extends TypedEmitter {
|
|
@@ -546,9 +605,39 @@ var WsClient = class extends TypedEmitter {
|
|
|
546
605
|
this.ws.on("reconnecting", this.onReconnecting);
|
|
547
606
|
this.ws.on("close", this.onClose);
|
|
548
607
|
}
|
|
608
|
+
/**
|
|
609
|
+
* @return {Promise<void>}
|
|
610
|
+
*/
|
|
611
|
+
connect() {
|
|
612
|
+
return this.ws.open();
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* @return {Promise<void>}
|
|
616
|
+
*/
|
|
617
|
+
async subscribe(options) {
|
|
618
|
+
const { channel, timeoutMs, ...rest } = options;
|
|
619
|
+
const messageId = ++this.lastMessageId;
|
|
620
|
+
const payload = {
|
|
621
|
+
id: messageId,
|
|
622
|
+
cmd: "subscribe",
|
|
623
|
+
params: {
|
|
624
|
+
channels: [channel],
|
|
625
|
+
...rest
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
const promise = this.subscribeAwaiters.add(messageId, timeoutMs ?? 2e3);
|
|
629
|
+
await this.ws.send(JSON.stringify(payload));
|
|
630
|
+
return promise;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* @return {Promise<void>}
|
|
634
|
+
*/
|
|
635
|
+
close() {
|
|
636
|
+
this.subscribeAwaiters.clear(new WsClosedByUserError());
|
|
637
|
+
return this.ws.close();
|
|
638
|
+
}
|
|
549
639
|
onReady = async (afterReconnect) => {
|
|
550
|
-
this.
|
|
551
|
-
this.emit("ready");
|
|
640
|
+
this.emit("ready", afterReconnect);
|
|
552
641
|
};
|
|
553
642
|
/**
|
|
554
643
|
* @param {WebSocket.RawData} data
|
|
@@ -582,21 +671,19 @@ var WsClient = class extends TypedEmitter {
|
|
|
582
671
|
* @param {number} attempt
|
|
583
672
|
*/
|
|
584
673
|
onReconnecting = (attempt) => {
|
|
585
|
-
this.log("debug", "reconnecting", { attempt });
|
|
586
674
|
this.emit("reconnect", attempt);
|
|
587
675
|
};
|
|
588
676
|
/**
|
|
589
677
|
* @param {Error} err
|
|
590
678
|
*/
|
|
591
679
|
onError = (err) => {
|
|
592
|
-
this.
|
|
680
|
+
this.emit("ws_error", err);
|
|
593
681
|
};
|
|
594
682
|
/**
|
|
595
683
|
*/
|
|
596
684
|
onClose = () => {
|
|
597
|
-
this.log("debug", "WebSocket connection closed");
|
|
598
685
|
this.emit("close");
|
|
599
|
-
this.subscribeAwaiters.clear();
|
|
686
|
+
this.subscribeAwaiters.clear(new WsClosedError());
|
|
600
687
|
};
|
|
601
688
|
/**
|
|
602
689
|
* @param {WsAnyMessage} msg
|
|
@@ -650,21 +737,192 @@ const WS_KALSHI_SERVER_ERRORS = [
|
|
|
650
737
|
WS_KALSHI_ERRORS.COMMAND_TIMEOUT
|
|
651
738
|
];
|
|
652
739
|
//#endregion
|
|
740
|
+
//#region src/api/metadata.ts
|
|
741
|
+
const METADATA = { NO_AUTH: Symbol("no-auth") };
|
|
742
|
+
//#endregion
|
|
743
|
+
//#region src/api/router/exchange.ts
|
|
744
|
+
const exchangeRouter = (0, _jsnw_api_client.createRouter)({
|
|
745
|
+
getStatus: {
|
|
746
|
+
method: "get",
|
|
747
|
+
path: "/status",
|
|
748
|
+
responses: { 200: zod.z.object({
|
|
749
|
+
exchange_active: zod.z.boolean(),
|
|
750
|
+
trading_active: zod.z.boolean(),
|
|
751
|
+
exchange_estimated_resume_time: zod.z.iso.datetime().nullable().optional()
|
|
752
|
+
}) }
|
|
753
|
+
},
|
|
754
|
+
getUserDataTimestamp: {
|
|
755
|
+
method: "get",
|
|
756
|
+
path: "/user_data_timestamp",
|
|
757
|
+
responses: { 200: zod.z.object({ as_of_time: zod.z.iso.datetime() }) }
|
|
758
|
+
}
|
|
759
|
+
}, {
|
|
760
|
+
path: "exchange",
|
|
761
|
+
metadata: { [METADATA.NO_AUTH]: true }
|
|
762
|
+
});
|
|
763
|
+
//#endregion
|
|
764
|
+
//#region src/api/router/account.ts
|
|
765
|
+
const accountRouter = (0, _jsnw_api_client.createRouter)({
|
|
766
|
+
getLimits: {
|
|
767
|
+
method: "get",
|
|
768
|
+
path: "/limits",
|
|
769
|
+
responses: { 200: zod.z.object({
|
|
770
|
+
usage_tier: account$accountTierSchema,
|
|
771
|
+
read: primitives$rateLimitBucketMetaSchema,
|
|
772
|
+
write: primitives$rateLimitBucketMetaSchema,
|
|
773
|
+
grants: zod.z.array(account$accountGrantSchema)
|
|
774
|
+
}) }
|
|
775
|
+
},
|
|
776
|
+
listNonDefaultEndpointCosts: {
|
|
777
|
+
method: "get",
|
|
778
|
+
path: "/endpoint_costs",
|
|
779
|
+
responses: { 200: zod.z.object({
|
|
780
|
+
default_cost: zod.z.number().min(0),
|
|
781
|
+
endpoint_costs: zod.z.array(zod.z.object({
|
|
782
|
+
method: zod.z.string(),
|
|
783
|
+
path: zod.z.string(),
|
|
784
|
+
cost: zod.z.number().min(0)
|
|
785
|
+
}))
|
|
786
|
+
}) },
|
|
787
|
+
metadata: { [METADATA.NO_AUTH]: true }
|
|
788
|
+
}
|
|
789
|
+
}, { path: "/account" });
|
|
790
|
+
//#endregion
|
|
791
|
+
//#region src/api/router/orders.ts
|
|
792
|
+
const ordersRouter = (0, _jsnw_api_client.createRouter)({
|
|
793
|
+
getOrder: {
|
|
794
|
+
method: "get",
|
|
795
|
+
path: "/orders/:order_id",
|
|
796
|
+
params: zod.z.object({ order_id: zod.z.uuid() }),
|
|
797
|
+
responses: { 200: zod.z.object({ order: orders$orderDetailedSchema }) }
|
|
798
|
+
},
|
|
799
|
+
createOrder: {
|
|
800
|
+
method: "post",
|
|
801
|
+
path: "/events/orders",
|
|
802
|
+
body: orders$createOrderDtoSchema,
|
|
803
|
+
responses: { 201: zod.z.object({
|
|
804
|
+
order_id: zod.z.uuid(),
|
|
805
|
+
client_order_id: orders$clientOrderIdSchema,
|
|
806
|
+
fill_count: primitives$fixedPointSchema,
|
|
807
|
+
remaining_count: primitives$fixedPointSchema,
|
|
808
|
+
average_fill_price: primitives$fixedPointSchema.nullable().optional(),
|
|
809
|
+
average_fee_paid: primitives$fixedPointSchema.nullable().optional(),
|
|
810
|
+
ts_ms: zod.z.number().min(0)
|
|
811
|
+
}) }
|
|
812
|
+
},
|
|
813
|
+
cancelOrderV1: {
|
|
814
|
+
method: "delete",
|
|
815
|
+
path: "/orders/:order_id",
|
|
816
|
+
params: zod.z.object({ order_id: zod.z.uuid() }),
|
|
817
|
+
query: zod.z.object({
|
|
818
|
+
subaccount: zod.z.number().min(0).max(63).default(0),
|
|
819
|
+
exchange_index: zod.z.number().min(0).default(0)
|
|
820
|
+
}).prefault({}),
|
|
821
|
+
responses: { 200: zod.z.object({
|
|
822
|
+
order: orders$orderDetailedSchema,
|
|
823
|
+
reduced_by_fp: primitives$fixedPointSchema
|
|
824
|
+
}) }
|
|
825
|
+
},
|
|
826
|
+
cancelOrderV2: {
|
|
827
|
+
method: "delete",
|
|
828
|
+
path: "/events/orders/:order_id",
|
|
829
|
+
params: zod.z.object({ order_id: zod.z.uuid() }),
|
|
830
|
+
query: zod.z.object({
|
|
831
|
+
subaccount: zod.z.number().min(0).max(63).default(0),
|
|
832
|
+
exchange_index: zod.z.number().min(0).default(0)
|
|
833
|
+
}).prefault({}),
|
|
834
|
+
responses: { 200: zod.z.object({
|
|
835
|
+
order_id: zod.z.uuid(),
|
|
836
|
+
client_order_id: orders$clientOrderIdSchema,
|
|
837
|
+
reduced_by: primitives$fixedPointSchema,
|
|
838
|
+
ts_ms: zod.z.number().min(0)
|
|
839
|
+
}) }
|
|
840
|
+
},
|
|
841
|
+
getOrderQueuePosition: {
|
|
842
|
+
method: "get",
|
|
843
|
+
path: "/orders/:order_id/queue_position",
|
|
844
|
+
params: zod.z.object({ order_id: zod.z.uuid() }),
|
|
845
|
+
responses: { 200: zod.z.object({ queue_position_fp: primitives$fixedPointSchema }) }
|
|
846
|
+
}
|
|
847
|
+
}, { path: "/portfolio" });
|
|
848
|
+
//#endregion
|
|
849
|
+
//#region src/api/router/index.ts
|
|
850
|
+
const apiRouter = (0, _jsnw_api_client.createRouter)({
|
|
851
|
+
exchange: exchangeRouter,
|
|
852
|
+
account: accountRouter,
|
|
853
|
+
orders: ordersRouter
|
|
854
|
+
}, { path: "/trade-api/v2" });
|
|
855
|
+
//#endregion
|
|
856
|
+
//#region src/api/client.ts
|
|
857
|
+
var ApiClient = class extends _jsnw_api_client.ApiClient {
|
|
858
|
+
/**
|
|
859
|
+
* @param {ApiClientConfig} config
|
|
860
|
+
*/
|
|
861
|
+
constructor(config) {
|
|
862
|
+
super(apiRouter, {
|
|
863
|
+
...config,
|
|
864
|
+
baseURL: KALSHI_API_URL[config.environment ?? "development"],
|
|
865
|
+
qsArrayFormat: "brackets",
|
|
866
|
+
contentType: "application/json"
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* @template {Route} TRoute
|
|
871
|
+
* @param {TRoute} route
|
|
872
|
+
* @param {ApiRequestParams<TRoute>} params
|
|
873
|
+
* @param {ApiCallOptions} options
|
|
874
|
+
* @return {Promise<ApiResponse<TRoute>>}
|
|
875
|
+
*/
|
|
876
|
+
/**
|
|
877
|
+
* @param {"force"} force
|
|
878
|
+
* @return {Promise<void>}
|
|
879
|
+
* @private
|
|
880
|
+
*/
|
|
881
|
+
/**
|
|
882
|
+
* @param {ApiRawRequest} req
|
|
883
|
+
* @return {ApiRawRequest}
|
|
884
|
+
* @protected
|
|
885
|
+
*/
|
|
886
|
+
onBeforeRequest(req) {
|
|
887
|
+
if (req.route.metadata?.[METADATA.NO_AUTH] && req.route.metadata[METADATA.NO_AUTH] === true) return req;
|
|
888
|
+
const ts = Date.now();
|
|
889
|
+
req.headers["kalshi-access-key"] = this.config.credentialsProvider.getAccessKey();
|
|
890
|
+
req.headers["kalshi-access-timestamp"] = ts.toString();
|
|
891
|
+
req.headers["kalshi-access-signature"] = this.config.credentialsProvider.getSignature({
|
|
892
|
+
httpMethod: req.route.method,
|
|
893
|
+
path: req.path,
|
|
894
|
+
timestamp: ts
|
|
895
|
+
});
|
|
896
|
+
return req;
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
//#endregion
|
|
900
|
+
exports.ApiClient = ApiClient;
|
|
653
901
|
exports.InMemoryCredentialsProvider = InMemoryCredentialsProvider;
|
|
654
902
|
exports.RequestSigner = RequestSigner;
|
|
655
903
|
exports.WS_KALSHI_ERRORS = WS_KALSHI_ERRORS;
|
|
656
904
|
exports.WS_KALSHI_SERVER_ERRORS = WS_KALSHI_SERVER_ERRORS;
|
|
657
905
|
exports.WsClient = WsClient;
|
|
906
|
+
exports.WsClosedByUserError = WsClosedByUserError;
|
|
907
|
+
exports.WsClosedError = WsClosedError;
|
|
658
908
|
exports.WsKalshiError = WsKalshiError;
|
|
909
|
+
exports.account$accountGrantSchema = account$accountGrantSchema;
|
|
910
|
+
exports.account$accountTierSchema = account$accountTierSchema;
|
|
911
|
+
exports.account$subaccountSchema = account$subaccountSchema;
|
|
912
|
+
exports.http$errorMessageSchema = http$errorMessageSchema;
|
|
913
|
+
exports.orders$clientOrderIdSchema = orders$clientOrderIdSchema;
|
|
914
|
+
exports.orders$createOrderDtoSchema = orders$createOrderDtoSchema;
|
|
659
915
|
exports.orders$orderDetailedSchema = orders$orderDetailedSchema;
|
|
660
916
|
exports.orders$orderStatusSchema = orders$orderStatusSchema;
|
|
661
917
|
exports.orders$orderTypeSchema = orders$orderTypeSchema;
|
|
662
918
|
exports.orders$orderWsSchema = orders$orderWsSchema;
|
|
663
919
|
exports.orders$selfTradePreventionTypeSchema = orders$selfTradePreventionTypeSchema;
|
|
920
|
+
exports.orders$timeInForceSchema = orders$timeInForceSchema;
|
|
664
921
|
exports.primitives$bookSideSchema = primitives$bookSideSchema;
|
|
665
922
|
exports.primitives$fixedPointSchema = primitives$fixedPointSchema;
|
|
666
923
|
exports.primitives$orderActionSchema = primitives$orderActionSchema;
|
|
667
924
|
exports.primitives$orderSideSchema = primitives$orderSideSchema;
|
|
925
|
+
exports.primitives$rateLimitBucketMetaSchema = primitives$rateLimitBucketMetaSchema;
|
|
668
926
|
exports.wsAnyMessageSchema = wsAnyMessageSchema;
|
|
669
927
|
exports.wsErrorMessageSchema = wsErrorMessageSchema;
|
|
670
928
|
exports.wsOkMessageSchema = wsOkMessageSchema;
|