Files
web/src/blockchain/orderlib.js
2023-12-09 00:12:24 -04:00

189 lines
5.9 KiB
JavaScript

import {uint32max, uint64max} from "@/misc.js";
import {decodeIEE754, encodeIEE754} from "@/blockchain/common.js";
export const MAX_FRACTION = 65535;
export const NO_CHAIN = uint64max;
export const NO_OCO = uint64max;
export const DISTANT_PAST = 0
export const DISTANT_FUTURE = uint32max
// struct SwapOrder {
// address tokenIn;
// address tokenOut;
// Route route;
// uint256 amount;
// uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed
// bool amountIsInput;
// bool outputDirectlyToOwner;
// uint64 chainOrder; // use NO_CHAIN for no chaining. chainOrder index must be < than this order's index for safety (written first) and chainOrder state must be Template
// Tranche[] tranches;
// }
// struct Route {
// Exchange exchange;
// uint24 fee;
// }
export function newOrder(tokenIn, tokenOut, exchange, fee, amount, amountIsInput, tranches, minAmount=null,
outputToOwner = false, chainOrder = NO_CHAIN) {
if (!tranches)
tranches = [newTranche({marketOrder: true})] // todo this is just a swap: issue warning?
if( minAmount === null )
minAmount = BigInt(amount) / 100n // default to min trade size of 1%
return [tokenIn, tokenOut, [exchange, fee], amount, minAmount, amountIsInput, outputToOwner, chainOrder, tranches]
}
// struct Tranche {
// uint16 fraction;
//
// bool startTimeIsRelative;
// bool endTimeIsRelative;
// bool minIsBarrier;
// bool maxIsBarrier;
// bool marketOrder; // if true, both min and max lines are ignored, and minIntercept is treated as a maximum slippage value (use positive numbers)
// bool _reserved5;
// bool _reserved6;
// bool _reserved7;
// uint8 _reserved8;
// uint32 _reserved16;
//
// uint32 startTime; // use DISTANT_PAST to disable
// uint32 endTime; // use DISTANT_FUTURE to disable
//
// // if intercept and slope are both 0 the line is disabled
// float minIntercept; // if marketOrder==true, this is the (positive) max slippage amount
// float minSlope;
// float maxIntercept;
// float maxSlope;
// }
export function newTranche({
fraction = MAX_FRACTION,
marketOrder = false,
startTimeIsRelative = false,
startTime = DISTANT_PAST,
endTimeIsRelative = false,
endTime = DISTANT_FUTURE,
minIsBarrier = false,
minIntercept = 0,
minSlope = 0,
maxIsBarrier = false,
maxIntercept = 0,
maxSlope = 0,
} = {}) {
if( minIntercept === 0 && minSlope === 0 && maxIntercept === 0 && maxSlope === 0 )
marketOrder = true
if( marketOrder )
minIntercept = encodeIEE754(minIntercept) // this is the slippage field for market orders
else {
minIntercept = encodeIEE754(minIntercept)
minSlope = encodeIEE754(minSlope)
maxIntercept = encodeIEE754(maxIntercept)
maxSlope = encodeIEE754(maxSlope)
}
return {
fraction: Math.min(MAX_FRACTION, Math.round(fraction)), marketOrder,
startTimeIsRelative, startTime, endTimeIsRelative, endTime,
minIsBarrier, minIntercept, minSlope, maxIsBarrier, maxIntercept, maxSlope,
_reserved5: false, _reserved6: false, _reserved7: false, _reserved8: 0, _reserved16: 0,
}
}
export const Exchange = {
UniswapV2: 0,
UniswapV3: 1,
}
export const OrderState = {
Unknown: -1,
Signing: 0,
Underfunded: 1,
Open: 2,
Canceled: 3,
Expired: 4,
Filled: 5,
}
export function orderIsOpen(order) {
return isOpen(order.state)
}
export function isOpen(state) {
return state < 3
}
export function parseOrderStatus(status) {
let [
order,
state,
start,
ocoGroup,
filledIn,
filledOut,
trancheFilledIn,
trancheFilledOut,
] = status
order = parseOrder(order)
filledIn = BigInt(filledIn)
filledOut = BigInt(filledOut)
trancheFilledIn = trancheFilledIn.map((f)=>BigInt(f))
trancheFilledOut = trancheFilledOut.map((f)=>BigInt(f))
return {
order, state, start, ocoGroup, filledIn, filledOut, trancheFilledIn, trancheFilledOut,
}
}
export function parseOrder(order) {
let [
tokenIn,
tokenOut,
route,
amount,
minFillAmount,
amountIsInput,
outputDirectlyToOwner,
chainOrder,
tranches,
] = order
route = parseRoute(route)
amount = BigInt(amount)
minFillAmount = BigInt(minFillAmount)
tranches = tranches.map(parseTranche)
return {
tokenIn, tokenOut, route, amount, minFillAmount, amountIsInput, outputDirectlyToOwner, chainOrder, tranches
}
}
export function parseRoute(route) {
let [exchange, fee] = route
return {exchange, fee} // todo enum?
}
export function parseTranche(tranche) {
let [
fraction,
startTimeIsRelative,
endTimeIsRelative,
minIsBarrier,
maxIsBarrier,
marketOrder,
_reserved5,
_reserved6,
_reserved7,
_reserved8,
_reserved16,
startTime,
endTime,
minIntercept,
minSlope,
maxIntercept,
maxSlope,
] = tranche
minIntercept = decodeIEE754(minIntercept)
minSlope = decodeIEE754(minSlope)
maxIntercept = decodeIEE754(maxIntercept)
maxSlope = decodeIEE754(maxSlope)
return {
fraction, startTimeIsRelative, endTimeIsRelative, minIsBarrier, maxIsBarrier, marketOrder,
startTime, endTime, minIntercept, minSlope, maxIntercept, maxSlope,
}
}