@fleupold/dex-contracts
Version:
Contracts for dFusion multi-token batch auction exchange
121 lines (120 loc) • 5.86 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const BatchExchange = artifacts.require("BatchExchange");
const logging_1 = require("../src/logging");
const log = logging_1.factory.getLogger("scripts.spread_orders");
const bn_js_1 = __importDefault(require("bn.js"));
const readline_1 = __importDefault(require("readline"));
const utilities_1 = require("../test/utilities");
const fee_token_liquidity_1 = require("../src/fee_token_liquidity");
const rl = readline_1.default.createInterface({
input: process.stdin,
output: process.stdout,
});
const promptUser = function (message) {
return new Promise((resolve) => rl.question(message, (answer) => resolve(answer)));
};
const formatAmount = function (amount, token) {
const exponent = token.decimals;
if (exponent) {
return new bn_js_1.default(10).pow(new bn_js_1.default(exponent)).muln(amount);
}
throw new Error("Insufficient token data for amount formatting");
};
const argv = require("yargs")
.option("tokens", {
alias: "t",
type: "string",
describe: "Collection of trusted tokenIds",
coerce: (str) => {
return str.split(",").map((t) => parseInt(t));
},
})
.option("accountId", {
describe: "Account index of the order placer",
type: "int",
default: 0,
})
.option("spread", {
type: "float",
describe: "Percentage increase required for trade (fees not accounted)",
default: 0.25,
})
.option("sellAmount", {
type: "int",
describe: "Maximum sell amount (in full token units)",
default: 1000,
})
.option("validFrom", {
type: "int",
describe: "Number of batches (from current) until order become valid",
default: 3,
})
.option("expiry", {
type: "int",
describe: "Maximum auction batch for which these orders are valid",
default: Math.pow(2, 32) - 1,
})
.demand(["tokens"])
.help("Make sure that you have an RPC connection to the network in consideration. For network configurations, please see truffle-config.js Example usage \n npx truffle exec scripts/place_spread_orders.js --tokens=2,3,4 --accountId 0 --spread 0.3 --validFrom 5")
.version(false).argv;
module.exports = (callback) => __awaiter(void 0, void 0, void 0, function* () {
try {
const instance = yield BatchExchange.deployed();
const accounts = yield web3.eth.getAccounts();
const account = accounts[argv.accountId];
const batch_index = (yield instance.getCurrentBatchId()).toNumber();
log.info("Communicating with exchange for requested token info...");
const token_data = yield fee_token_liquidity_1.fetchTokenInfoFromExchange(instance, argv.tokens, artifacts);
argv.tokens.map((id) => {
const token = token_data.get(id);
log.info(`Found ${token === null || token === void 0 ? void 0 : token.symbol} with ID ${id} at ${token === null || token === void 0 ? void 0 : token.address} having ${token === null || token === void 0 ? void 0 : token.decimals} decimals`);
});
const expectedReturnFactor = 1 + argv.spread / 100;
const sellAmount = argv.sellAmount;
const buyAmount = sellAmount * expectedReturnFactor;
let buyTokens = [];
let sellTokens = [];
let buyAmounts = [];
let sellAmounts = [];
for (let i = 0; i < argv.tokens.length - 1; i++) {
const tokenA = token_data.get(argv.tokens[i]);
for (let j = i + 1; j < argv.tokens.length; j++) {
const tokenB = token_data.get(argv.tokens[j]);
if (tokenA && tokenB) {
buyTokens = buyTokens.concat(tokenA.id, tokenB.id);
sellTokens = sellTokens.concat(tokenB.id, tokenA.id);
buyAmounts = buyAmounts.concat(formatAmount(buyAmount, tokenA), formatAmount(buyAmount, tokenB));
sellAmounts = sellAmounts.concat(formatAmount(sellAmount, tokenB), formatAmount(sellAmount, tokenA));
log.info(`Sell ${sellAmounts.slice(-2)[0]} ${tokenB.symbol} for ${buyAmounts.slice(-2)[0]} ${tokenA.symbol}`);
log.info(`Sell ${sellAmounts.slice(-2)[1]} ${tokenA.symbol} for ${buyAmounts.slice(-2)[1]} ${tokenB.symbol}`);
}
}
}
const validFroms = Array(buyTokens.length).fill(batch_index + argv.validFrom);
const validTos = Array(buyTokens.length).fill(argv.expiry);
const answer = yield promptUser("Are you sure you want to send this transaction to the EVM? [yN] ");
if (answer.toLowerCase() == "y" || answer.toLowerCase() == "yes") {
const ids = yield utilities_1.sendTxAndGetReturnValue(instance.placeValidFromOrders, buyTokens, sellTokens, validFroms, validTos, buyAmounts, sellAmounts, {
from: account,
});
log.info(`Successfully placed spread orders with IDs ${ids}.\n`);
}
callback();
}
catch (error) {
callback(error);
}
});