mirror of
https://github.com/ZigZagExchange/zksync-lite-market-maker.git
synced 2025-12-17 07:04:23 +01:00
Merge pull request #100 from TrooperCrypto/feat/add-V2.0
add V2.0 order
This commit is contained in:
163
marketmaker.js
163
marketmaker.js
@@ -107,6 +107,7 @@ async function handleMessage(json) {
|
|||||||
"liquidity2",
|
"liquidity2",
|
||||||
"fillstatus",
|
"fillstatus",
|
||||||
"marketinfo",
|
"marketinfo",
|
||||||
|
"error",
|
||||||
].includes(msg.op)
|
].includes(msg.op)
|
||||||
)
|
)
|
||||||
console.log(json.toString());
|
console.log(json.toString());
|
||||||
@@ -132,11 +133,6 @@ async function handleMessage(json) {
|
|||||||
// pass, no old marketInfo
|
// pass, no old marketInfo
|
||||||
}
|
}
|
||||||
MARKETS[marketId] = marketInfo;
|
MARKETS[marketId] = marketInfo;
|
||||||
const newBaseFee = MARKETS[marketId].baseFee;
|
|
||||||
const newQuoteFee = MARKETS[marketId].quoteFee;
|
|
||||||
console.log(
|
|
||||||
`marketinfo ${marketId} - update baseFee ${oldBaseFee} -> ${newBaseFee}, quoteFee ${oldQuoteFee} -> ${newQuoteFee}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (FEE_TOKEN) break;
|
if (FEE_TOKEN) break;
|
||||||
if (
|
if (
|
||||||
@@ -507,15 +503,14 @@ async function sendOrders(pairs = MM_CONFIG.pairs) {
|
|||||||
mmConfig.minSpread -
|
mmConfig.minSpread -
|
||||||
(mmConfig.slippageRate * maxBuySize * i) / buySplits);
|
(mmConfig.slippageRate * maxBuySize * i) / buySplits);
|
||||||
if (["b", "d"].includes(side)) {
|
if (["b", "d"].includes(side)) {
|
||||||
orderArray.push(
|
const order = await getOrderCalldata(
|
||||||
await getOrderCalldata(
|
marketId,
|
||||||
marketId,
|
"b",
|
||||||
"b",
|
buyPrice,
|
||||||
buyPrice,
|
maxBuySize / buySplits - marketInfo.baseFee,
|
||||||
maxBuySize / buySplits - marketInfo.baseFee,
|
expires
|
||||||
expires
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
if (order) orderArray.push(order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let i = 1; i <= sellSplits; i++) {
|
for (let i = 1; i <= sellSplits; i++) {
|
||||||
@@ -525,20 +520,19 @@ async function sendOrders(pairs = MM_CONFIG.pairs) {
|
|||||||
mmConfig.minSpread +
|
mmConfig.minSpread +
|
||||||
(mmConfig.slippageRate * maxSellSize * i) / sellSplits);
|
(mmConfig.slippageRate * maxSellSize * i) / sellSplits);
|
||||||
if (["s", "d"].includes(side)) {
|
if (["s", "d"].includes(side)) {
|
||||||
orderArray.push(
|
const order = await getOrderCalldata(
|
||||||
await getOrderCalldata(
|
marketId,
|
||||||
marketId,
|
"s",
|
||||||
"s",
|
sellPrice,
|
||||||
sellPrice,
|
maxSellSize / sellSplits - marketInfo.baseFee,
|
||||||
maxSellSize / sellSplits - marketInfo.baseFee,
|
expires
|
||||||
expires
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
if (order) orderArray.push(order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign all orders to be canceled
|
// sign all orders to be canceled
|
||||||
const cancelOrderArray = []
|
const cancelOrderArray = [];
|
||||||
const result = MY_ORDERS[marketId].map(async (order) => {
|
const result = MY_ORDERS[marketId].map(async (order) => {
|
||||||
cancelOrderArray.push(await getCancelOrderEntry(order));
|
cancelOrderArray.push(await getCancelOrderEntry(order));
|
||||||
});
|
});
|
||||||
@@ -547,6 +541,8 @@ async function sendOrders(pairs = MM_CONFIG.pairs) {
|
|||||||
// clear all orders, they either failed to cancel or got canceld
|
// clear all orders, they either failed to cancel or got canceld
|
||||||
MY_ORDERS[marketId] = [];
|
MY_ORDERS[marketId] = [];
|
||||||
|
|
||||||
|
if (orderArray.length === 0) return;
|
||||||
|
|
||||||
zigzagws.send(
|
zigzagws.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
op: "submitorder4",
|
op: "submitorder4",
|
||||||
@@ -582,26 +578,18 @@ async function getOrderCalldata(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [baseToken, quoteToken] = marketId.split("-");
|
const [baseToken, quoteToken] = marketId.split("-");
|
||||||
let sellToken, buyToken, sellAmountBN, buyAmountBN, gasFeeBN, balanceBN;
|
let sellToken, buyToken, sellAmountBN, buyAmountBN, balanceBN;
|
||||||
if (side === "s") {
|
if (side === "s") {
|
||||||
sellToken = marketInfo.baseAsset.address;
|
sellToken = marketInfo.baseAsset.address;
|
||||||
buyToken = marketInfo.quoteAsset.address;
|
buyToken = marketInfo.quoteAsset.address;
|
||||||
sellAmountBN = baseAmountBN;
|
sellAmountBN = baseAmountBN;
|
||||||
buyAmountBN = quoteAmountBN;
|
buyAmountBN = quoteAmountBN;
|
||||||
gasFeeBN = ethers.utils.parseUnits(
|
|
||||||
Number(marketInfo.baseFee).toFixed(marketInfo.baseAsset.decimals),
|
|
||||||
marketInfo.baseAsset.decimals
|
|
||||||
);
|
|
||||||
balanceBN = BALANCES[baseToken].value;
|
balanceBN = BALANCES[baseToken].value;
|
||||||
} else {
|
} else {
|
||||||
sellToken = marketInfo.quoteAsset.address;
|
sellToken = marketInfo.quoteAsset.address;
|
||||||
buyToken = marketInfo.baseAsset.address;
|
buyToken = marketInfo.baseAsset.address;
|
||||||
sellAmountBN = quoteAmountBN;
|
sellAmountBN = quoteAmountBN;
|
||||||
buyAmountBN = baseAmountBN;
|
buyAmountBN = baseAmountBN;
|
||||||
gasFeeBN = ethers.utils.parseUnits(
|
|
||||||
Number(marketInfo.quoteFee).toFixed(marketInfo.quoteAsset.decimals),
|
|
||||||
marketInfo.quoteAsset.decimals
|
|
||||||
);
|
|
||||||
balanceBN = BALANCES[quoteToken].value;
|
balanceBN = BALANCES[quoteToken].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,27 +600,40 @@ async function getOrderCalldata(
|
|||||||
.mul(marketInfo.takerVolumeFee * 10000)
|
.mul(marketInfo.takerVolumeFee * 10000)
|
||||||
.div(9999);
|
.div(9999);
|
||||||
|
|
||||||
// size check
|
|
||||||
if (makerVolumeFeeBN.gte(takerVolumeFeeBN)) {
|
|
||||||
balanceBN = balanceBN.sub(gasFeeBN).sub(makerVolumeFeeBN);
|
|
||||||
} else {
|
|
||||||
balanceBN = balanceBN.sub(gasFeeBN).sub(takerVolumeFeeBN);
|
|
||||||
}
|
|
||||||
const delta = sellAmountBN.mul("100000").div(balanceBN).toNumber();
|
|
||||||
if (delta > 100100) {
|
|
||||||
// 100.1 %
|
|
||||||
throw new Error(`Amount exceeds balance.`);
|
|
||||||
}
|
|
||||||
// prevent dust issues
|
|
||||||
if (delta > 99990) {
|
|
||||||
// 99.9 %
|
|
||||||
sellAmountBN = balanceBN;
|
|
||||||
buyAmountBN = buyAmountBN.mul(100000).div(delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
const userAccount = await WALLET.getAddress();
|
const userAccount = await WALLET.getAddress();
|
||||||
let domain, Order, types;
|
let domain, Order, types;
|
||||||
if (Number(marketInfo.contractVersion) === 6) {
|
if (Number(marketInfo.contractVersion) === 6) {
|
||||||
|
let gasFeeBN;
|
||||||
|
if (side === "s") {
|
||||||
|
gasFeeBN = ethers.utils.parseUnits(
|
||||||
|
Number(marketInfo.baseFee).toFixed(marketInfo.baseAsset.decimals),
|
||||||
|
marketInfo.baseAsset.decimals
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
gasFeeBN = ethers.utils.parseUnits(
|
||||||
|
Number(marketInfo.quoteFee).toFixed(marketInfo.quoteAsset.decimals),
|
||||||
|
marketInfo.quoteAsset.decimals
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// size check
|
||||||
|
if (makerVolumeFeeBN.gte(takerVolumeFeeBN)) {
|
||||||
|
balanceBN = balanceBN.sub(gasFeeBN).sub(makerVolumeFeeBN);
|
||||||
|
} else {
|
||||||
|
balanceBN = balanceBN.sub(gasFeeBN).sub(takerVolumeFeeBN);
|
||||||
|
}
|
||||||
|
const delta = sellAmountBN.mul("100000").div(balanceBN).toNumber();
|
||||||
|
if (delta > 100100) {
|
||||||
|
// 100.1 %
|
||||||
|
throw new Error(`Amount exceeds balance.`);
|
||||||
|
}
|
||||||
|
// prevent dust issues
|
||||||
|
if (delta > 99990) {
|
||||||
|
// 99.9 %
|
||||||
|
sellAmountBN = balanceBN;
|
||||||
|
buyAmountBN = buyAmountBN.mul(100000).div(delta);
|
||||||
|
}
|
||||||
|
|
||||||
Order = {
|
Order = {
|
||||||
user: userAccount,
|
user: userAccount,
|
||||||
sellToken: sellToken,
|
sellToken: sellToken,
|
||||||
@@ -670,6 +671,53 @@ async function getOrderCalldata(
|
|||||||
{ name: "salt", type: "uint256" },
|
{ name: "salt", type: "uint256" },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
} else if (Number(marketInfo.contractVersion) == 2.0) {
|
||||||
|
// size check
|
||||||
|
if (makerVolumeFeeBN.gte(takerVolumeFeeBN)) {
|
||||||
|
balanceBN = balanceBN.sub(makerVolumeFeeBN);
|
||||||
|
} else {
|
||||||
|
balanceBN = balanceBN.sub(takerVolumeFeeBN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (balanceBN.lte(0)) return null;
|
||||||
|
|
||||||
|
const delta = sellAmountBN.mul("100000").div(balanceBN).toNumber();
|
||||||
|
if (delta > 100100) {
|
||||||
|
// 100.1 %
|
||||||
|
throw new Error(`Amount exceeds balance.`);
|
||||||
|
}
|
||||||
|
// prevent dust issues
|
||||||
|
if (delta > 99990) {
|
||||||
|
// 99.9 %
|
||||||
|
sellAmountBN = balanceBN;
|
||||||
|
buyAmountBN = buyAmountBN.mul(100000).div(delta);
|
||||||
|
}
|
||||||
|
Order = {
|
||||||
|
user: userAccount,
|
||||||
|
sellToken,
|
||||||
|
buyToken,
|
||||||
|
sellAmount: sellAmountBN.toString(),
|
||||||
|
buyAmount: buyAmountBN.toString(),
|
||||||
|
expirationTimeSeconds: expirationTimeSeconds.toFixed(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
domain = {
|
||||||
|
name: "ZigZag",
|
||||||
|
version: "2.0",
|
||||||
|
chainId: CHAIN_ID,
|
||||||
|
verifyingContract: marketInfo.exchangeAddress,
|
||||||
|
};
|
||||||
|
|
||||||
|
types = {
|
||||||
|
Order: [
|
||||||
|
{ name: "user", type: "address" },
|
||||||
|
{ name: "sellToken", type: "address" },
|
||||||
|
{ name: "buyToken", type: "address" },
|
||||||
|
{ name: "sellAmount", type: "uint256" },
|
||||||
|
{ name: "buyAmount", type: "uint256" },
|
||||||
|
{ name: "expirationTimeSeconds", type: "uint256" },
|
||||||
|
],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const signature = await WALLET._signTypedData(domain, types, Order);
|
const signature = await WALLET._signTypedData(domain, types, Order);
|
||||||
@@ -723,10 +771,10 @@ function getCurrencyInfo(currency) {
|
|||||||
async function getBalances() {
|
async function getBalances() {
|
||||||
const contractAddress = getExchangeAddress();
|
const contractAddress = getExchangeAddress();
|
||||||
const tokens = getCurrencies();
|
const tokens = getCurrencies();
|
||||||
const Promis = tokens.map(async (token) => {
|
for(let i = 0; i < tokens.length; i++) {
|
||||||
|
const token = tokens[i];
|
||||||
BALANCES[token] = await getBalanceOfCurrency(token, contractAddress);
|
BALANCES[token] = await getBalanceOfCurrency(token, contractAddress);
|
||||||
});
|
}
|
||||||
await Promise.all(Promis);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getBalanceOfCurrency(token, contractAddress) {
|
async function getBalanceOfCurrency(token, contractAddress) {
|
||||||
@@ -749,15 +797,18 @@ async function getBalanceOfCurrency(token, contractAddress) {
|
|||||||
ERC20ABI,
|
ERC20ABI,
|
||||||
rollupProvider
|
rollupProvider
|
||||||
);
|
);
|
||||||
result.value = await contract.balanceOf(account);
|
result.value = await contract.balanceOf(account);
|
||||||
if (contractAddress) {
|
if (contractAddress) {
|
||||||
result.allowance = await contract.allowance(account, contractAddress);
|
result.allowance = await contract.allowance(account, contractAddress);
|
||||||
|
|
||||||
|
if (result.value.gte(result.allowance)) {
|
||||||
|
console.log(`Sending approve for ${tokenInfo.address}`)
|
||||||
|
await contract.connect(WALLET).approve(contractAddress, ethers.constants.MaxUint256);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result.allowance = 0;
|
result.allowance = 0;
|
||||||
}
|
}
|
||||||
if (result.value.gte(result.allowance)) {
|
|
||||||
result.value = result.allowance;
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|||||||
Reference in New Issue
Block a user