@usherlabs/cex-broker 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/cli.js +209 -40
- package/dist/helpers/index.d.ts +1 -0
- package/dist/index.js +210 -41
- package/dist/index.js.map +7 -6
- package/dist/utils/payload-reader.d.ts +13 -0
- package/package.json +1 -1
package/dist/commands/cli.js
CHANGED
|
@@ -313654,20 +313654,33 @@ function loadPolicy(policyPath) {
|
|
|
313654
313654
|
if (error) {
|
|
313655
313655
|
throw new Error(`Policy validation failed: ${error.details.map((d) => d.message).join("; ")}`);
|
|
313656
313656
|
}
|
|
313657
|
-
|
|
313658
|
-
normalizedPolicy.withdraw.rule = normalizedPolicy.withdraw.rule.map((rule) => ({
|
|
313659
|
-
...rule,
|
|
313660
|
-
exchange: rule.exchange.trim().toUpperCase(),
|
|
313661
|
-
network: rule.network.trim().toUpperCase(),
|
|
313662
|
-
whitelist: rule.whitelist.map((a) => a.trim().toLowerCase())
|
|
313663
|
-
}));
|
|
313664
|
-
normalizedPolicy.order.rule.limits = normalizedPolicy.order.rule.limits ?? [];
|
|
313665
|
-
return normalizedPolicy;
|
|
313657
|
+
return normalizePolicyConfig(value);
|
|
313666
313658
|
} catch (error) {
|
|
313667
313659
|
console.error("Failed to load policy:", error);
|
|
313668
313660
|
throw new Error("Policy configuration could not be loaded");
|
|
313669
313661
|
}
|
|
313670
313662
|
}
|
|
313663
|
+
function normalizePolicyConfig(policy) {
|
|
313664
|
+
return {
|
|
313665
|
+
...policy,
|
|
313666
|
+
withdraw: {
|
|
313667
|
+
...policy.withdraw,
|
|
313668
|
+
rule: policy.withdraw.rule.map((rule) => ({
|
|
313669
|
+
...rule,
|
|
313670
|
+
exchange: rule.exchange.trim().toUpperCase(),
|
|
313671
|
+
network: rule.network.trim().toUpperCase(),
|
|
313672
|
+
whitelist: rule.whitelist.map((address) => address.trim().toLowerCase())
|
|
313673
|
+
}))
|
|
313674
|
+
},
|
|
313675
|
+
order: {
|
|
313676
|
+
...policy.order,
|
|
313677
|
+
rule: {
|
|
313678
|
+
...policy.order.rule,
|
|
313679
|
+
limits: policy.order.rule.limits ?? []
|
|
313680
|
+
}
|
|
313681
|
+
}
|
|
313682
|
+
};
|
|
313683
|
+
}
|
|
313671
313684
|
function getWithdrawRulePriority(rule, exchange, network) {
|
|
313672
313685
|
const exchangeMatch = rule.exchange === exchange || rule.exchange === "*";
|
|
313673
313686
|
const networkMatch = rule.network === network || rule.network === "*";
|
|
@@ -313686,15 +313699,16 @@ function getWithdrawRulePriority(rule, exchange, network) {
|
|
|
313686
313699
|
return 1;
|
|
313687
313700
|
}
|
|
313688
313701
|
function validateWithdraw(policy, exchange, network, recipientAddress, _amount, _ticker) {
|
|
313702
|
+
const normalizedPolicy = normalizePolicyConfig(policy);
|
|
313689
313703
|
const exchangeNorm = exchange.trim().toUpperCase();
|
|
313690
313704
|
const networkNorm = network.trim().toUpperCase();
|
|
313691
|
-
const matchingRules =
|
|
313705
|
+
const matchingRules = normalizedPolicy.withdraw.rule.map((rule) => ({
|
|
313692
313706
|
rule,
|
|
313693
313707
|
priority: getWithdrawRulePriority(rule, exchangeNorm, networkNorm)
|
|
313694
313708
|
})).filter((r) => r.priority > 0).sort((a, b2) => b2.priority - a.priority);
|
|
313695
313709
|
const withdrawRule = matchingRules[0]?.rule;
|
|
313696
313710
|
if (!withdrawRule) {
|
|
313697
|
-
const allowedPairs =
|
|
313711
|
+
const allowedPairs = normalizedPolicy.withdraw.rule.map((r) => `${r.exchange}:${r.network}`);
|
|
313698
313712
|
return {
|
|
313699
313713
|
valid: false,
|
|
313700
313714
|
error: `Network ${networkNorm} is not allowed for exchange ${exchangeNorm}. Allowed exchange/network pairs: ${allowedPairs.join(", ")}`
|
|
@@ -314303,10 +314317,77 @@ var descriptor = {
|
|
|
314303
314317
|
};
|
|
314304
314318
|
var node_descriptor_default = descriptor;
|
|
314305
314319
|
|
|
314320
|
+
// src/utils/payload-reader.ts
|
|
314321
|
+
class PayloadValidationError extends Error {
|
|
314322
|
+
constructor(message) {
|
|
314323
|
+
super(`ValidationError: ${message}`);
|
|
314324
|
+
this.name = "PayloadValidationError";
|
|
314325
|
+
}
|
|
314326
|
+
}
|
|
314327
|
+
function parseNumberField(value, fieldName) {
|
|
314328
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
314329
|
+
throw new PayloadValidationError(`'${fieldName}' must be a numeric string`);
|
|
314330
|
+
}
|
|
314331
|
+
const parsed = typeof value === "number" ? value : Number(value.trim());
|
|
314332
|
+
if (!Number.isFinite(parsed)) {
|
|
314333
|
+
throw new PayloadValidationError(`'${fieldName}' must be a valid number`);
|
|
314334
|
+
}
|
|
314335
|
+
return parsed;
|
|
314336
|
+
}
|
|
314337
|
+
function parseJsonField(value, fieldName, expected) {
|
|
314338
|
+
const parsedValue = typeof value === "string" ? (() => {
|
|
314339
|
+
try {
|
|
314340
|
+
return JSON.parse(value);
|
|
314341
|
+
} catch {
|
|
314342
|
+
throw new PayloadValidationError(`Failed to parse JSON for '${fieldName}'`);
|
|
314343
|
+
}
|
|
314344
|
+
})() : value;
|
|
314345
|
+
if (expected === "jsonObject") {
|
|
314346
|
+
if (typeof parsedValue !== "object" || parsedValue === null || Array.isArray(parsedValue)) {
|
|
314347
|
+
throw new PayloadValidationError(`'${fieldName}' must be a JSON object`);
|
|
314348
|
+
}
|
|
314349
|
+
return parsedValue;
|
|
314350
|
+
}
|
|
314351
|
+
if (!Array.isArray(parsedValue)) {
|
|
314352
|
+
throw new PayloadValidationError(`'${fieldName}' must be a JSON array`);
|
|
314353
|
+
}
|
|
314354
|
+
return parsedValue;
|
|
314355
|
+
}
|
|
314356
|
+
|
|
314357
|
+
class PayloadReader {
|
|
314358
|
+
payload;
|
|
314359
|
+
constructor(payload) {
|
|
314360
|
+
this.payload = { ...payload ?? {} };
|
|
314361
|
+
}
|
|
314362
|
+
read(shape) {
|
|
314363
|
+
const prepared = { ...this.payload };
|
|
314364
|
+
for (const [fieldName, spec] of Object.entries(shape)) {
|
|
314365
|
+
const rawValue = prepared[fieldName];
|
|
314366
|
+
const isMissing = rawValue === undefined || rawValue === null;
|
|
314367
|
+
if (isMissing) {
|
|
314368
|
+
if (spec.required) {
|
|
314369
|
+
throw new PayloadValidationError(`'${fieldName}' is required`);
|
|
314370
|
+
}
|
|
314371
|
+
continue;
|
|
314372
|
+
}
|
|
314373
|
+
if (spec.type === "number") {
|
|
314374
|
+
prepared[fieldName] = parseNumberField(rawValue, fieldName);
|
|
314375
|
+
continue;
|
|
314376
|
+
}
|
|
314377
|
+
prepared[fieldName] = parseJsonField(rawValue, fieldName, spec.type);
|
|
314378
|
+
}
|
|
314379
|
+
return prepared;
|
|
314380
|
+
}
|
|
314381
|
+
}
|
|
314382
|
+
|
|
314306
314383
|
// src/server.ts
|
|
314307
314384
|
var packageDef = protoLoader.fromJSON(node_descriptor_default);
|
|
314308
314385
|
var grpcObj = grpc.loadPackageDefinition(packageDef);
|
|
314309
314386
|
var cexNode = grpcObj.cex_broker;
|
|
314387
|
+
function preparePayload(rawPayload, shape) {
|
|
314388
|
+
const payload = new PayloadReader(rawPayload);
|
|
314389
|
+
return payload.read(shape);
|
|
314390
|
+
}
|
|
314310
314391
|
function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, otelMetrics) {
|
|
314311
314392
|
const server = new grpc.Server;
|
|
314312
314393
|
server.addService(cexNode.cex_service.service, {
|
|
@@ -314383,9 +314464,25 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314383
314464
|
amount: import_joi2.default.number().positive().required(),
|
|
314384
314465
|
transactionHash: import_joi2.default.string().required(),
|
|
314385
314466
|
since: import_joi2.default.number(),
|
|
314386
|
-
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
|
|
314467
|
+
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
|
|
314387
314468
|
});
|
|
314388
|
-
|
|
314469
|
+
let payload;
|
|
314470
|
+
try {
|
|
314471
|
+
payload = preparePayload(call.request.payload, {
|
|
314472
|
+
amount: { type: "number", required: true },
|
|
314473
|
+
since: { type: "number" },
|
|
314474
|
+
params: { type: "jsonObject" }
|
|
314475
|
+
});
|
|
314476
|
+
} catch (error2) {
|
|
314477
|
+
if (error2 instanceof PayloadValidationError) {
|
|
314478
|
+
return wrappedCallback({
|
|
314479
|
+
code: grpc.status.INVALID_ARGUMENT,
|
|
314480
|
+
message: error2.message
|
|
314481
|
+
}, null);
|
|
314482
|
+
}
|
|
314483
|
+
throw error2;
|
|
314484
|
+
}
|
|
314485
|
+
const { value, error } = transactionSchema.validate(payload);
|
|
314389
314486
|
if (error) {
|
|
314390
314487
|
return wrappedCallback({
|
|
314391
314488
|
code: grpc.status.INVALID_ARGUMENT,
|
|
@@ -314494,20 +314591,20 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314494
314591
|
args: import_joi2.default.array().items(import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number(), import_joi2.default.boolean(), import_joi2.default.object(), import_joi2.default.array())).default([]),
|
|
314495
314592
|
params: import_joi2.default.object().default({})
|
|
314496
314593
|
});
|
|
314497
|
-
|
|
314498
|
-
const preparedPayload = { ...rawPayload };
|
|
314594
|
+
let preparedPayload;
|
|
314499
314595
|
try {
|
|
314500
|
-
|
|
314501
|
-
|
|
314502
|
-
|
|
314503
|
-
|
|
314504
|
-
|
|
314596
|
+
preparedPayload = preparePayload(call.request.payload, {
|
|
314597
|
+
args: { type: "jsonArray" },
|
|
314598
|
+
params: { type: "jsonObject" }
|
|
314599
|
+
});
|
|
314600
|
+
} catch (error) {
|
|
314601
|
+
if (error instanceof PayloadValidationError) {
|
|
314602
|
+
return wrappedCallback({
|
|
314603
|
+
code: grpc.status.INVALID_ARGUMENT,
|
|
314604
|
+
message: error.message
|
|
314605
|
+
}, null);
|
|
314505
314606
|
}
|
|
314506
|
-
|
|
314507
|
-
return wrappedCallback({
|
|
314508
|
-
code: grpc.status.INVALID_ARGUMENT,
|
|
314509
|
-
message: "ValidationError: Failed to parse JSON for 'args' or 'params'"
|
|
314510
|
-
}, null);
|
|
314607
|
+
throw error;
|
|
314511
314608
|
}
|
|
314512
314609
|
const { value: callValue, error: callError } = callSchema.validate(preparedPayload);
|
|
314513
314610
|
if (callError) {
|
|
@@ -314564,11 +314661,24 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314564
314661
|
const {
|
|
314565
314662
|
value: fetchDepositAddresses,
|
|
314566
314663
|
error: errorFetchDepositAddresses
|
|
314567
|
-
} =
|
|
314664
|
+
} = (() => {
|
|
314665
|
+
try {
|
|
314666
|
+
const payload = preparePayload(call.request.payload, {
|
|
314667
|
+
params: { type: "jsonObject" }
|
|
314668
|
+
});
|
|
314669
|
+
return fetchDepositAddressesSchema.validate(payload);
|
|
314670
|
+
} catch (error) {
|
|
314671
|
+
if (error instanceof PayloadValidationError) {
|
|
314672
|
+
return { value: null, error };
|
|
314673
|
+
}
|
|
314674
|
+
throw error;
|
|
314675
|
+
}
|
|
314676
|
+
})();
|
|
314568
314677
|
if (errorFetchDepositAddresses) {
|
|
314678
|
+
const message = errorFetchDepositAddresses instanceof PayloadValidationError ? errorFetchDepositAddresses.message : `ValidationError: ${errorFetchDepositAddresses.message}`;
|
|
314569
314679
|
return wrappedCallback({
|
|
314570
314680
|
code: grpc.status.INVALID_ARGUMENT,
|
|
314571
|
-
message
|
|
314681
|
+
message
|
|
314572
314682
|
}, null);
|
|
314573
314683
|
}
|
|
314574
314684
|
try {
|
|
@@ -314612,16 +314722,31 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314612
314722
|
recipientAddress: import_joi2.default.string().required(),
|
|
314613
314723
|
amount: import_joi2.default.number().positive().required(),
|
|
314614
314724
|
chain: import_joi2.default.string().required(),
|
|
314615
|
-
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
|
|
314725
|
+
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
|
|
314616
314726
|
});
|
|
314617
|
-
|
|
314727
|
+
let payload;
|
|
314728
|
+
try {
|
|
314729
|
+
payload = preparePayload(call.request.payload, {
|
|
314730
|
+
amount: { type: "number", required: true },
|
|
314731
|
+
params: { type: "jsonObject" }
|
|
314732
|
+
});
|
|
314733
|
+
} catch (error) {
|
|
314734
|
+
if (error instanceof PayloadValidationError) {
|
|
314735
|
+
return wrappedCallback({
|
|
314736
|
+
code: grpc.status.INVALID_ARGUMENT,
|
|
314737
|
+
message: error.message
|
|
314738
|
+
}, null);
|
|
314739
|
+
}
|
|
314740
|
+
throw error;
|
|
314741
|
+
}
|
|
314742
|
+
const { value: transferValue, error: transferError } = transferSchema.validate(payload);
|
|
314618
314743
|
if (transferError) {
|
|
314619
314744
|
return wrappedCallback({
|
|
314620
314745
|
code: grpc.status.INVALID_ARGUMENT,
|
|
314621
314746
|
message: `ValidationError:" ${transferError?.message}`
|
|
314622
314747
|
}, null);
|
|
314623
314748
|
}
|
|
314624
|
-
const transferValidation = validateWithdraw(policy, cex3, transferValue.chain, transferValue.recipientAddress,
|
|
314749
|
+
const transferValidation = validateWithdraw(policy, cex3, transferValue.chain, transferValue.recipientAddress, transferValue.amount, symbol);
|
|
314625
314750
|
if (!transferValidation.valid) {
|
|
314626
314751
|
return wrappedCallback({
|
|
314627
314752
|
code: grpc.status.PERMISSION_DENIED,
|
|
@@ -314637,7 +314762,7 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314637
314762
|
message: `Broker ${cex3} doesnt support this ${transferValue.chain} for token ${symbol}`
|
|
314638
314763
|
}, null);
|
|
314639
314764
|
}
|
|
314640
|
-
const transaction = await broker.withdraw(symbol,
|
|
314765
|
+
const transaction = await broker.withdraw(symbol, transferValue.amount, transferValue.recipientAddress, undefined, { network: transferValue.chain });
|
|
314641
314766
|
log.info(`Withdraw Result: ${JSON.stringify(transaction)}`);
|
|
314642
314767
|
wrappedCallback(null, {
|
|
314643
314768
|
proof: verityProof,
|
|
@@ -314659,9 +314784,25 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314659
314784
|
fromToken: import_joi2.default.string().required(),
|
|
314660
314785
|
toToken: import_joi2.default.string().required(),
|
|
314661
314786
|
price: import_joi2.default.number().positive().required(),
|
|
314662
|
-
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
|
|
314787
|
+
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
|
|
314663
314788
|
});
|
|
314664
|
-
|
|
314789
|
+
let payload;
|
|
314790
|
+
try {
|
|
314791
|
+
payload = preparePayload(call.request.payload, {
|
|
314792
|
+
amount: { type: "number", required: true },
|
|
314793
|
+
price: { type: "number", required: true },
|
|
314794
|
+
params: { type: "jsonObject" }
|
|
314795
|
+
});
|
|
314796
|
+
} catch (error) {
|
|
314797
|
+
if (error instanceof PayloadValidationError) {
|
|
314798
|
+
return wrappedCallback({
|
|
314799
|
+
code: grpc.status.INVALID_ARGUMENT,
|
|
314800
|
+
message: error.message
|
|
314801
|
+
}, null);
|
|
314802
|
+
}
|
|
314803
|
+
throw error;
|
|
314804
|
+
}
|
|
314805
|
+
const { value: orderValue, error: orderError } = createOrderSchema.validate(payload);
|
|
314665
314806
|
if (orderError) {
|
|
314666
314807
|
return wrappedCallback({
|
|
314667
314808
|
code: grpc.status.INVALID_ARGUMENT,
|
|
@@ -314675,14 +314816,14 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314675
314816
|
message: `Invalid CEX key: ${cex3}. Supported keys: ${Object.keys(brokers).join(", ")}`
|
|
314676
314817
|
}, null);
|
|
314677
314818
|
}
|
|
314678
|
-
const resolution = await resolveOrderExecution(policy, broker, cex3, orderValue.fromToken, orderValue.toToken,
|
|
314819
|
+
const resolution = await resolveOrderExecution(policy, broker, cex3, orderValue.fromToken, orderValue.toToken, orderValue.amount, orderValue.price);
|
|
314679
314820
|
if (!resolution.valid || !resolution.symbol || !resolution.side) {
|
|
314680
314821
|
return wrappedCallback({
|
|
314681
314822
|
code: grpc.status.INVALID_ARGUMENT,
|
|
314682
314823
|
message: resolution.error ?? "Order rejected by policy: market or limits not satisfied"
|
|
314683
314824
|
}, null);
|
|
314684
314825
|
}
|
|
314685
|
-
const order = await broker.createOrder(resolution.symbol, orderValue.orderType, resolution.side,
|
|
314826
|
+
const order = await broker.createOrder(resolution.symbol, orderValue.orderType, resolution.side, resolution.amountBase ?? orderValue.amount, orderValue.price, orderValue.params ?? {});
|
|
314686
314827
|
wrappedCallback(null, { result: JSON.stringify({ ...order }) });
|
|
314687
314828
|
} catch (error) {
|
|
314688
314829
|
log.error({ error });
|
|
@@ -314696,9 +314837,23 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314696
314837
|
case Action.GetOrderDetails: {
|
|
314697
314838
|
const getOrderSchema = import_joi2.default.object({
|
|
314698
314839
|
orderId: import_joi2.default.string().required(),
|
|
314699
|
-
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
|
|
314840
|
+
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
|
|
314700
314841
|
});
|
|
314701
|
-
|
|
314842
|
+
let payload;
|
|
314843
|
+
try {
|
|
314844
|
+
payload = preparePayload(call.request.payload, {
|
|
314845
|
+
params: { type: "jsonObject" }
|
|
314846
|
+
});
|
|
314847
|
+
} catch (error) {
|
|
314848
|
+
if (error instanceof PayloadValidationError) {
|
|
314849
|
+
return wrappedCallback({
|
|
314850
|
+
code: grpc.status.INVALID_ARGUMENT,
|
|
314851
|
+
message: error.message
|
|
314852
|
+
}, null);
|
|
314853
|
+
}
|
|
314854
|
+
throw error;
|
|
314855
|
+
}
|
|
314856
|
+
const { value: getOrderValue, error: getOrderError } = getOrderSchema.validate(payload);
|
|
314702
314857
|
if (getOrderError) {
|
|
314703
314858
|
return wrappedCallback({
|
|
314704
314859
|
code: grpc.status.INVALID_ARGUMENT,
|
|
@@ -314736,9 +314891,23 @@ function getServer(policy, brokers, whitelistIps, useVerity, verityProverUrl, ot
|
|
|
314736
314891
|
case Action.CancelOrder: {
|
|
314737
314892
|
const cancelOrderSchema = import_joi2.default.object({
|
|
314738
314893
|
orderId: import_joi2.default.string().required(),
|
|
314739
|
-
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.string()).default({})
|
|
314894
|
+
params: import_joi2.default.object().pattern(import_joi2.default.string(), import_joi2.default.alternatives(import_joi2.default.string(), import_joi2.default.number())).default({})
|
|
314740
314895
|
});
|
|
314741
|
-
|
|
314896
|
+
let payload;
|
|
314897
|
+
try {
|
|
314898
|
+
payload = preparePayload(call.request.payload, {
|
|
314899
|
+
params: { type: "jsonObject" }
|
|
314900
|
+
});
|
|
314901
|
+
} catch (error) {
|
|
314902
|
+
if (error instanceof PayloadValidationError) {
|
|
314903
|
+
return wrappedCallback({
|
|
314904
|
+
code: grpc.status.INVALID_ARGUMENT,
|
|
314905
|
+
message: error.message
|
|
314906
|
+
}, null);
|
|
314907
|
+
}
|
|
314908
|
+
throw error;
|
|
314909
|
+
}
|
|
314910
|
+
const { value: cancelOrderValue, error: cancelOrderError } = cancelOrderSchema.validate(payload);
|
|
314742
314911
|
if (cancelOrderError) {
|
|
314743
314912
|
return wrappedCallback({
|
|
314744
314913
|
code: grpc.status.INVALID_ARGUMENT,
|
|
@@ -315272,7 +315441,7 @@ class CEXBroker {
|
|
|
315272
315441
|
this.policy = loadPolicy(policies);
|
|
315273
315442
|
this.port = config?.port ?? 8086;
|
|
315274
315443
|
} else {
|
|
315275
|
-
this.policy = policies;
|
|
315444
|
+
this.policy = normalizePolicyConfig(policies);
|
|
315276
315445
|
}
|
|
315277
315446
|
if (this.#policyFilePath) {
|
|
315278
315447
|
this.watchPolicyFile(this.#policyFilePath);
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export declare function selectBroker(brokers: {
|
|
|
31
31
|
* Loads and validates policy configuration
|
|
32
32
|
*/
|
|
33
33
|
export declare function loadPolicy(policyPath: string): PolicyConfig;
|
|
34
|
+
export declare function normalizePolicyConfig(policy: PolicyConfig): PolicyConfig;
|
|
34
35
|
export declare function validateWithdraw(policy: PolicyConfig, exchange: string, network: string, recipientAddress: string, _amount: number, _ticker: string): {
|
|
35
36
|
valid: boolean;
|
|
36
37
|
error?: string;
|