@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.
package/dist/index.js CHANGED
@@ -270118,6 +270118,45 @@ var CCXT_METHODS_WITH_VERITY = [
270118
270118
  "fetchWithdrawal",
270119
270119
  "fetchAccountId"
270120
270120
  ];
270121
+ var Action = {
270122
+ NoAction: 0,
270123
+ Deposit: 1,
270124
+ Withdraw: 2,
270125
+ CreateOrder: 3,
270126
+ GetOrderDetails: 4,
270127
+ CancelOrder: 5,
270128
+ FetchBalances: 6,
270129
+ FetchDepositAddresses: 7,
270130
+ FetchTicker: 8,
270131
+ FetchCurrency: 9,
270132
+ Call: 10,
270133
+ FetchAccountId: 11,
270134
+ FetchFees: 12,
270135
+ InternalTransfer: 13
270136
+ };
270137
+ var SubscriptionType = {
270138
+ NO_ACTION: 0,
270139
+ ORDERBOOK: 1,
270140
+ TRADES: 2,
270141
+ TICKER: 3,
270142
+ OHLCV: 4,
270143
+ BALANCE: 5,
270144
+ ORDERS: 6
270145
+ };
270146
+ function createEnumNameMap(enumValues) {
270147
+ return Object.fromEntries(Object.entries(enumValues).map(([name, value]) => [value, name]));
270148
+ }
270149
+ var actionNames = createEnumNameMap(Action);
270150
+ var subscriptionTypeNames = createEnumNameMap(SubscriptionType);
270151
+ function getActionName(action) {
270152
+ return typeof action === "number" ? actionNames[action] ?? `unknown_${action}` : `unknown_${action ?? "undefined"}`;
270153
+ }
270154
+ function getSubscriptionTypeName(subscriptionType) {
270155
+ return subscriptionTypeNames[subscriptionType] ?? `unknown_${subscriptionType}`;
270156
+ }
270157
+ function resolveSubscriptionType(type2) {
270158
+ return type2 === undefined || type2 === SubscriptionType.NO_ACTION ? SubscriptionType.ORDERBOOK : type2;
270159
+ }
270121
270160
 
270122
270161
  // node_modules/@loglayer/plugin-opentelemetry/dist/index.mjs
270123
270162
  var import_api = __toESM(require_src2(), 1);
