@usherlabs/cex-broker 0.2.34 → 0.2.36

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.
@@ -316534,8 +316534,256 @@ class AccountBalanceArchivePoller {
316534
316534
  }
316535
316535
  }
316536
316536
 
316537
- // src/helpers/fill-archive-poller.ts
316537
+ // src/helpers/deposit-archive-poller.ts
316538
316538
  var DEFAULT_CONFIG2 = {
316539
+ pollIntervalMs: 60000,
316540
+ lookbackMs: 24 * 60 * 60 * 1000,
316541
+ depositsLimit: 50
316542
+ };
316543
+ var ALL_CURRENCIES_CODE = "*";
316544
+ function depositTimestamp(record) {
316545
+ const observedAt = depositField(record, [
316546
+ "timestamp",
316547
+ "creditedAt",
316548
+ "credited_at",
316549
+ "updated",
316550
+ "updatedAt",
316551
+ "datetime"
316552
+ ]);
316553
+ const timestamp = typeof observedAt === "number" ? observedAt : typeof observedAt === "string" ? Date.parse(observedAt) : Number.NaN;
316554
+ return Number.isFinite(timestamp) ? timestamp : undefined;
316555
+ }
316556
+ function archivedDepositStatus(exchangeId, record) {
316557
+ const rawStatus = asRecord(record.info)?.status;
316558
+ if (exchangeId?.toLowerCase() === "binance" && String(rawStatus ?? "").trim() === "6") {
316559
+ return "credited_not_withdrawable";
316560
+ }
316561
+ return normalizeCcxtTransactionForArchive(record).status;
316562
+ }
316563
+ function nextDepositCursor(deposits, currentSince, depositsLimit, exchangeId) {
316564
+ if (deposits.length >= depositsLimit) {
316565
+ return currentSince;
316566
+ }
316567
+ let next = currentSince;
316568
+ let oldestPending = Number.POSITIVE_INFINITY;
316569
+ for (const deposit of deposits) {
316570
+ const record = asRecord(deposit);
316571
+ if (!record) {
316572
+ return currentSince;
316573
+ }
316574
+ const timestamp = depositTimestamp(record);
316575
+ const archiveStatus = archivedDepositStatus(exchangeId, record);
316576
+ const status = normalizeDepositStatus(depositField(record, ["status", "state"]));
316577
+ const isPending = archiveStatus === "credited_not_withdrawable" || status === "pending";
316578
+ if (timestamp === undefined) {
316579
+ if (isPending) {
316580
+ return currentSince;
316581
+ }
316582
+ continue;
316583
+ }
316584
+ if (isPending) {
316585
+ oldestPending = Math.min(oldestPending, timestamp);
316586
+ } else {
316587
+ next = Math.max(next, timestamp + 1);
316588
+ }
316589
+ }
316590
+ return Number.isFinite(oldestPending) ? Math.max(currentSince, oldestPending) : next;
316591
+ }
316592
+
316593
+ class DepositArchivePoller {
316594
+ params;
316595
+ #timer = null;
316596
+ #stopped = false;
316597
+ #running = null;
316598
+ #cursors = new Map;
316599
+ #lastArchivedByTarget = new Map;
316600
+ #unsupportedLogged = new Set;
316601
+ #config;
316602
+ constructor(params) {
316603
+ this.params = params;
316604
+ this.#config = { ...DEFAULT_CONFIG2, ...params.config };
316605
+ }
316606
+ start() {
316607
+ if (this.#timer || this.#stopped || !this.params.archiver.isEnabled()) {
316608
+ return;
316609
+ }
316610
+ log.info("\uD83D\uDCE5 Deposit archive poller started");
316611
+ this.#schedule(0);
316612
+ }
316613
+ async stop() {
316614
+ this.#stopped = true;
316615
+ if (this.#timer) {
316616
+ clearTimeout(this.#timer);
316617
+ this.#timer = null;
316618
+ }
316619
+ await this.#running;
316620
+ }
316621
+ async pollAllOnce() {
316622
+ if (this.#stopped || this.#running || !this.params.archiver.isEnabled()) {
316623
+ return false;
316624
+ }
316625
+ this.#running = this.#pollAllSequentially();
316626
+ try {
316627
+ return await this.#running;
316628
+ } finally {
316629
+ this.#running = null;
316630
+ }
316631
+ }
316632
+ #targets() {
316633
+ const targets = [];
316634
+ for (const [exchangeId, pool] of Object.entries(this.params.brokers)) {
316635
+ for (const account of [pool.primary, ...pool.secondaryBrokers]) {
316636
+ targets.push({
316637
+ exchangeId,
316638
+ account,
316639
+ code: ALL_CURRENCIES_CODE
316640
+ });
316641
+ }
316642
+ }
316643
+ return targets;
316644
+ }
316645
+ async#pollAllSequentially() {
316646
+ for (const target of this.#targets()) {
316647
+ if (this.#stopped) {
316648
+ break;
316649
+ }
316650
+ await this.#pollOne(target);
316651
+ }
316652
+ return true;
316653
+ }
316654
+ async#pollOne(target) {
316655
+ const exchange = target.account.exchange;
316656
+ const key = this.#targetKey(target);
316657
+ if (typeof exchange.fetchDeposits !== "function" || exchange.has?.fetchDeposits === false) {
316658
+ if (!this.#unsupportedLogged.has(key)) {
316659
+ this.#unsupportedLogged.add(key);
316660
+ log.info("Deposit archive poll skipped: fetchDeposits unsupported", {
316661
+ exchange: target.exchangeId,
316662
+ account: target.account.label
316663
+ });
316664
+ }
316665
+ return;
316666
+ }
316667
+ const since = this.#cursors.get(key) ?? Date.now() - this.#config.lookbackMs;
316668
+ let deposits;
316669
+ try {
316670
+ deposits = await exchange.fetchDeposits(undefined, since, this.#config.depositsLimit);
316671
+ } catch (error) {
316672
+ this.params.metrics?.recordCounter("cex_deposit_poller_errors_total", 1, { exchange: target.exchangeId });
316673
+ log.warn("Deposit archive poll failed", {
316674
+ exchange: target.exchangeId,
316675
+ account: target.account.label,
316676
+ error
316677
+ });
316678
+ return;
316679
+ }
316680
+ if (!Array.isArray(deposits) || deposits.length === 0) {
316681
+ return;
316682
+ }
316683
+ let archived = 0;
316684
+ for (const deposit of deposits) {
316685
+ const record = asRecord(deposit);
316686
+ if (!record) {
316687
+ continue;
316688
+ }
316689
+ const assetSymbol = depositField(record, ["currency", "code", "asset"]);
316690
+ const amount = depositField(record, ["amount"]);
316691
+ const address = depositField(record, [
316692
+ "address",
316693
+ "recipientAddress",
316694
+ "to",
316695
+ "destination"
316696
+ ]);
316697
+ const txid = depositField(record, ["txid", "txId", "tx_hash", "txHash"]);
316698
+ const network = depositField(record, ["network", "chain"]);
316699
+ const archiveStatus = archivedDepositStatus(target.exchangeId, record);
316700
+ const creditedAt = depositField(record, [
316701
+ "creditedAt",
316702
+ "credited_at",
316703
+ "updated",
316704
+ "updatedAt",
316705
+ "timestamp",
316706
+ "datetime"
316707
+ ]);
316708
+ const depositTxid = txid === undefined ? undefined : String(txid);
316709
+ const lastArchived = depositTxid === undefined ? undefined : this.#lastArchivedByTarget.get(key)?.get(depositTxid);
316710
+ if (lastArchived && lastArchived.status === archiveStatus) {
316711
+ continue;
316712
+ }
316713
+ this.params.archiver.enqueue(buildTransferEventArchiveRow({
316714
+ tags: buildCommonArchiveTags({
316715
+ deploymentId: this.params.archiver.getDeploymentId(),
316716
+ accountSelector: target.account.label,
316717
+ exchange: target.exchangeId,
316718
+ symbol: assetSymbol === undefined ? undefined : String(assetSymbol)
316719
+ }),
316720
+ transfer: {
316721
+ eventKind: "deposit",
316722
+ lifecycleAction: "observe_deposit",
316723
+ status: archiveStatus,
316724
+ amount: amount === undefined ? undefined : String(amount),
316725
+ address: address === undefined ? undefined : String(address),
316726
+ network: network === undefined ? undefined : String(network),
316727
+ externalId: depositTxid,
316728
+ txid: depositTxid,
316729
+ exchangeTimestamp: typeof creditedAt === "string" ? creditedAt : undefined,
316730
+ payload: record
316731
+ }
316732
+ }));
316733
+ if (depositTxid !== undefined) {
316734
+ let targetDeposits2 = this.#lastArchivedByTarget.get(key);
316735
+ if (!targetDeposits2) {
316736
+ targetDeposits2 = new Map;
316737
+ this.#lastArchivedByTarget.set(key, targetDeposits2);
316738
+ }
316739
+ targetDeposits2.set(depositTxid, {
316740
+ status: archiveStatus,
316741
+ timestamp: depositTimestamp(record)
316742
+ });
316743
+ }
316744
+ archived += 1;
316745
+ }
316746
+ if (archived > 0) {
316747
+ this.params.metrics?.recordCounter("cex_deposit_poller_deposits_archived_total", archived, { exchange: target.exchangeId });
316748
+ }
316749
+ const nextCursor = nextDepositCursor(deposits, since, this.#config.depositsLimit, target.exchangeId);
316750
+ this.#cursors.set(key, nextCursor);
316751
+ const targetDeposits = this.#lastArchivedByTarget.get(key);
316752
+ if (targetDeposits) {
316753
+ for (const [externalId, lastArchived] of targetDeposits) {
316754
+ if (lastArchived.timestamp !== undefined && lastArchived.timestamp < nextCursor) {
316755
+ targetDeposits.delete(externalId);
316756
+ }
316757
+ }
316758
+ if (targetDeposits.size === 0) {
316759
+ this.#lastArchivedByTarget.delete(key);
316760
+ }
316761
+ }
316762
+ }
316763
+ #targetKey(target) {
316764
+ return `${target.exchangeId}|${target.account.label}|${target.code}`;
316765
+ }
316766
+ #schedule(delayMs) {
316767
+ this.#timer = setTimeout(() => void this.#tick(), delayMs);
316768
+ this.#timer.unref?.();
316769
+ }
316770
+ async#tick() {
316771
+ this.#timer = null;
316772
+ try {
316773
+ await this.pollAllOnce();
316774
+ } catch (error) {
316775
+ rethrowArchiveDurabilityError(error);
316776
+ log.error("Deposit archive poller tick failed", error);
316777
+ } finally {
316778
+ if (!this.#stopped) {
316779
+ this.#schedule(this.#config.pollIntervalMs);
316780
+ }
316781
+ }
316782
+ }
316783
+ }
316784
+
316785
+ // src/helpers/fill-archive-poller.ts
316786
+ var DEFAULT_CONFIG3 = {
316539
316787
  pollIntervalMs: 60000,
316540
316788
  lookbackMs: 24 * 60 * 60 * 1000,
316541
316789
  tradesLimit: 500
@@ -316560,7 +316808,7 @@ class FillArchivePoller {
316560
316808
  #config;
316561
316809
  constructor(params) {
316562
316810
  this.params = params;
316563
- this.#config = { ...DEFAULT_CONFIG2, ...params.config };
316811
+ this.#config = { ...DEFAULT_CONFIG3, ...params.config };
316564
316812
  }
316565
316813
  start() {
316566
316814
  if (this.#timer || this.#stopped) {
@@ -316764,6 +317012,7 @@ function toAttributes(labels, service) {
316764
317012
  class OtelMetrics extends BaseOtelSignal {
316765
317013
  counters = new Map;
316766
317014
  histograms = new Map;
317015
+ observableGauges = new Map;
316767
317016
  constructor(config) {
316768
317017
  super(config, "metrics");
316769
317018
  }
@@ -316849,6 +317098,32 @@ class OtelMetrics extends BaseOtelSignal {
316849
317098
  log.error("Failed to record gauge:", error);
316850
317099
  }
316851
317100
  }
317101
+ async setObservableGauge(metricName, value, labels, service = this.getServiceName()) {
317102
+ const provider = this.getProvider();
317103
+ if (!this.isOtelEnabled() || !provider)
317104
+ return;
317105
+ try {
317106
+ let state = this.observableGauges.get(metricName);
317107
+ if (!state) {
317108
+ const observations = new Map;
317109
+ const instrument = provider.getMeter("cex-broker-metrics", "1.0.0").createObservableGauge(metricName, { description: metricName });
317110
+ instrument.addCallback((result) => {
317111
+ for (const observation of observations.values()) {
317112
+ result.observe(observation.value, observation.attributes);
317113
+ }
317114
+ });
317115
+ state = { instrument, observations };
317116
+ this.observableGauges.set(metricName, state);
317117
+ }
317118
+ const attributes = toAttributes(labels, service);
317119
+ state.observations.set(stableAttributeKey(attributes), {
317120
+ value,
317121
+ attributes
317122
+ });
317123
+ } catch (error) {
317124
+ log.error("Failed to set observable gauge:", error);
317125
+ }
317126
+ }
316852
317127
  async recordHistogram(metricName, value, labels, service = this.getServiceName()) {
316853
317128
  const provider = this.getProvider();
316854
317129
  if (!this.isOtelEnabled() || !provider)
@@ -316953,27 +317228,33 @@ function getOtelProtocolFromEnv() {
316953
317228
  const protocol = process.env.CEX_BROKER_OTEL_PROTOCOL ?? process.env.CEX_BROKER_CLICKHOUSE_PROTOCOL;
316954
317229
  return protocol || "http";
316955
317230
  }
316956
- function createOtelMetricsFromEnv() {
317231
+ function createOtelMetricsFromEnv(options = {}) {
316957
317232
  const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
316958
- const host = getOtelHostFromEnv();
317233
+ const serviceName = process.env.OTEL_SERVICE_NAME || options.defaultServiceName || DEFAULT_SERVICE;
316959
317234
  if (otlpEndpoint) {
316960
317235
  return new OtelMetrics({
316961
- otlpEndpoint: otlpEndpoint.replace(/\/v1\/metrics\/?$/, ""),
316962
- serviceName: process.env.OTEL_SERVICE_NAME || DEFAULT_SERVICE
317236
+ otlpEndpoint,
317237
+ serviceName
316963
317238
  });
316964
317239
  }
316965
- if (!host) {
316966
- return new OtelMetrics;
317240
+ if (options.allowLegacyBrokerConfig === false) {
317241
+ return new OtelMetrics({ serviceName });
316967
317242
  }
317243
+ const host = getOtelHostFromEnv();
317244
+ if (!host)
317245
+ return new OtelMetrics({ serviceName });
316968
317246
  const port = getOtelPortFromEnv();
316969
317247
  const config = {
316970
317248
  host,
316971
317249
  port: port ?? DEFAULT_OTLP_PORT,
316972
317250
  protocol: getOtelProtocolFromEnv(),
316973
- serviceName: process.env.OTEL_SERVICE_NAME || DEFAULT_SERVICE
317251
+ serviceName
316974
317252
  };
316975
317253
  return new OtelMetrics(config);
316976
317254
  }
317255
+ function stableAttributeKey(attributes) {
317256
+ return JSON.stringify(Object.entries(attributes).sort(([left], [right]) => left.localeCompare(right)));
317257
+ }
316977
317258
  function createOtelLogsFromEnv() {
316978
317259
  const logsEndpoint = process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT;
316979
317260
  const genericEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
@@ -330786,6 +331067,12 @@ function parseActionPayload(schema, rawPayload, callback) {
330786
331067
  // src/helpers/grpc/status.ts
330787
331068
  var grpc2 = __toESM(require_src3(), 1);
330788
331069
  function stableGrpcErrorCode(message) {
331070
+ if (message.startsWith("AuthenticationError:")) {
331071
+ return grpc2.status.UNAUTHENTICATED;
331072
+ }
331073
+ if (message.startsWith("InsufficientFunds:")) {
331074
+ return grpc2.status.FAILED_PRECONDITION;
331075
+ }
330789
331076
  if (message.startsWith("venue_discovery_unavailable:")) {
330790
331077
  return grpc2.status.UNIMPLEMENTED;
330791
331078
  }
@@ -330936,7 +331223,8 @@ async function handleDeposit(ctx) {
330936
331223
  message: `deposit_address_mismatch: expected address ${value.recipientAddress}, observed ${String(observedAddress)}`
330937
331224
  }, null);
330938
331225
  }
330939
- const status4 = normalizeDepositStatus(depositField(deposit, ["status", "state"]));
331226
+ const responseStatus = normalizeDepositStatus(depositField(deposit, ["status", "state"]));
331227
+ const archiveStatus = normalizeCcxtTransactionForArchive(deposit).status;
330940
331228
  const depositTxid = String(depositField(deposit, ["txid", "txId", "tx_hash", "txHash"]) ?? value.transactionHash);
330941
331229
  const creditedAt = depositField(deposit, [
330942
331230
  "creditedAt",
@@ -330953,7 +331241,7 @@ async function handleDeposit(ctx) {
330953
331241
  transfer: {
330954
331242
  eventKind: "deposit",
330955
331243
  lifecycleAction: "observe_deposit",
330956
- status: status4,
331244
+ status: archiveStatus,
330957
331245
  amount: observedAmount !== undefined ? String(observedAmount) : undefined,
330958
331246
  address: String(observedAddress ?? value.recipientAddress),
330959
331247
  network: depositNetwork?.exchangeNetworkId,
@@ -330967,7 +331255,7 @@ async function handleDeposit(ctx) {
330967
331255
  return ctx.wrappedCallback(null, {
330968
331256
  proof: ctx.verity.proof,
330969
331257
  result: JSON.stringify({
330970
- status: status4,
331258
+ status: responseStatus,
330971
331259
  exchange: normalizedCex,
330972
331260
  accountSelector: selectedBrokerAccount?.label,
330973
331261
  asset: symbol2,
@@ -331486,6 +331774,12 @@ function identifiesUnsupported(message) {
331486
331774
  return /post[\s-]?only\b.*\b(?:not supported|unsupported|does not support)\b/.test(normalized) || /\b(?:not supported|unsupported|does not support)\b.*\bpost[\s-]?only\b/.test(normalized);
331487
331775
  }
331488
331776
  function classifyPassiveOrderError(error48) {
331777
+ if (error48 instanceof ccxt_default.InsufficientFunds) {
331778
+ return "InsufficientFunds";
331779
+ }
331780
+ if (error48 instanceof ccxt_default.AuthenticationError) {
331781
+ return "AuthenticationError";
331782
+ }
331489
331783
  const message = getErrorMessage(error48);
331490
331784
  if (error48 instanceof ccxt_default.OrderImmediatelyFillable || identifiesWouldCross(message)) {
331491
331785
  return PASSIVE_ORDER_ERROR_CODES.wouldCross;
@@ -331614,9 +331908,9 @@ async function handleCreateOrder(ctx) {
331614
331908
  emitOrderExecutionTelemetryInBackground(otelMetrics, failedCreateContext, undefined, error48);
331615
331909
  archiveOrderExecutionInBackground(brokerArchiver, failedCreateContext, undefined, error48, { marketMetadataHash });
331616
331910
  if (isPassiveOrder && submission === "in_flight") {
331617
- const passiveErrorCode = classifyPassiveOrderError(error48);
331911
+ const stableErrorCode = classifyPassiveOrderError(error48);
331618
331912
  return rejectWithGrpcError(ctx, error48, {
331619
- message: `${passiveErrorCode}: ${sanitizeErrorDetail(error48)}`,
331913
+ message: `${stableErrorCode}: ${sanitizeErrorDetail(error48)}`,
331620
331914
  preferStableMessageOnly: true
331621
331915
  });
331622
331916
  }
@@ -334516,6 +334810,7 @@ class CEXBroker {
334516
334810
  orderActivityTracker = new OrderActivityTracker;
334517
334811
  withdrawalObservationTracker = new WithdrawalObservationTracker;
334518
334812
  fillArchivePoller;
334813
+ depositArchivePoller;
334519
334814
  accountBalanceArchivePoller;
334520
334815
  loadEnvConfig() {
334521
334816
  log.info("\uD83D\uDD27 Loading CEX_BROKER_ environment variables:");
@@ -334661,6 +334956,10 @@ class CEXBroker {
334661
334956
  this.fillArchivePoller.stop();
334662
334957
  this.fillArchivePoller = undefined;
334663
334958
  }
334959
+ if (this.depositArchivePoller) {
334960
+ await this.depositArchivePoller.stop();
334961
+ this.depositArchivePoller = undefined;
334962
+ }
334664
334963
  if (this.accountBalanceArchivePoller) {
334665
334964
  await this.accountBalanceArchivePoller.stop();
334666
334965
  this.accountBalanceArchivePoller = undefined;
@@ -334690,6 +334989,10 @@ class CEXBroker {
334690
334989
  this.fillArchivePoller.stop();
334691
334990
  this.fillArchivePoller = undefined;
334692
334991
  }
334992
+ if (this.depositArchivePoller) {
334993
+ await this.depositArchivePoller.stop();
334994
+ this.depositArchivePoller = undefined;
334995
+ }
334693
334996
  if (this.accountBalanceArchivePoller) {
334694
334997
  await this.accountBalanceArchivePoller.stop();
334695
334998
  this.accountBalanceArchivePoller = undefined;
@@ -334721,6 +335024,12 @@ class CEXBroker {
334721
335024
  metrics: this.otelMetrics
334722
335025
  });
334723
335026
  this.fillArchivePoller.start();
335027
+ this.depositArchivePoller = new DepositArchivePoller({
335028
+ brokers: this.brokers,
335029
+ archiver: this.brokerArchiver,
335030
+ metrics: this.otelMetrics
335031
+ });
335032
+ this.depositArchivePoller.start();
334724
335033
  }
334725
335034
  if (this.brokerArchiver?.canPersistAccountBalanceSnapshots()) {
334726
335035
  this.accountBalanceArchivePoller = new AccountBalanceArchivePoller({
@@ -0,0 +1,32 @@
1
+ import type { BrokerPoolEntry } from "./broker";
2
+ import { type BrokerExecutionArchiver } from "./broker-execution-archive";
3
+ import type { OtelMetrics } from "./otel";
4
+ export type DepositArchivePollerConfig = {
5
+ pollIntervalMs: number;
6
+ lookbackMs: number;
7
+ depositsLimit: number;
8
+ };
9
+ /**
10
+ * Advances the inclusive since-watermark only across a fully observed,
11
+ * terminal prefix of deposit history.
12
+ */
13
+ export declare function nextDepositCursor(deposits: unknown[], currentSince: number, depositsLimit: number, exchangeId?: string): number;
14
+ /**
15
+ * Broker-internal periodic capture of venue deposit history. It polls every
16
+ * configured account sequentially, using ccxt's unfiltered deposit-history
17
+ * surface so newly funded currencies do not depend on balance or market
18
+ * discovery.
19
+ */
20
+ export declare class DepositArchivePoller {
21
+ #private;
22
+ private readonly params;
23
+ constructor(params: {
24
+ brokers: Record<string, BrokerPoolEntry>;
25
+ archiver: BrokerExecutionArchiver;
26
+ metrics?: OtelMetrics;
27
+ config?: Partial<DepositArchivePollerConfig>;
28
+ });
29
+ start(): void;
30
+ stop(): Promise<void>;
31
+ pollAllOnce(): Promise<boolean>;
32
+ }
@@ -27,6 +27,12 @@ export interface MetricData {
27
27
  labels: string;
28
28
  service: string;
29
29
  }
30
+ export interface OtelMetricsEnvOptions {
31
+ /** Service name used when OTEL_SERVICE_NAME is not configured. */
32
+ defaultServiceName?: string;
33
+ /** Whether broker-specific legacy collector host variables are accepted. */
34
+ allowLegacyBrokerConfig?: boolean;
35
+ }
30
36
  declare abstract class BaseOtelSignal<TProvider> {
31
37
  private readonly signal;
32
38
  private provider;
@@ -45,6 +51,7 @@ declare abstract class BaseOtelSignal<TProvider> {
45
51
  export declare class OtelMetrics extends BaseOtelSignal<MeterProviderType> {
46
52
  private readonly counters;
47
53
  private readonly histograms;
54
+ private readonly observableGauges;
48
55
  constructor(config?: OtelConfig);
49
56
  protected createProvider(endpoint: string, serviceName: string, appendSignalPath: boolean): MeterProviderType;
50
57
  protected onProviderCreated(provider: MeterProviderType): void;
@@ -54,6 +61,11 @@ export declare class OtelMetrics extends BaseOtelSignal<MeterProviderType> {
54
61
  insertMetrics(metricsList: MetricData[]): Promise<void>;
55
62
  recordCounter(metricName: string, value: number, labels: Record<string, string | number>, service?: string): Promise<void>;
56
63
  recordGauge(metricName: string, value: number, labels: Record<string, string | number>, service?: string): Promise<void>;
64
+ /**
65
+ * Set a gauge value that is observed on every export. This is suitable for
66
+ * staleness signals where a quiet live process must keep exporting its last value.
67
+ */
68
+ setObservableGauge(metricName: string, value: number, labels: Record<string, string | number>, service?: string): Promise<void>;
57
69
  recordHistogram(metricName: string, value: number, labels: Record<string, string | number>, service?: string): Promise<void>;
58
70
  }
59
71
  export declare class OtelLogs extends BaseOtelSignal<LoggerProvider> {
@@ -65,6 +77,6 @@ export declare class OtelLogs extends BaseOtelSignal<LoggerProvider> {
65
77
  protected onProviderClosed(): void;
66
78
  emit(record: LogRecord): void;
67
79
  }
68
- export declare function createOtelMetricsFromEnv(): OtelMetrics;
80
+ export declare function createOtelMetricsFromEnv(options?: OtelMetricsEnvOptions): OtelMetrics;
69
81
  export declare function createOtelLogsFromEnv(): OtelLogs;
70
82
  export {};
@@ -4,4 +4,5 @@ export declare const PASSIVE_ORDER_ERROR_CODES: {
4
4
  readonly wouldCross: "passive_order_would_cross";
5
5
  };
6
6
  export type PassiveOrderErrorCode = (typeof PASSIVE_ORDER_ERROR_CODES)[keyof typeof PASSIVE_ORDER_ERROR_CODES];
7
- export declare function classifyPassiveOrderError(error: unknown): PassiveOrderErrorCode;
7
+ export type PassiveOrderSubmissionErrorCode = PassiveOrderErrorCode | "AuthenticationError" | "InsufficientFunds";
8
+ export declare function classifyPassiveOrderError(error: unknown): PassiveOrderSubmissionErrorCode;
package/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ export default class CEXBroker {
16
16
  private readonly orderActivityTracker;
17
17
  private readonly withdrawalObservationTracker;
18
18
  private fillArchivePoller?;
19
+ private depositArchivePoller?;
19
20
  private accountBalanceArchivePoller?;
20
21
  /**
21
22
  * Loads environment variables prefixed with CEX_BROKER_