@taphubhq/sdk-core 0.15.3 → 0.16.1
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 +209 -189
- package/dist/index.d.mts +94 -94
- package/dist/index.d.ts +94 -94
- package/dist/index.js +208 -188
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,10 +33,10 @@ __export(index_exports, {
|
|
|
33
33
|
AgencyPairModule: () => AgencyPairModule,
|
|
34
34
|
AuthModule: () => AuthModule,
|
|
35
35
|
BidModule: () => BidModule,
|
|
36
|
-
GameModule: () => GameModule,
|
|
37
36
|
LeaderboardModule: () => LeaderboardModule,
|
|
38
37
|
LocaleModule: () => LocaleModule,
|
|
39
38
|
NetworkQualityMonitor: () => NetworkQualityMonitor,
|
|
39
|
+
PairModule: () => PairModule,
|
|
40
40
|
RealtimeModule: () => RealtimeModule,
|
|
41
41
|
TaphubAuthError: () => TaphubAuthError,
|
|
42
42
|
TaphubClient: () => TaphubClient,
|
|
@@ -574,8 +574,151 @@ var BidModule = class {
|
|
|
574
574
|
}
|
|
575
575
|
};
|
|
576
576
|
|
|
577
|
-
// src/modules/
|
|
578
|
-
function
|
|
577
|
+
// src/modules/leaderboard/normalise.ts
|
|
578
|
+
function normaliseLeaderboard(rows) {
|
|
579
|
+
if (!Array.isArray(rows)) {
|
|
580
|
+
throw new TaphubServerError("Invalid response from server", {
|
|
581
|
+
code: "InvalidResponse"
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
return rows.map((row) => ({
|
|
585
|
+
userId: row.user_id,
|
|
586
|
+
username: row.username,
|
|
587
|
+
rank: row.rank,
|
|
588
|
+
totalBids: row.total_bids,
|
|
589
|
+
totalWins: row.total_wins,
|
|
590
|
+
totalWagered: row.total_wagered,
|
|
591
|
+
totalPayout: row.total_payout,
|
|
592
|
+
gain: row.gain
|
|
593
|
+
}));
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// src/modules/leaderboard/queries.ts
|
|
597
|
+
var LEADERBOARD_QUERY = `query Leaderboard($period: String!, $sort_by: String!) {
|
|
598
|
+
leaderboard(period: $period, sort_by: $sort_by) {
|
|
599
|
+
user_id username rank total_bids total_wins total_wagered total_payout gain
|
|
600
|
+
}
|
|
601
|
+
}`;
|
|
602
|
+
|
|
603
|
+
// src/modules/leaderboard/index.ts
|
|
604
|
+
var LeaderboardModule = class {
|
|
605
|
+
#graphql;
|
|
606
|
+
constructor(deps) {
|
|
607
|
+
this.#graphql = deps.graphql;
|
|
608
|
+
}
|
|
609
|
+
async list(args) {
|
|
610
|
+
const body = await this.#graphql.request(
|
|
611
|
+
LEADERBOARD_QUERY,
|
|
612
|
+
{ period: args.period, sort_by: args.sortBy },
|
|
613
|
+
args.signal ? { signal: args.signal } : void 0
|
|
614
|
+
);
|
|
615
|
+
return normaliseLeaderboard(body.leaderboard);
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
// src/modules/locale/normalise.ts
|
|
620
|
+
function normaliseLocaleResponse(node) {
|
|
621
|
+
let translations = null;
|
|
622
|
+
if (node.translations !== null) {
|
|
623
|
+
try {
|
|
624
|
+
translations = JSON.parse(node.translations);
|
|
625
|
+
} catch (err) {
|
|
626
|
+
throw new TaphubValidationError("Malformed translations JSON string from backend", {
|
|
627
|
+
code: "InvalidLocaleResponse",
|
|
628
|
+
details: {
|
|
629
|
+
lang: node.lang,
|
|
630
|
+
version: node.version,
|
|
631
|
+
parseError: err instanceof Error ? err.message : String(err)
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
return {
|
|
637
|
+
lang: node.lang,
|
|
638
|
+
version: node.version,
|
|
639
|
+
notModified: node.notModified,
|
|
640
|
+
translations
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
function normaliseRefreshLocalesPayload(node) {
|
|
644
|
+
let versions;
|
|
645
|
+
try {
|
|
646
|
+
versions = JSON.parse(node.versions);
|
|
647
|
+
} catch (err) {
|
|
648
|
+
throw new TaphubValidationError("Malformed versions JSON string from backend", {
|
|
649
|
+
code: "InvalidRefreshLocalesPayload",
|
|
650
|
+
details: {
|
|
651
|
+
parseError: err instanceof Error ? err.message : String(err)
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
return {
|
|
656
|
+
refreshed: node.refreshed,
|
|
657
|
+
versions
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// src/modules/locale/queries.ts
|
|
662
|
+
var LOCALES_QUERY = `query Locales($input: LocalesInput!) {
|
|
663
|
+
locales(input: $input) {
|
|
664
|
+
lang
|
|
665
|
+
version
|
|
666
|
+
notModified
|
|
667
|
+
translations
|
|
668
|
+
}
|
|
669
|
+
}`;
|
|
670
|
+
var REFRESH_LOCALES_MUTATION = `mutation RefreshLocales {
|
|
671
|
+
refreshLocales {
|
|
672
|
+
refreshed
|
|
673
|
+
versions
|
|
674
|
+
}
|
|
675
|
+
}`;
|
|
676
|
+
|
|
677
|
+
// src/modules/locale/index.ts
|
|
678
|
+
var LocaleModule = class {
|
|
679
|
+
#graphql;
|
|
680
|
+
constructor(deps) {
|
|
681
|
+
this.#graphql = deps.graphql;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Fetch translations for a single language.
|
|
685
|
+
*
|
|
686
|
+
* Pass the last-seen `version` as `knownVersion` to opt into not-modified
|
|
687
|
+
* short-circuit semantics: backend returns `{notModified: true, translations: null}`
|
|
688
|
+
* when the cached body still matches, and the caller keeps prior state.
|
|
689
|
+
*
|
|
690
|
+
* Errors surface as TaphubError subclasses with `extensions.code` codes from
|
|
691
|
+
* the backend (e.g. `LangNotSupported`, `InsufficientUpstream`, `FeatureDisabled`).
|
|
692
|
+
* Caller decides the fallback strategy.
|
|
693
|
+
*/
|
|
694
|
+
async get(lang, knownVersion, opts) {
|
|
695
|
+
const input = { lang };
|
|
696
|
+
if (knownVersion !== void 0 && knownVersion !== "") {
|
|
697
|
+
input.knownVersion = knownVersion;
|
|
698
|
+
}
|
|
699
|
+
const body = await this.#graphql.request(LOCALES_QUERY, { input }, opts);
|
|
700
|
+
return normaliseLocaleResponse(body.locales);
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Trigger an admin refresh — backend re-pulls the source Sheet, invalidates
|
|
704
|
+
* its cache, and writes fresh entries for every supported language.
|
|
705
|
+
*
|
|
706
|
+
* Requires `X-API-Key` header equal to backend `InternalApiKey`. The transport
|
|
707
|
+
* layer is responsible for attaching the header; this method does not handle
|
|
708
|
+
* auth concerns directly.
|
|
709
|
+
*/
|
|
710
|
+
async refresh(opts) {
|
|
711
|
+
const body = await this.#graphql.request(
|
|
712
|
+
REFRESH_LOCALES_MUTATION,
|
|
713
|
+
{},
|
|
714
|
+
opts
|
|
715
|
+
);
|
|
716
|
+
return normaliseRefreshLocalesPayload(body.refreshLocales);
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
// src/modules/pair/normalise.ts
|
|
721
|
+
function normalisePair(node) {
|
|
579
722
|
if (typeof node.id !== "string" || node.id === "" || typeof node.pair !== "string" || node.pair === "" || typeof node.status !== "string" || node.status === "" || !node.config) {
|
|
580
723
|
throw new TaphubServerError("Invalid response from server", {
|
|
581
724
|
code: "InvalidResponse"
|
|
@@ -634,7 +777,7 @@ function normaliseCandles(list) {
|
|
|
634
777
|
coefMults: c.coefMults
|
|
635
778
|
}));
|
|
636
779
|
}
|
|
637
|
-
function
|
|
780
|
+
function normalisePairInfo(node) {
|
|
638
781
|
if (typeof node.id !== "string" || node.id === "" || typeof node.pair !== "string" || node.pair === "") {
|
|
639
782
|
throw new TaphubServerError("Invalid response from server", { code: "InvalidResponse" });
|
|
640
783
|
}
|
|
@@ -644,13 +787,14 @@ function normaliseGamePairInfo(node) {
|
|
|
644
787
|
gameplayId: node.gameplayId,
|
|
645
788
|
gameplayName: node.gameplayName,
|
|
646
789
|
source: node.source,
|
|
647
|
-
|
|
790
|
+
// REVIEW[bid-260602]: maps node.agencyPairId (was: node.gameId)
|
|
791
|
+
agencyPairId: node.agencyPairId ?? null
|
|
648
792
|
};
|
|
649
793
|
}
|
|
650
794
|
|
|
651
|
-
// src/modules/
|
|
652
|
-
var
|
|
653
|
-
|
|
795
|
+
// src/modules/pair/queries.ts
|
|
796
|
+
var PAIR_QUERY = `query Pair($pair: String!, $gameplaySlug: String) {
|
|
797
|
+
pair(pair: $pair, gameplaySlug: $gameplaySlug) {
|
|
654
798
|
id pair status created_at
|
|
655
799
|
config {
|
|
656
800
|
gridConfig { cellSizeTime cellSizeValue candleSize baseline baselineTime }
|
|
@@ -659,8 +803,8 @@ var GAME_QUERY = `query Game($pair: String!, $gameplaySlug: String) {
|
|
|
659
803
|
}
|
|
660
804
|
}
|
|
661
805
|
}`;
|
|
662
|
-
var CHART_HISTORY_QUERY = `query ChartHistory($
|
|
663
|
-
chartHistory(
|
|
806
|
+
var CHART_HISTORY_QUERY = `query ChartHistory($agencyPairId: ID!, $limit: Int) {
|
|
807
|
+
chartHistory(agencyPairId: $agencyPairId, limit: $limit) {
|
|
664
808
|
time o h l c volatility coefMults
|
|
665
809
|
}
|
|
666
810
|
}`;
|
|
@@ -671,12 +815,12 @@ var BUILDER_AVAILABLE_GAME_PAIRS_QUERY = `query BuilderAvailableGamePairs($gamep
|
|
|
671
815
|
gameplayId
|
|
672
816
|
gameplayName
|
|
673
817
|
source
|
|
674
|
-
|
|
818
|
+
agencyPairId
|
|
675
819
|
}
|
|
676
820
|
}`;
|
|
677
821
|
|
|
678
|
-
// src/modules/
|
|
679
|
-
var
|
|
822
|
+
// src/modules/pair/index.ts
|
|
823
|
+
var PairModule = class {
|
|
680
824
|
#graphql;
|
|
681
825
|
constructor(deps) {
|
|
682
826
|
this.#graphql = deps.graphql;
|
|
@@ -686,7 +830,7 @@ var GameModule = class {
|
|
|
686
830
|
if (opts?.gameplaySlug) variables.gameplaySlug = opts.gameplaySlug;
|
|
687
831
|
let body;
|
|
688
832
|
try {
|
|
689
|
-
body = await this.#graphql.request(
|
|
833
|
+
body = await this.#graphql.request(PAIR_QUERY, variables, opts);
|
|
690
834
|
} catch (err) {
|
|
691
835
|
if (err instanceof TaphubValidationError && err.code === "NotExist") {
|
|
692
836
|
throw new TaphubValidationError("Game not found for pair", {
|
|
@@ -696,13 +840,13 @@ var GameModule = class {
|
|
|
696
840
|
}
|
|
697
841
|
throw err;
|
|
698
842
|
}
|
|
699
|
-
if (body.
|
|
843
|
+
if (body.pair === null) {
|
|
700
844
|
throw new TaphubValidationError("Game not found for pair", {
|
|
701
845
|
code: "GameNotFound",
|
|
702
846
|
details: { pair }
|
|
703
847
|
});
|
|
704
848
|
}
|
|
705
|
-
return
|
|
849
|
+
return normalisePair(body.pair);
|
|
706
850
|
}
|
|
707
851
|
/**
|
|
708
852
|
* Returns available game pairs, optionally filtered by gameplay.
|
|
@@ -711,9 +855,9 @@ var GameModule = class {
|
|
|
711
855
|
* `gameId` — use it directly as the MQTT topic `game/{gameId}/candle`.
|
|
712
856
|
*
|
|
713
857
|
* @example
|
|
714
|
-
* const pairs = await client.
|
|
715
|
-
* const game = await client.
|
|
716
|
-
* const ch = client.realtime?.subscribe(pairs[0].
|
|
858
|
+
* const pairs = await client.pair.availableGamePairs({ gameplayId: 'taptrading' });
|
|
859
|
+
* const game = await client.pair.get(pairs[0].pair, { gameplaySlug: pairs[0].gameplayId });
|
|
860
|
+
* const ch = client.realtime?.subscribe(pairs[0].agencyPairId ?? game.id, userId);
|
|
717
861
|
*/
|
|
718
862
|
async availableGamePairs(opts) {
|
|
719
863
|
const variables = {};
|
|
@@ -723,10 +867,11 @@ var GameModule = class {
|
|
|
723
867
|
variables,
|
|
724
868
|
opts
|
|
725
869
|
);
|
|
726
|
-
return body.builderAvailableGamePairs.map(
|
|
870
|
+
return body.builderAvailableGamePairs.map(normalisePairInfo);
|
|
727
871
|
}
|
|
728
|
-
|
|
729
|
-
|
|
872
|
+
// REVIEW[bid-260602]: chartHistory param/variable renamed agencyPairId (was: gameId)
|
|
873
|
+
async chartHistory(agencyPairId, limit, opts) {
|
|
874
|
+
const variables = { agencyPairId };
|
|
730
875
|
if (limit !== void 0) {
|
|
731
876
|
variables.limit = limit;
|
|
732
877
|
}
|
|
@@ -739,149 +884,6 @@ var GameModule = class {
|
|
|
739
884
|
}
|
|
740
885
|
};
|
|
741
886
|
|
|
742
|
-
// src/modules/leaderboard/normalise.ts
|
|
743
|
-
function normaliseLeaderboard(rows) {
|
|
744
|
-
if (!Array.isArray(rows)) {
|
|
745
|
-
throw new TaphubServerError("Invalid response from server", {
|
|
746
|
-
code: "InvalidResponse"
|
|
747
|
-
});
|
|
748
|
-
}
|
|
749
|
-
return rows.map((row) => ({
|
|
750
|
-
userId: row.user_id,
|
|
751
|
-
username: row.username,
|
|
752
|
-
rank: row.rank,
|
|
753
|
-
totalBids: row.total_bids,
|
|
754
|
-
totalWins: row.total_wins,
|
|
755
|
-
totalWagered: row.total_wagered,
|
|
756
|
-
totalPayout: row.total_payout,
|
|
757
|
-
gain: row.gain
|
|
758
|
-
}));
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
// src/modules/leaderboard/queries.ts
|
|
762
|
-
var LEADERBOARD_QUERY = `query Leaderboard($period: String!, $sort_by: String!) {
|
|
763
|
-
leaderboard(period: $period, sort_by: $sort_by) {
|
|
764
|
-
user_id username rank total_bids total_wins total_wagered total_payout gain
|
|
765
|
-
}
|
|
766
|
-
}`;
|
|
767
|
-
|
|
768
|
-
// src/modules/leaderboard/index.ts
|
|
769
|
-
var LeaderboardModule = class {
|
|
770
|
-
#graphql;
|
|
771
|
-
constructor(deps) {
|
|
772
|
-
this.#graphql = deps.graphql;
|
|
773
|
-
}
|
|
774
|
-
async list(args) {
|
|
775
|
-
const body = await this.#graphql.request(
|
|
776
|
-
LEADERBOARD_QUERY,
|
|
777
|
-
{ period: args.period, sort_by: args.sortBy },
|
|
778
|
-
args.signal ? { signal: args.signal } : void 0
|
|
779
|
-
);
|
|
780
|
-
return normaliseLeaderboard(body.leaderboard);
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
|
|
784
|
-
// src/modules/locale/normalise.ts
|
|
785
|
-
function normaliseLocaleResponse(node) {
|
|
786
|
-
let translations = null;
|
|
787
|
-
if (node.translations !== null) {
|
|
788
|
-
try {
|
|
789
|
-
translations = JSON.parse(node.translations);
|
|
790
|
-
} catch (err) {
|
|
791
|
-
throw new TaphubValidationError("Malformed translations JSON string from backend", {
|
|
792
|
-
code: "InvalidLocaleResponse",
|
|
793
|
-
details: {
|
|
794
|
-
lang: node.lang,
|
|
795
|
-
version: node.version,
|
|
796
|
-
parseError: err instanceof Error ? err.message : String(err)
|
|
797
|
-
}
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
return {
|
|
802
|
-
lang: node.lang,
|
|
803
|
-
version: node.version,
|
|
804
|
-
notModified: node.notModified,
|
|
805
|
-
translations
|
|
806
|
-
};
|
|
807
|
-
}
|
|
808
|
-
function normaliseRefreshLocalesPayload(node) {
|
|
809
|
-
let versions;
|
|
810
|
-
try {
|
|
811
|
-
versions = JSON.parse(node.versions);
|
|
812
|
-
} catch (err) {
|
|
813
|
-
throw new TaphubValidationError("Malformed versions JSON string from backend", {
|
|
814
|
-
code: "InvalidRefreshLocalesPayload",
|
|
815
|
-
details: {
|
|
816
|
-
parseError: err instanceof Error ? err.message : String(err)
|
|
817
|
-
}
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
return {
|
|
821
|
-
refreshed: node.refreshed,
|
|
822
|
-
versions
|
|
823
|
-
};
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
// src/modules/locale/queries.ts
|
|
827
|
-
var LOCALES_QUERY = `query Locales($input: LocalesInput!) {
|
|
828
|
-
locales(input: $input) {
|
|
829
|
-
lang
|
|
830
|
-
version
|
|
831
|
-
notModified
|
|
832
|
-
translations
|
|
833
|
-
}
|
|
834
|
-
}`;
|
|
835
|
-
var REFRESH_LOCALES_MUTATION = `mutation RefreshLocales {
|
|
836
|
-
refreshLocales {
|
|
837
|
-
refreshed
|
|
838
|
-
versions
|
|
839
|
-
}
|
|
840
|
-
}`;
|
|
841
|
-
|
|
842
|
-
// src/modules/locale/index.ts
|
|
843
|
-
var LocaleModule = class {
|
|
844
|
-
#graphql;
|
|
845
|
-
constructor(deps) {
|
|
846
|
-
this.#graphql = deps.graphql;
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* Fetch translations for a single language.
|
|
850
|
-
*
|
|
851
|
-
* Pass the last-seen `version` as `knownVersion` to opt into not-modified
|
|
852
|
-
* short-circuit semantics: backend returns `{notModified: true, translations: null}`
|
|
853
|
-
* when the cached body still matches, and the caller keeps prior state.
|
|
854
|
-
*
|
|
855
|
-
* Errors surface as TaphubError subclasses with `extensions.code` codes from
|
|
856
|
-
* the backend (e.g. `LangNotSupported`, `InsufficientUpstream`, `FeatureDisabled`).
|
|
857
|
-
* Caller decides the fallback strategy.
|
|
858
|
-
*/
|
|
859
|
-
async get(lang, knownVersion, opts) {
|
|
860
|
-
const input = { lang };
|
|
861
|
-
if (knownVersion !== void 0 && knownVersion !== "") {
|
|
862
|
-
input.knownVersion = knownVersion;
|
|
863
|
-
}
|
|
864
|
-
const body = await this.#graphql.request(LOCALES_QUERY, { input }, opts);
|
|
865
|
-
return normaliseLocaleResponse(body.locales);
|
|
866
|
-
}
|
|
867
|
-
/**
|
|
868
|
-
* Trigger an admin refresh — backend re-pulls the source Sheet, invalidates
|
|
869
|
-
* its cache, and writes fresh entries for every supported language.
|
|
870
|
-
*
|
|
871
|
-
* Requires `X-API-Key` header equal to backend `InternalApiKey`. The transport
|
|
872
|
-
* layer is responsible for attaching the header; this method does not handle
|
|
873
|
-
* auth concerns directly.
|
|
874
|
-
*/
|
|
875
|
-
async refresh(opts) {
|
|
876
|
-
const body = await this.#graphql.request(
|
|
877
|
-
REFRESH_LOCALES_MUTATION,
|
|
878
|
-
{},
|
|
879
|
-
opts
|
|
880
|
-
);
|
|
881
|
-
return normaliseRefreshLocalesPayload(body.refreshLocales);
|
|
882
|
-
}
|
|
883
|
-
};
|
|
884
|
-
|
|
885
887
|
// src/transport/mqtt/index.ts
|
|
886
888
|
var import_mqtt = __toESM(require("mqtt"));
|
|
887
889
|
|
|
@@ -952,6 +954,19 @@ function createMqttTransport(endpoint, opts = {}) {
|
|
|
952
954
|
}
|
|
953
955
|
});
|
|
954
956
|
client.on("connect", () => {
|
|
957
|
+
const c = client;
|
|
958
|
+
for (const sub of subscriptions.values()) {
|
|
959
|
+
for (const t of sub.topics) c.subscribe(t, { qos: 1 });
|
|
960
|
+
}
|
|
961
|
+
for (const entry of candleSubscriptions.values()) {
|
|
962
|
+
c.subscribe(entry.topic, { qos: 0 });
|
|
963
|
+
}
|
|
964
|
+
for (const entry of statsSubscriptions.values()) {
|
|
965
|
+
c.subscribe(entry.topic, { qos: 0 });
|
|
966
|
+
}
|
|
967
|
+
for (const entry of walletSubscriptions.values()) {
|
|
968
|
+
c.subscribe(entry.topic, { qos: 1 });
|
|
969
|
+
}
|
|
955
970
|
fireLifecycle({ kind: "connect", rttMs: Date.now() - connectStartedAt });
|
|
956
971
|
});
|
|
957
972
|
client.on("reconnect", () => {
|
|
@@ -1666,10 +1681,18 @@ function classifyBackendHealth(samples) {
|
|
|
1666
1681
|
}
|
|
1667
1682
|
return "ok";
|
|
1668
1683
|
}
|
|
1669
|
-
var
|
|
1670
|
-
var
|
|
1671
|
-
var
|
|
1672
|
-
var
|
|
1684
|
+
var RTT_GOOD_TO_FAIR = 180;
|
|
1685
|
+
var RTT_FAIR_TO_GOOD = 120;
|
|
1686
|
+
var RTT_FAIR_TO_POOR = 450;
|
|
1687
|
+
var RTT_POOR_TO_FAIR = 350;
|
|
1688
|
+
var JITTER_POOR = 150;
|
|
1689
|
+
var JITTER_LEAVE_POOR = 120;
|
|
1690
|
+
var LOSS_POOR = 0.05;
|
|
1691
|
+
var LOSS_LEAVE_POOR = 0.03;
|
|
1692
|
+
var isPoor = (m) => m.rtt > RTT_FAIR_TO_POOR || m.jitter > JITTER_POOR || m.lossRate > LOSS_POOR;
|
|
1693
|
+
var canLeavePoor = (m) => m.rtt < RTT_POOR_TO_FAIR && m.jitter < JITTER_LEAVE_POOR && m.lossRate < LOSS_LEAVE_POOR;
|
|
1694
|
+
var isFairUpper = (rtt) => rtt > RTT_GOOD_TO_FAIR;
|
|
1695
|
+
var canReachGood = (rtt) => rtt < RTT_FAIR_TO_GOOD;
|
|
1673
1696
|
function classifyNetworkLevel(metrics, current) {
|
|
1674
1697
|
if (current === "offline") {
|
|
1675
1698
|
return isPoor(metrics) ? "poor" : "fair";
|
|
@@ -1796,13 +1819,11 @@ var NetworkQualityMonitor = class {
|
|
|
1796
1819
|
if (bucket.length > WINDOW_MAX_SAMPLES_PER_SOURCE) {
|
|
1797
1820
|
bucket.shift();
|
|
1798
1821
|
}
|
|
1799
|
-
if (sample.source !== "connection" && sample.source !== "browser") {
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
this.smoother.add(sample.rtt, this.deriveMetrics());
|
|
1805
|
-
}
|
|
1822
|
+
if (sample.reason === "ok" && sample.source !== "connection" && sample.source !== "browser") {
|
|
1823
|
+
this.lastSuccessfulHttpAt = sample.ts;
|
|
1824
|
+
}
|
|
1825
|
+
if (sample.source === "mqtt" && sample.reason === "ok") {
|
|
1826
|
+
this.smoother.add(sample.rtt, this.deriveMetrics());
|
|
1806
1827
|
}
|
|
1807
1828
|
this.recompute(prevMqttConnectedOverride);
|
|
1808
1829
|
}
|
|
@@ -1973,17 +1994,15 @@ var NetworkQualityMonitor = class {
|
|
|
1973
1994
|
(s) => s.reason === "network" || s.reason === "timeout" || s.reason === "offline"
|
|
1974
1995
|
).length;
|
|
1975
1996
|
const lossRate = total > 0 ? lossCount / total : 0;
|
|
1976
|
-
const
|
|
1977
|
-
(s) => s.reason === "ok" || s.reason === "backend5xx" || s.reason === "backend4xx" || s.reason === "gqlError"
|
|
1978
|
-
).map((s) => s.rtt).filter((r) => Number.isFinite(r));
|
|
1997
|
+
const mqttRtts = samples.filter((s) => s.source === "mqtt" && s.reason === "ok").map((s) => s.rtt).filter((r) => Number.isFinite(r));
|
|
1979
1998
|
let jitter = 0;
|
|
1980
|
-
if (
|
|
1981
|
-
const mean =
|
|
1982
|
-
const variance =
|
|
1999
|
+
if (mqttRtts.length > 1) {
|
|
2000
|
+
const mean = mqttRtts.reduce((a, b) => a + b, 0) / mqttRtts.length;
|
|
2001
|
+
const variance = mqttRtts.reduce((a, b) => a + (b - mean) ** 2, 0) / mqttRtts.length;
|
|
1983
2002
|
jitter = Math.sqrt(variance);
|
|
1984
2003
|
}
|
|
1985
2004
|
const connectionFallback = samples.filter((s) => s.source === "connection" && Number.isFinite(s.rtt)).slice(-1)[0]?.rtt;
|
|
1986
|
-
const emaForLevel = this.smoother.ema > 0 ? this.smoother.ema :
|
|
2005
|
+
const emaForLevel = this.smoother.ema > 0 ? this.smoother.ema : mqttRtts.length > 0 ? mqttRtts[mqttRtts.length - 1] ?? 0 : connectionFallback ?? 0;
|
|
1987
2006
|
return { jitter, lossRate, emaForLevel };
|
|
1988
2007
|
}
|
|
1989
2008
|
isHardOffline() {
|
|
@@ -2536,8 +2555,9 @@ var TaphubClient = class {
|
|
|
2536
2555
|
user;
|
|
2537
2556
|
/** @readonly Auth module — reassignment has no effect at runtime. */
|
|
2538
2557
|
auth;
|
|
2539
|
-
/** @readonly
|
|
2540
|
-
game
|
|
2558
|
+
/** @readonly Pair module — reassignment has no effect at runtime. */
|
|
2559
|
+
// REVIEW[bid-260602]: field pair: PairModule (was: game: GameModule)
|
|
2560
|
+
pair;
|
|
2541
2561
|
/** @readonly Bid module — reassignment has no effect at runtime. */
|
|
2542
2562
|
bid;
|
|
2543
2563
|
/** @readonly Leaderboard module — reassignment has no effect at runtime. */
|
|
@@ -2621,7 +2641,7 @@ var TaphubClient = class {
|
|
|
2621
2641
|
this.user.clearCurrencies();
|
|
2622
2642
|
}
|
|
2623
2643
|
});
|
|
2624
|
-
this.
|
|
2644
|
+
this.pair = new PairModule({ graphql: this.#graphql });
|
|
2625
2645
|
this.bid = new BidModule({ graphql: this.#graphql });
|
|
2626
2646
|
this.leaderboard = new LeaderboardModule({ graphql: this.#graphql });
|
|
2627
2647
|
this.agencyPairs = new AgencyPairModule({ graphql: this.#graphql });
|
|
@@ -2644,8 +2664,8 @@ var TaphubClient = class {
|
|
|
2644
2664
|
enumerable: true,
|
|
2645
2665
|
configurable: false
|
|
2646
2666
|
});
|
|
2647
|
-
Object.defineProperty(this, "
|
|
2648
|
-
value: this.
|
|
2667
|
+
Object.defineProperty(this, "pair", {
|
|
2668
|
+
value: this.pair,
|
|
2649
2669
|
writable: false,
|
|
2650
2670
|
enumerable: true,
|
|
2651
2671
|
configurable: false
|
|
@@ -2807,10 +2827,10 @@ function calculateProbWin_v2(time1, time2, _price1, price2, creationTime, curren
|
|
|
2807
2827
|
AgencyPairModule,
|
|
2808
2828
|
AuthModule,
|
|
2809
2829
|
BidModule,
|
|
2810
|
-
GameModule,
|
|
2811
2830
|
LeaderboardModule,
|
|
2812
2831
|
LocaleModule,
|
|
2813
2832
|
NetworkQualityMonitor,
|
|
2833
|
+
PairModule,
|
|
2814
2834
|
RealtimeModule,
|
|
2815
2835
|
TaphubAuthError,
|
|
2816
2836
|
TaphubClient,
|