@usherlabs/cex-broker 0.2.9 → 0.2.11

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.
@@ -310995,6 +310995,45 @@ var CCXT_METHODS_WITH_VERITY = [
310995
310995
  "fetchWithdrawal",
310996
310996
  "fetchAccountId"
310997
310997
  ];
310998
+ var Action = {
310999
+ NoAction: 0,
311000
+ Deposit: 1,
311001
+ Withdraw: 2,
311002
+ CreateOrder: 3,
311003
+ GetOrderDetails: 4,
311004
+ CancelOrder: 5,
311005
+ FetchBalances: 6,
311006
+ FetchDepositAddresses: 7,
311007
+ FetchTicker: 8,
311008
+ FetchCurrency: 9,
311009
+ Call: 10,
311010
+ FetchAccountId: 11,
311011
+ FetchFees: 12,
311012
+ InternalTransfer: 13
311013
+ };
311014
+ var SubscriptionType = {
311015
+ NO_ACTION: 0,
311016
+ ORDERBOOK: 1,
311017
+ TRADES: 2,
311018
+ TICKER: 3,
311019
+ OHLCV: 4,
311020
+ BALANCE: 5,
311021
+ ORDERS: 6
311022
+ };
311023
+ function createEnumNameMap(enumValues) {
311024
+ return Object.fromEntries(Object.entries(enumValues).map(([name, value]) => [value, name]));
311025
+ }
311026
+ var actionNames = createEnumNameMap(Action);
311027
+ var subscriptionTypeNames = createEnumNameMap(SubscriptionType);
311028
+ function getActionName(action) {
311029
+ return typeof action === "number" ? actionNames[action] ?? `unknown_${action}` : `unknown_${action ?? "undefined"}`;
311030
+ }
311031
+ function getSubscriptionTypeName(subscriptionType) {
311032
+ return subscriptionTypeNames[subscriptionType] ?? `unknown_${subscriptionType}`;
311033
+ }
311034
+ function resolveSubscriptionType(type2) {
311035
+ return type2 === undefined || type2 === SubscriptionType.NO_ACTION ? SubscriptionType.ORDERBOOK : type2;
311036
+ }
310998
311037
 
310999
311038
  // node_modules/@loglayer/plugin-opentelemetry/dist/index.mjs
311000
311039
  var import_api = __toESM(require_src5(), 1);
