@usherlabs/cex-broker 0.2.0 → 0.2.2

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.
@@ -313654,20 +313654,33 @@ function loadPolicy(policyPath) {
313654
313654
  if (error) {
313655
313655
  throw new Error(`Policy validation failed: ${error.details.map((d) => d.message).join("; ")}`);
313656
313656
  }
313657
- const normalizedPolicy = value;
313658
- normalizedPolicy.withdraw.rule = normalizedPolicy.withdraw.rule.map((rule) => ({
313659
- ...rule,
313660
- exchange: rule.exchange.trim().toUpperCase(),
313661
- network: rule.network.trim().toUpperCase(),
313662
- whitelist: rule.whitelist.map((a) => a.trim().toLowerCase())
313663
- }));
313664
- normalizedPolicy.order.rule.limits = normalizedPolicy.order.rule.limits ?? [];
313665
- return normalizedPolicy;
313657
+ return normalizePolicyConfig(value);
313666
313658
  } catch (error) {
313667
313659
  console.error("Failed to load policy:", error);
313668
313660
  throw new Error("Policy configuration could not be loaded");
313669
313661
  }
313670
313662
  }
313663
+ function normalizePolicyConfig(policy) {
313664
+ return {
313665
+ ...policy,
313666
+ withdraw: {
313667
+ ...policy.withdraw,
313668
+ rule: policy.withdraw.rule.map((rule) => ({
313669
+ ...rule,
313670
+ exchange: rule.exchange.trim().toUpperCase(),
313671
+ network: rule.network.trim().toUpperCase(),
313672
+ whitelist: rule.whitelist.map((address) => address.trim().toLowerCase())
313673
+ }))
313674
+ },
313675
+ order: {
313676
+ ...policy.order,
313677
+ rule: {
313678
+ ...policy.order.rule,
313679
+ limits: policy.order.rule.limits ?? []
313680
+ }
313681
+ }
313682
+ };
313683
+ }
313671
313684
  function getWithdrawRulePriority(rule, exchange, network) {
313672
313685
  const exchangeMatch = rule.exchange === exchange || rule.exchange === "*";
313673
313686
  const networkMatch = rule.network === network || rule.network === "*";
@@ -313686,15 +313699,16 @@ function getWithdrawRulePriority(rule, exchange, network) {
313686
313699
  return 1;
313687
313700
  }
313688
313701
  function validateWithdraw(policy, exchange, network, recipientAddress, _amount, _ticker) {
313702
+ const normalizedPolicy = normalizePolicyConfig(policy);
313689
313703
  const exchangeNorm = exchange.trim().toUpperCase();
313690
313704
  const networkNorm = network.trim().toUpperCase();
313691
- const matchingRules = policy.withdraw.rule.map((rule) => ({
313705
+ const matchingRules = normalizedPolicy.withdraw.rule.map((rule) => ({
313692
313706
  rule,
313693
313707
  priority: getWithdrawRulePriority(rule, exchangeNorm, networkNorm)
313694
313708
  })).filter((r) => r.priority > 0).sort((a, b2) => b2.priority - a.priority);
313695
313709
  const withdrawRule = matchingRules[0]?.rule;
313696
313710
  if (!withdrawRule) {
313697
- const allowedPairs = policy.withdraw.rule.map((r) => `${r.exchange}:${r.network}`);
313711
+ const allowedPairs = normalizedPolicy.withdraw.rule.map((r) => `${r.exchange}:${r.network}`);
313698
313712
  return {
313699
313713
  valid: false,
313700
313714
  error: `Network ${networkNorm} is not allowed for exchange ${exchangeNorm}. Allowed exchange/network pairs: ${allowedPairs.join(", ")}`
@@ -314303,10 +314317,77 @@ var descriptor = {
314303
314317
  };
314304
314318
  var node_descriptor_default = descriptor;
314305
314319
 
314320
+ // src/utils/payload-reader.ts
314321
+ class PayloadValidationError extends Error {
314322
+ constructor(message) {
314323
+ super(`ValidationError: ${message}`);
314324
+ this.name = "PayloadValidationError";
314325
+ }
314326
+ }
314327
+ function parseNumberField(value, fieldName) {
314328
+ if (typeof value !== "string" && typeof value !== "number") {
314329
+ throw new PayloadValidationError(`'${fieldName}' must be a numeric string`);
314330
+ }
314331
+ const parsed = typeof value === "number" ? value : Number(value.trim());
314332
+ if (!Number.isFinite(parsed)) {
314333
+ throw new PayloadValidationError(`'${fieldName}' must be a valid number`);
314334
+ }
314335
+ return parsed;
314336
+ }
314337
+ function parseJsonField(value, fieldName, expected) {
314338
+ const parsedValue = typeof value === "string" ? (() => {
314339
+ try {
314340
+ return JSON.parse(value);
314341
+ } catch {
314342
+ throw new PayloadValidationError(`Failed to parse JSON for '${fieldName}'`);
314343
+ }
314344
+ })() : value;
314345
+ if (expected === "jsonObject") {
314346
+ if (typeof parsedValue !== "object" || parsedValue === null || Array.isArray(parsedValue)) {
314347
+ throw new PayloadValidationError(`'${fieldName}' must be a JSON object`);
314348
+ }
314349
+ return parsedValue;
314350
+ }
314351
+ if (!Array.isArray(parsedValue)) {
314352
+ throw new PayloadValidationError(`'${fieldName}' must be a JSON array`);
314353
+ }
314354
+ return parsedValue;
314355
+ }
314356
+
314357
+ class PayloadReader {
314358
+ payload;
314359
+ constructor(payload) {
314360
+ this.payload = { ...payload ?? {} };
314361
+ }
314362
+ read(shape) {
314363
+ const prepared = { ...this.payload };
314364
+ for (const [fieldName, spec] of Object.entries(shape)) {
314365
+ const rawValue = prepared[fieldName];
314366
+ const isMissing = rawValue === undefined || rawValue === null;
314367
+ if (isMissing) {
314368
+ if (spec.required) {
314369
+ throw new PayloadValidationError(`'${fieldName}' is required`);
314370
+ }
314371
+ continue;
314372
+ }
314373
+ if (spec.type === "number") {
314374
+ prepared[fieldName] = parseNumberField(rawValue, fieldName);
314375
+ continue;
314376
+ }
314377
+ prepared[fieldName] = parseJsonField(rawValue, fieldName, spec.type);
314378
+ }
314379
+ return prepared;
314380
+ }
314381
+ }
314382
+
314306
314383
  // src/server.ts
314307
314384
  var packageDef = protoLoader.fromJSON(node_descriptor_default);
314308
314385
  var grpcObj = grpc.loadPackageDefinition(packageDef);
314309
314386
  var cexNode = grpcObj.cex_broker;
314387
+ function preparePayload(rawPayload, shape) {
314388
+ const payload = new PayloadReader(rawPayload);
314389
+ return payload.read(shape);
314390
+ }
314310
314391
  function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, otelMetrics) {
314311
314392
  const server = new grpc.Server;
314312
314393
  server.addService(cexNode.cex_service.service, {
@@ -314383,9 +314464,25 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314383
314464
  amount: import_joi2.default.number().positive().required(),
314384
314465
  transactionHash: import_joi2.default.string().required(),
314385
314466
  since: import_joi2.default.number(),
314386
- params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
314467
+ params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
314387
314468
  });
314388
- const { value, error } = transactionSchema.validate(call.request.payload ?? {});
314469
+ let payload;
314470
+ try {
314471
+ payload = preparePayload(call.request.payload, {
314472
+ amount: { type: "number", required: true },
314473
+ since: { type: "number" },
314474
+ params: { type: "jsonObject" }
314475
+ });
314476
+ } catch (error2) {
314477
+ if (error2 instanceof PayloadValidationError) {
314478
+ return wrappedCallback({
314479
+ code: grpc.status.INVALID_ARGUMENT,
314480
+ message: error2.message
314481
+ }, null);
314482
+ }
314483
+ throw error2;
314484
+ }
314485
+ const { value, error } = transactionSchema.validate(payload);
314389
314486
  if (error) {
314390
314487
  return wrappedCallback({
314391
314488
  code: grpc.status.INVALID_ARGUMENT,
@@ -314446,7 +314543,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314446
314543
  }
314447
314544
  case Action.FetchAccountId: {
314448
314545
  try {
314449
- let accountId = await broker.fetchAccountId();
314546
+ const accountId = await broker.fetchAccountId();
314450
314547
  return wrappedCallback(null, {
314451
314548
  proof: verityProof,
314452
314549
  result: JSON.stringify({ accountId })
@@ -314494,20 +314591,20 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314494
314591
  args: import_joi2.default.array().items(import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number(), import_joi2.default.boolean(), import_joi2.default.object(), import_joi2.default.array())).default([]),
314495
314592
  params: import_joi2.default.object().default({})
314496
314593
  });
314497
- const rawPayload = call.request.payload ?? {};
314498
- const preparedPayload = { ...rawPayload };
314594
+ let preparedPayload;
314499
314595
  try {
314500
- if (typeof preparedPayload.args === "string") {
314501
- preparedPayload.args = JSON.parse(preparedPayload.args);
314502
- }
314503
- if (typeof preparedPayload.params === "string") {
314504
- preparedPayload.params = JSON.parse(preparedPayload.params);
314596
+ preparedPayload = preparePayload(call.request.payload, {
314597
+ args: { type: "jsonArray" },
314598
+ params: { type: "jsonObject" }
314599
+ });
314600
+ } catch (error) {
314601
+ if (error instanceof PayloadValidationError) {
314602
+ return wrappedCallback({
314603
+ code: grpc.status.INVALID_ARGUMENT,
314604
+ message: error.message
314605
+ }, null);
314505
314606
  }
314506
- } catch {
314507
- return wrappedCallback({
314508
- code: grpc.status.INVALID_ARGUMENT,
314509
- message: "ValidationError: Failed to parse JSON for 'args' or 'params'"
314510
- }, null);
314607
+ throw error;
314511
314608
  }
314512
314609
  const { value: callValue, error: callError } = callSchema.validate(preparedPayload);
314513
314610
  if (callError) {
@@ -314564,11 +314661,24 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314564
314661
  const {
314565
314662
  value: fetchDepositAddresses,
314566
314663
  error: errorFetchDepositAddresses
314567
- } = fetchDepositAddressesSchema.validate(call.request.payload ?? {});
314664
+ } = (() => {
314665
+ try {
314666
+ const payload = preparePayload(call.request.payload, {
314667
+ params: { type: "jsonObject" }
314668
+ });
314669
+ return fetchDepositAddressesSchema.validate(payload);
314670
+ } catch (error) {
314671
+ if (error instanceof PayloadValidationError) {
314672
+ return { value: null, error };
314673
+ }
314674
+ throw error;
314675
+ }
314676
+ })();
314568
314677
  if (errorFetchDepositAddresses) {
314678
+ const message = errorFetchDepositAddresses instanceof PayloadValidationError ? errorFetchDepositAddresses.message : `ValidationError: ${errorFetchDepositAddresses.message}`;
314569
314679
  return wrappedCallback({
314570
314680
  code: grpc.status.INVALID_ARGUMENT,
314571
- message: `ValidationError: ${errorFetchDepositAddresses?.message}`
314681
+ message
314572
314682
  }, null);
314573
314683
  }
314574
314684
  try {
@@ -314612,16 +314722,31 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314612
314722
  recipientAddress: import_joi2.default.string().required(),
314613
314723
  amount: import_joi2.default.number().positive().required(),
314614
314724
  chain: import_joi2.default.string().required(),
314615
- params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
314725
+ params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
314616
314726
  });
314617
- const { value: transferValue, error: transferError } = transferSchema.validate(call.request.payload ?? {});
314727
+ let payload;
314728
+ try {
314729
+ payload = preparePayload(call.request.payload, {
314730
+ amount: { type: "number", required: true },
314731
+ params: { type: "jsonObject" }
314732
+ });
314733
+ } catch (error) {
314734
+ if (error instanceof PayloadValidationError) {
314735
+ return wrappedCallback({
314736
+ code: grpc.status.INVALID_ARGUMENT,
314737
+ message: error.message
314738
+ }, null);
314739
+ }
314740
+ throw error;
314741
+ }
314742
+ const { value: transferValue, error: transferError } = transferSchema.validate(payload);
314618
314743
  if (transferError) {
314619
314744
  return wrappedCallback({
314620
314745
  code: grpc.status.INVALID_ARGUMENT,
314621
314746
  message: `ValidationError:" ${transferError?.message}`
314622
314747
  }, null);
314623
314748
  }
314624
- const transferValidation = validateWithdraw(policy, cex3, transferValue.chain, transferValue.recipientAddress, Number(transferValue.amount), symbol);
314749
+ const transferValidation = validateWithdraw(policy, cex3, transferValue.chain, transferValue.recipientAddress, transferValue.amount, symbol);
314625
314750
  if (!transferValidation.valid) {
314626
314751
  return wrappedCallback({
314627
314752
  code: grpc.status.PERMISSION_DENIED,
@@ -314637,7 +314762,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314637
314762
  message: `Broker ${cex3} doesnt support this ${transferValue.chain} for token ${symbol}`
314638
314763
  }, null);
314639
314764
  }
314640
- const transaction = await broker.withdraw(symbol, Number(transferValue.amount), transferValue.recipientAddress, undefined, { network: transferValue.chain });
314765
+ const transaction = await broker.withdraw(symbol, transferValue.amount, transferValue.recipientAddress, undefined, { network: transferValue.chain });
314641
314766
  log.info(`Withdraw Result: ${JSON.stringify(transaction)}`);
314642
314767
  wrappedCallback(null, {
314643
314768
  proof: verityProof,
@@ -314659,9 +314784,25 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314659
314784
  fromToken: import_joi2.default.string().required(),
314660
314785
  toToken: import_joi2.default.string().required(),
314661
314786
  price: import_joi2.default.number().positive().required(),
314662
- params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
314787
+ params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
314663
314788
  });
314664
- const { value: orderValue, error: orderError } = createOrderSchema.validate(call.request.payload ?? {});
314789
+ let payload;
314790
+ try {
314791
+ payload = preparePayload(call.request.payload, {
314792
+ amount: { type: "number", required: true },
314793
+ price: { type: "number", required: true },
314794
+ params: { type: "jsonObject" }
314795
+ });
314796
+ } catch (error) {
314797
+ if (error instanceof PayloadValidationError) {
314798
+ return wrappedCallback({
314799
+ code: grpc.status.INVALID_ARGUMENT,
314800
+ message: error.message
314801
+ }, null);
314802
+ }
314803
+ throw error;
314804
+ }
314805
+ const { value: orderValue, error: orderError } = createOrderSchema.validate(payload);
314665
314806
  if (orderError) {
314666
314807
  return wrappedCallback({
314667
314808
  code: grpc.status.INVALID_ARGUMENT,
@@ -314675,14 +314816,14 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314675
314816
  message: `Invalid CEX key: ${cex3}. Supported keys: ${Object.keys(brokers).join(", ")}`
314676
314817
  }, null);
314677
314818
  }
314678
- const resolution = await resolveOrderExecution(policy, broker, cex3, orderValue.fromToken, orderValue.toToken, Number(orderValue.amount), Number(orderValue.price));
314819
+ const resolution = await resolveOrderExecution(policy, broker, cex3, orderValue.fromToken, orderValue.toToken, orderValue.amount, orderValue.price);
314679
314820
  if (!resolution.valid || !resolution.symbol || !resolution.side) {
314680
314821
  return wrappedCallback({
314681
314822
  code: grpc.status.INVALID_ARGUMENT,
314682
314823
  message: resolution.error ?? "Order rejected by policy: market or limits not satisfied"
314683
314824
  }, null);
314684
314825
  }
314685
- const order = await broker.createOrder(resolution.symbol, orderValue.orderType, resolution.side, Number(resolution.amountBase ?? orderValue.amount), Number(orderValue.price), orderValue.params ?? {});
314826
+ const order = await broker.createOrder(resolution.symbol, orderValue.orderType, resolution.side, resolution.amountBase ?? orderValue.amount, orderValue.price, orderValue.params ?? {});
314686
314827
  wrappedCallback(null, { result: JSON.stringify({ ...order }) });
314687
314828
  } catch (error) {
314688
314829
  log.error({ error });
@@ -314696,9 +314837,23 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314696
314837
  case Action.GetOrderDetails: {
314697
314838
  const getOrderSchema = import_joi2.default.object({
314698
314839
  orderId: import_joi2.default.string().required(),
314699
- params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
314840
+ params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
314700
314841
  });
314701
- const { value: getOrderValue, error: getOrderError } = getOrderSchema.validate(call.request.payload ?? {});
314842
+ let payload;
314843
+ try {
314844
+ payload = preparePayload(call.request.payload, {
314845
+ params: { type: "jsonObject" }
314846
+ });
314847
+ } catch (error) {
314848
+ if (error instanceof PayloadValidationError) {
314849
+ return wrappedCallback({
314850
+ code: grpc.status.INVALID_ARGUMENT,
314851
+ message: error.message
314852
+ }, null);
314853
+ }
314854
+ throw error;
314855
+ }
314856
+ const { value: getOrderValue, error: getOrderError } = getOrderSchema.validate(payload);
314702
314857
  if (getOrderError) {
314703
314858
  return wrappedCallback({
314704
314859
  code: grpc.status.INVALID_ARGUMENT,
@@ -314736,9 +314891,23 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314736
314891
  case Action.CancelOrder: {
314737
314892
  const cancelOrderSchema = import_joi2.default.object({
314738
314893
  orderId: import_joi2.default.string().required(),
314739
- params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
314894
+ params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
314740
314895
  });
314741
- const { value: cancelOrderValue, error: cancelOrderError } = cancelOrderSchema.validate(call.request.payload ?? {});
314896
+ let payload;
314897
+ try {
314898
+ payload = preparePayload(call.request.payload, {
314899
+ params: { type: "jsonObject" }
314900
+ });
314901
+ } catch (error) {
314902
+ if (error instanceof PayloadValidationError) {
314903
+ return wrappedCallback({
314904
+ code: grpc.status.INVALID_ARGUMENT,
314905
+ message: error.message
314906
+ }, null);
314907
+ }
314908
+ throw error;
314909
+ }
314910
+ const { value: cancelOrderValue, error: cancelOrderError } = cancelOrderSchema.validate(payload);
314742
314911
  if (cancelOrderError) {
314743
314912
  return wrappedCallback({
314744
314913
  code: grpc.status.INVALID_ARGUMENT,
@@ -314855,7 +315024,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
314855
315024
  });
314856
315025
  const subscriptionTypeName = (() => {
314857
315026
  for (const [key, value] of Object.entries(SubscriptionType)) {
314858
- if (value === subscriptionType && isNaN(Number(key))) {
315027
+ if (value === subscriptionType && Number.isNaN(Number(key))) {
314859
315028
  return key;
314860
315029
  }
314861
315030
  }
@@ -315272,7 +315441,7 @@ class CEXBroker {
315272
315441
  this.policy = loadPolicy(policies);
315273
315442
  this.port = config?.port ?? 8086;
315274
315443
  } else {
315275
- this.policy = policies;
315444
+ this.policy = normalizePolicyConfig(policies);
315276
315445
  }
315277
315446
  if (this.#policyFilePath) {
315278
315447
  this.watchPolicyFile(this.#policyFilePath);
@@ -0,0 +1 @@
1
+ export declare const CCXT_METHODS_WITH_VERITY: string[];
@@ -0,0 +1,63 @@
1
+ import type { PolicyConfig, BrokerCredentials } from "../types";
2
+ import type { Metadata, ServerUnaryCall } from "@grpc/grpc-js";
3
+ import type { Exchange, HttpClientOverride, HttpOverridePredicate } from "@usherlabs/ccxt";
4
+ export declare function authenticateRequest<T, E>(call: ServerUnaryCall<T, E>, whitelistIps: string[]): boolean;
5
+ export declare function createVerityHttpClientOverride(verityProverUrl: string, onProofCallback: (proof: string, notaryPubKey?: string) => void): (redact: string, proofTimeout: number) => HttpClientOverride;
6
+ export declare function applyCommonExchangeConfig(exchange: Exchange): void;
7
+ export declare function buildHttpClientOverrideFromMetadata(metadata: Metadata, verityProverUrl: string, onProofCallback: (proof: string, notaryPubKey?: string) => void): HttpClientOverride;
8
+ export declare const verityHttpClientOverridePredicate: HttpOverridePredicate;
9
+ export declare function createBroker(cex: string, credsOrMetadata: {
10
+ apiKey: string;
11
+ apiSecret: string;
12
+ } | Metadata): Exchange | null;
13
+ type EnvConfigMap = Record<string, Partial<BrokerCredentials> & {
14
+ _secondaryMap?: Record<number, {
15
+ apiKey?: string;
16
+ apiSecret?: string;
17
+ }>;
18
+ }>;
19
+ type ValidatedCredentialsMap = Record<string, BrokerCredentials & {
20
+ secondaryKeys: BrokerCredentials[];
21
+ }>;
22
+ export declare function createBrokerPool(cfg: EnvConfigMap | ValidatedCredentialsMap): Record<string, {
23
+ primary: Exchange;
24
+ secondaryBrokers: Exchange[];
25
+ }>;
26
+ export declare function selectBroker(brokers: {
27
+ primary: Exchange;
28
+ secondaryBrokers: Exchange[];
29
+ } | undefined, metadata: Metadata): Exchange | null;
30
+ /**
31
+ * Loads and validates policy configuration
32
+ */
33
+ export declare function loadPolicy(policyPath: string): PolicyConfig;
34
+ export declare function normalizePolicyConfig(policy: PolicyConfig): PolicyConfig;
35
+ export declare function validateWithdraw(policy: PolicyConfig, exchange: string, network: string, recipientAddress: string, _amount: number, _ticker: string): {
36
+ valid: boolean;
37
+ error?: string;
38
+ };
39
+ /**
40
+ * Validates order request against policy rules
41
+ */
42
+ export declare function validateOrder(policy: PolicyConfig, fromToken: string, toToken: string, amount: number, broker: string): {
43
+ valid: boolean;
44
+ error?: string;
45
+ };
46
+ type OrderExecutionResolution = {
47
+ valid: boolean;
48
+ error?: string;
49
+ symbol?: string;
50
+ side?: "buy" | "sell";
51
+ amountBase?: number;
52
+ limitsApplied?: boolean;
53
+ matchedPatterns?: string[];
54
+ };
55
+ export declare function resolveOrderExecution(policy: PolicyConfig, broker: Exchange, cex: string, fromToken: string, toToken: string, amount: number, price: number): Promise<OrderExecutionResolution>;
56
+ /**
57
+ * Validates deposit request (currently empty but can be extended)
58
+ */
59
+ export declare function validateDeposit(_policy: PolicyConfig, _chain: string, _amount: number): {
60
+ valid: boolean;
61
+ error?: string;
62
+ };
63
+ export {};
@@ -0,0 +1,9 @@
1
+ declare const log: {
2
+ trace: (...args: unknown[]) => void;
3
+ debug: (...args: unknown[]) => void;
4
+ info: (...args: unknown[]) => void;
5
+ warn: (...args: unknown[]) => void;
6
+ error: (...args: unknown[]) => void;
7
+ fatal: (...args: unknown[]) => void;
8
+ };
9
+ export { log };
@@ -0,0 +1,70 @@
1
+ import { type LogRecord } from "@opentelemetry/api-logs";
2
+ import { LoggerProvider } from "@opentelemetry/sdk-logs";
3
+ import { type MeterProvider as MeterProviderType } from "@opentelemetry/sdk-metrics";
4
+ /** OTLP/OpenTelemetry metrics config. Metrics are sent to an OTel Collector. */
5
+ export interface OtelConfig {
6
+ /** OTLP HTTP endpoint (e.g. http://localhost:4318). Takes precedence over host/port. */
7
+ otlpEndpoint?: string;
8
+ /** Collector host (legacy). Used with port to build otlpEndpoint when otlpEndpoint is not set. */
9
+ host?: string;
10
+ /** Collector port (legacy). Default 4318 for OTLP HTTP. */
11
+ port?: number;
12
+ protocol?: "http" | "https";
13
+ /** Service name for metrics. */
14
+ serviceName?: string;
15
+ /** @deprecated Unused when using OTLP; kept for config compatibility. */
16
+ username?: string;
17
+ /** @deprecated Unused when using OTLP; kept for config compatibility. */
18
+ password?: string;
19
+ /** @deprecated Unused when using OTLP; kept for config compatibility. */
20
+ database?: string;
21
+ }
22
+ export interface MetricData {
23
+ timestamp: Date;
24
+ metric_name: string;
25
+ metric_type: "counter" | "gauge" | "histogram";
26
+ value: number;
27
+ labels: string;
28
+ service: string;
29
+ }
30
+ declare abstract class BaseOtelSignal<TProvider> {
31
+ private readonly signal;
32
+ private provider;
33
+ private isEnabled;
34
+ private readonly serviceName;
35
+ protected constructor(config: OtelConfig | undefined, signal: "metrics" | "logs");
36
+ protected abstract createProvider(endpoint: string, serviceName: string, appendSignalPath: boolean): TProvider;
37
+ protected onProviderCreated(_provider: TProvider): void;
38
+ protected abstract shutdownProvider(provider: TProvider): Promise<void>;
39
+ protected onProviderClosed(): void;
40
+ protected getProvider(): TProvider | null;
41
+ protected getServiceName(): string;
42
+ isOtelEnabled(): boolean;
43
+ close(): Promise<void>;
44
+ }
45
+ export declare class OtelMetrics extends BaseOtelSignal<MeterProviderType> {
46
+ private readonly counters;
47
+ private readonly histograms;
48
+ constructor(config?: OtelConfig);
49
+ protected createProvider(endpoint: string, serviceName: string, appendSignalPath: boolean): MeterProviderType;
50
+ protected onProviderCreated(provider: MeterProviderType): void;
51
+ protected shutdownProvider(provider: MeterProviderType): Promise<void>;
52
+ initialize(): Promise<void>;
53
+ insertMetric(metric: MetricData): Promise<void>;
54
+ insertMetrics(metricsList: MetricData[]): Promise<void>;
55
+ recordCounter(metricName: string, value: number, labels: Record<string, string | number>, service?: string): Promise<void>;
56
+ recordGauge(metricName: string, value: number, labels: Record<string, string | number>, service?: string): Promise<void>;
57
+ recordHistogram(metricName: string, value: number, labels: Record<string, string | number>, service?: string): Promise<void>;
58
+ }
59
+ export declare class OtelLogs extends BaseOtelSignal<LoggerProvider> {
60
+ private logger;
61
+ constructor(config?: OtelConfig);
62
+ protected createProvider(endpoint: string, serviceName: string, appendSignalPath: boolean): LoggerProvider;
63
+ protected onProviderCreated(provider: LoggerProvider): void;
64
+ protected shutdownProvider(provider: LoggerProvider): Promise<void>;
65
+ protected onProviderClosed(): void;
66
+ emit(record: LogRecord): void;
67
+ }
68
+ export declare function createOtelMetricsFromEnv(): OtelMetrics;
69
+ export declare function createOtelLogsFromEnv(): OtelLogs;
70
+ export {};