@d8x/perpetuals-sdk
Version:
Node TypeScript SDK for D8X Perpetual Futures
500 lines • 27.3 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const d8XMath_1 = require("./d8XMath");
const perpetualDataHandler_1 = __importDefault(require("./perpetualDataHandler"));
const writeAccessHandler_1 = __importDefault(require("./writeAccessHandler"));
const buffer_1 = require("buffer");
const accountTrade_1 = __importDefault(require("./accountTrade"));
const ethers_1 = require("ethers");
const constants_1 = require("./constants");
/**
* Functions for white-label partners to determine fees, deposit lots, and sign-up traders.
* This class requires a private key and executes smart-contract interactions that
* require gas-payments.
* @extends WriteAccessHandler
*/
class BrokerTool extends writeAccessHandler_1.default {
/**
* Constructor
* @param {NodeSDKConfig} config Configuration object, see PerpetualDataHandler.
* readSDKConfig.
* @param {string} privateKey Private key of a white-label partner.
* @param {Signer} signer Signer (ignored if a private key is provided)
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // load configuration for Polygon zkEVM (testnet)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* // BrokerTool (authentication required, PK is an environment variable with a private key)
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* // Create a proxy instance to access the blockchain
* await brokTool.createProxyInstance();
* }
* main();
*
*/
constructor(config, signer) {
super(config, signer);
}
// Fee getters
/**
* Determine the exchange fee based on lots, traded volume, and D8X balance of this white-label partner.
* This is the final exchange fee that this white-label partner can offer to traders that trade through him.
* @param {string} poolSymbolName Pool symbol name (e.g. MATIC, USDC, etc).
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // get white-label partner induced fee
* let brokFee = await brokTool.getBrokerInducedFee("MATIC");
* console.log(brokFee);
* }
* main();
*
* @returns {number} Exchange fee for this white-label partner, in decimals (i.e. 0.1% is 0.001)
*/
async getBrokerInducedFee(poolSymbolName, overrides) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
let feeTbps = await this.proxyContract.getBrokerInducedFee(poolId, this.traderAddr, overrides || {});
let fee = Number(feeTbps) / 100000;
if (fee == 0.65535) {
return undefined;
}
return fee;
}
/**
* Determine the exchange fee based on lots purchased by this white-label partner.
* The final exchange fee that this white-label partner can offer to traders that trade through him is equal to
* maximum(brokerTool.getFeeForBrokerDesignation(poolSymbolName), brokerTool.getFeeForBrokerVolume(poolSymbolName), brokerTool.getFeeForBrokerStake())
* @param {string} poolSymbolName Pool symbol name (e.g. MATIC, USDC, etc).
* @param {number=} lots Optional, designation to use if different from this white-label partner's.
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // get white-label partner fee induced by lots
* let brokFeeLots = await brokTool.getFeeForBrokerDesignation("MATIC");
* console.log(brokFeeLots);
* }
* main();
*
* @returns {number} Fee based solely on this white-label partner's designation, in decimals (i.e. 0.1% is 0.001).
*/
async getFeeForBrokerDesignation(poolSymbolName, lots, overrides) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
// check if designation should be taken from the caller or as a parameter
let brokerDesignation;
if (typeof lots == "undefined") {
brokerDesignation = await this.getBrokerDesignation(poolSymbolName);
brokerDesignation = brokerDesignation > 0 ? brokerDesignation : 0;
}
else {
brokerDesignation = lots;
}
let feeTbps = await this.proxyContract.getFeeForBrokerDesignation(brokerDesignation, overrides || {});
return Number(feeTbps) / 100000;
}
/**
* Determine the exchange fee based on volume traded under this white-label partner.
* The final exchange fee that this white-label partner can offer to traders that trade through him is equal to
* maximum(brokerTool.getFeeForBrokerDesignation(poolSymbolName), brokerTool.getFeeForBrokerVolume(poolSymbolName), brokerTool.getFeeForBrokerStake())
* @param {string} poolSymbolName Pool symbol name (e.g. MATIC, USDC, etc).
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // get white-label partner fee induced by volume
* let brokFeeVol = await brokTool.getFeeForBrokerVolume("MATIC");
* console.log(brokFeeVol);
* }
* main();
*
* @returns {number} Fee based solely on a white-label partner's traded volume in the corresponding pool, in decimals (i.e. 0.1% is 0.001).
*/
async getFeeForBrokerVolume(poolSymbolName, overrides) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
let feeTbps = await this.proxyContract.getFeeForBrokerVolume(poolId, this.traderAddr, overrides || {});
return Number(feeTbps) / 100000;
}
/**
* Determine the exchange fee based on the current D8X balance in a white-label partner's wallet.
* The final exchange fee that this white-label partner can offer to traders that trade through him is equal to
* maximum(brokerTool.getFeeForBrokerDesignation(symbol, lots), brokerTool.getFeeForBrokerVolume(symbol), brokerTool.getFeeForBrokerStake)
* @param {string=} brokerAddr Address of the white-label partner in question, if different from the one calling this function.
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // get white-label partner fee induced by staked d8x
* let brokFeeStake = await brokTool.getFeeForBrokerStake("0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B");
* console.log(brokFeeStake);
* }
* main();
*
* @returns {number} Fee based solely on a white-label partner's D8X balance, in decimals (i.e. 0.1% is 0.001).
*/
async getFeeForBrokerStake(brokerAddr, overrides) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
if (typeof brokerAddr == "undefined") {
brokerAddr = this.traderAddr;
}
let feeTbps = await this.proxyContract.getFeeForBrokerStake(brokerAddr, overrides || {});
return Number(feeTbps) / 100000;
}
/**
* Determine exchange fee based on an order and a trader.
* This is the fee charged by the exchange only, excluding the white-label partner fee,
* For regular perpetuals, the result takes into account whether the order given here has been
* signed by a white-label partner or not.
* Use this, for instance, to verify that the fee to be charged for a given order is as expected,
* before and after signing it with brokerTool.signOrder.
* This fee is equal or lower than the white-label partner induced fee, provided the order is properly signed.
*
* For prediction markets, the correct fee is to be applied as tradeamt * fee/s3.
*
* @param {Order} order Order structure. As a minimum the structure needs to
* specify symbol, side, type and quantity.
* @param {string} traderAddr Address of the trader for whom to determine the fee.
* @example
* import { BrokerTool, PerpetualDataHandler, Order } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // get exchange fee based on an order and trader
* let order: Order = {
* symbol: "MATIC-USD-MATIC",
* side: "BUY",
* type: "MARKET",
* quantity: 100,
* executionTimestamp: Date.now()/1000
* };
* let exchFee = await brokTool.determineExchangeFee(order,
* "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B");
* console.log(exchFee);
* }
* main();
*
* @returns {number} Fee in decimals (i.e. 0.1% is 0.001).
*/
async determineExchangeFee(order, traderAddr, overrides) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
if (this.isPredictionMarket(order.symbol)) {
const id = BrokerTool.symbolToPerpetualId(order.symbol, this.symbolToPerpStaticInfo);
const fAmount = order.side == constants_1.BUY_SIDE ? (0, d8XMath_1.floatToABK64x64)(order.quantity) : (0, d8XMath_1.floatToABK64x64)(-order.quantity);
const lvgTdr = order.leverage == undefined ? 0 : Math.round(100 * order.leverage);
const feeTbps = await this.proxyContract.getExchangeFeePrdMkts(id, fAmount, lvgTdr, traderAddr);
return Number(feeTbps) / 100000;
}
// regular markets
let scOrder = accountTrade_1.default.toSmartContractOrder(order, traderAddr, this.symbolToPerpStaticInfo);
let feeTbps = await this.proxyContract.determineExchangeFee(scOrder, overrides || {});
return Number(feeTbps) / 100000;
}
// Volume
/**
* Exponentially weighted EMA of the total trading volume of all trades performed under this white-label partner.
* The weights are chosen so that in average this coincides with the 30 day volume.
* @param {string} poolSymbolName Pool symbol name (e.g. MATIC, USDC, etc).
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // get 30 day volume for white-label partner
* let brokVolume = await brokTool.getCurrentBrokerVolume("MATIC");
* console.log(brokVolume);
* }
* main();
*
* @returns {number} Current trading volume for this white-label partner, in USD.
*/
async getCurrentBrokerVolume(poolSymbolName, overrides) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
let volume = await this.proxyContract.getCurrentBrokerVolume(poolId, this.traderAddr, overrides || {});
return (0, d8XMath_1.ABK64x64ToFloat)(volume);
}
// Lots
/**
* Total amount of collateral currency a white-label partner has to deposit into the default fund to purchase one lot.
* This is equivalent to the price of a lot expressed in a given pool's currency (e.g. MATIC, USDC, etc).
* @param {string} poolSymbolName Pool symbol name (e.g. MATIC, USDC, etc).
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // get lot price
* let brokLotSize = await brokTool.getLotSize("MATIC");
* console.log(brokLotSize);
* }
* main();
*
* @returns {number} White-label partner lot size in a given pool's currency, e.g. in MATIC for poolSymbolName MATIC.
*/
async getLotSize(poolSymbolName, overrides) {
if (this.proxyContract == null) {
throw Error("no proxy contract initialized. Use createProxyInstance().");
}
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
let pool = await this.proxyContract.getLiquidityPool(poolId, overrides || {});
let lot = (0, d8XMath_1.ABK64x64ToFloat)(pool.fBrokerCollateralLotSize);
return lot;
}
/**
* Provides information on how many lots a white-label partner purchased for a given pool.
* This is relevant to determine the white-label partner's fee tier.
* @param {string} poolSymbolName Pool symbol name (e.g. MATIC, USDC, etc).
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // get white-label partner designation
* let brokDesignation = await brokTool.getBrokerDesignation("MATIC");
* console.log(brokDesignation);
* }
* main();
*
* @returns {number} Number of lots purchased by this white-label partner.
*/
async getBrokerDesignation(poolSymbolName, overrides) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
let designation = await this.proxyContract.getBrokerDesignation(poolId, this.traderAddr, overrides || {});
return Number(designation);
}
/**
* Deposit lots to the default fund of a given pool.
* @param {string} poolSymbolName Pool symbol name (e.g. MATIC, USDC, etc).
* @param {number} lots Number of lots to deposit into this pool.
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // deposit to perpetuals
* await brokTool.setAllowance("MATIC");
* let respDeposit = await brokTool.depositBrokerLots("MATIC",1);
* console.log(respDeposit);
* }
* main();
*
* @returns {ContractTransaction} ContractTransaction object.
*/
async depositBrokerLots(poolSymbolName, lots, overrides) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
let tx = await this.proxyContract.depositBrokerLots(poolId, lots, overrides || {});
return tx;
}
// Signatures
/**
* Adds this white-label partner's signature to a user-friendly order. An order signed by a white-label partner is considered
* to be routed through this white-label partner and benefits from the white-label partner's fee conditions.
* @param {Order} order Order to sign. It must contain valid white-label partner fee, white-label partner address, and order deadline.
* @param {string} traderAddr Address of trader submitting the order.
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // sign order
* let order = {symbol: "ETH-USD-MATIC",
* side: "BUY",
* type: "MARKET",
* quantity: 1,
* executionTimestamp: Date.now()/1000
* };
* let signedOrder = await brokTool.signOrder(order, "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
* 0.0001, 1669723339);
* console.log(signedOrder);
* // execute order
* let orderTransaction = await accTrade.order(signedOrder);
* console.log(orderTransaction.hash);
* }
* main();
*
* @returns {Order} An order signed by this white-label partner, which can be submitted directly with AccountTrade.order.
*/
async signOrder(order, traderAddr) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
order.brokerAddr = this.traderAddr;
if (order.deadline == undefined) {
throw Error("brokerTool::signOrder: deadline not defined");
}
order.brokerSignature = await BrokerTool._signOrder(order.symbol, order.brokerFeeTbps, traderAddr, order.deadline, this.signer, this.chainId, this.proxyAddr, this.symbolToPerpStaticInfo);
return order;
}
/**
* Generates a white-label partner's signature of a smart-contract ready order. An order signed by a white-label partner is considered
* to be routed through this white-label partner and benefits from the white-label partner's fee conditions.
* @param {SmartContractOrder} scOrder Order to sign. It must contain valid white-label partner fee, white-label partner address, and order deadline.
* @param {string} traderAddr Address of trader submitting the order.
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* const brokTool = new BrokerTool(config, pk);
* const traderAPI = new TraderInterface(config);
* await brokTool.createProxyInstance();
* await traderAPI.createProxyInstance();
* // sign order
* const order = {symbol: "ETH-USD-MATIC",
* side: "BUY",
* type: "MARKET",
* quantity: 1,
* executionTimestamp: Date.now()/1000
* };
* const scOrder = await traderAPI.createSmartContractOrder(order, "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B")
* const signature = await brokTool.signSCOrder(order, "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
* 0.0001, 1669723339);
* console.log(signature);
* }
* main();
*
* @returns {string} Signature of order.
*/
async signSCOrder(scOrder) {
return await BrokerTool._signOrderFromRawData(scOrder.iPerpetualId, scOrder.brokerFeeTbps, scOrder.traderAddr, scOrder.iDeadline, this.signer, this.chainId, this.proxyAddr);
}
/**
* Creates a signature that a trader can use to place orders with this white-label partner.
* This signature can be used to pass on to a trader who wishes to trade via this SDK or directly on the blockchain.
* @param {string} traderAddr Address of the trader signing up with this white-label partner.
* @param {string} symbol Perpetual that this trader will be trading, of the form ETH-USD-MATIC.
* @param {number} brokerFee White-label partner fee for this trader, in decimals (i.e. 0.1% is 0.001).
* @param {number} deadline Deadline for the order to be executed.
* @returns {string} White-label partner signature approving this trader's fee, symbol, and deadline.
* @ignore
*/
async createSignatureForTrader(traderAddr, symbol, brokerFee, deadline) {
if (this.proxyContract == null || this.signer == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
let brokerFeeTbps = 100000 * brokerFee;
return await BrokerTool._signOrder(symbol, brokerFeeTbps, traderAddr, deadline, this.signer, this.chainId, this.proxyAddr, this.symbolToPerpStaticInfo);
}
static async _signOrderFromRawData(iPerpetualId, brokerFeeTbps, traderAddr, iDeadline, signer, chainId, proxyAddress) {
const NAME = "Perpetual Trade Manager";
const DOMAIN_TYPEHASH = (0, ethers_1.keccak256)(buffer_1.Buffer.from("EIP712Domain(string name,uint256 chainId,address verifyingContract)"));
let abiCoder = new ethers_1.AbiCoder();
let domainSeparator = (0, ethers_1.keccak256)(abiCoder.encode(["bytes32", "bytes32", "uint256", "address"], [DOMAIN_TYPEHASH, (0, ethers_1.keccak256)(buffer_1.Buffer.from(NAME)), chainId, proxyAddress]));
//
const TRADE_BROKER_TYPEHASH = (0, ethers_1.keccak256)(buffer_1.Buffer.from("Order(uint24 iPerpetualId,uint16 brokerFeeTbps,address traderAddr,uint32 iDeadline)"));
let structHash = (0, ethers_1.keccak256)(abiCoder.encode(["bytes32", "uint24", "uint16", "address", "uint32"], [TRADE_BROKER_TYPEHASH, iPerpetualId, brokerFeeTbps, traderAddr, iDeadline]));
let digest = (0, ethers_1.keccak256)(abiCoder.encode(["bytes32", "bytes32"], [domainSeparator, structHash]));
let digestBuffer = buffer_1.Buffer.from(digest.substring(2, digest.length), "hex");
return await signer.signMessage(digestBuffer);
}
static async _signOrder(symbol, brokerFeeTbps, traderAddr, iDeadline, signer, chainId, proxyAddress, symbolToPerpStaticInfo) {
let iPerpetualId = perpetualDataHandler_1.default.symbolToPerpetualId(symbol, symbolToPerpStaticInfo);
return await BrokerTool._signOrderFromRawData(iPerpetualId, brokerFeeTbps, traderAddr, iDeadline, signer, chainId, proxyAddress);
}
// Transfer ownership
/**
* Transfer ownership of a white-label partner's status to a new wallet. This function transfers the values related to
* (i) trading volume and (ii) deposited lots to newAddress. The white-label partner needs in addition to manually transfer
* his D8X holdings to newAddress. Until this transfer is completed, the white-label partner will not have his current designation reflected at newAddress.
* @param {string} poolSymbolName Pool symbol name (e.g. MATIC, USDC, etc).
* @param {string} newAddress The address this white-label partner wants to use from now on.
* @example
* import { BrokerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
* async function main() {
* console.log(BrokerTool);
* // setup (authentication required, PK is an environment variable with a private key)
* const config = PerpetualDataHandler.readSDKConfig("cardona");
* const pk: string = <string>process.env.PK;
* let brokTool = new BrokerTool(config, pk);
* await brokTool.createProxyInstance();
* // transfer ownership
* let respTransferOwnership = await brokTool.transferOwnership("MATIC", "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B");
* console.log(respTransferOwnership);
* }
* main();
*
* @returns {ContractTransaction} ethers transaction object
*/
async transferOwnership(poolSymbolName, newAddress, overrides) {
if (this.proxyContract == null) {
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
}
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
let tx = await this.proxyContract.transferBrokerOwnership(poolId, newAddress, overrides || {});
return tx;
}
}
exports.default = BrokerTool;
//# sourceMappingURL=brokerTool.js.map