@xyo-network/chain-bridge 1.18.1 → 1.18.4
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/node/config/getGateway.d.ts.map +1 -1
- package/dist/node/index.mjs +44 -65
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/interface/service/Observer/LiquidityPoolBridgeObserver/LiquidityPoolBridgeObserver.d.ts +4 -4
- package/dist/node/interface/service/Observer/LiquidityPoolBridgeObserver/LiquidityPoolBridgeObserver.d.ts.map +1 -1
- package/dist/node/manifest/{getLocator.d.ts → getModuleLocator.d.ts} +4 -3
- package/dist/node/manifest/getModuleLocator.d.ts.map +1 -0
- package/dist/node/manifest/getNode.d.ts.map +1 -1
- package/dist/node/manifest/getServices.d.ts.map +1 -1
- package/dist/node/manifest/index.d.ts +1 -1
- package/dist/node/manifest/index.d.ts.map +1 -1
- package/package.json +66 -63
- package/src/config/getGateway.ts +6 -6
- package/src/interface/service/Observer/LiquidityPoolBridgeObserver/LiquidityPoolBridgeObserver.ts +6 -6
- package/src/interface/service/Relay/LiquidityPoolBridgeRelay/LiquidityPoolBridgeRelay.ts +2 -2
- package/src/manifest/{getLocator.ts → getModuleLocator.ts} +18 -28
- package/src/manifest/getNode.ts +10 -4
- package/src/manifest/getServices.ts +4 -23
- package/src/manifest/index.ts +1 -1
- package/src/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/EVMLiquidityBridgeTransactionCompletionMonitorSentinel.ts +1 -1
- package/src/queue/workers/ethTransactionPreparation.ts +1 -1
- package/src/queue/workers/xl1TransactionMonitor.ts +1 -1
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteEstimate.ts +1 -1
- package/dist/node/manifest/getLocator.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getGateway.d.ts","sourceRoot":"","sources":["../../../src/config/getGateway.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,MAAM,
|
|
1
|
+
{"version":3,"file":"getGateway.d.ts","sourceRoot":"","sources":["../../../src/config/getGateway.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,MAAM,EACN,gBAAgB,EACjB,MAAM,sBAAsB,CAAA;AAU7B,eAAO,MAAM,UAAU,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAUzE,CAAA"}
|
package/dist/node/index.mjs
CHANGED
|
@@ -84,7 +84,7 @@ var createWorker2 = /* @__PURE__ */ __name((connection2) => {
|
|
|
84
84
|
const amount = hexToBigInt(bridgeIntent.destAmount);
|
|
85
85
|
const srcAddress = getAddress(bridgeIntent.srcAddress);
|
|
86
86
|
const destAddress = getAddress(bridgeIntent.destAddress);
|
|
87
|
-
const preparedTx = await bridge.getFunction("bridgeFromRemote").populateTransaction(srcAddress, destAddress, amount);
|
|
87
|
+
const preparedTx = await bridge.getFunction("bridgeFromRemote").populateTransaction(srcAddress, destAddress, amount, 0n);
|
|
88
88
|
await job.log(`[${hash}] built ETH transaction`);
|
|
89
89
|
await job.log(`[${hash}] storing ETH preparedTx`);
|
|
90
90
|
await stateMap.set(hash, {
|
|
@@ -175,7 +175,7 @@ var createWorker5 = /* @__PURE__ */ __name((connection2) => {
|
|
|
175
175
|
new Worker5(queueName5, async (job) => {
|
|
176
176
|
const { gateway, tx, xl1TxStateMap: stateMap } = job.data;
|
|
177
177
|
const hash = await PayloadBuilder4.hash(tx[0]);
|
|
178
|
-
const viewer = assertEx4(gateway.
|
|
178
|
+
const viewer = assertEx4(gateway.connection.viewer, () => `[${hash}] viewer not defined on gateway`);
|
|
179
179
|
const state = assertEx4(await stateMap.get(hash), () => `[${hash}] state not found`);
|
|
180
180
|
await job.log(`[${hash}] Checking for XL1 transaction inclusion on chain`);
|
|
181
181
|
const foundTx = await viewer.transactionByHash(hash);
|
|
@@ -518,23 +518,22 @@ var getBridgeSettings = /* @__PURE__ */ __name(async (config) => {
|
|
|
518
518
|
// src/config/getGateway.ts
|
|
519
519
|
import { isDefined as isDefined9 } from "@xylabs/sdk-js";
|
|
520
520
|
import { HDWallet as HDWallet2 } from "@xyo-network/wallet";
|
|
521
|
-
import { buildJsonRpcProviderLocator, HttpRpcTransport, SimpleXyoGatewayRunner, SimpleXyoSigner,
|
|
521
|
+
import { buildJsonRpcProviderLocator, HttpRpcTransport, SimpleXyoGatewayRunner, SimpleXyoSigner, XyoGatewayRunnerMoniker } from "@xyo-network/xl1-sdk";
|
|
522
522
|
var gatewayInstance;
|
|
523
523
|
var getGateway = /* @__PURE__ */ __name(async (config) => {
|
|
524
524
|
if (isDefined9(gatewayInstance)) return gatewayInstance;
|
|
525
525
|
const { mnemonic, chainRpcApiUrl: endpoint } = config.bridge;
|
|
526
526
|
const walletPromise = isDefined9(mnemonic) ? HDWallet2.fromPhrase(mnemonic) : HDWallet2.random();
|
|
527
527
|
const account = await walletPromise;
|
|
528
|
-
const signer = await SimpleXyoSigner.create({
|
|
529
|
-
account
|
|
530
|
-
});
|
|
531
528
|
const transportFactory = /* @__PURE__ */ __name((schemas) => new HttpRpcTransport(endpoint, schemas), "transportFactory");
|
|
532
529
|
const locator = await buildJsonRpcProviderLocator({
|
|
533
530
|
transportFactory
|
|
534
531
|
});
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
532
|
+
locator.register(SimpleXyoSigner.factory(SimpleXyoSigner.dependencies, {
|
|
533
|
+
account
|
|
534
|
+
}));
|
|
535
|
+
locator.register(SimpleXyoGatewayRunner.factory(SimpleXyoGatewayRunner.dependencies));
|
|
536
|
+
return await locator.getInstance(XyoGatewayRunnerMoniker);
|
|
538
537
|
}, "getGateway");
|
|
539
538
|
|
|
540
539
|
// src/server/routes/bridge/routeDefinitions/routes/bridgeConfig.ts
|
|
@@ -822,7 +821,7 @@ var makeBridgeToRemoteEstimateRoute = /* @__PURE__ */ __name((config) => {
|
|
|
822
821
|
const [bridgeIntent, transfer] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config);
|
|
823
822
|
const sender = toAddress3(srcAddress);
|
|
824
823
|
const gateway = await getGateway(config);
|
|
825
|
-
const viewer = assertEx11(gateway.
|
|
824
|
+
const viewer = assertEx11(gateway.connection.viewer, () => new Error("Viewer not available on gateway connection"));
|
|
826
825
|
const currentBlockNumber = await viewer.currentBlockNumber();
|
|
827
826
|
const nbf = toXL1BlockNumber(currentBlockNumber, true);
|
|
828
827
|
const exp = toXL1BlockNumber(currentBlockNumber + 1e3, true);
|
|
@@ -979,9 +978,9 @@ var getApp = /* @__PURE__ */ __name((node, config) => {
|
|
|
979
978
|
// src/server/server.ts
|
|
980
979
|
import { assertEx as assertEx16, isDefined as isDefined15, isString } from "@xylabs/sdk-js";
|
|
981
980
|
import { boot } from "@xyo-network/bios";
|
|
982
|
-
import { HDWallet as
|
|
981
|
+
import { HDWallet as HDWallet4 } from "@xyo-network/wallet";
|
|
983
982
|
|
|
984
|
-
// src/manifest/
|
|
983
|
+
// src/manifest/getModuleLocator.ts
|
|
985
984
|
import { BaseMongoSdk } from "@xylabs/mongo";
|
|
986
985
|
import { assertEx as assertEx14, isDefined as isDefined13 } from "@xylabs/sdk-js";
|
|
987
986
|
import { MemoryArchivist } from "@xyo-network/archivist-memory";
|
|
@@ -993,8 +992,7 @@ import { initTelemetry } from "@xyo-network/chain-telemetry";
|
|
|
993
992
|
import { AbstractModule, LoggerModuleStatusReporter } from "@xyo-network/module-abstract";
|
|
994
993
|
import { ModuleFactoryLocator } from "@xyo-network/module-factory-locator";
|
|
995
994
|
import { MemorySentinel } from "@xyo-network/sentinel-memory";
|
|
996
|
-
import {
|
|
997
|
-
import { hasMongoConfig, mapToMapType, SimpleXyoConnection, SimpleXyoGatewayRunner as SimpleXyoGatewayRunner2, SimpleXyoSigner as SimpleXyoSigner2 } from "@xyo-network/xl1-sdk";
|
|
995
|
+
import { hasMongoConfig, mapToMapType, XyoGatewayRunnerMoniker as XyoGatewayRunnerMoniker2 } from "@xyo-network/xl1-sdk";
|
|
998
996
|
|
|
999
997
|
// src/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/EVMLiquidityBridgeTransactionCompletionMonitorSentinel.ts
|
|
1000
998
|
import { asAddress as asAddress6, asHex as asHex4, assertEx as assertEx12, delay, hexFromBigInt, hexToBigInt as hexToBigInt4, isDefined as isDefined11, isUndefined as isUndefined4 } from "@xylabs/sdk-js";
|
|
@@ -1133,9 +1131,7 @@ var EVMLiquidityBridgeTransactionCompletionMonitorSentinel = class extends Abstr
|
|
|
1133
1131
|
const nonce = await this.wallet.getNonce();
|
|
1134
1132
|
const srcAddress = getAddress2(bridgeIntent.srcAddress);
|
|
1135
1133
|
const destAddress = getAddress2(bridgeIntent.destAddress);
|
|
1136
|
-
const tx = await this.bridge.bridgeFromRemote(srcAddress, destAddress, amount,
|
|
1137
|
-
nonce
|
|
1138
|
-
});
|
|
1134
|
+
const tx = await this.bridge.bridgeFromRemote(srcAddress, destAddress, amount, nonce);
|
|
1139
1135
|
const confirmation = await tx.wait();
|
|
1140
1136
|
const transactionResponse = await confirmation?.getTransaction();
|
|
1141
1137
|
const destConfirmation = asHex4(transactionResponse?.hash ?? "", true);
|
|
@@ -1266,9 +1262,9 @@ var XL1TransactionCompletionMonitorSentinel = class extends AbstractSentinel2 {
|
|
|
1266
1262
|
}
|
|
1267
1263
|
};
|
|
1268
1264
|
|
|
1269
|
-
// src/manifest/
|
|
1270
|
-
var
|
|
1271
|
-
const { config, logger } = context;
|
|
1265
|
+
// src/manifest/getModuleLocator.ts
|
|
1266
|
+
var getModuleLocator = /* @__PURE__ */ __name(async (context) => {
|
|
1267
|
+
const { config, locator, logger } = context;
|
|
1272
1268
|
const { otlpEndpoint } = config.telemetry?.otel ?? {};
|
|
1273
1269
|
const { path: endpoint = "/metrics", port = 9468 } = config.telemetry?.metrics?.scrape ?? {};
|
|
1274
1270
|
const { traceProvider, meterProvider } = await initTelemetry({
|
|
@@ -1284,7 +1280,7 @@ var getLocator = /* @__PURE__ */ __name(async (context) => {
|
|
|
1284
1280
|
});
|
|
1285
1281
|
if (isDefined13(logger)) AbstractModule.defaultLogger = logger;
|
|
1286
1282
|
const statusReporter = logger ? new LoggerModuleStatusReporter(logger) : void 0;
|
|
1287
|
-
const
|
|
1283
|
+
const moduleLocator = new ModuleFactoryLocator();
|
|
1288
1284
|
const mongoConfig = config.storage?.mongo;
|
|
1289
1285
|
if (hasMongoConfig(mongoConfig)) {
|
|
1290
1286
|
const { connectionString: dbConnectionString, database: dbName, domain: dbDomain, password: dbPassword, username: dbUserName } = mongoConfig;
|
|
@@ -1301,25 +1297,25 @@ var getLocator = /* @__PURE__ */ __name(async (context) => {
|
|
|
1301
1297
|
statusReporter,
|
|
1302
1298
|
traceProvider
|
|
1303
1299
|
};
|
|
1304
|
-
|
|
1300
|
+
moduleLocator.register(MongoDBArchivistV2.factory(params), void 0, true);
|
|
1305
1301
|
}
|
|
1306
|
-
|
|
1302
|
+
moduleLocator.register(MemoryArchivist.factory({
|
|
1307
1303
|
traceProvider,
|
|
1308
1304
|
meterProvider,
|
|
1309
1305
|
statusReporter
|
|
1310
1306
|
}));
|
|
1311
|
-
|
|
1307
|
+
moduleLocator.register(MemorySentinel.factory({
|
|
1312
1308
|
traceProvider,
|
|
1313
1309
|
meterProvider,
|
|
1314
1310
|
statusReporter
|
|
1315
1311
|
}));
|
|
1316
|
-
|
|
1312
|
+
moduleLocator.register(ViewArchivist.factory({
|
|
1317
1313
|
traceProvider,
|
|
1318
1314
|
meterProvider,
|
|
1319
1315
|
statusReporter
|
|
1320
1316
|
}));
|
|
1321
|
-
const gateway = await
|
|
1322
|
-
const viewer = assertEx14(gateway.
|
|
1317
|
+
const gateway = await locator.getInstance(XyoGatewayRunnerMoniker2);
|
|
1318
|
+
const viewer = assertEx14(gateway.connection.viewer, () => "Gateway viewer is not defined");
|
|
1323
1319
|
const pendingXl1ToEthXl1BridgeIntentTransactions = await getIterableMap(config, "liquidity_bridge_xl1_to_eth_xl1_pending");
|
|
1324
1320
|
const completedXl1ToEthXl1BridgeIntentTransactions = await getIterableMap(config, "liquidity_bridge_xl1_to_eth_xl1_completed");
|
|
1325
1321
|
const xl1TransactionCompletionMonitorSentinelParams = {
|
|
@@ -1333,7 +1329,7 @@ var getLocator = /* @__PURE__ */ __name(async (context) => {
|
|
|
1333
1329
|
traceProvider,
|
|
1334
1330
|
viewer
|
|
1335
1331
|
};
|
|
1336
|
-
|
|
1332
|
+
moduleLocator.register(XL1TransactionCompletionMonitorSentinel.factory(xl1TransactionCompletionMonitorSentinelParams));
|
|
1337
1333
|
const completedEthXl1BridgeTransactions = await getIterableMap(config, "liquidity_bridge_eth_xl1_bridge_completed");
|
|
1338
1334
|
const provider = await initEvmProvider({
|
|
1339
1335
|
config
|
|
@@ -1351,20 +1347,9 @@ var getLocator = /* @__PURE__ */ __name(async (context) => {
|
|
|
1351
1347
|
statusReporter,
|
|
1352
1348
|
traceProvider
|
|
1353
1349
|
};
|
|
1354
|
-
|
|
1355
|
-
return
|
|
1356
|
-
}, "
|
|
1357
|
-
var getGateway2 = /* @__PURE__ */ __name(async (config) => {
|
|
1358
|
-
const { mnemonic, chainRpcApiUrl: endpoint } = config.bridge;
|
|
1359
|
-
const walletPromise = isDefined13(mnemonic) ? HDWallet3.fromPhrase(mnemonic) : HDWallet3.random();
|
|
1360
|
-
const account = await walletPromise;
|
|
1361
|
-
const signer = await SimpleXyoSigner2.create({
|
|
1362
|
-
account
|
|
1363
|
-
});
|
|
1364
|
-
const connection2 = await SimpleXyoConnection.create();
|
|
1365
|
-
const gateway = new SimpleXyoGatewayRunner2(connection2, signer);
|
|
1366
|
-
return gateway;
|
|
1367
|
-
}, "getGateway");
|
|
1350
|
+
moduleLocator.register(EVMLiquidityBridgeTransactionCompletionMonitorSentinel.factory(evmLiquidityBridgeTransactionCompletionMonitorSentinelParams));
|
|
1351
|
+
return moduleLocator;
|
|
1352
|
+
}, "getModuleLocator");
|
|
1368
1353
|
var getIterableMap = /* @__PURE__ */ __name(async (config, collection) => {
|
|
1369
1354
|
const mongoConfig = config.storage?.mongo;
|
|
1370
1355
|
if (hasMongoConfig(mongoConfig)) {
|
|
@@ -1395,6 +1380,7 @@ var getIterableMap = /* @__PURE__ */ __name(async (config, collection) => {
|
|
|
1395
1380
|
|
|
1396
1381
|
// src/manifest/getNode.ts
|
|
1397
1382
|
import { ManifestWrapper } from "@xyo-network/manifest-wrapper";
|
|
1383
|
+
import { buildJsonRpcProviderLocator as buildJsonRpcProviderLocator2, HttpRpcTransport as HttpRpcTransport2 } from "@xyo-network/xl1-sdk";
|
|
1398
1384
|
|
|
1399
1385
|
// src/manifest/node.json
|
|
1400
1386
|
var node_default = {
|
|
@@ -1532,8 +1518,16 @@ var PublicChildManifests = [
|
|
|
1532
1518
|
// src/manifest/getNode.ts
|
|
1533
1519
|
var getNode = /* @__PURE__ */ __name(async (context) => {
|
|
1534
1520
|
const { wallet } = context;
|
|
1535
|
-
const
|
|
1536
|
-
const
|
|
1521
|
+
const { chainRpcApiUrl: endpoint } = context.config.bridge;
|
|
1522
|
+
const transportFactory = /* @__PURE__ */ __name((schemas) => new HttpRpcTransport2(endpoint, schemas), "transportFactory");
|
|
1523
|
+
const locator = await buildJsonRpcProviderLocator2({
|
|
1524
|
+
transportFactory
|
|
1525
|
+
});
|
|
1526
|
+
const moduleLocator = await getModuleLocator({
|
|
1527
|
+
...context,
|
|
1528
|
+
locator
|
|
1529
|
+
});
|
|
1530
|
+
const wrapper = new ManifestWrapper(NodeManifest, wallet, moduleLocator, PublicChildManifests, PrivateChildManifests);
|
|
1537
1531
|
const [node, ...childNodes] = await wrapper.loadNodes();
|
|
1538
1532
|
if (childNodes?.length > 0) {
|
|
1539
1533
|
await Promise.all(childNodes.map((childNode) => node.register(childNode)));
|
|
@@ -1548,19 +1542,19 @@ import { assertEx as assertEx15, isDefined as isDefined14 } from "@xylabs/sdk-js
|
|
|
1548
1542
|
import { MongoMap as MongoMap2 } from "@xyo-network/chain-protocol";
|
|
1549
1543
|
import { initEvmProvider as initEvmProvider2 } from "@xyo-network/chain-services";
|
|
1550
1544
|
import { LiquidityPoolBridge__factory as LiquidityPoolBridge__factory2 } from "@xyo-network/typechain";
|
|
1551
|
-
import { HDWallet as
|
|
1552
|
-
import {
|
|
1545
|
+
import { HDWallet as HDWallet3 } from "@xyo-network/wallet";
|
|
1546
|
+
import { hasMongoConfig as hasMongoConfig2, mapToMapType as mapToMapType2 } from "@xyo-network/xl1-sdk";
|
|
1553
1547
|
import { getAddress as getAddress3, Wallet as Wallet2 } from "ethers";
|
|
1554
1548
|
var getServices = /* @__PURE__ */ __name(async (context) => {
|
|
1555
1549
|
const { config } = context;
|
|
1556
|
-
const gateway = await
|
|
1550
|
+
const gateway = await getGateway(config);
|
|
1557
1551
|
const ethTxStateMap = await getIterableMap2(config, "liquidity_bridge_xl1_to_eth_eth_tx_state");
|
|
1558
1552
|
const xl1TxStateMap = await getIterableMap2(config, "liquidity_bridge_xl1_to_eth_xl1_tx_state");
|
|
1559
1553
|
const provider = await initEvmProvider2({
|
|
1560
1554
|
config
|
|
1561
1555
|
});
|
|
1562
1556
|
const { remoteBridgeContractAddress, remoteChainWalletPrivateKey, mnemonic } = config.bridge;
|
|
1563
|
-
const account = isDefined14(mnemonic) ? await
|
|
1557
|
+
const account = isDefined14(mnemonic) ? await HDWallet3.fromPhrase(mnemonic) : await HDWallet3.random();
|
|
1564
1558
|
const wallet = new Wallet2(remoteChainWalletPrivateKey, provider);
|
|
1565
1559
|
const bridge = LiquidityPoolBridge__factory2.connect(getAddress3(remoteBridgeContractAddress), wallet);
|
|
1566
1560
|
const bridgeOwner = await bridge.owner();
|
|
@@ -1575,21 +1569,6 @@ var getServices = /* @__PURE__ */ __name(async (context) => {
|
|
|
1575
1569
|
xl1TxStateMap
|
|
1576
1570
|
};
|
|
1577
1571
|
}, "getServices");
|
|
1578
|
-
var getGateway3 = /* @__PURE__ */ __name(async (config) => {
|
|
1579
|
-
const { mnemonic, chainRpcApiUrl: endpoint } = config.bridge;
|
|
1580
|
-
const walletPromise = isDefined14(mnemonic) ? HDWallet4.fromPhrase(mnemonic) : HDWallet4.random();
|
|
1581
|
-
const account = await walletPromise;
|
|
1582
|
-
const signer = await SimpleXyoSigner3.create({
|
|
1583
|
-
account
|
|
1584
|
-
});
|
|
1585
|
-
const transportFactory = /* @__PURE__ */ __name((schemas) => new HttpRpcTransport2(endpoint, schemas), "transportFactory");
|
|
1586
|
-
const locator = await buildJsonRpcProviderLocator2({
|
|
1587
|
-
transportFactory
|
|
1588
|
-
});
|
|
1589
|
-
const connection2 = await locator.getInstance(XyoConnectionMoniker2);
|
|
1590
|
-
const gateway = new SimpleXyoGatewayRunner3(connection2, signer);
|
|
1591
|
-
return gateway;
|
|
1592
|
-
}, "getGateway");
|
|
1593
1572
|
var getIterableMap2 = /* @__PURE__ */ __name(async (config, collection) => {
|
|
1594
1573
|
const mongoConfig = config.storage?.mongo;
|
|
1595
1574
|
if (hasMongoConfig2(mongoConfig)) {
|
|
@@ -1632,7 +1611,7 @@ var getSeedPhrase = /* @__PURE__ */ __name(async (bios, config, logger) => {
|
|
|
1632
1611
|
if (isString(mnemonic)) {
|
|
1633
1612
|
seedPhrase = mnemonic;
|
|
1634
1613
|
} else {
|
|
1635
|
-
seedPhrase =
|
|
1614
|
+
seedPhrase = HDWallet4.generateMnemonic();
|
|
1636
1615
|
logger?.log("[Bridge] No mnemonic provided, using random mnemonic. This is not recommended for production use.");
|
|
1637
1616
|
logger?.log(`[Bridge] Mnemonic: ${seedPhrase}`);
|
|
1638
1617
|
}
|
|
@@ -1645,7 +1624,7 @@ var getServer = /* @__PURE__ */ __name(async (context) => {
|
|
|
1645
1624
|
const { port, mnemonic } = config.bridge;
|
|
1646
1625
|
const bios = await boot();
|
|
1647
1626
|
const seedPhrase = isDefined15(mnemonic) ? mnemonic : await getSeedPhrase(bios, config, logger);
|
|
1648
|
-
const wallet = await
|
|
1627
|
+
const wallet = await HDWallet4.fromPhrase(seedPhrase);
|
|
1649
1628
|
const nodeContext = {
|
|
1650
1629
|
wallet,
|
|
1651
1630
|
logger,
|