@taphubhq/sdk-core 0.16.2 → 0.17.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 +54 -46
- package/dist/index.d.mts +30 -29
- package/dist/index.d.ts +30 -29
- package/dist/index.js +54 -46
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -139,7 +139,7 @@ function normaliseAgencyPairs(rows) {
|
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
return rows.map((row) => ({
|
|
142
|
-
|
|
142
|
+
pairId: row.pairId,
|
|
143
143
|
pair: row.pair,
|
|
144
144
|
thumb: row.thumb,
|
|
145
145
|
ordering: Number(row.ordering),
|
|
@@ -153,7 +153,7 @@ function normaliseAgencyPairs(rows) {
|
|
|
153
153
|
// src/modules/agencyPair/queries.ts
|
|
154
154
|
var FETCH_AGENCY_PAIRS_QUERY = `query FetchAgencyPairs($filter: AgencyPairFilter) {
|
|
155
155
|
fetchAgencyPairs(filter: $filter) {
|
|
156
|
-
|
|
156
|
+
pairId pair thumb ordering status maxCoef currentPrice currentVol24h
|
|
157
157
|
}
|
|
158
158
|
}`;
|
|
159
159
|
|
|
@@ -479,8 +479,8 @@ var PLACE_BID_MUTATION = `mutation PlaceBid($input: PlaceBidInput!) {
|
|
|
479
479
|
id user_id game_id currency amount coefficient time1 time2 price1 price2 status payout slippage created_at
|
|
480
480
|
}
|
|
481
481
|
}`;
|
|
482
|
-
var MY_BIDS_QUERY = `query MyBids($statuses: [BidStatus!], $limit: Int, $offset: Int, $
|
|
483
|
-
myBids(statuses: $statuses, limit: $limit, offset: $offset,
|
|
482
|
+
var MY_BIDS_QUERY = `query MyBids($statuses: [BidStatus!], $limit: Int, $offset: Int, $pairId: ID) {
|
|
483
|
+
myBids(statuses: $statuses, limit: $limit, offset: $offset, pairId: $pairId) {
|
|
484
484
|
id user_id game_id currency amount coefficient time1 time2 price1 price2 status payout slippage created_at
|
|
485
485
|
}
|
|
486
486
|
}`;
|
|
@@ -508,7 +508,9 @@ var BidModule = class {
|
|
|
508
508
|
async placeBid(input, opts) {
|
|
509
509
|
const variables = {
|
|
510
510
|
input: {
|
|
511
|
-
|
|
511
|
+
// REVIEW[bid-260602-v2]: input field pairId (was: game_id) — the #2 game_pairs.id.
|
|
512
|
+
// Server composes the agencyPairId composite and stores it in bids.game_id (frozen).
|
|
513
|
+
pairId: input.pairId,
|
|
512
514
|
// wallet_id is forwarded as-is — grid-api enforces ownership +
|
|
513
515
|
// currency validation. See openspec/bid-260518-wallet-id D1/D8.
|
|
514
516
|
wallet_id: input.walletId,
|
|
@@ -532,7 +534,7 @@ var BidModule = class {
|
|
|
532
534
|
if (err instanceof TaphubValidationError && err.code === "NotExist") {
|
|
533
535
|
throw new TaphubValidationError("Game not found", {
|
|
534
536
|
code: "GameNotFound",
|
|
535
|
-
details: {
|
|
537
|
+
details: { pairId: input.pairId }
|
|
536
538
|
});
|
|
537
539
|
}
|
|
538
540
|
throw err;
|
|
@@ -563,8 +565,8 @@ var BidModule = class {
|
|
|
563
565
|
if (opts?.offset !== void 0) {
|
|
564
566
|
variables.offset = opts.offset;
|
|
565
567
|
}
|
|
566
|
-
if (opts?.
|
|
567
|
-
variables.
|
|
568
|
+
if (opts?.pairId !== void 0) {
|
|
569
|
+
variables.pairId = opts.pairId;
|
|
568
570
|
}
|
|
569
571
|
const body = await this.#graphql.request(
|
|
570
572
|
MY_BIDS_QUERY,
|
|
@@ -794,8 +796,8 @@ function normalisePairInfo(node) {
|
|
|
794
796
|
}
|
|
795
797
|
|
|
796
798
|
// src/modules/pair/queries.ts
|
|
797
|
-
var PAIR_QUERY = `query Pair($
|
|
798
|
-
pair(
|
|
799
|
+
var PAIR_QUERY = `query Pair($pairId: ID!) {
|
|
800
|
+
pair(pairId: $pairId) {
|
|
799
801
|
id pair status created_at
|
|
800
802
|
config {
|
|
801
803
|
gridConfig { cellSizeTime cellSizeValue candleSize baseline baselineTime }
|
|
@@ -804,8 +806,8 @@ var PAIR_QUERY = `query Pair($pair: String!, $gameplaySlug: String) {
|
|
|
804
806
|
}
|
|
805
807
|
}
|
|
806
808
|
}`;
|
|
807
|
-
var CHART_HISTORY_QUERY = `query ChartHistory($
|
|
808
|
-
chartHistory(
|
|
809
|
+
var CHART_HISTORY_QUERY = `query ChartHistory($pairId: ID!, $limit: Int) {
|
|
810
|
+
chartHistory(pairId: $pairId, limit: $limit) {
|
|
809
811
|
time o h l c volatility coefMults
|
|
810
812
|
}
|
|
811
813
|
}`;
|
|
@@ -826,9 +828,11 @@ var PairModule = class {
|
|
|
826
828
|
constructor(deps) {
|
|
827
829
|
this.#graphql = deps.graphql;
|
|
828
830
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
831
|
+
// REVIEW[bid-260602-v2]: keyed by pairId (the #2 game_pairs.id, e.g. "grid-ETH-USD").
|
|
832
|
+
// Dropped the `pair` symbol arg + `gameplaySlug` option — the gameplay is already
|
|
833
|
+
// encoded in pairId, and the server composes agencyPairId from agency context.
|
|
834
|
+
async get(pairId, opts) {
|
|
835
|
+
const variables = { pairId };
|
|
832
836
|
let body;
|
|
833
837
|
try {
|
|
834
838
|
body = await this.#graphql.request(PAIR_QUERY, variables, opts);
|
|
@@ -836,7 +840,7 @@ var PairModule = class {
|
|
|
836
840
|
if (err instanceof TaphubValidationError && err.code === "NotExist") {
|
|
837
841
|
throw new TaphubValidationError("Game not found for pair", {
|
|
838
842
|
code: "GameNotFound",
|
|
839
|
-
details: {
|
|
843
|
+
details: { pairId }
|
|
840
844
|
});
|
|
841
845
|
}
|
|
842
846
|
throw err;
|
|
@@ -844,7 +848,7 @@ var PairModule = class {
|
|
|
844
848
|
if (body.pair === null) {
|
|
845
849
|
throw new TaphubValidationError("Game not found for pair", {
|
|
846
850
|
code: "GameNotFound",
|
|
847
|
-
details: {
|
|
851
|
+
details: { pairId }
|
|
848
852
|
});
|
|
849
853
|
}
|
|
850
854
|
return normalisePair(body.pair);
|
|
@@ -857,8 +861,8 @@ var PairModule = class {
|
|
|
857
861
|
*
|
|
858
862
|
* @example
|
|
859
863
|
* const pairs = await client.pair.availableGamePairs({ gameplayId: 'taptrading' });
|
|
860
|
-
* const
|
|
861
|
-
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ??
|
|
864
|
+
* const pair = await client.pair.get(pairs[0].id);
|
|
865
|
+
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ?? pair.id, userId);
|
|
862
866
|
*/
|
|
863
867
|
async availableGamePairs(opts) {
|
|
864
868
|
const variables = {};
|
|
@@ -870,9 +874,9 @@ var PairModule = class {
|
|
|
870
874
|
);
|
|
871
875
|
return body.builderAvailableGamePairs.map(normalisePairInfo);
|
|
872
876
|
}
|
|
873
|
-
// REVIEW[bid-260602]: chartHistory param/variable renamed
|
|
874
|
-
async chartHistory(
|
|
875
|
-
const variables = {
|
|
877
|
+
// REVIEW[bid-260602-v2]: chartHistory param/variable renamed pairId (was: agencyPairId/gameId)
|
|
878
|
+
async chartHistory(pairId, limit, opts) {
|
|
879
|
+
const variables = { pairId };
|
|
876
880
|
if (limit !== void 0) {
|
|
877
881
|
variables.limit = limit;
|
|
878
882
|
}
|
|
@@ -902,8 +906,8 @@ var WALLET_TOPIC_PREFIX = "wallet";
|
|
|
902
906
|
function walletBalanceTopic(userId) {
|
|
903
907
|
return `${WALLET_TOPIC_PREFIX}/users/${userId}/balance`;
|
|
904
908
|
}
|
|
905
|
-
function agencyPairStatsTopic(aid,
|
|
906
|
-
return `public/agency/${aid}/pair/${
|
|
909
|
+
function agencyPairStatsTopic(aid, pairId) {
|
|
910
|
+
return `public/agency/${aid}/pair/${pairId}/stats`;
|
|
907
911
|
}
|
|
908
912
|
function topicFor(gameId, suffix, userId) {
|
|
909
913
|
if (USER_SCOPED_SUFFIXES.includes(suffix)) {
|
|
@@ -1063,28 +1067,28 @@ function createMqttTransport(endpoint, opts = {}) {
|
|
|
1063
1067
|
mqttClient.subscribe(t, { qos: 1 });
|
|
1064
1068
|
}
|
|
1065
1069
|
},
|
|
1066
|
-
subscribeCandle(
|
|
1067
|
-
const topic = `${MARKET_TOPIC_PREFIX}/${
|
|
1068
|
-
if (candleSubscriptions.has(
|
|
1070
|
+
subscribeCandle(pairId, onCandle) {
|
|
1071
|
+
const topic = `${MARKET_TOPIC_PREFIX}/${pairId}/candle`;
|
|
1072
|
+
if (candleSubscriptions.has(pairId)) return;
|
|
1069
1073
|
const mqttClient = ensureConnected();
|
|
1070
|
-
candleSubscriptions.set(
|
|
1074
|
+
candleSubscriptions.set(pairId, { topic, onCandle });
|
|
1071
1075
|
mqttClient.subscribe(topic, { qos: 0 });
|
|
1072
1076
|
},
|
|
1073
|
-
unsubscribeCandle(
|
|
1074
|
-
const entry = candleSubscriptions.get(
|
|
1077
|
+
unsubscribeCandle(pairId) {
|
|
1078
|
+
const entry = candleSubscriptions.get(pairId);
|
|
1075
1079
|
if (!entry) return;
|
|
1076
1080
|
if (client) client.unsubscribe(entry.topic);
|
|
1077
|
-
candleSubscriptions.delete(
|
|
1081
|
+
candleSubscriptions.delete(pairId);
|
|
1078
1082
|
},
|
|
1079
|
-
subscribeAgencyPairStats(aid,
|
|
1080
|
-
const topic = agencyPairStatsTopic(aid,
|
|
1083
|
+
subscribeAgencyPairStats(aid, pairId, onStats) {
|
|
1084
|
+
const topic = agencyPairStatsTopic(aid, pairId);
|
|
1081
1085
|
if (statsSubscriptions.has(topic)) return;
|
|
1082
1086
|
const mqttClient = ensureConnected();
|
|
1083
1087
|
statsSubscriptions.set(topic, { topic, onStats });
|
|
1084
1088
|
mqttClient.subscribe(topic, { qos: 0 });
|
|
1085
1089
|
},
|
|
1086
|
-
unsubscribeAgencyPairStats(aid,
|
|
1087
|
-
const topic = agencyPairStatsTopic(aid,
|
|
1090
|
+
unsubscribeAgencyPairStats(aid, pairId) {
|
|
1091
|
+
const topic = agencyPairStatsTopic(aid, pairId);
|
|
1088
1092
|
const entry = statsSubscriptions.get(topic);
|
|
1089
1093
|
if (!entry) return;
|
|
1090
1094
|
if (client) client.unsubscribe(entry.topic);
|
|
@@ -1420,22 +1424,25 @@ var RealtimeModule = class extends import_eventemitter33.default {
|
|
|
1420
1424
|
this.#transport.unsubscribeWallet(cleanUserId);
|
|
1421
1425
|
}
|
|
1422
1426
|
/**
|
|
1423
|
-
* Subscribe to public market candle data for a pair
|
|
1424
|
-
* Independent of game/agency —
|
|
1427
|
+
* Subscribe to public market candle data for a pair, keyed by pairId
|
|
1428
|
+
* (the #2 game_pairs.id, e.g. "grid-ETH-USD"). Independent of game/agency —
|
|
1429
|
+
* candle is market-wide public data.
|
|
1425
1430
|
*/
|
|
1426
|
-
|
|
1427
|
-
|
|
1431
|
+
// REVIEW[bid-260602-v2]: param pairId (was: pair) — slash-free #2 game_pairs.id.
|
|
1432
|
+
subscribeCandle(pairId, onCandle) {
|
|
1433
|
+
this.#transport.subscribeCandle(pairId, onCandle);
|
|
1428
1434
|
}
|
|
1429
|
-
/** Unsubscribe from candle data for a
|
|
1430
|
-
unsubscribeCandle(
|
|
1431
|
-
this.#transport.unsubscribeCandle(
|
|
1435
|
+
/** Unsubscribe from candle data for a pairId. */
|
|
1436
|
+
unsubscribeCandle(pairId) {
|
|
1437
|
+
this.#transport.unsubscribeCandle(pairId);
|
|
1432
1438
|
}
|
|
1433
1439
|
/**
|
|
1434
1440
|
* Subscribe to the live per-pair stats stream for the client's own agency.
|
|
1435
1441
|
* Scoped to the agency the client was constructed with — there is no argument
|
|
1436
1442
|
* to target another agency by design.
|
|
1437
1443
|
*/
|
|
1438
|
-
|
|
1444
|
+
// REVIEW[bid-260602-v2]: param pairId (was: gamePairId) — the #2 game_pairs.id.
|
|
1445
|
+
subscribeAgencyPairStats(pairId, handler) {
|
|
1439
1446
|
if (!this.#agencyId) {
|
|
1440
1447
|
throw new TaphubError("agencyId is required to subscribe to agency pair stats", {
|
|
1441
1448
|
code: "AgencyIdRequired"
|
|
@@ -1450,12 +1457,13 @@ var RealtimeModule = class extends import_eventemitter33.default {
|
|
|
1450
1457
|
ts: Number(p.ts)
|
|
1451
1458
|
});
|
|
1452
1459
|
};
|
|
1453
|
-
this.#transport.subscribeAgencyPairStats(this.#agencyId,
|
|
1460
|
+
this.#transport.subscribeAgencyPairStats(this.#agencyId, pairId, onStats);
|
|
1454
1461
|
}
|
|
1455
1462
|
/** Unsubscribe from the per-pair stats stream for the client's own agency. */
|
|
1456
|
-
|
|
1463
|
+
// REVIEW[bid-260602-v2]: param pairId (was: gamePairId).
|
|
1464
|
+
unsubscribeAgencyPairStats(pairId) {
|
|
1457
1465
|
if (!this.#agencyId) return;
|
|
1458
|
-
this.#transport.unsubscribeAgencyPairStats(this.#agencyId,
|
|
1466
|
+
this.#transport.unsubscribeAgencyPairStats(this.#agencyId, pairId);
|
|
1459
1467
|
}
|
|
1460
1468
|
disconnect() {
|
|
1461
1469
|
for (const entry of this.#entries.values()) {
|
package/dist/index.d.mts
CHANGED
|
@@ -71,8 +71,8 @@ interface AgencyPairFilter {
|
|
|
71
71
|
status?: AgencyPairStatus;
|
|
72
72
|
}
|
|
73
73
|
interface AgencyPairStats {
|
|
74
|
-
/** game_pairs.id
|
|
75
|
-
|
|
74
|
+
/** game_pairs.id, e.g. "grid-ETH-USD". Use to build the stats MQTT topic. */
|
|
75
|
+
pairId: string;
|
|
76
76
|
/** Display name, e.g. "ETH/USD". */
|
|
77
77
|
pair: string;
|
|
78
78
|
/** Icon URL. */
|
|
@@ -186,7 +186,7 @@ interface CancelBidResult {
|
|
|
186
186
|
newBalance: string;
|
|
187
187
|
}
|
|
188
188
|
interface PlaceBidInput {
|
|
189
|
-
|
|
189
|
+
pairId: string;
|
|
190
190
|
/**
|
|
191
191
|
* UUID of the user's wallet to debit. Required (non-optional) since
|
|
192
192
|
* grid-api's `PlaceBidInput.wallet_id` is NON_NULL (`ID!`). The SDK stays
|
|
@@ -230,7 +230,7 @@ declare class BidModule {
|
|
|
230
230
|
statuses?: BidStatus[];
|
|
231
231
|
limit?: number;
|
|
232
232
|
offset?: number;
|
|
233
|
-
|
|
233
|
+
pairId?: string;
|
|
234
234
|
signal?: AbortSignal;
|
|
235
235
|
}): Promise<Bid[]>;
|
|
236
236
|
}
|
|
@@ -405,8 +405,7 @@ interface PairModuleDeps {
|
|
|
405
405
|
declare class PairModule {
|
|
406
406
|
#private;
|
|
407
407
|
constructor(deps: PairModuleDeps);
|
|
408
|
-
get(
|
|
409
|
-
gameplaySlug?: string;
|
|
408
|
+
get(pairId: string, opts?: {
|
|
410
409
|
signal?: AbortSignal;
|
|
411
410
|
}): Promise<Pair>;
|
|
412
411
|
/**
|
|
@@ -417,14 +416,14 @@ declare class PairModule {
|
|
|
417
416
|
*
|
|
418
417
|
* @example
|
|
419
418
|
* const pairs = await client.pair.availableGamePairs({ gameplayId: 'taptrading' });
|
|
420
|
-
* const
|
|
421
|
-
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ??
|
|
419
|
+
* const pair = await client.pair.get(pairs[0].id);
|
|
420
|
+
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ?? pair.id, userId);
|
|
422
421
|
*/
|
|
423
422
|
availableGamePairs(opts?: {
|
|
424
423
|
gameplayId?: string;
|
|
425
424
|
signal?: AbortSignal;
|
|
426
425
|
}): Promise<PairInfo[]>;
|
|
427
|
-
chartHistory(
|
|
426
|
+
chartHistory(pairId: string, limit?: number, opts?: {
|
|
428
427
|
signal?: AbortSignal;
|
|
429
428
|
}): Promise<Candle[]>;
|
|
430
429
|
}
|
|
@@ -538,22 +537,23 @@ interface MqttTransport {
|
|
|
538
537
|
*/
|
|
539
538
|
unsubscribeAll(gameId: string, userId?: string | null): void;
|
|
540
539
|
/**
|
|
541
|
-
* Subscribe to public market candle data for a pair
|
|
542
|
-
*
|
|
543
|
-
*
|
|
540
|
+
* Subscribe to public market candle data for a pair, keyed by pairId
|
|
541
|
+
* (the slash-free #2 game_pairs.id, e.g. "grid-ETH-USD"). Independent of
|
|
542
|
+
* game/agency context — candle is market-wide public data.
|
|
543
|
+
* Idempotent: multiple calls for the same pairId are deduplicated.
|
|
544
544
|
*/
|
|
545
|
-
subscribeCandle(
|
|
546
|
-
/** Tear down the candle subscription for a
|
|
547
|
-
unsubscribeCandle(
|
|
545
|
+
subscribeCandle(pairId: string, onCandle: MqttCandleHandler): void;
|
|
546
|
+
/** Tear down the candle subscription for a pairId. */
|
|
547
|
+
unsubscribeCandle(pairId: string): void;
|
|
548
548
|
/**
|
|
549
549
|
* Subscribe to the public per-pair stats stream for an agency, topic
|
|
550
|
-
* `public/agency/{aid}/pair/{
|
|
551
|
-
*
|
|
552
|
-
* Idempotent: multiple calls for the same `(aid,
|
|
550
|
+
* `public/agency/{aid}/pair/{pairId}/stats`. `aid` and `pairId` are used raw
|
|
551
|
+
* (no slash escaping — pairId is slash-free) to byte-match the backend publisher.
|
|
552
|
+
* Idempotent: multiple calls for the same `(aid, pairId)` are deduplicated.
|
|
553
553
|
*/
|
|
554
|
-
subscribeAgencyPairStats(aid: string,
|
|
555
|
-
/** Tear down the stats subscription for an `(aid,
|
|
556
|
-
unsubscribeAgencyPairStats(aid: string,
|
|
554
|
+
subscribeAgencyPairStats(aid: string, pairId: string, onStats: MqttAgencyPairStatsHandler): void;
|
|
555
|
+
/** Tear down the stats subscription for an `(aid, pairId)`. */
|
|
556
|
+
unsubscribeAgencyPairStats(aid: string, pairId: string): void;
|
|
557
557
|
/**
|
|
558
558
|
* Subscribe to the user-scoped wallet balance stream, topic
|
|
559
559
|
* `wallet/users/{userId}/balance`. Independent of any game subscription — NOT
|
|
@@ -667,7 +667,7 @@ interface MqttIdealConfigEvent {
|
|
|
667
667
|
}
|
|
668
668
|
/**
|
|
669
669
|
* Live per-pair stats tick from the public stream
|
|
670
|
-
* `public/agency/{aid}/pair/{
|
|
670
|
+
* `public/agency/{aid}/pair/{pairId}/stats`. The backend suppresses
|
|
671
671
|
* unchanged ticks, so a subscriber may not receive an event until price or
|
|
672
672
|
* vol24h actually moves — seed initial values from `agencyPairs.list()`.
|
|
673
673
|
*/
|
|
@@ -755,20 +755,21 @@ declare class RealtimeModule extends EventEmitter<RealtimeModuleEvents> {
|
|
|
755
755
|
*/
|
|
756
756
|
unsubscribeWallet(userId: string): void;
|
|
757
757
|
/**
|
|
758
|
-
* Subscribe to public market candle data for a pair
|
|
759
|
-
* Independent of game/agency —
|
|
758
|
+
* Subscribe to public market candle data for a pair, keyed by pairId
|
|
759
|
+
* (the #2 game_pairs.id, e.g. "grid-ETH-USD"). Independent of game/agency —
|
|
760
|
+
* candle is market-wide public data.
|
|
760
761
|
*/
|
|
761
|
-
subscribeCandle(
|
|
762
|
-
/** Unsubscribe from candle data for a
|
|
763
|
-
unsubscribeCandle(
|
|
762
|
+
subscribeCandle(pairId: string, onCandle: MqttCandleHandler): void;
|
|
763
|
+
/** Unsubscribe from candle data for a pairId. */
|
|
764
|
+
unsubscribeCandle(pairId: string): void;
|
|
764
765
|
/**
|
|
765
766
|
* Subscribe to the live per-pair stats stream for the client's own agency.
|
|
766
767
|
* Scoped to the agency the client was constructed with — there is no argument
|
|
767
768
|
* to target another agency by design.
|
|
768
769
|
*/
|
|
769
|
-
subscribeAgencyPairStats(
|
|
770
|
+
subscribeAgencyPairStats(pairId: string, handler: (event: MqttAgencyPairStatsEvent) => void): void;
|
|
770
771
|
/** Unsubscribe from the per-pair stats stream for the client's own agency. */
|
|
771
|
-
unsubscribeAgencyPairStats(
|
|
772
|
+
unsubscribeAgencyPairStats(pairId: string): void;
|
|
772
773
|
disconnect(): void;
|
|
773
774
|
}
|
|
774
775
|
|
package/dist/index.d.ts
CHANGED
|
@@ -71,8 +71,8 @@ interface AgencyPairFilter {
|
|
|
71
71
|
status?: AgencyPairStatus;
|
|
72
72
|
}
|
|
73
73
|
interface AgencyPairStats {
|
|
74
|
-
/** game_pairs.id
|
|
75
|
-
|
|
74
|
+
/** game_pairs.id, e.g. "grid-ETH-USD". Use to build the stats MQTT topic. */
|
|
75
|
+
pairId: string;
|
|
76
76
|
/** Display name, e.g. "ETH/USD". */
|
|
77
77
|
pair: string;
|
|
78
78
|
/** Icon URL. */
|
|
@@ -186,7 +186,7 @@ interface CancelBidResult {
|
|
|
186
186
|
newBalance: string;
|
|
187
187
|
}
|
|
188
188
|
interface PlaceBidInput {
|
|
189
|
-
|
|
189
|
+
pairId: string;
|
|
190
190
|
/**
|
|
191
191
|
* UUID of the user's wallet to debit. Required (non-optional) since
|
|
192
192
|
* grid-api's `PlaceBidInput.wallet_id` is NON_NULL (`ID!`). The SDK stays
|
|
@@ -230,7 +230,7 @@ declare class BidModule {
|
|
|
230
230
|
statuses?: BidStatus[];
|
|
231
231
|
limit?: number;
|
|
232
232
|
offset?: number;
|
|
233
|
-
|
|
233
|
+
pairId?: string;
|
|
234
234
|
signal?: AbortSignal;
|
|
235
235
|
}): Promise<Bid[]>;
|
|
236
236
|
}
|
|
@@ -405,8 +405,7 @@ interface PairModuleDeps {
|
|
|
405
405
|
declare class PairModule {
|
|
406
406
|
#private;
|
|
407
407
|
constructor(deps: PairModuleDeps);
|
|
408
|
-
get(
|
|
409
|
-
gameplaySlug?: string;
|
|
408
|
+
get(pairId: string, opts?: {
|
|
410
409
|
signal?: AbortSignal;
|
|
411
410
|
}): Promise<Pair>;
|
|
412
411
|
/**
|
|
@@ -417,14 +416,14 @@ declare class PairModule {
|
|
|
417
416
|
*
|
|
418
417
|
* @example
|
|
419
418
|
* const pairs = await client.pair.availableGamePairs({ gameplayId: 'taptrading' });
|
|
420
|
-
* const
|
|
421
|
-
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ??
|
|
419
|
+
* const pair = await client.pair.get(pairs[0].id);
|
|
420
|
+
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ?? pair.id, userId);
|
|
422
421
|
*/
|
|
423
422
|
availableGamePairs(opts?: {
|
|
424
423
|
gameplayId?: string;
|
|
425
424
|
signal?: AbortSignal;
|
|
426
425
|
}): Promise<PairInfo[]>;
|
|
427
|
-
chartHistory(
|
|
426
|
+
chartHistory(pairId: string, limit?: number, opts?: {
|
|
428
427
|
signal?: AbortSignal;
|
|
429
428
|
}): Promise<Candle[]>;
|
|
430
429
|
}
|
|
@@ -538,22 +537,23 @@ interface MqttTransport {
|
|
|
538
537
|
*/
|
|
539
538
|
unsubscribeAll(gameId: string, userId?: string | null): void;
|
|
540
539
|
/**
|
|
541
|
-
* Subscribe to public market candle data for a pair
|
|
542
|
-
*
|
|
543
|
-
*
|
|
540
|
+
* Subscribe to public market candle data for a pair, keyed by pairId
|
|
541
|
+
* (the slash-free #2 game_pairs.id, e.g. "grid-ETH-USD"). Independent of
|
|
542
|
+
* game/agency context — candle is market-wide public data.
|
|
543
|
+
* Idempotent: multiple calls for the same pairId are deduplicated.
|
|
544
544
|
*/
|
|
545
|
-
subscribeCandle(
|
|
546
|
-
/** Tear down the candle subscription for a
|
|
547
|
-
unsubscribeCandle(
|
|
545
|
+
subscribeCandle(pairId: string, onCandle: MqttCandleHandler): void;
|
|
546
|
+
/** Tear down the candle subscription for a pairId. */
|
|
547
|
+
unsubscribeCandle(pairId: string): void;
|
|
548
548
|
/**
|
|
549
549
|
* Subscribe to the public per-pair stats stream for an agency, topic
|
|
550
|
-
* `public/agency/{aid}/pair/{
|
|
551
|
-
*
|
|
552
|
-
* Idempotent: multiple calls for the same `(aid,
|
|
550
|
+
* `public/agency/{aid}/pair/{pairId}/stats`. `aid` and `pairId` are used raw
|
|
551
|
+
* (no slash escaping — pairId is slash-free) to byte-match the backend publisher.
|
|
552
|
+
* Idempotent: multiple calls for the same `(aid, pairId)` are deduplicated.
|
|
553
553
|
*/
|
|
554
|
-
subscribeAgencyPairStats(aid: string,
|
|
555
|
-
/** Tear down the stats subscription for an `(aid,
|
|
556
|
-
unsubscribeAgencyPairStats(aid: string,
|
|
554
|
+
subscribeAgencyPairStats(aid: string, pairId: string, onStats: MqttAgencyPairStatsHandler): void;
|
|
555
|
+
/** Tear down the stats subscription for an `(aid, pairId)`. */
|
|
556
|
+
unsubscribeAgencyPairStats(aid: string, pairId: string): void;
|
|
557
557
|
/**
|
|
558
558
|
* Subscribe to the user-scoped wallet balance stream, topic
|
|
559
559
|
* `wallet/users/{userId}/balance`. Independent of any game subscription — NOT
|
|
@@ -667,7 +667,7 @@ interface MqttIdealConfigEvent {
|
|
|
667
667
|
}
|
|
668
668
|
/**
|
|
669
669
|
* Live per-pair stats tick from the public stream
|
|
670
|
-
* `public/agency/{aid}/pair/{
|
|
670
|
+
* `public/agency/{aid}/pair/{pairId}/stats`. The backend suppresses
|
|
671
671
|
* unchanged ticks, so a subscriber may not receive an event until price or
|
|
672
672
|
* vol24h actually moves — seed initial values from `agencyPairs.list()`.
|
|
673
673
|
*/
|
|
@@ -755,20 +755,21 @@ declare class RealtimeModule extends EventEmitter<RealtimeModuleEvents> {
|
|
|
755
755
|
*/
|
|
756
756
|
unsubscribeWallet(userId: string): void;
|
|
757
757
|
/**
|
|
758
|
-
* Subscribe to public market candle data for a pair
|
|
759
|
-
* Independent of game/agency —
|
|
758
|
+
* Subscribe to public market candle data for a pair, keyed by pairId
|
|
759
|
+
* (the #2 game_pairs.id, e.g. "grid-ETH-USD"). Independent of game/agency —
|
|
760
|
+
* candle is market-wide public data.
|
|
760
761
|
*/
|
|
761
|
-
subscribeCandle(
|
|
762
|
-
/** Unsubscribe from candle data for a
|
|
763
|
-
unsubscribeCandle(
|
|
762
|
+
subscribeCandle(pairId: string, onCandle: MqttCandleHandler): void;
|
|
763
|
+
/** Unsubscribe from candle data for a pairId. */
|
|
764
|
+
unsubscribeCandle(pairId: string): void;
|
|
764
765
|
/**
|
|
765
766
|
* Subscribe to the live per-pair stats stream for the client's own agency.
|
|
766
767
|
* Scoped to the agency the client was constructed with — there is no argument
|
|
767
768
|
* to target another agency by design.
|
|
768
769
|
*/
|
|
769
|
-
subscribeAgencyPairStats(
|
|
770
|
+
subscribeAgencyPairStats(pairId: string, handler: (event: MqttAgencyPairStatsEvent) => void): void;
|
|
770
771
|
/** Unsubscribe from the per-pair stats stream for the client's own agency. */
|
|
771
|
-
unsubscribeAgencyPairStats(
|
|
772
|
+
unsubscribeAgencyPairStats(pairId: string): void;
|
|
772
773
|
disconnect(): void;
|
|
773
774
|
}
|
|
774
775
|
|
package/dist/index.js
CHANGED
|
@@ -74,7 +74,7 @@ function normaliseAgencyPairs(rows) {
|
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
return rows.map((row) => ({
|
|
77
|
-
|
|
77
|
+
pairId: row.pairId,
|
|
78
78
|
pair: row.pair,
|
|
79
79
|
thumb: row.thumb,
|
|
80
80
|
ordering: Number(row.ordering),
|
|
@@ -88,7 +88,7 @@ function normaliseAgencyPairs(rows) {
|
|
|
88
88
|
// src/modules/agencyPair/queries.ts
|
|
89
89
|
var FETCH_AGENCY_PAIRS_QUERY = `query FetchAgencyPairs($filter: AgencyPairFilter) {
|
|
90
90
|
fetchAgencyPairs(filter: $filter) {
|
|
91
|
-
|
|
91
|
+
pairId pair thumb ordering status maxCoef currentPrice currentVol24h
|
|
92
92
|
}
|
|
93
93
|
}`;
|
|
94
94
|
|
|
@@ -414,8 +414,8 @@ var PLACE_BID_MUTATION = `mutation PlaceBid($input: PlaceBidInput!) {
|
|
|
414
414
|
id user_id game_id currency amount coefficient time1 time2 price1 price2 status payout slippage created_at
|
|
415
415
|
}
|
|
416
416
|
}`;
|
|
417
|
-
var MY_BIDS_QUERY = `query MyBids($statuses: [BidStatus!], $limit: Int, $offset: Int, $
|
|
418
|
-
myBids(statuses: $statuses, limit: $limit, offset: $offset,
|
|
417
|
+
var MY_BIDS_QUERY = `query MyBids($statuses: [BidStatus!], $limit: Int, $offset: Int, $pairId: ID) {
|
|
418
|
+
myBids(statuses: $statuses, limit: $limit, offset: $offset, pairId: $pairId) {
|
|
419
419
|
id user_id game_id currency amount coefficient time1 time2 price1 price2 status payout slippage created_at
|
|
420
420
|
}
|
|
421
421
|
}`;
|
|
@@ -443,7 +443,9 @@ var BidModule = class {
|
|
|
443
443
|
async placeBid(input, opts) {
|
|
444
444
|
const variables = {
|
|
445
445
|
input: {
|
|
446
|
-
|
|
446
|
+
// REVIEW[bid-260602-v2]: input field pairId (was: game_id) — the #2 game_pairs.id.
|
|
447
|
+
// Server composes the agencyPairId composite and stores it in bids.game_id (frozen).
|
|
448
|
+
pairId: input.pairId,
|
|
447
449
|
// wallet_id is forwarded as-is — grid-api enforces ownership +
|
|
448
450
|
// currency validation. See openspec/bid-260518-wallet-id D1/D8.
|
|
449
451
|
wallet_id: input.walletId,
|
|
@@ -467,7 +469,7 @@ var BidModule = class {
|
|
|
467
469
|
if (err instanceof TaphubValidationError && err.code === "NotExist") {
|
|
468
470
|
throw new TaphubValidationError("Game not found", {
|
|
469
471
|
code: "GameNotFound",
|
|
470
|
-
details: {
|
|
472
|
+
details: { pairId: input.pairId }
|
|
471
473
|
});
|
|
472
474
|
}
|
|
473
475
|
throw err;
|
|
@@ -498,8 +500,8 @@ var BidModule = class {
|
|
|
498
500
|
if (opts?.offset !== void 0) {
|
|
499
501
|
variables.offset = opts.offset;
|
|
500
502
|
}
|
|
501
|
-
if (opts?.
|
|
502
|
-
variables.
|
|
503
|
+
if (opts?.pairId !== void 0) {
|
|
504
|
+
variables.pairId = opts.pairId;
|
|
503
505
|
}
|
|
504
506
|
const body = await this.#graphql.request(
|
|
505
507
|
MY_BIDS_QUERY,
|
|
@@ -729,8 +731,8 @@ function normalisePairInfo(node) {
|
|
|
729
731
|
}
|
|
730
732
|
|
|
731
733
|
// src/modules/pair/queries.ts
|
|
732
|
-
var PAIR_QUERY = `query Pair($
|
|
733
|
-
pair(
|
|
734
|
+
var PAIR_QUERY = `query Pair($pairId: ID!) {
|
|
735
|
+
pair(pairId: $pairId) {
|
|
734
736
|
id pair status created_at
|
|
735
737
|
config {
|
|
736
738
|
gridConfig { cellSizeTime cellSizeValue candleSize baseline baselineTime }
|
|
@@ -739,8 +741,8 @@ var PAIR_QUERY = `query Pair($pair: String!, $gameplaySlug: String) {
|
|
|
739
741
|
}
|
|
740
742
|
}
|
|
741
743
|
}`;
|
|
742
|
-
var CHART_HISTORY_QUERY = `query ChartHistory($
|
|
743
|
-
chartHistory(
|
|
744
|
+
var CHART_HISTORY_QUERY = `query ChartHistory($pairId: ID!, $limit: Int) {
|
|
745
|
+
chartHistory(pairId: $pairId, limit: $limit) {
|
|
744
746
|
time o h l c volatility coefMults
|
|
745
747
|
}
|
|
746
748
|
}`;
|
|
@@ -761,9 +763,11 @@ var PairModule = class {
|
|
|
761
763
|
constructor(deps) {
|
|
762
764
|
this.#graphql = deps.graphql;
|
|
763
765
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
766
|
+
// REVIEW[bid-260602-v2]: keyed by pairId (the #2 game_pairs.id, e.g. "grid-ETH-USD").
|
|
767
|
+
// Dropped the `pair` symbol arg + `gameplaySlug` option — the gameplay is already
|
|
768
|
+
// encoded in pairId, and the server composes agencyPairId from agency context.
|
|
769
|
+
async get(pairId, opts) {
|
|
770
|
+
const variables = { pairId };
|
|
767
771
|
let body;
|
|
768
772
|
try {
|
|
769
773
|
body = await this.#graphql.request(PAIR_QUERY, variables, opts);
|
|
@@ -771,7 +775,7 @@ var PairModule = class {
|
|
|
771
775
|
if (err instanceof TaphubValidationError && err.code === "NotExist") {
|
|
772
776
|
throw new TaphubValidationError("Game not found for pair", {
|
|
773
777
|
code: "GameNotFound",
|
|
774
|
-
details: {
|
|
778
|
+
details: { pairId }
|
|
775
779
|
});
|
|
776
780
|
}
|
|
777
781
|
throw err;
|
|
@@ -779,7 +783,7 @@ var PairModule = class {
|
|
|
779
783
|
if (body.pair === null) {
|
|
780
784
|
throw new TaphubValidationError("Game not found for pair", {
|
|
781
785
|
code: "GameNotFound",
|
|
782
|
-
details: {
|
|
786
|
+
details: { pairId }
|
|
783
787
|
});
|
|
784
788
|
}
|
|
785
789
|
return normalisePair(body.pair);
|
|
@@ -792,8 +796,8 @@ var PairModule = class {
|
|
|
792
796
|
*
|
|
793
797
|
* @example
|
|
794
798
|
* const pairs = await client.pair.availableGamePairs({ gameplayId: 'taptrading' });
|
|
795
|
-
* const
|
|
796
|
-
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ??
|
|
799
|
+
* const pair = await client.pair.get(pairs[0].id);
|
|
800
|
+
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ?? pair.id, userId);
|
|
797
801
|
*/
|
|
798
802
|
async availableGamePairs(opts) {
|
|
799
803
|
const variables = {};
|
|
@@ -805,9 +809,9 @@ var PairModule = class {
|
|
|
805
809
|
);
|
|
806
810
|
return body.builderAvailableGamePairs.map(normalisePairInfo);
|
|
807
811
|
}
|
|
808
|
-
// REVIEW[bid-260602]: chartHistory param/variable renamed
|
|
809
|
-
async chartHistory(
|
|
810
|
-
const variables = {
|
|
812
|
+
// REVIEW[bid-260602-v2]: chartHistory param/variable renamed pairId (was: agencyPairId/gameId)
|
|
813
|
+
async chartHistory(pairId, limit, opts) {
|
|
814
|
+
const variables = { pairId };
|
|
811
815
|
if (limit !== void 0) {
|
|
812
816
|
variables.limit = limit;
|
|
813
817
|
}
|
|
@@ -837,8 +841,8 @@ var WALLET_TOPIC_PREFIX = "wallet";
|
|
|
837
841
|
function walletBalanceTopic(userId) {
|
|
838
842
|
return `${WALLET_TOPIC_PREFIX}/users/${userId}/balance`;
|
|
839
843
|
}
|
|
840
|
-
function agencyPairStatsTopic(aid,
|
|
841
|
-
return `public/agency/${aid}/pair/${
|
|
844
|
+
function agencyPairStatsTopic(aid, pairId) {
|
|
845
|
+
return `public/agency/${aid}/pair/${pairId}/stats`;
|
|
842
846
|
}
|
|
843
847
|
function topicFor(gameId, suffix, userId) {
|
|
844
848
|
if (USER_SCOPED_SUFFIXES.includes(suffix)) {
|
|
@@ -998,28 +1002,28 @@ function createMqttTransport(endpoint, opts = {}) {
|
|
|
998
1002
|
mqttClient.subscribe(t, { qos: 1 });
|
|
999
1003
|
}
|
|
1000
1004
|
},
|
|
1001
|
-
subscribeCandle(
|
|
1002
|
-
const topic = `${MARKET_TOPIC_PREFIX}/${
|
|
1003
|
-
if (candleSubscriptions.has(
|
|
1005
|
+
subscribeCandle(pairId, onCandle) {
|
|
1006
|
+
const topic = `${MARKET_TOPIC_PREFIX}/${pairId}/candle`;
|
|
1007
|
+
if (candleSubscriptions.has(pairId)) return;
|
|
1004
1008
|
const mqttClient = ensureConnected();
|
|
1005
|
-
candleSubscriptions.set(
|
|
1009
|
+
candleSubscriptions.set(pairId, { topic, onCandle });
|
|
1006
1010
|
mqttClient.subscribe(topic, { qos: 0 });
|
|
1007
1011
|
},
|
|
1008
|
-
unsubscribeCandle(
|
|
1009
|
-
const entry = candleSubscriptions.get(
|
|
1012
|
+
unsubscribeCandle(pairId) {
|
|
1013
|
+
const entry = candleSubscriptions.get(pairId);
|
|
1010
1014
|
if (!entry) return;
|
|
1011
1015
|
if (client) client.unsubscribe(entry.topic);
|
|
1012
|
-
candleSubscriptions.delete(
|
|
1016
|
+
candleSubscriptions.delete(pairId);
|
|
1013
1017
|
},
|
|
1014
|
-
subscribeAgencyPairStats(aid,
|
|
1015
|
-
const topic = agencyPairStatsTopic(aid,
|
|
1018
|
+
subscribeAgencyPairStats(aid, pairId, onStats) {
|
|
1019
|
+
const topic = agencyPairStatsTopic(aid, pairId);
|
|
1016
1020
|
if (statsSubscriptions.has(topic)) return;
|
|
1017
1021
|
const mqttClient = ensureConnected();
|
|
1018
1022
|
statsSubscriptions.set(topic, { topic, onStats });
|
|
1019
1023
|
mqttClient.subscribe(topic, { qos: 0 });
|
|
1020
1024
|
},
|
|
1021
|
-
unsubscribeAgencyPairStats(aid,
|
|
1022
|
-
const topic = agencyPairStatsTopic(aid,
|
|
1025
|
+
unsubscribeAgencyPairStats(aid, pairId) {
|
|
1026
|
+
const topic = agencyPairStatsTopic(aid, pairId);
|
|
1023
1027
|
const entry = statsSubscriptions.get(topic);
|
|
1024
1028
|
if (!entry) return;
|
|
1025
1029
|
if (client) client.unsubscribe(entry.topic);
|
|
@@ -1355,22 +1359,25 @@ var RealtimeModule = class extends EventEmitter3 {
|
|
|
1355
1359
|
this.#transport.unsubscribeWallet(cleanUserId);
|
|
1356
1360
|
}
|
|
1357
1361
|
/**
|
|
1358
|
-
* Subscribe to public market candle data for a pair
|
|
1359
|
-
* Independent of game/agency —
|
|
1362
|
+
* Subscribe to public market candle data for a pair, keyed by pairId
|
|
1363
|
+
* (the #2 game_pairs.id, e.g. "grid-ETH-USD"). Independent of game/agency —
|
|
1364
|
+
* candle is market-wide public data.
|
|
1360
1365
|
*/
|
|
1361
|
-
|
|
1362
|
-
|
|
1366
|
+
// REVIEW[bid-260602-v2]: param pairId (was: pair) — slash-free #2 game_pairs.id.
|
|
1367
|
+
subscribeCandle(pairId, onCandle) {
|
|
1368
|
+
this.#transport.subscribeCandle(pairId, onCandle);
|
|
1363
1369
|
}
|
|
1364
|
-
/** Unsubscribe from candle data for a
|
|
1365
|
-
unsubscribeCandle(
|
|
1366
|
-
this.#transport.unsubscribeCandle(
|
|
1370
|
+
/** Unsubscribe from candle data for a pairId. */
|
|
1371
|
+
unsubscribeCandle(pairId) {
|
|
1372
|
+
this.#transport.unsubscribeCandle(pairId);
|
|
1367
1373
|
}
|
|
1368
1374
|
/**
|
|
1369
1375
|
* Subscribe to the live per-pair stats stream for the client's own agency.
|
|
1370
1376
|
* Scoped to the agency the client was constructed with — there is no argument
|
|
1371
1377
|
* to target another agency by design.
|
|
1372
1378
|
*/
|
|
1373
|
-
|
|
1379
|
+
// REVIEW[bid-260602-v2]: param pairId (was: gamePairId) — the #2 game_pairs.id.
|
|
1380
|
+
subscribeAgencyPairStats(pairId, handler) {
|
|
1374
1381
|
if (!this.#agencyId) {
|
|
1375
1382
|
throw new TaphubError("agencyId is required to subscribe to agency pair stats", {
|
|
1376
1383
|
code: "AgencyIdRequired"
|
|
@@ -1385,12 +1392,13 @@ var RealtimeModule = class extends EventEmitter3 {
|
|
|
1385
1392
|
ts: Number(p.ts)
|
|
1386
1393
|
});
|
|
1387
1394
|
};
|
|
1388
|
-
this.#transport.subscribeAgencyPairStats(this.#agencyId,
|
|
1395
|
+
this.#transport.subscribeAgencyPairStats(this.#agencyId, pairId, onStats);
|
|
1389
1396
|
}
|
|
1390
1397
|
/** Unsubscribe from the per-pair stats stream for the client's own agency. */
|
|
1391
|
-
|
|
1398
|
+
// REVIEW[bid-260602-v2]: param pairId (was: gamePairId).
|
|
1399
|
+
unsubscribeAgencyPairStats(pairId) {
|
|
1392
1400
|
if (!this.#agencyId) return;
|
|
1393
|
-
this.#transport.unsubscribeAgencyPairStats(this.#agencyId,
|
|
1401
|
+
this.#transport.unsubscribeAgencyPairStats(this.#agencyId, pairId);
|
|
1394
1402
|
}
|
|
1395
1403
|
disconnect() {
|
|
1396
1404
|
for (const entry of this.#entries.values()) {
|