@xyo-network/chain-bridge 1.20.21 → 1.20.23

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.
@@ -6,6 +6,8 @@ export type BridgeActorParams = ActorParamsV3<{
6
6
  }>;
7
7
  export declare class BridgeActor extends ActorV3<BridgeActorParams> {
8
8
  protected _gatewayRunner: XyoGatewayRunner;
9
+ private _balanceMonitor?;
10
+ private _queueMetrics?;
9
11
  private server?;
10
12
  protected get gatewayRunner(): XyoGatewayRunner;
11
13
  createHandler(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"BridgeActor.d.ts","sourceRoot":"","sources":["../../src/BridgeActor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEpE,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EACjB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,OAAO,EAER,MAAM,sBAAsB,CAAA;AAI7B,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAAC;IAC5C,MAAM,EAAE,YAAY,CAAA;CACrB,CAAC,CAAA;AAEF,qBACa,WAAY,SAAQ,OAAO,CAAC,iBAAiB,CAAC;IACzD,SAAS,CAAC,cAAc,EAAG,gBAAgB,CAAA;IAC3C,OAAO,CAAC,MAAM,CAAC,CAAQ;IAEvB,SAAS,KAAK,aAAa,qBAE1B;IAEc,aAAa;IAKb,YAAY;IAMZ,WAAW;YAKZ,WAAW;IAIzB,OAAO,CAAC,UAAU;CAInB"}
1
+ {"version":3,"file":"BridgeActor.d.ts","sourceRoot":"","sources":["../../src/BridgeActor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEpE,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EACjB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,OAAO,EAER,MAAM,sBAAsB,CAAA;AAO7B,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAAC;IAC5C,MAAM,EAAE,YAAY,CAAA;CACrB,CAAC,CAAA;AAEF,qBACa,WAAY,SAAQ,OAAO,CAAC,iBAAiB,CAAC;IACzD,SAAS,CAAC,cAAc,EAAG,gBAAgB,CAAA;IAC3C,OAAO,CAAC,eAAe,CAAC,CAAsB;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAoB;IAC1C,OAAO,CAAC,MAAM,CAAC,CAAQ;IAEvB,SAAS,KAAK,aAAa,qBAE1B;IAEc,aAAa;IAKb,YAAY;IAMZ,WAAW;YASZ,WAAW;IA0BzB,OAAO,CAAC,UAAU;CAInB"}
@@ -1 +1 @@
1
- {"version":3,"file":"getBridgeWalletAccount.d.ts","sourceRoot":"","sources":["../../../src/config/getBridgeWalletAccount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,gBAAgB,CAAA;AAGzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAKvD,eAAO,MAAM,sBAAsB,GAAU,QAAQ,WAAW,KAAG,OAAO,CAAC,cAAc,CAiBxF,CAAA;AAED,eAAO,MAAM,sCAAsC,GACjD,kBAAkB,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,GAAG,SAAS,EAC9D,QAAQ,WAAW,KAClB,OAAO,CAAC,OAAO,CAKjB,CAAA"}
1
+ {"version":3,"file":"getBridgeWalletAccount.d.ts","sourceRoot":"","sources":["../../../src/config/getBridgeWalletAccount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,gBAAgB,CAAA;AAGzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAIvD,eAAO,MAAM,sBAAsB,GAAU,QAAQ,WAAW,KAAG,OAAO,CAAC,cAAc,CAMxF,CAAA;AAED,eAAO,MAAM,sCAAsC,GACjD,kBAAkB,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,GAAG,SAAS,EAC9D,QAAQ,WAAW,KAClB,OAAO,CAAC,OAAO,CAKjB,CAAA"}
@@ -1,4 +1,4 @@
1
- import { type BridgeConfig } from '@xyo-network/chain-orchestration';
1
+ import type { BridgeConfig } from '@xyo-network/chain-orchestration';
2
2
  import type { XyoGatewayRunner } from '@xyo-network/xl1-sdk';
3
3
  export declare const getTestGateway: (config: BridgeConfig) => Promise<XyoGatewayRunner>;
4
4
  //# sourceMappingURL=getTestGateway.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getTestGateway.d.ts","sourceRoot":"","sources":["../../../src/config/getTestGateway.ts"],"names":[],"mappings":"AACA,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAE9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAK5D,eAAO,MAAM,cAAc,GAAU,QAAQ,YAAY,KAAG,OAAO,CAAC,gBAAgB,CAYnF,CAAA"}
1
+ {"version":3,"file":"getTestGateway.d.ts","sourceRoot":"","sources":["../../../src/config/getTestGateway.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAG5D,eAAO,MAAM,cAAc,GAAU,QAAQ,YAAY,KAAG,OAAO,CAAC,gBAAgB,CASnF,CAAA"}
@@ -1,2 +1,3 @@
1
1
  export * from './BridgeActor.ts';
2
+ export * from './monitoring/index.ts';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,uBAAuB,CAAA"}
@@ -6,10 +6,138 @@ import { creatable } from "@xylabs/sdk-js";
6
6
  import { asBridgeConfigContext } from "@xyo-network/chain-orchestration";
7
7
  import { ActorV3, XyoGatewayRunnerMoniker } from "@xyo-network/xl1-sdk";
8
8
 
9
- // src/server/app.ts
10
- import { standardErrors } from "@xylabs/express";
11
- import { sharedMiddleware } from "@xyo-network/chain-orchestration";
12
- import express from "express";
9
+ // src/monitoring/createBalanceMonitor.ts
10
+ var DEFAULT_INTERVAL_MS = 6e4;
11
+ var WEI_PER_GWEI = 10n ** 9n;
12
+ var TOKEN_DECIMALS = 10n ** 18n;
13
+ function createBalanceMonitor(config) {
14
+ const { account, bridge, bridgeableToken, gateway, meter, provider, wallet, intervalMs = DEFAULT_INTERVAL_MS } = config;
15
+ let timer;
16
+ const ethWalletGasBalance = meter.createGauge("bridge_eth_wallet_gas_balance_gwei", {
17
+ description: "ETH balance of the bridge runner wallet (in gwei)",
18
+ unit: "gwei"
19
+ });
20
+ const liquidityTokenBalance = meter.createGauge("bridge_eth_liquidity_token_balance", {
21
+ description: "ERC-20 token balance of the liquidity source (in whole tokens)",
22
+ unit: "tokens"
23
+ });
24
+ const liquidityTokenAllowance = meter.createGauge("bridge_eth_liquidity_token_allowance", {
25
+ description: "ERC-20 token allowance from liquidity source to bridge contract (in whole tokens)",
26
+ unit: "tokens"
27
+ });
28
+ const xl1AccountBalance = meter.createGauge("bridge_xl1_account_balance", {
29
+ description: "XL1 native balance of the bridge account (in whole XL1)",
30
+ unit: "xl1"
31
+ });
32
+ const walletAddress = wallet.address;
33
+ async function poll() {
34
+ try {
35
+ const balance = await provider.getBalance(walletAddress);
36
+ ethWalletGasBalance.record(Number(balance / WEI_PER_GWEI), {
37
+ address: walletAddress
38
+ });
39
+ } catch (err) {
40
+ console.error("[BalanceMonitor] Failed to read ETH wallet gas balance:", err);
41
+ }
42
+ try {
43
+ const liquiditySourceAddress = await bridge.liquiditySource();
44
+ const balance = await bridgeableToken.balanceOf(liquiditySourceAddress);
45
+ liquidityTokenBalance.record(Number(balance / TOKEN_DECIMALS), {
46
+ address: liquiditySourceAddress
47
+ });
48
+ } catch (err) {
49
+ console.error("[BalanceMonitor] Failed to read liquidity source token balance:", err);
50
+ }
51
+ try {
52
+ const liquiditySourceAddress = await bridge.liquiditySource();
53
+ const bridgeAddress = await bridge.getAddress();
54
+ const allowance = await bridgeableToken.allowance(liquiditySourceAddress, bridgeAddress);
55
+ liquidityTokenAllowance.record(Number(allowance / TOKEN_DECIMALS), {
56
+ address: liquiditySourceAddress
57
+ });
58
+ } catch (err) {
59
+ console.error("[BalanceMonitor] Failed to read liquidity source token allowance:", err);
60
+ }
61
+ try {
62
+ const viewer = gateway.connection.viewer;
63
+ if (viewer) {
64
+ const balance = await viewer.account.balance.accountBalance(account.address);
65
+ xl1AccountBalance.record(Number(balance / TOKEN_DECIMALS), {
66
+ address: account.address.toString()
67
+ });
68
+ }
69
+ } catch (err) {
70
+ console.error("[BalanceMonitor] Failed to read XL1 account balance:", err);
71
+ }
72
+ }
73
+ __name(poll, "poll");
74
+ return {
75
+ start() {
76
+ void poll();
77
+ timer = setInterval(() => void poll(), intervalMs);
78
+ },
79
+ stop() {
80
+ if (timer) {
81
+ clearInterval(timer);
82
+ timer = void 0;
83
+ }
84
+ }
85
+ };
86
+ }
87
+ __name(createBalanceMonitor, "createBalanceMonitor");
88
+
89
+ // src/monitoring/createQueueMetrics.ts
90
+ var DEFAULT_INTERVAL_MS2 = 3e4;
91
+ function createQueueMetrics(config) {
92
+ const { meter, queues, intervalMs = DEFAULT_INTERVAL_MS2 } = config;
93
+ let timer;
94
+ const waitingGauge = meter.createGauge("bridge_queue_waiting", {
95
+ description: "Number of waiting jobs in the bridge queue"
96
+ });
97
+ const activeGauge = meter.createGauge("bridge_queue_active", {
98
+ description: "Number of active jobs in the bridge queue"
99
+ });
100
+ const completedGauge = meter.createGauge("bridge_queue_completed", {
101
+ description: "Number of completed jobs in the bridge queue"
102
+ });
103
+ const failedGauge = meter.createGauge("bridge_queue_failed", {
104
+ description: "Number of failed jobs in the bridge queue"
105
+ });
106
+ const delayedGauge = meter.createGauge("bridge_queue_delayed", {
107
+ description: "Number of delayed jobs in the bridge queue"
108
+ });
109
+ async function poll() {
110
+ for (const [name10, queue] of Object.entries(queues)) {
111
+ try {
112
+ const counts = await queue.getJobCounts("waiting", "active", "completed", "failed", "delayed");
113
+ const attrs = {
114
+ queue_name: name10
115
+ };
116
+ waitingGauge.record(counts.waiting ?? 0, attrs);
117
+ activeGauge.record(counts.active ?? 0, attrs);
118
+ completedGauge.record(counts.completed ?? 0, attrs);
119
+ failedGauge.record(counts.failed ?? 0, attrs);
120
+ delayedGauge.record(counts.delayed ?? 0, attrs);
121
+ } catch (err) {
122
+ console.error(`[QueueMetrics] Failed to read job counts for queue ${name10}:`, err);
123
+ }
124
+ }
125
+ }
126
+ __name(poll, "poll");
127
+ return {
128
+ start() {
129
+ void poll();
130
+ timer = setInterval(() => void poll(), intervalMs);
131
+ },
132
+ stop() {
133
+ if (timer) {
134
+ clearInterval(timer);
135
+ timer = void 0;
136
+ }
137
+ }
138
+ };
139
+ }
140
+ __name(createQueueMetrics, "createQueueMetrics");
13
141
 
14
142
  // src/queue/connection.ts
15
143
  import { isDefined } from "@xylabs/sdk-js";
@@ -96,7 +224,7 @@ import { Worker as Worker2 } from "bullmq";
96
224
  import { getAddress } from "ethers";
97
225
 
98
226
  // src/validation/validateBridgeEstimateExact.ts
99
- import { hexToBigInt as hexToBigInt4, isUndefined as isUndefined2 } from "@xylabs/sdk-js";
227
+ import { hexToBigInt as hexToBigInt4, isUndefined } from "@xylabs/sdk-js";
100
228
  import { PayloadBuilder as PayloadBuilder3 } from "@xyo-network/sdk-js";
101
229
 
102
230
  // src/config/asChainId.ts
@@ -163,25 +291,13 @@ var getRemoteTokenAddress = /* @__PURE__ */ __name((config) => {
163
291
  }, "getRemoteTokenAddress");
164
292
 
165
293
  // src/config/getBridgeWalletAccount.ts
166
- import { isDefined as isDefined3, isUndefined } from "@xylabs/sdk-js";
167
- import { HDWallet } from "@xyo-network/sdk-js";
168
- import { ADDRESS_INDEX, generateXyoBaseWalletFromPhrase } from "@xyo-network/xl1-sdk";
294
+ import { isDefined as isDefined3 } from "@xylabs/sdk-js";
295
+ import { resolveWalletForActor } from "@xyo-network/chain-orchestration";
169
296
  var accountServiceSingleton;
170
297
  var getBridgeWalletAccount = /* @__PURE__ */ __name(async (config) => {
171
298
  if (accountServiceSingleton) return accountServiceSingleton;
172
- let walletPhrase = config.mnemonic;
173
- if (isUndefined(walletPhrase)) {
174
- console.log("[Bridge] No wallet mnemonic specified!");
175
- const randomMnemonic = HDWallet.generateMnemonic();
176
- console.log(`[Bridge] Using randomly generated mnemonic:
177
-
178
- ${randomMnemonic}
179
-
180
- `);
181
- walletPhrase = randomMnemonic;
182
- }
183
- const wallet = await generateXyoBaseWalletFromPhrase(walletPhrase);
184
- const account = await wallet.derivePath(ADDRESS_INDEX.XYO);
299
+ const accountPath = typeof config.accountPath === "string" ? config.accountPath : void 0;
300
+ const account = await resolveWalletForActor(config.name, accountPath);
185
301
  accountServiceSingleton = account;
186
302
  return accountServiceSingleton;
187
303
  }, "getBridgeWalletAccount");
@@ -322,7 +438,7 @@ var validateBridgeEstimateExact = /* @__PURE__ */ __name(async (intent, transfer
322
438
  if (hexToBigInt4(srcAmount) < hexToBigInt4(getMinBridgeAmount(config))) return false;
323
439
  if (hexToBigInt4(srcAmount) > hexToBigInt4(getMaxBridgeAmount(config))) return false;
324
440
  const [calculatedIntent, calculatedTransfer] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config);
325
- if (isUndefined2(calculatedIntent) || isUndefined2(calculatedTransfer)) return false;
441
+ if (isUndefined(calculatedIntent) || isUndefined(calculatedTransfer)) return false;
326
442
  const { nonce: expectedIntentNonce, ...expectedIntentStatic } = calculatedIntent;
327
443
  const { nonce: actualIntentNonce, ...actualIntentStatic } = intent;
328
444
  if (await PayloadBuilder3.dataHash(expectedIntentStatic) !== await PayloadBuilder3.dataHash(actualIntentStatic)) return false;
@@ -1091,6 +1207,11 @@ var getTelemetry = /* @__PURE__ */ __name(() => {
1091
1207
  return telemetry;
1092
1208
  }, "getTelemetry");
1093
1209
 
1210
+ // src/server/app.ts
1211
+ import { standardErrors } from "@xylabs/express";
1212
+ import { sharedMiddleware } from "@xyo-network/chain-orchestration";
1213
+ import express from "express";
1214
+
1094
1215
  // src/server/addFlowProducer.ts
1095
1216
  var addFlowProducer = /* @__PURE__ */ __name((app, config) => {
1096
1217
  const connection2 = getConnection(config);
@@ -1195,12 +1316,12 @@ import { BridgeDestinationObservationFieldsZod, BridgeDestinationObservationSche
1195
1316
  import { z } from "zod";
1196
1317
 
1197
1318
  // src/server/routes/bridge/routeDefinitions/pathParams/ChainIdPathParam.ts
1198
- import { asHex as asHex2, HexZod, isUndefined as isUndefined3 } from "@xylabs/sdk-js";
1319
+ import { asHex as asHex2, HexZod, isUndefined as isUndefined2 } from "@xylabs/sdk-js";
1199
1320
  var getRemoteChainIdZod = /* @__PURE__ */ __name((config) => {
1200
1321
  const remoteChainId = getRemoteChainId(config);
1201
1322
  return HexZod.superRefine((val, ctx) => {
1202
1323
  const chainId = asHex2(val);
1203
- if (isUndefined3(chainId)) {
1324
+ if (isUndefined2(chainId)) {
1204
1325
  ctx.addIssue("Not a valid chain id");
1205
1326
  return;
1206
1327
  }
@@ -1555,9 +1676,8 @@ var getApp = /* @__PURE__ */ __name((config, gateway) => {
1555
1676
  }, "getApp");
1556
1677
 
1557
1678
  // src/services/getServices.ts
1558
- import { assertEx as assertEx21, isDefined as isDefined14 } from "@xylabs/sdk-js";
1559
- import { initEvmProvider } from "@xyo-network/chain-orchestration";
1560
- import { HDWallet as HDWallet2 } from "@xyo-network/sdk-js";
1679
+ import { assertEx as assertEx21 } from "@xylabs/sdk-js";
1680
+ import { initEvmProvider, resolveWalletForActor as resolveWalletForActor2 } from "@xyo-network/chain-orchestration";
1561
1681
  import { BridgeableToken__factory, LiquidityPoolBridge__factory } from "@xyo-network/typechain";
1562
1682
  import { getAddress as getAddress2, Wallet } from "ethers";
1563
1683
 
@@ -1599,8 +1719,8 @@ var getServices = /* @__PURE__ */ __name(async (context, gateway) => {
1599
1719
  const ethTxStateMap = await getIterableMap(config, "liquidity_bridge_xl1_to_eth_eth_tx_state");
1600
1720
  const xl1TxStateMap = await getIterableMap(config, "liquidity_bridge_xl1_to_eth_xl1_tx_state");
1601
1721
  const provider = await initEvmProvider(context);
1602
- const { remoteBridgeContractAddress, remoteChainWalletPrivateKey, remoteTokenAddress, mnemonic } = config;
1603
- const account = isDefined14(mnemonic) ? await HDWallet2.fromPhrase(mnemonic) : await HDWallet2.random();
1722
+ const { remoteBridgeContractAddress, remoteChainWalletPrivateKey, remoteTokenAddress, accountPath } = config;
1723
+ const account = await resolveWalletForActor2(config.name, accountPath);
1604
1724
  const wallet = new Wallet(remoteChainWalletPrivateKey, provider);
1605
1725
  const bridgeableToken = BridgeableToken__factory.connect(getAddress2(remoteTokenAddress), wallet);
1606
1726
  const bridge = LiquidityPoolBridge__factory.connect(getAddress2(remoteBridgeContractAddress), wallet);
@@ -1636,7 +1756,10 @@ var getServer = /* @__PURE__ */ __name(async (context, gateway) => {
1636
1756
  addWorkers(config, services);
1637
1757
  const server = app.listen(port, hostname, () => logger?.log(`[Bridge] Server listening at http://${hostname}:${port}`));
1638
1758
  server.setTimeout(2e4);
1639
- return server;
1759
+ return {
1760
+ server,
1761
+ services
1762
+ };
1640
1763
  }, "getServer");
1641
1764
 
1642
1765
  // src/BridgeActor.ts
@@ -1652,6 +1775,8 @@ var BridgeActor = class extends ActorV3 {
1652
1775
  __name(this, "BridgeActor");
1653
1776
  }
1654
1777
  _gatewayRunner;
1778
+ _balanceMonitor;
1779
+ _queueMetrics;
1655
1780
  server;
1656
1781
  get gatewayRunner() {
1657
1782
  return this._gatewayRunner;
@@ -1667,10 +1792,34 @@ var BridgeActor = class extends ActorV3 {
1667
1792
  }
1668
1793
  async stopHandler() {
1669
1794
  await super.stopHandler();
1795
+ this._balanceMonitor?.stop();
1796
+ this._queueMetrics?.stop();
1797
+ this._balanceMonitor = void 0;
1798
+ this._queueMetrics = void 0;
1670
1799
  this.stopServer();
1671
1800
  }
1672
1801
  async startServer() {
1673
- this.server = await getServer(asBridgeConfigContext(this.context, true), this._gatewayRunner);
1802
+ const context = asBridgeConfigContext(this.context, true);
1803
+ const { server, services } = await getServer(context, this._gatewayRunner);
1804
+ this.server = server;
1805
+ if (this.meter) {
1806
+ this._balanceMonitor = createBalanceMonitor({
1807
+ account: services.account,
1808
+ bridge: services.bridge,
1809
+ bridgeableToken: services.bridgeableToken,
1810
+ gateway: services.gateway,
1811
+ meter: this.meter,
1812
+ provider: services.provider,
1813
+ wallet: services.wallet
1814
+ });
1815
+ this._balanceMonitor.start();
1816
+ const queues = getXl1ToEthQueues(context.config);
1817
+ this._queueMetrics = createQueueMetrics({
1818
+ meter: this.meter,
1819
+ queues
1820
+ });
1821
+ this._queueMetrics.start();
1822
+ }
1674
1823
  }
1675
1824
  stopServer() {
1676
1825
  this.server?.close();
@@ -1681,6 +1830,8 @@ BridgeActor = _ts_decorate([
1681
1830
  creatable()
1682
1831
  ], BridgeActor);
1683
1832
  export {
1684
- BridgeActor
1833
+ BridgeActor,
1834
+ createBalanceMonitor,
1835
+ createQueueMetrics
1685
1836
  };
1686
1837
  //# sourceMappingURL=index.mjs.map