@@ -313495,16 +313534,18 @@ if (process.env.LOG_LEVEL !== "debug") {
313495
313534
  var log = baseLogger;
313496
313535
 
313497
313536
  // src/helpers/index.ts
313498
- class WithdrawRoutingError extends Error {
313499
- }
313500
-
313501
- class WithdrawRoutingUnavailableError extends WithdrawRoutingError {
313502
- }
313503
- function isMasterBrokerAccount(account) {
313504
- return account.label === "primary" || account.role === "master";
313537
+ class BrokerAccountPreconditionError extends Error {
313538
+ constructor(message) {
313539
+ super(message);
313540
+ this.name = "BrokerAccountPreconditionError";
313541
+ }
313505
313542
  }
313506
- function isSubaccountBrokerAccount(account) {
313507
- return !isMasterBrokerAccount(account);
313543
+ function requireDestinationEmail(dest, transferType) {
313544
+ const email = dest.email?.trim();
313545
+ if (!email) {
313546
+ throw new BrokerAccountPreconditionError(`Destination account '${dest.label}' requires an email configured for ${transferType} transfers`);
313547
+ }
313548
+ return email;
313508
313549
  }
313509
313550
  function authenticateRequest(call, whitelistIps) {
313510
313551
  const clientIp = call.getPeer().split(":")[0];
@@ -313826,81 +313867,50 @@ function validateWithdraw(policy, exchange, network, recipientAddress, _amount,
313826
313867
  }
313827
313868
  return { valid: true };
313828
313869
  }
313829
- function normalizeAccountSelector(selector2, metadata, defaultSelector) {
313830
- const raw = selector2?.trim().toLowerCase() ?? defaultSelector;
313831
- if (raw === "current") {
313832
- return getCurrentBrokerSelector(metadata);
313833
- }
313834
- if (raw === "primary") {
313835
- return "primary";
313836
- }
313837
- const secondaryMatch = raw.match(/^secondary:(\d+)$/);
313838
- if (secondaryMatch) {
313839
- return `secondary:${secondaryMatch[1]}`;
313840
- }
313841
- throw new WithdrawRoutingError(`Invalid account selector "${selector2}"`);
313842
- }
313843
- async function transferBinanceSubAccountToMaster(source, code, amount) {
313870
+ async function transferBinanceInternal(source, dest, code, amount) {
313844
313871
  const exchange = source.exchange;
313845
- if (typeof exchange.sapiPostSubAccountTransferSubToMaster !== "function") {
313846
- throw new WithdrawRoutingUnavailableError("Binance sub-account to master transfer is unavailable in this CCXT build");
313847
- }
313848
313872
  await source.exchange.loadMarkets();
313849
313873
  const currency = source.exchange.currency(code);
313850
- return await exchange.sapiPostSubAccountTransferSubToMaster({
313851
- asset: currency.id,
313852
- amount: source.exchange.currencyToPrecision(code, amount)
313853
- });
313854
- }
313855
- async function executeWithdrawWithRouting(args) {
313856
- const {
313857
- cex: cex3,
313858
- brokers,
313859
- metadata,
313860
- selectedBroker,
313861
- code,
313862
- amount,
313863
- recipientAddress,
313864
- network,
313865
- params,
313866
- routeViaMaster,
313867
- sourceAccount,
313868
- masterAccount
313869
- } = args;
313870
- const withdrawParams = {
313871
- ...params ?? {},
313872
- network
313873
- };
313874
- if (!routeViaMaster) {
313875
- return await selectedBroker.withdraw(code, amount, recipientAddress, undefined, withdrawParams);
313876
- }
313877
- const sourceSelector = normalizeAccountSelector(sourceAccount, metadata, "current");
313878
- const masterSelector = normalizeAccountSelector(masterAccount, metadata, "primary");
313879
- if (!brokers) {
313880
- throw new WithdrawRoutingUnavailableError("Routed withdraw requires configured broker accounts");
313881
- }
313882
- const source = resolveBrokerAccount(brokers, sourceSelector);
313883
- if (!source) {
313884
- throw new WithdrawRoutingError(`Source account ${sourceSelector} is not configured`);
313885
- }
313886
- const master = resolveBrokerAccount(brokers, masterSelector);
313887
- if (!master) {
313888
- throw new WithdrawRoutingError(`Master account ${masterSelector} is not configured`);
313889
- }
313890
- if (!isMasterBrokerAccount(master)) {
313891
- throw new WithdrawRoutingError(`Master account ${masterSelector} must resolve to the primary/master account`);
313892
- }
313893
- if (source.label === master.label) {
313894
- return await master.exchange.withdraw(code, amount, recipientAddress, undefined, withdrawParams);
313874
+ const asset = currency.id;
313875
+ const amountStr = source.exchange.currencyToPrecision(code, amount);
313876
+ const isSourceSecondary = source.label.startsWith("secondary:");
313877
+ const isDestPrimary = dest.label === "primary";
313878
+ const isDestSecondary = dest.label.startsWith("secondary:");
313879
+ const isSourcePrimary = source.label === "primary";
313880
+ if (isSourceSecondary && isDestPrimary) {
313881
+ if (typeof exchange.sapiPostSubAccountTransferSubToMaster !== "function") {
313882
+ throw new Error("Binance sub→master transfer is unavailable in this CCXT build");
313883
+ }
313884
+ return await exchange.sapiPostSubAccountTransferSubToMaster({
313885
+ asset,
313886
+ amount: amountStr
313887
+ });
313895
313888
  }
313896
- if (!isSubaccountBrokerAccount(source)) {
313897
- throw new WithdrawRoutingError(`Source account ${sourceSelector} must resolve to a subaccount when routeViaMaster is enabled`);
313889
+ if (isSourceSecondary && isDestSecondary) {
313890
+ if (typeof exchange.sapiPostSubAccountTransferSubToSub !== "function") {
313891
+ throw new Error("Binance sub→sub transfer is unavailable in this CCXT build");
313892
+ }
313893
+ const destEmail = requireDestinationEmail(dest, "sub-to-sub");
313894
+ return await exchange.sapiPostSubAccountTransferSubToSub({
313895
+ toEmail: destEmail,
313896
+ asset,
313897
+ amount: amountStr
313898
+ });
313898
313899
  }
313899
- if (cex3.trim().toLowerCase() !== "binance") {
313900
- throw new WithdrawRoutingUnavailableError(`Withdraw routing via master is not supported for ${cex3}`);
313900
+ if (isSourcePrimary && isDestSecondary) {
313901
+ if (typeof exchange.sapiPostSubAccountUniversalTransfer !== "function") {
313902
+ throw new Error("Binance universal transfer is unavailable in this CCXT build");
313903
+ }
313904
+ const destEmail = requireDestinationEmail(dest, "primary-to-sub");
313905
+ return await exchange.sapiPostSubAccountUniversalTransfer({
313906
+ fromAccountType: "SPOT",
313907
+ toAccountType: "SPOT",
313908
+ toEmail: destEmail,
313909
+ asset,
313910
+ amount: amountStr
313911
+ });
313901
313912
  }
313902
- await transferBinanceSubAccountToMaster(source, code, amount);
313903
- return await master.exchange.withdraw(code, amount, recipientAddress, undefined, withdrawParams);
313913
+ throw new Error(`Unsupported transfer direction: ${source.label} ${dest.label}`);
313904
313914
  }
313905
313915
  function isMarketPatternMatch(pattern, broker, fromToken, toToken) {
313906
313916
  const normalizedPattern = pattern.toUpperCase().trim();
@@ -314368,160 +314378,8 @@ function createOtelLogsFromEnv() {
314368
314378
  // src/server.ts
314369
314379
  var grpc = __toESM(require_src3(), 1);
314370
314380
  var protoLoader = __toESM(require_src2(), 1);
314371
-
314372
- // src/proto/cex_broker/Action.ts
314373
- var Action = {
314374
- NoAction: 0,
314375
- Deposit: 1,
314376
- Withdraw: 2,
314377
- CreateOrder: 3,
314378
- GetOrderDetails: 4,
314379
- CancelOrder: 5,
314380
- FetchBalances: 6,
314381
- FetchDepositAddresses: 7,
314382
- FetchTicker: 8,
314383
- FetchCurrency: 9,
314384
- Call: 10,
314385
- FetchAccountId: 11,
314386
- FetchFees: 12
314387
- };
314388
-
314389
- // src/proto/cex_broker/SubscriptionType.ts
314390
- var SubscriptionType = {
314391
- NO_ACTION: 0,
314392
- ORDERBOOK: 1,
314393
- TRADES: 2,
314394
- TICKER: 3,
314395
- OHLCV: 4,
314396
- BALANCE: 5,
314397
- ORDERS: 6
314398
- };
314399
-
314400
- // src/proto/node.descriptor.ts
314401
- var descriptor = {
314402
- nested: {
314403
- cex_broker: {
314404
- nested: {
314405
- ActionRequest: {
314406
- fields: {
314407
- action: {
314408
- type: "Action",
314409
- id: 1
314410
- },
314411
- payload: {
314412
- keyType: "string",
314413
- type: "string",
314414
- id: 2
314415
- },
314416
- cex: {
314417
- type: "string",
314418
- id: 3
314419
- },
314420
- symbol: {
314421
- type: "string",
314422
- id: 4
314423
- }
314424
- }
314425
- },
314426
- ActionResponse: {
314427
- fields: {
314428
- result: {
314429
- type: "string",
314430
- id: 1
314431
- },
314432
- proof: {
314433
- type: "string",
314434
- id: 2
314435
- }
314436
- }
314437
- },
314438
- SubscribeRequest: {
314439
- fields: {
314440
- cex: {
314441
- type: "string",
314442
- id: 1
314443
- },
314444
- symbol: {
314445
- type: "string",
314446
- id: 2
314447
- },
314448
- type: {
314449
- type: "SubscriptionType",
314450
- id: 3
314451
- },
314452
- options: {
314453
- keyType: "string",
314454
- type: "string",
314455
- id: 4
314456
- }
314457
- }
314458
- },
314459
- SubscribeResponse: {
314460
- fields: {
314461
- data: {
314462
- type: "string",
314463
- id: 1
314464
- },
314465
- timestamp: {
314466
- type: "int64",
314467
- id: 2
314468
- },
314469
- symbol: {
314470
- type: "string",
314471
- id: 3
314472
- },
314473
- type: {
314474
- type: "SubscriptionType",
314475
- id: 4
314476
- }
314477
- }
314478
- },
314479
- SubscriptionType: {
314480
- values: {
314481
- NO_ACTION: 0,
314482
- ORDERBOOK: 1,
314483
- TRADES: 2,
314484
- TICKER: 3,
314485
- OHLCV: 4,
314486
- BALANCE: 5,
314487
- ORDERS: 6
314488
- }
314489
- },
314490
- cex_service: {
314491
- methods: {
314492
- ExecuteAction: {
314493
- requestType: "ActionRequest",
314494
- responseType: "ActionResponse"
314495
- },
314496
- Subscribe: {
314497
- requestType: "SubscribeRequest",
314498
- responseType: "SubscribeResponse",
314499
- responseStream: true
314500
- }
314501
- }
314502
- },
314503
- Action: {
314504
- values: {
314505
- NoAction: 0,
314506
- Deposit: 1,
314507
- Withdraw: 2,
314508
- CreateOrder: 3,
314509
- GetOrderDetails: 4,
314510
- CancelOrder: 5,
314511
- FetchBalances: 6,
314512
- FetchDepositAddresses: 7,
314513
- FetchTicker: 8,
314514
- FetchCurrency: 9,
314515
- Call: 10,
314516
- FetchAccountId: 11,
314517
- FetchFees: 12
314518
- }
314519
- }
314520
- }
314521
- }
314522
- }
314523
- };
314524
- var node_descriptor_default = descriptor;
314381
+ import path from "path";
314382
+ import { fileURLToPath } from "url";
314525
314383
 
314526
314384
  // node_modules/zod/v4/classic/external.js
314527
314385
  var exports_external = {};
@@ -315464,9 +315322,9 @@ function createTransparentProxy(getter) {
315464
315322
  target ?? (target = getter());
315465
315323
  return Reflect.getOwnPropertyDescriptor(target, prop3);
315466
315324
  },
315467
- defineProperty(_, prop3, descriptor2) {
315325
+ defineProperty(_, prop3, descriptor) {
315468
315326
  target ?? (target = getter());
315469
- return Reflect.defineProperty(target, prop3, descriptor2);
315327
+ return Reflect.defineProperty(target, prop3, descriptor);
315470
315328
  }
315471
315329
  });
315472
315330
  }
@@ -328100,11 +327958,13 @@ var WithdrawPayloadSchema = exports_external.object({
328100
327958
  recipientAddress: exports_external.string().min(1),
328101
327959
  amount: exports_external.coerce.number().positive(),
328102
327960
  chain: exports_external.string().min(1),
328103
- routeViaMaster: booleanLikeSchema.optional().default(false),
328104
- sourceAccount: exports_external.string().min(1).optional(),
328105
- masterAccount: exports_external.string().min(1).optional(),
328106
327961
  params: exports_external.preprocess(parseJsonString, stringNumberRecordSchema).default({})
328107
327962
  });
327963
+ var InternalTransferPayloadSchema = exports_external.object({
327964
+ amount: exports_external.coerce.number().positive(),
327965
+ fromAccount: exports_external.string().min(1).optional(),
327966
+ toAccount: exports_external.string().min(1).optional()
327967
+ });
328108
327968
  var CreateOrderPayloadSchema = exports_external.object({
328109
327969
  orderType: exports_external.enum(["market", "limit"]).default("limit"),
328110
327970
  amount: exports_external.coerce.number().positive(),
@@ -328127,7 +327987,15 @@ var FetchFeesPayloadSchema = exports_external.object({
328127
327987
  });
328128
327988
 
328129
327989
  // src/server.ts
328130
- var packageDef = protoLoader.fromJSON(node_descriptor_default);
327990
+ var __filename2 = fileURLToPath(import.meta.url);
327991
+ var __dirname2 = path.dirname(__filename2);
327992
+ var protoPath = path.join(__dirname2, "proto", "node.proto");
327993
+ var packageDef = protoLoader.loadSync(protoPath, {
327994
+ keepCase: true,
327995
+ longs: String,
327996
+ defaults: true,
327997
+ oneofs: true
327998
+ });
328131
327999
  var grpcObj = grpc.loadPackageDefinition(packageDef);
328132
328000
  var cexNode = grpcObj.cex_broker;
328133
328001
  function parsePayload(schema, rawPayload) {
@@ -328136,10 +328004,10 @@ function parsePayload(schema, rawPayload) {
328136
328004
  return { success: true, data: parsed.data };
328137
328005
  }
328138
328006
  const firstIssue = parsed.error.issues[0];
328139
- const path = firstIssue && firstIssue.path.length > 0 ? `${firstIssue.path.join(".")}: ` : "";
328007
+ const path2 = firstIssue && firstIssue.path.length > 0 ? `${firstIssue.path.join(".")}: ` : "";
328140
328008
  return {
328141
328009
  success: false,
328142
- message: `ValidationError: ${path}${firstIssue?.message ?? "Invalid payload"}`
328010
+ message: `ValidationError: ${path2}${firstIssue?.message ?? "Invalid payload"}`
328143
328011
  };
328144
328012
  }
328145
328013
  function getErrorMessage(error48) {
@@ -328152,6 +328020,31 @@ function safeLogError(context2, error48) {
328152
328020
  console.error(context2, error48);
328153
328021
  }
328154
328022
  }
328023
+ function mapCcxtErrorToGrpcStatus(error48) {
328024
+ if (error48 instanceof ccxt_default.AuthenticationError)
328025
+ return grpc.status.UNAUTHENTICATED;
328026
+ if (error48 instanceof ccxt_default.PermissionDenied)
328027
+ return grpc.status.PERMISSION_DENIED;
328028
+ if (error48 instanceof ccxt_default.InsufficientFunds)
328029
+ return grpc.status.FAILED_PRECONDITION;
328030
+ if (error48 instanceof ccxt_default.InvalidAddress)
328031
+ return grpc.status.INVALID_ARGUMENT;
328032
+ if (error48 instanceof ccxt_default.BadSymbol)
328033
+ return grpc.status.NOT_FOUND;
328034
+ if (error48 instanceof ccxt_default.BadRequest)
328035
+ return grpc.status.INVALID_ARGUMENT;
328036
+ if (error48 instanceof ccxt_default.NotSupported)
328037
+ return grpc.status.UNIMPLEMENTED;
328038
+ if (error48 instanceof ccxt_default.RateLimitExceeded)
328039
+ return grpc.status.RESOURCE_EXHAUSTED;
328040
+ if (error48 instanceof ccxt_default.OnMaintenance)
328041
+ return grpc.status.UNAVAILABLE;
328042
+ if (error48 instanceof ccxt_default.ExchangeNotAvailable)
328043
+ return grpc.status.UNAVAILABLE;
328044
+ if (error48 instanceof ccxt_default.NetworkError)
328045
+ return grpc.status.UNAVAILABLE;
328046
+ return;
328047
+ }
328155
328048
  function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, otelMetrics) {
328156
328049
  const server = new grpc.Server;
328157
328050
  server.addService(cexNode.cex_service.service, {
@@ -328163,7 +328056,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328163
328056
  if (!actionCompleted) {
328164
328057
  actionCompleted = true;
328165
328058
  const latency = Date.now() - startTime;
328166
- const actionName = action !== undefined && action in Action ? Action[action] : `unknown_${action ?? "undefined"}`;
328059
+ const actionName = getActionName(action);
328167
328060
  otelMetrics?.recordHistogram("execute_action_duration_ms", latency, {
328168
328061
  action: actionName,
328169
328062
  cex: cex3 || "unknown"
@@ -328189,7 +328082,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328189
328082
  cex: cex3,
328190
328083
  symbol: symbol2
328191
328084
  });
328192
- const actionName = action !== undefined && action in Action ? Action[action] : `unknown_${action ?? "undefined"}`;
328085
+ const actionName = getActionName(action);
328193
328086
  otelMetrics?.recordCounter("execute_action_requests_total", 1, {
328194
328087
  action: actionName,
328195
328088
  cex: cex3 || "unknown"
@@ -328207,7 +328100,8 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328207
328100
  message: "`action` AND `cex` fields are required"
328208
328101
  }, null);
328209
328102
  }
328210
- const broker = selectBroker(brokers[cex3], metadata) ?? createBroker(cex3, metadata);
328103
+ const normalizedCex = cex3.trim().toLowerCase();
328104
+ const broker = selectBroker(brokers[normalizedCex], metadata) ?? createBroker(normalizedCex, metadata);
328211
328105
  if (!broker) {
328212
328106
  return wrappedCallback({
328213
328107
  code: grpc.status.UNAUTHENTICATED,
@@ -328545,39 +328439,10 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328545
328439
  }, null);
328546
328440
  }
328547
328441
  try {
328548
- let transaction;
328549
- try {
328550
- transaction = await executeWithdrawWithRouting({
328551
- cex: cex3,
328552
- brokers: brokers[cex3],
328553
- metadata,
328554
- selectedBroker: broker,
328555
- code: symbol2,
328556
- amount: transferValue.amount,
328557
- recipientAddress: transferValue.recipientAddress,
328558
- network: transferValue.chain,
328559
- params: transferValue.params,
328560
- routeViaMaster: transferValue.routeViaMaster,
328561
- sourceAccount: transferValue.sourceAccount,
328562
- masterAccount: transferValue.masterAccount
328563
- });
328564
- } catch (error48) {
328565
- if (error48 instanceof WithdrawRoutingUnavailableError) {
328566
- log.warn("Withdraw routing unavailable, falling back", {
328567
- cex: cex3,
328568
- error: error48.message
328569
- });
328570
- if (transferValue.routeViaMaster) {
328571
- throw error48;
328572
- }
328573
- transaction = await broker.withdraw(symbol2, transferValue.amount, transferValue.recipientAddress, undefined, {
328574
- ...transferValue.params ?? {},
328575
- network: transferValue.chain
328576
- });
328577
- } else {
328578
- throw error48;
328579
- }
328580
- }
328442
+ const transaction = await broker.withdraw(symbol2, transferValue.amount, transferValue.recipientAddress, undefined, {
328443
+ ...transferValue.params ?? {},
328444
+ network: transferValue.chain
328445
+ });
328581
328446
  log.info(`Withdraw Result: ${JSON.stringify(transaction)}`);
328582
328447
  wrappedCallback(null, {
328583
328448
  proof: verityProof,
@@ -328585,10 +328450,10 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328585
328450
  });
328586
328451
  } catch (error48) {
328587
328452
  safeLogError("Withdraw failed", error48);
328588
- const message = error48 instanceof WithdrawRoutingError ? error48.message : getErrorMessage(error48);
328453
+ const code = mapCcxtErrorToGrpcStatus(error48) ?? grpc.status.INTERNAL;
328589
328454
  wrappedCallback({
328590
- code: error48 instanceof WithdrawRoutingError ? grpc.status.INVALID_ARGUMENT : grpc.status.INTERNAL,
328591
- message: `Withdraw failed: ${message}`
328455
+ code,
328456
+ message: `Withdraw failed: ${getErrorMessage(error48)}`
328592
328457
  }, null);
328593
328458
  }
328594
328459
  break;
@@ -328761,6 +328626,86 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328761
328626
  }, null);
328762
328627
  }
328763
328628
  break;
328629
+ case Action.InternalTransfer: {
328630
+ if (!symbol2) {
328631
+ return wrappedCallback({
328632
+ code: grpc.status.INVALID_ARGUMENT,
328633
+ message: `ValidationError: Symbol required`
328634
+ }, null);
328635
+ }
328636
+ const parsedPayload = parsePayload(InternalTransferPayloadSchema, call.request.payload);
328637
+ if (!parsedPayload.success) {
328638
+ return wrappedCallback({
328639
+ code: grpc.status.INVALID_ARGUMENT,
328640
+ message: parsedPayload.message
328641
+ }, null);
328642
+ }
328643
+ const transferPayload = parsedPayload.data;
328644
+ if (normalizedCex !== "binance") {
328645
+ return wrappedCallback({
328646
+ code: grpc.status.UNIMPLEMENTED,
328647
+ message: `InternalTransfer is only supported for Binance`
328648
+ }, null);
328649
+ }
328650
+ const pool = brokers[normalizedCex];
328651
+ if (!pool) {
328652
+ return wrappedCallback({
328653
+ code: grpc.status.FAILED_PRECONDITION,
328654
+ message: `No broker accounts configured for ${normalizedCex}`
328655
+ }, null);
328656
+ }
328657
+ const fromSelector = transferPayload.fromAccount ?? getCurrentBrokerSelector(metadata);
328658
+ const toSelector = transferPayload.toAccount ?? "primary";
328659
+ const sourceAccount = resolveBrokerAccount(pool, fromSelector);
328660
+ if (!sourceAccount) {
328661
+ return wrappedCallback({
328662
+ code: grpc.status.INVALID_ARGUMENT,
328663
+ message: `Source account "${fromSelector}" is not configured`
328664
+ }, null);
328665
+ }
328666
+ const destAccount = resolveBrokerAccount(pool, toSelector);
328667
+ if (!destAccount) {
328668
+ return wrappedCallback({
328669
+ code: grpc.status.INVALID_ARGUMENT,
328670
+ message: `Destination account "${toSelector}" is not configured`
328671
+ }, null);
328672
+ }
328673
+ try {
328674
+ if (useVerity) {
328675
+ sourceAccount.exchange.setHttpClientOverride(buildHttpClientOverrideFromMetadata(metadata, verityProverUrl, (proof, notaryPubKey) => {
328676
+ verityProof = proof;
328677
+ log.debug(`Verity proof:`, { proof, notaryPubKey });
328678
+ }), verityHttpClientOverridePredicate);
328679
+ }
328680
+ const result = await transferBinanceInternal(sourceAccount, destAccount, symbol2, transferPayload.amount);
328681
+ wrappedCallback(null, {
328682
+ proof: verityProof,
328683
+ result: JSON.stringify(result)
328684
+ });
328685
+ } catch (error48) {
328686
+ safeLogError("InternalTransfer failed", error48);
328687
+ if (error48 instanceof BrokerAccountPreconditionError) {
328688
+ return wrappedCallback({
328689
+ code: grpc.status.FAILED_PRECONDITION,
328690
+ message: getErrorMessage(error48)
328691
+ }, null);
328692
+ }
328693
+ const msg = getErrorMessage(error48);
328694
+ let code;
328695
+ if (msg.includes("Unsupported transfer direction")) {
328696
+ code = grpc.status.INVALID_ARGUMENT;
328697
+ } else if (msg.includes("unavailable in this CCXT build")) {
328698
+ code = grpc.status.UNIMPLEMENTED;
328699
+ } else {
328700
+ code = mapCcxtErrorToGrpcStatus(error48) ?? grpc.status.INTERNAL;
328701
+ }
328702
+ wrappedCallback({
328703
+ code,
328704
+ message: `InternalTransfer failed: ${msg}`
328705
+ }, null);
328706
+ }
328707
+ break;
328708
+ }
328764
328709
  default:
328765
328710
  return wrappedCallback({
328766
328711
  code: grpc.status.INVALID_ARGUMENT,
@@ -328793,20 +328738,13 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328793
328738
  try {
328794
328739
  const request = call.request;
328795
328740
  const { cex: cex3, symbol: symbol2, type: type2, options } = request;
328796
- const subscriptionType = type2 !== undefined ? type2 : SubscriptionType.ORDERBOOK;
328741
+ const subscriptionType = resolveSubscriptionType(type2);
328797
328742
  log.info(`Request - Subscribe:`, {
328798
328743
  cex: request.cex,
328799
328744
  symbol: request.symbol,
328800
328745
  type: subscriptionType
328801
328746
  });
328802
- const subscriptionTypeName = (() => {
328803
- for (const [key, value] of Object.entries(SubscriptionType)) {
328804
- if (value === subscriptionType && Number.isNaN(Number(key))) {
328805
- return key;
328806
- }
328807
- }
328808
- return `unknown_${subscriptionType}`;
328809
- })();
328747
+ const subscriptionTypeName = getSubscriptionTypeName(subscriptionType);
328810
328748
  otelMetrics?.recordCounter("subscribe_requests_total", 1, {
328811
328749
  cex: cex3 || "unknown",
328812
328750
  symbol: symbol2 || "unknown",
@@ -328894,7 +328832,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328894
328832
  data: JSON.stringify(ticker),
328895
328833
  timestamp: Date.now(),
328896
328834
  symbol: symbol2,
328897
- type: type2
328835
+ type: subscriptionType
328898
328836
  });
328899
328837
  }
328900
328838
  } catch (error48) {
@@ -328919,7 +328857,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328919
328857
  data: JSON.stringify(ohlcv),
328920
328858
  timestamp: Date.now(),
328921
328859
  symbol: symbol2,
328922
- type: type2
328860
+ type: subscriptionType
328923
328861
  });
328924
328862
  }
328925
328863
  } catch (error48) {
@@ -328943,7 +328881,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328943
328881
  data: JSON.stringify(balance),
328944
328882
  timestamp: Date.now(),
328945
328883
  symbol: symbol2,
328946
- type: type2
328884
+ type: subscriptionType
328947
328885
  });
328948
328886
  }
328949
328887
  } catch (error48) {
@@ -328967,7 +328905,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328967
328905
  data: JSON.stringify(orders),
328968
328906
  timestamp: Date.now(),
328969
328907
  symbol: symbol2,
328970
- type: type2
328908
+ type: subscriptionType
328971
328909
  });
328972
328910
  }
328973
328911
  } catch (error48) {
@@ -328988,7 +328926,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
328988
328926
  data: JSON.stringify({ error: "Invalid subscription type" }),
328989
328927
  timestamp: Date.now(),
328990
328928
  symbol: symbol2,
328991
- type: type2
328929
+ type: subscriptionType
328992
328930
  });
328993
328931
  }
328994
328932
  } catch (error48) {