@@ -272748,16 +272787,18 @@ if (process.env.LOG_LEVEL !== "debug") {
272748
272787
  var log = baseLogger;
272749
272788
 
272750
272789
  // src/helpers/index.ts
272751
- class WithdrawRoutingError extends Error {
272752
- }
272753
-
272754
- class WithdrawRoutingUnavailableError extends WithdrawRoutingError {
272755
- }
272756
- function isMasterBrokerAccount(account) {
272757
- return account.label === "primary" || account.role === "master";
272790
+ class BrokerAccountPreconditionError extends Error {
272791
+ constructor(message) {
272792
+ super(message);
272793
+ this.name = "BrokerAccountPreconditionError";
272794
+ }
272758
272795
  }
272759
- function isSubaccountBrokerAccount(account) {
272760
- return !isMasterBrokerAccount(account);
272796
+ function requireDestinationEmail(dest, transferType) {
272797
+ const email = dest.email?.trim();
272798
+ if (!email) {
272799
+ throw new BrokerAccountPreconditionError(`Destination account '${dest.label}' requires an email configured for ${transferType} transfers`);
272800
+ }
272801
+ return email;
272761
272802
  }
272762
272803
  function authenticateRequest(call, whitelistIps) {
272763
272804
  const clientIp = call.getPeer().split(":")[0];
@@ -273079,81 +273120,50 @@ function validateWithdraw(policy, exchange, network, recipientAddress, _amount,
273079
273120
  }
273080
273121
  return { valid: true };
273081
273122
  }
273082
- function normalizeAccountSelector(selector2, metadata, defaultSelector) {
273083
- const raw = selector2?.trim().toLowerCase() ?? defaultSelector;
273084
- if (raw === "current") {
273085
- return getCurrentBrokerSelector(metadata);
273086
- }
273087
- if (raw === "primary") {
273088
- return "primary";
273089
- }
273090
- const secondaryMatch = raw.match(/^secondary:(\d+)$/);
273091
- if (secondaryMatch) {
273092
- return `secondary:${secondaryMatch[1]}`;
273093
- }
273094
- throw new WithdrawRoutingError(`Invalid account selector "${selector2}"`);
273095
- }
273096
- async function transferBinanceSubAccountToMaster(source, code, amount) {
273123
+ async function transferBinanceInternal(source, dest, code, amount) {
273097
273124
  const exchange = source.exchange;
273098
- if (typeof exchange.sapiPostSubAccountTransferSubToMaster !== "function") {
273099
- throw new WithdrawRoutingUnavailableError("Binance sub-account to master transfer is unavailable in this CCXT build");
273100
- }
273101
273125
  await source.exchange.loadMarkets();
273102
273126
  const currency = source.exchange.currency(code);
273103
- return await exchange.sapiPostSubAccountTransferSubToMaster({
273104
- asset: currency.id,
273105
- amount: source.exchange.currencyToPrecision(code, amount)
273106
- });
273107
- }
273108
- async function executeWithdrawWithRouting(args) {
273109
- const {
273110
- cex: cex3,
273111
- brokers,
273112
- metadata,
273113
- selectedBroker,
273114
- code,
273115
- amount,
273116
- recipientAddress,
273117
- network,
273118
- params,
273119
- routeViaMaster,
273120
- sourceAccount,
273121
- masterAccount
273122
- } = args;
273123
- const withdrawParams = {
273124
- ...params ?? {},
273125
- network
273126
- };
273127
- if (!routeViaMaster) {
273128
- return await selectedBroker.withdraw(code, amount, recipientAddress, undefined, withdrawParams);
273129
- }
273130
- const sourceSelector = normalizeAccountSelector(sourceAccount, metadata, "current");
273131
- const masterSelector = normalizeAccountSelector(masterAccount, metadata, "primary");
273132
- if (!brokers) {
273133
- throw new WithdrawRoutingUnavailableError("Routed withdraw requires configured broker accounts");
273134
- }
273135
- const source = resolveBrokerAccount(brokers, sourceSelector);
273136
- if (!source) {
273137
- throw new WithdrawRoutingError(`Source account ${sourceSelector} is not configured`);
273138
- }
273139
- const master = resolveBrokerAccount(brokers, masterSelector);
273140
- if (!master) {
273141
- throw new WithdrawRoutingError(`Master account ${masterSelector} is not configured`);
273142
- }
273143
- if (!isMasterBrokerAccount(master)) {
273144
- throw new WithdrawRoutingError(`Master account ${masterSelector} must resolve to the primary/master account`);
273145
- }
273146
- if (source.label === master.label) {
273147
- return await master.exchange.withdraw(code, amount, recipientAddress, undefined, withdrawParams);
273127
+ const asset = currency.id;
273128
+ const amountStr = source.exchange.currencyToPrecision(code, amount);
273129
+ const isSourceSecondary = source.label.startsWith("secondary:");
273130
+ const isDestPrimary = dest.label === "primary";
273131
+ const isDestSecondary = dest.label.startsWith("secondary:");
273132
+ const isSourcePrimary = source.label === "primary";
273133
+ if (isSourceSecondary && isDestPrimary) {
273134
+ if (typeof exchange.sapiPostSubAccountTransferSubToMaster !== "function") {
273135
+ throw new Error("Binance sub\u2192master transfer is unavailable in this CCXT build");
273136
+ }
273137
+ return await exchange.sapiPostSubAccountTransferSubToMaster({
273138
+ asset,
273139
+ amount: amountStr
273140
+ });
273148
273141
  }
273149
- if (!isSubaccountBrokerAccount(source)) {
273150
- throw new WithdrawRoutingError(`Source account ${sourceSelector} must resolve to a subaccount when routeViaMaster is enabled`);
273142
+ if (isSourceSecondary && isDestSecondary) {
273143
+ if (typeof exchange.sapiPostSubAccountTransferSubToSub !== "function") {
273144
+ throw new Error("Binance sub\u2192sub transfer is unavailable in this CCXT build");
273145
+ }
273146
+ const destEmail = requireDestinationEmail(dest, "sub-to-sub");
273147
+ return await exchange.sapiPostSubAccountTransferSubToSub({
273148
+ toEmail: destEmail,
273149
+ asset,
273150
+ amount: amountStr
273151
+ });
273151
273152
  }
273152
- if (cex3.trim().toLowerCase() !== "binance") {
273153
- throw new WithdrawRoutingUnavailableError(`Withdraw routing via master is not supported for ${cex3}`);
273153
+ if (isSourcePrimary && isDestSecondary) {
273154
+ if (typeof exchange.sapiPostSubAccountUniversalTransfer !== "function") {
273155
+ throw new Error("Binance universal transfer is unavailable in this CCXT build");
273156
+ }
273157
+ const destEmail = requireDestinationEmail(dest, "primary-to-sub");
273158
+ return await exchange.sapiPostSubAccountUniversalTransfer({
273159
+ fromAccountType: "SPOT",
273160
+ toAccountType: "SPOT",
273161
+ toEmail: destEmail,
273162
+ asset,
273163
+ amount: amountStr
273164
+ });
273154
273165
  }
273155
- await transferBinanceSubAccountToMaster(source, code, amount);
273156
- return await master.exchange.withdraw(code, amount, recipientAddress, undefined, withdrawParams);
273166
+ throw new Error(`Unsupported transfer direction: ${source.label} \u2192 ${dest.label}`);
273157
273167
  }
273158
273168
  function isMarketPatternMatch(pattern, broker, fromToken, toToken) {
273159
273169
  const normalizedPattern = pattern.toUpperCase().trim();
@@ -277321,160 +277331,8 @@ function createOtelLogsFromEnv() {
277321
277331
  // src/server.ts
277322
277332
  import * as grpc from "@grpc/grpc-js";
277323
277333
  import * as protoLoader from "@grpc/proto-loader";
277324
-
277325
- // src/proto/cex_broker/Action.ts
277326
- var Action = {
277327
- NoAction: 0,
277328
- Deposit: 1,
277329
- Withdraw: 2,
277330
- CreateOrder: 3,
277331
- GetOrderDetails: 4,
277332
- CancelOrder: 5,
277333
- FetchBalances: 6,
277334
- FetchDepositAddresses: 7,
277335
- FetchTicker: 8,
277336
- FetchCurrency: 9,
277337
- Call: 10,
277338
- FetchAccountId: 11,
277339
- FetchFees: 12
277340
- };
277341
-
277342
- // src/proto/cex_broker/SubscriptionType.ts
277343
- var SubscriptionType = {
277344
- NO_ACTION: 0,
277345
- ORDERBOOK: 1,
277346
- TRADES: 2,
277347
- TICKER: 3,
277348
- OHLCV: 4,
277349
- BALANCE: 5,
277350
- ORDERS: 6
277351
- };
277352
-
277353
- // src/proto/node.descriptor.ts
277354
- var descriptor = {
277355
- nested: {
277356
- cex_broker: {
277357
- nested: {
277358
- ActionRequest: {
277359
- fields: {
277360
- action: {
277361
- type: "Action",
277362
- id: 1
277363
- },
277364
- payload: {
277365
- keyType: "string",
277366
- type: "string",
277367
- id: 2
277368
- },
277369
- cex: {
277370
- type: "string",
277371
- id: 3
277372
- },
277373
- symbol: {
277374
- type: "string",
277375
- id: 4
277376
- }
277377
- }
277378
- },
277379
- ActionResponse: {
277380
- fields: {
277381
- result: {
277382
- type: "string",
277383
- id: 1
277384
- },
277385
- proof: {
277386
- type: "string",
277387
- id: 2
277388
- }
277389
- }
277390
- },
277391
- SubscribeRequest: {
277392
- fields: {
277393
- cex: {
277394
- type: "string",
277395
- id: 1
277396
- },
277397
- symbol: {
277398
- type: "string",
277399
- id: 2
277400
- },
277401
- type: {
277402
- type: "SubscriptionType",
277403
- id: 3
277404
- },
277405
- options: {
277406
- keyType: "string",
277407
- type: "string",
277408
- id: 4
277409
- }
277410
- }
277411
- },
277412
- SubscribeResponse: {
277413
- fields: {
277414
- data: {
277415
- type: "string",
277416
- id: 1
277417
- },
277418
- timestamp: {
277419
- type: "int64",
277420
- id: 2
277421
- },
277422
- symbol: {
277423
- type: "string",
277424
- id: 3
277425
- },
277426
- type: {
277427
- type: "SubscriptionType",
277428
- id: 4
277429
- }
277430
- }
277431
- },
277432
- SubscriptionType: {
277433
- values: {
277434
- NO_ACTION: 0,
277435
- ORDERBOOK: 1,
277436
- TRADES: 2,
277437
- TICKER: 3,
277438
- OHLCV: 4,
277439
- BALANCE: 5,
277440
- ORDERS: 6
277441
- }
277442
- },
277443
- cex_service: {
277444
- methods: {
277445
- ExecuteAction: {
277446
- requestType: "ActionRequest",
277447
- responseType: "ActionResponse"
277448
- },
277449
- Subscribe: {
277450
- requestType: "SubscribeRequest",
277451
- responseType: "SubscribeResponse",
277452
- responseStream: true
277453
- }
277454
- }
277455
- },
277456
- Action: {
277457
- values: {
277458
- NoAction: 0,
277459
- Deposit: 1,
277460
- Withdraw: 2,
277461
- CreateOrder: 3,
277462
- GetOrderDetails: 4,
277463
- CancelOrder: 5,
277464
- FetchBalances: 6,
277465
- FetchDepositAddresses: 7,
277466
- FetchTicker: 8,
277467
- FetchCurrency: 9,
277468
- Call: 10,
277469
- FetchAccountId: 11,
277470
- FetchFees: 12
277471
- }
277472
- }
277473
- }
277474
- }
277475
- }
277476
- };
277477
- var node_descriptor_default = descriptor;
277334
+ import path from "path";
277335
+ import { fileURLToPath } from "url";
277478
277336
 
277479
277337
  // node_modules/zod/v4/classic/external.js
277480
277338
  var exports_external = {};
@@ -278417,9 +278275,9 @@ function createTransparentProxy(getter) {
278417
278275
  target ?? (target = getter());
278418
278276
  return Reflect.getOwnPropertyDescriptor(target, prop3);
278419
278277
  },
278420
- defineProperty(_, prop3, descriptor2) {
278278
+ defineProperty(_, prop3, descriptor) {
278421
278279
  target ?? (target = getter());
278422
- return Reflect.defineProperty(target, prop3, descriptor2);
278280
+ return Reflect.defineProperty(target, prop3, descriptor);
278423
278281
  }
278424
278282
  });
278425
278283
  }
@@ -291053,11 +290911,13 @@ var WithdrawPayloadSchema = exports_external.object({
291053
290911
  recipientAddress: exports_external.string().min(1),
291054
290912
  amount: exports_external.coerce.number().positive(),
291055
290913
  chain: exports_external.string().min(1),
291056
- routeViaMaster: booleanLikeSchema.optional().default(false),
291057
- sourceAccount: exports_external.string().min(1).optional(),
291058
- masterAccount: exports_external.string().min(1).optional(),
291059
290914
  params: exports_external.preprocess(parseJsonString, stringNumberRecordSchema).default({})
291060
290915
  });
290916
+ var InternalTransferPayloadSchema = exports_external.object({
290917
+ amount: exports_external.coerce.number().positive(),
290918
+ fromAccount: exports_external.string().min(1).optional(),
290919
+ toAccount: exports_external.string().min(1).optional()
290920
+ });
291061
290921
  var CreateOrderPayloadSchema = exports_external.object({
291062
290922
  orderType: exports_external.enum(["market", "limit"]).default("limit"),
291063
290923
  amount: exports_external.coerce.number().positive(),
@@ -291080,7 +290940,15 @@ var FetchFeesPayloadSchema = exports_external.object({
291080
290940
  });
291081
290941
 
291082
290942
  // src/server.ts
291083
- var packageDef = protoLoader.fromJSON(node_descriptor_default);
290943
+ var __filename2 = fileURLToPath(import.meta.url);
290944
+ var __dirname2 = path.dirname(__filename2);
290945
+ var protoPath = path.join(__dirname2, "proto", "node.proto");
290946
+ var packageDef = protoLoader.loadSync(protoPath, {
290947
+ keepCase: true,
290948
+ longs: String,
290949
+ defaults: true,
290950
+ oneofs: true
290951
+ });
291084
290952
  var grpcObj = grpc.loadPackageDefinition(packageDef);
291085
290953
  var cexNode = grpcObj.cex_broker;
291086
290954
  function parsePayload(schema, rawPayload) {
@@ -291089,10 +290957,10 @@ function parsePayload(schema, rawPayload) {
291089
290957
  return { success: true, data: parsed.data };
291090
290958
  }
291091
290959
  const firstIssue = parsed.error.issues[0];
291092
- const path = firstIssue && firstIssue.path.length > 0 ? `${firstIssue.path.join(".")}: ` : "";
290960
+ const path2 = firstIssue && firstIssue.path.length > 0 ? `${firstIssue.path.join(".")}: ` : "";
291093
290961
  return {
291094
290962
  success: false,
291095
- message: `ValidationError: ${path}${firstIssue?.message ?? "Invalid payload"}`
290963
+ message: `ValidationError: ${path2}${firstIssue?.message ?? "Invalid payload"}`
291096
290964
  };
291097
290965
  }
291098
290966
  function getErrorMessage(error48) {
@@ -291105,6 +290973,31 @@ function safeLogError(context3, error48) {
291105
290973
  console.error(context3, error48);
291106
290974
  }
291107
290975
  }
290976
+ function mapCcxtErrorToGrpcStatus(error48) {
290977
+ if (error48 instanceof ccxt_default.AuthenticationError)
290978
+ return grpc.status.UNAUTHENTICATED;
290979
+ if (error48 instanceof ccxt_default.PermissionDenied)
290980
+ return grpc.status.PERMISSION_DENIED;
290981
+ if (error48 instanceof ccxt_default.InsufficientFunds)
290982
+ return grpc.status.FAILED_PRECONDITION;
290983
+ if (error48 instanceof ccxt_default.InvalidAddress)
290984
+ return grpc.status.INVALID_ARGUMENT;
290985
+ if (error48 instanceof ccxt_default.BadSymbol)
290986
+ return grpc.status.NOT_FOUND;
290987
+ if (error48 instanceof ccxt_default.BadRequest)
290988
+ return grpc.status.INVALID_ARGUMENT;
290989
+ if (error48 instanceof ccxt_default.NotSupported)
290990
+ return grpc.status.UNIMPLEMENTED;
290991
+ if (error48 instanceof ccxt_default.RateLimitExceeded)
290992
+ return grpc.status.RESOURCE_EXHAUSTED;
290993
+ if (error48 instanceof ccxt_default.OnMaintenance)
290994
+ return grpc.status.UNAVAILABLE;
290995
+ if (error48 instanceof ccxt_default.ExchangeNotAvailable)
290996
+ return grpc.status.UNAVAILABLE;
290997
+ if (error48 instanceof ccxt_default.NetworkError)
290998
+ return grpc.status.UNAVAILABLE;
290999
+ return;
291000
+ }
291108
291001
  function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, otelMetrics) {
291109
291002
  const server = new grpc.Server;
291110
291003
  server.addService(cexNode.cex_service.service, {
@@ -291116,7 +291009,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291116
291009
  if (!actionCompleted) {
291117
291010
  actionCompleted = true;
291118
291011
  const latency = Date.now() - startTime;
291119
- const actionName = action !== undefined && action in Action ? Action[action] : `unknown_${action ?? "undefined"}`;
291012
+ const actionName = getActionName(action);
291120
291013
  otelMetrics?.recordHistogram("execute_action_duration_ms", latency, {
291121
291014
  action: actionName,
291122
291015
  cex: cex3 || "unknown"
@@ -291142,7 +291035,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291142
291035
  cex: cex3,
291143
291036
  symbol: symbol2
291144
291037
  });
291145
- const actionName = action !== undefined && action in Action ? Action[action] : `unknown_${action ?? "undefined"}`;
291038
+ const actionName = getActionName(action);
291146
291039
  otelMetrics?.recordCounter("execute_action_requests_total", 1, {
291147
291040
  action: actionName,
291148
291041
  cex: cex3 || "unknown"
@@ -291160,7 +291053,8 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291160
291053
  message: "`action` AND `cex` fields are required"
291161
291054
  }, null);
291162
291055
  }
291163
- const broker = selectBroker(brokers[cex3], metadata) ?? createBroker(cex3, metadata);
291056
+ const normalizedCex = cex3.trim().toLowerCase();
291057
+ const broker = selectBroker(brokers[normalizedCex], metadata) ?? createBroker(normalizedCex, metadata);
291164
291058
  if (!broker) {
291165
291059
  return wrappedCallback({
291166
291060
  code: grpc.status.UNAUTHENTICATED,
@@ -291498,39 +291392,10 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291498
291392
  }, null);
291499
291393
  }
291500
291394
  try {
291501
- let transaction;
291502
- try {
291503
- transaction = await executeWithdrawWithRouting({
291504
- cex: cex3,
291505
- brokers: brokers[cex3],
291506
- metadata,
291507
- selectedBroker: broker,
291508
- code: symbol2,
291509
- amount: transferValue.amount,
291510
- recipientAddress: transferValue.recipientAddress,
291511
- network: transferValue.chain,
291512
- params: transferValue.params,
291513
- routeViaMaster: transferValue.routeViaMaster,
291514
- sourceAccount: transferValue.sourceAccount,
291515
- masterAccount: transferValue.masterAccount
291516
- });
291517
- } catch (error48) {
291518
- if (error48 instanceof WithdrawRoutingUnavailableError) {
291519
- log.warn("Withdraw routing unavailable, falling back", {
291520
- cex: cex3,
291521
- error: error48.message
291522
- });
291523
- if (transferValue.routeViaMaster) {
291524
- throw error48;
291525
- }
291526
- transaction = await broker.withdraw(symbol2, transferValue.amount, transferValue.recipientAddress, undefined, {
291527
- ...transferValue.params ?? {},
291528
- network: transferValue.chain
291529
- });
291530
- } else {
291531
- throw error48;
291532
- }
291533
- }
291395
+ const transaction = await broker.withdraw(symbol2, transferValue.amount, transferValue.recipientAddress, undefined, {
291396
+ ...transferValue.params ?? {},
291397
+ network: transferValue.chain
291398
+ });
291534
291399
  log.info(`Withdraw Result: ${JSON.stringify(transaction)}`);
291535
291400
  wrappedCallback(null, {
291536
291401
  proof: verityProof,
@@ -291538,10 +291403,10 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291538
291403
  });
291539
291404
  } catch (error48) {
291540
291405
  safeLogError("Withdraw failed", error48);
291541
- const message = error48 instanceof WithdrawRoutingError ? error48.message : getErrorMessage(error48);
291406
+ const code = mapCcxtErrorToGrpcStatus(error48) ?? grpc.status.INTERNAL;
291542
291407
  wrappedCallback({
291543
- code: error48 instanceof WithdrawRoutingError ? grpc.status.INVALID_ARGUMENT : grpc.status.INTERNAL,
291544
- message: `Withdraw failed: ${message}`
291408
+ code,
291409
+ message: `Withdraw failed: ${getErrorMessage(error48)}`
291545
291410
  }, null);
291546
291411
  }
291547
291412
  break;
@@ -291714,6 +291579,86 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291714
291579
  }, null);
291715
291580
  }
291716
291581
  break;
291582
+ case Action.InternalTransfer: {
291583
+ if (!symbol2) {
291584
+ return wrappedCallback({
291585
+ code: grpc.status.INVALID_ARGUMENT,
291586
+ message: `ValidationError: Symbol required`
291587
+ }, null);
291588
+ }
291589
+ const parsedPayload = parsePayload(InternalTransferPayloadSchema, call.request.payload);
291590
+ if (!parsedPayload.success) {
291591
+ return wrappedCallback({
291592
+ code: grpc.status.INVALID_ARGUMENT,
291593
+ message: parsedPayload.message
291594
+ }, null);
291595
+ }
291596
+ const transferPayload = parsedPayload.data;
291597
+ if (normalizedCex !== "binance") {
291598
+ return wrappedCallback({
291599
+ code: grpc.status.UNIMPLEMENTED,
291600
+ message: `InternalTransfer is only supported for Binance`
291601
+ }, null);
291602
+ }
291603
+ const pool = brokers[normalizedCex];
291604
+ if (!pool) {
291605
+ return wrappedCallback({
291606
+ code: grpc.status.FAILED_PRECONDITION,
291607
+ message: `No broker accounts configured for ${normalizedCex}`
291608
+ }, null);
291609
+ }
291610
+ const fromSelector = transferPayload.fromAccount ?? getCurrentBrokerSelector(metadata);
291611
+ const toSelector = transferPayload.toAccount ?? "primary";
291612
+ const sourceAccount = resolveBrokerAccount(pool, fromSelector);
291613
+ if (!sourceAccount) {
291614
+ return wrappedCallback({
291615
+ code: grpc.status.INVALID_ARGUMENT,
291616
+ message: `Source account "${fromSelector}" is not configured`
291617
+ }, null);
291618
+ }
291619
+ const destAccount = resolveBrokerAccount(pool, toSelector);
291620
+ if (!destAccount) {
291621
+ return wrappedCallback({
291622
+ code: grpc.status.INVALID_ARGUMENT,
291623
+ message: `Destination account "${toSelector}" is not configured`
291624
+ }, null);
291625
+ }
291626
+ try {
291627
+ if (useVerity) {
291628
+ sourceAccount.exchange.setHttpClientOverride(buildHttpClientOverrideFromMetadata(metadata, verityProverUrl, (proof, notaryPubKey) => {
291629
+ verityProof = proof;
291630
+ log.debug(`Verity proof:`, { proof, notaryPubKey });
291631
+ }), verityHttpClientOverridePredicate);
291632
+ }
291633
+ const result = await transferBinanceInternal(sourceAccount, destAccount, symbol2, transferPayload.amount);
291634
+ wrappedCallback(null, {
291635
+ proof: verityProof,
291636
+ result: JSON.stringify(result)
291637
+ });
291638
+ } catch (error48) {
291639
+ safeLogError("InternalTransfer failed", error48);
291640
+ if (error48 instanceof BrokerAccountPreconditionError) {
291641
+ return wrappedCallback({
291642
+ code: grpc.status.FAILED_PRECONDITION,
291643
+ message: getErrorMessage(error48)
291644
+ }, null);
291645
+ }
291646
+ const msg = getErrorMessage(error48);
291647
+ let code;
291648
+ if (msg.includes("Unsupported transfer direction")) {
291649
+ code = grpc.status.INVALID_ARGUMENT;
291650
+ } else if (msg.includes("unavailable in this CCXT build")) {
291651
+ code = grpc.status.UNIMPLEMENTED;
291652
+ } else {
291653
+ code = mapCcxtErrorToGrpcStatus(error48) ?? grpc.status.INTERNAL;
291654
+ }
291655
+ wrappedCallback({
291656
+ code,
291657
+ message: `InternalTransfer failed: ${msg}`
291658
+ }, null);
291659
+ }
291660
+ break;
291661
+ }
291717
291662
  default:
291718
291663
  return wrappedCallback({
291719
291664
  code: grpc.status.INVALID_ARGUMENT,
@@ -291746,20 +291691,13 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291746
291691
  try {
291747
291692
  const request = call.request;
291748
291693
  const { cex: cex3, symbol: symbol2, type: type2, options } = request;
291749
- const subscriptionType = type2 !== undefined ? type2 : SubscriptionType.ORDERBOOK;
291694
+ const subscriptionType = resolveSubscriptionType(type2);
291750
291695
  log.info(`Request - Subscribe:`, {
291751
291696
  cex: request.cex,
291752
291697
  symbol: request.symbol,
291753
291698
  type: subscriptionType
291754
291699
  });
291755
- const subscriptionTypeName = (() => {
291756
- for (const [key, value] of Object.entries(SubscriptionType)) {
291757
- if (value === subscriptionType && Number.isNaN(Number(key))) {
291758
- return key;
291759
- }
291760
- }
291761
- return `unknown_${subscriptionType}`;
291762
- })();
291700
+ const subscriptionTypeName = getSubscriptionTypeName(subscriptionType);
291763
291701
  otelMetrics?.recordCounter("subscribe_requests_total", 1, {
291764
291702
  cex: cex3 || "unknown",
291765
291703
  symbol: symbol2 || "unknown",
@@ -291847,7 +291785,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291847
291785
  data: JSON.stringify(ticker),
291848
291786
  timestamp: Date.now(),
291849
291787
  symbol: symbol2,
291850
- type: type2
291788
+ type: subscriptionType
291851
291789
  });
291852
291790
  }
291853
291791
  } catch (error48) {
@@ -291872,7 +291810,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291872
291810
  data: JSON.stringify(ohlcv),
291873
291811
  timestamp: Date.now(),
291874
291812
  symbol: symbol2,
291875
- type: type2
291813
+ type: subscriptionType
291876
291814
  });
291877
291815
  }
291878
291816
  } catch (error48) {
@@ -291896,7 +291834,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291896
291834
  data: JSON.stringify(balance),
291897
291835
  timestamp: Date.now(),
291898
291836
  symbol: symbol2,
291899
- type: type2
291837
+ type: subscriptionType
291900
291838
  });
291901
291839
  }
291902
291840
  } catch (error48) {
@@ -291920,7 +291858,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291920
291858
  data: JSON.stringify(orders),
291921
291859
  timestamp: Date.now(),
291922
291860
  symbol: symbol2,
291923
- type: type2
291861
+ type: subscriptionType
291924
291862
  });
291925
291863
  }
291926
291864
  } catch (error48) {
@@ -291941,7 +291879,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
291941
291879
  data: JSON.stringify({ error: "Invalid subscription type" }),
291942
291880
  timestamp: Date.now(),
291943
291881
  symbol: symbol2,
291944
- type: type2
291882
+ type: subscriptionType
291945
291883
  });
291946
291884
  }
291947
291885
  } catch (error48) {
@@ -292272,4 +292210,4 @@ export {
292272
292210
  CEXBroker as default
292273
292211
  };
292274
292212
 
292275
- //# debugId=D692BFF7F06F00CD64756E2164756E21
292213
+ //# debugId=EC06775BC83A508D64756E2164756E21