@defisaver/ethena-sdk 0.0.4 → 0.0.5
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/cjs/constants/index.d.ts +4 -0
- package/cjs/constants/index.js +7 -0
- package/cjs/exchange/index.d.ts +10 -0
- package/cjs/exchange/index.js +185 -0
- package/cjs/index.d.ts +3 -1
- package/cjs/index.js +5 -1
- package/cjs/positionData/index.d.ts +1 -1
- package/cjs/positionData/index.js +2 -2
- package/cjs/positionData/morpho.d.ts +1 -1
- package/cjs/positionData/morpho.js +15 -7
- package/cjs/types/common.d.ts +10 -0
- package/cjs/types/exchange.d.ts +19 -0
- package/cjs/types/exchange.js +12 -0
- package/cjs/types/index.d.ts +1 -0
- package/cjs/types/index.js +1 -0
- package/esm/constants/index.d.ts +4 -0
- package/esm/constants/index.js +4 -0
- package/esm/exchange/index.d.ts +10 -0
- package/esm/exchange/index.js +176 -0
- package/esm/index.d.ts +3 -1
- package/esm/index.js +3 -1
- package/esm/positionData/index.d.ts +1 -1
- package/esm/positionData/index.js +2 -2
- package/esm/positionData/morpho.d.ts +1 -1
- package/esm/positionData/morpho.js +16 -8
- package/esm/types/common.d.ts +10 -0
- package/esm/types/exchange.d.ts +19 -0
- package/esm/types/exchange.js +9 -0
- package/esm/types/index.d.ts +1 -0
- package/esm/types/index.js +1 -0
- package/package.json +2 -1
- package/src/constants/index.ts +4 -0
- package/src/exchange/index.ts +195 -0
- package/src/index.ts +4 -0
- package/src/positionData/index.ts +2 -2
- package/src/positionData/morpho.ts +17 -8
- package/src/types/common.ts +11 -0
- package/src/types/exchange.ts +21 -0
- package/src/types/index.ts +2 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SLIPPAGE_PERCENT = exports.ZERO_ADDRESS = exports.DFS_API_URL = exports.STABLE_PAIR_FEE_DIVIDER = void 0;
|
|
4
|
+
exports.STABLE_PAIR_FEE_DIVIDER = '10000';
|
|
5
|
+
exports.DFS_API_URL = 'https://fe.defisaver.com';
|
|
6
|
+
exports.ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
7
|
+
exports.SLIPPAGE_PERCENT = 0.05;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NetworkNumber } from '@defisaver/positions-sdk';
|
|
2
|
+
import { OffchainExchanges, PriceData } from '../types';
|
|
3
|
+
export declare const numStringToBytes: (num: number) => string;
|
|
4
|
+
export declare const getBestPrice: (fromAsset: string, toAsset: string, amount: string, userAddress: string, network?: NetworkNumber) => Promise<PriceData>;
|
|
5
|
+
export declare const getExchangeOrder: (fromAsset: string, toAsset: string, amount: string, userAddress: string, minPrice: string, network?: NetworkNumber) => Promise<{
|
|
6
|
+
orderData: (string | string[])[];
|
|
7
|
+
value: string;
|
|
8
|
+
source: OffchainExchanges | "None";
|
|
9
|
+
price: string;
|
|
10
|
+
}>;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getExchangeOrder = exports.getBestPrice = exports.numStringToBytes = void 0;
|
|
16
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
17
|
+
const bn_js_1 = __importDefault(require("bn.js"));
|
|
18
|
+
const positions_sdk_1 = require("@defisaver/positions-sdk");
|
|
19
|
+
const tokens_1 = require("@defisaver/tokens");
|
|
20
|
+
const types_1 = require("../types");
|
|
21
|
+
const constants_1 = require("../constants");
|
|
22
|
+
const getOffchainEmptyData = (source = 'None') => ({
|
|
23
|
+
wrapper: constants_1.ZERO_ADDRESS,
|
|
24
|
+
to: constants_1.ZERO_ADDRESS,
|
|
25
|
+
allowanceTarget: constants_1.ZERO_ADDRESS,
|
|
26
|
+
price: '0',
|
|
27
|
+
priceWithFee: '0',
|
|
28
|
+
protocolFee: '0',
|
|
29
|
+
data: '0x00',
|
|
30
|
+
value: '0',
|
|
31
|
+
gas: '0',
|
|
32
|
+
source,
|
|
33
|
+
});
|
|
34
|
+
const parsePriceWithDecimals = (price, fromDecimals, toDecimals) => new decimal_js_1.default(price)
|
|
35
|
+
.div(Math.pow(10, toDecimals))
|
|
36
|
+
.div(Math.pow(10, (18 - fromDecimals)))
|
|
37
|
+
.toString();
|
|
38
|
+
const formatPriceWithDecimalForContract = (price, fromDecimals, toDecimals) => new decimal_js_1.default(price)
|
|
39
|
+
.mul(Math.pow(10, toDecimals))
|
|
40
|
+
.mul(Math.pow(10, (18 - fromDecimals)))
|
|
41
|
+
.floor()
|
|
42
|
+
.toString();
|
|
43
|
+
const includeFeeInPrice = (price, from, to, fee) => {
|
|
44
|
+
if (from === to)
|
|
45
|
+
return price;
|
|
46
|
+
return new decimal_js_1.default(price).mul(new decimal_js_1.default(1).sub(fee)).toString();
|
|
47
|
+
};
|
|
48
|
+
const excludeFeeFromPrice = (price, from, to, fee) => {
|
|
49
|
+
if (from === to)
|
|
50
|
+
return price;
|
|
51
|
+
return new decimal_js_1.default(price).mul(new decimal_js_1.default(1).add(fee)).toString();
|
|
52
|
+
};
|
|
53
|
+
const parseOffchainPrice = (fromTokenSymbol, fromTokenDecimals, toTokenSymbol, toTokenDecimals, amount, feeDecimal) => {
|
|
54
|
+
const _price = parsePriceWithDecimals(amount, fromTokenDecimals, toTokenDecimals);
|
|
55
|
+
return includeFeeInPrice(_price, fromTokenSymbol, toTokenSymbol, feeDecimal);
|
|
56
|
+
};
|
|
57
|
+
const getFeeDecimal = () => new decimal_js_1.default(1).div(constants_1.STABLE_PAIR_FEE_DIVIDER).toString();
|
|
58
|
+
const numStringToBytes = (num) => {
|
|
59
|
+
const bn = new bn_js_1.default(num.toString()).toTwos(256);
|
|
60
|
+
return bn.toString(16);
|
|
61
|
+
};
|
|
62
|
+
exports.numStringToBytes = numStringToBytes;
|
|
63
|
+
const getPriceFromServer = (fromAsset_1, toAsset_1, amount_1, userAddress_1, ...args_1) => __awaiter(void 0, [fromAsset_1, toAsset_1, amount_1, userAddress_1, ...args_1], void 0, function* (fromAsset, toAsset, amount, userAddress, network = positions_sdk_1.NetworkNumber.Eth, infoOnly = true) {
|
|
64
|
+
const fromAssetData = (0, tokens_1.getAssetInfo)(fromAsset, network);
|
|
65
|
+
const toAssetData = (0, tokens_1.getAssetInfo)(toAsset, network);
|
|
66
|
+
const feeDecimal = getFeeDecimal();
|
|
67
|
+
const excludedSources = ['Balancer_V2', 'Beethovenx'];
|
|
68
|
+
const allSources = Object.values(types_1.OffchainExchanges);
|
|
69
|
+
try {
|
|
70
|
+
const res = yield fetch(`${constants_1.DFS_API_URL}/api/exchange/get-best-price`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: {
|
|
73
|
+
'Content-Type': 'application/json',
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
fromAsset: fromAssetData.address,
|
|
77
|
+
fromAssetDecimals: fromAssetData.decimals,
|
|
78
|
+
fromAssetSymbol: fromAssetData.symbol,
|
|
79
|
+
toAsset: toAssetData.address,
|
|
80
|
+
toAssetDecimals: toAssetData.decimals,
|
|
81
|
+
toAssetSymbol: toAssetData.symbol,
|
|
82
|
+
sources: [...allSources.map(s => s.toLowerCase())],
|
|
83
|
+
chainId: network,
|
|
84
|
+
amount,
|
|
85
|
+
excludedSources,
|
|
86
|
+
infoOnly,
|
|
87
|
+
takerAddress: userAddress,
|
|
88
|
+
account: userAddress,
|
|
89
|
+
noFee: false,
|
|
90
|
+
feeDecimal,
|
|
91
|
+
// temporary fix for paraswap until old exchange service is removed
|
|
92
|
+
shouldFormatParaswapPrice: true,
|
|
93
|
+
}),
|
|
94
|
+
});
|
|
95
|
+
if (!res.ok)
|
|
96
|
+
throw new Error(yield res.text());
|
|
97
|
+
const data = (yield res.json());
|
|
98
|
+
const formattedData = data.map((d, i) => {
|
|
99
|
+
const source = allSources[i];
|
|
100
|
+
if (typeof d === 'string')
|
|
101
|
+
return getOffchainEmptyData(source);
|
|
102
|
+
return {
|
|
103
|
+
wrapper: d.wrapper || constants_1.ZERO_ADDRESS,
|
|
104
|
+
to: d.to || constants_1.ZERO_ADDRESS,
|
|
105
|
+
allowanceTarget: d.allowanceTarget || constants_1.ZERO_ADDRESS,
|
|
106
|
+
protocolFee: d.protocolFee || '0',
|
|
107
|
+
data: d.data || '0x00',
|
|
108
|
+
value: d.value || '0',
|
|
109
|
+
gas: d.gas || '0',
|
|
110
|
+
source: allSources[i],
|
|
111
|
+
price: d.price,
|
|
112
|
+
priceWithFee: +(d.price || '0') > 0
|
|
113
|
+
? parseOffchainPrice(fromAssetData.symbol, fromAssetData.decimals, toAssetData.symbol, toAssetData.decimals, d.price, feeDecimal)
|
|
114
|
+
: '0',
|
|
115
|
+
};
|
|
116
|
+
}).filter((d) => d.wrapper !== constants_1.ZERO_ADDRESS && d.price !== '0').sort((a, b) => (new decimal_js_1.default(a.price).gt(b.price) ? -1 : 1));
|
|
117
|
+
return formattedData;
|
|
118
|
+
}
|
|
119
|
+
catch (_a) {
|
|
120
|
+
return allSources.map(source => getOffchainEmptyData(source));
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const getBestPrice = (fromAsset_1, toAsset_1, amount_1, userAddress_1, ...args_1) => __awaiter(void 0, [fromAsset_1, toAsset_1, amount_1, userAddress_1, ...args_1], void 0, function* (fromAsset, toAsset, amount, userAddress, network = positions_sdk_1.NetworkNumber.Eth) {
|
|
124
|
+
try {
|
|
125
|
+
const formattedData = yield getPriceFromServer(fromAsset, toAsset, amount, userAddress, network);
|
|
126
|
+
return formattedData[0] || getOffchainEmptyData();
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
console.error('Error fetching best price:', e);
|
|
130
|
+
return getOffchainEmptyData();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
exports.getBestPrice = getBestPrice;
|
|
134
|
+
const getExchangeOrder = (fromAsset_1, toAsset_1, amount_1, userAddress_1, minPrice_1, ...args_1) => __awaiter(void 0, [fromAsset_1, toAsset_1, amount_1, userAddress_1, minPrice_1, ...args_1], void 0, function* (fromAsset, toAsset, amount, userAddress, minPrice, network = positions_sdk_1.NetworkNumber.Eth) {
|
|
135
|
+
const fromAssetData = (0, tokens_1.getAssetInfo)(fromAsset, network);
|
|
136
|
+
const toAssetData = (0, tokens_1.getAssetInfo)(toAsset, network);
|
|
137
|
+
const feeDecimal = getFeeDecimal();
|
|
138
|
+
const offchainQuotes = yield getPriceFromServer(fromAsset, toAsset, amount, userAddress, network, false);
|
|
139
|
+
const formattedOffchainQuotes = offchainQuotes.map((quote) => ({
|
|
140
|
+
source: quote.source,
|
|
141
|
+
price: quote.priceWithFee,
|
|
142
|
+
wrapper: quote.wrapper,
|
|
143
|
+
wrapperData: quote.data,
|
|
144
|
+
offchainData: quote,
|
|
145
|
+
}));
|
|
146
|
+
const bestQuote = formattedOffchainQuotes[0];
|
|
147
|
+
const { offchainData, source, price } = bestQuote;
|
|
148
|
+
const minPriceFormatted = new decimal_js_1.default(excludeFeeFromPrice(minPrice, fromAssetData.address, toAssetData.address, feeDecimal))
|
|
149
|
+
.mul(100 - constants_1.SLIPPAGE_PERCENT)
|
|
150
|
+
.div(100)
|
|
151
|
+
.toString();
|
|
152
|
+
const minPriceForContract = formatPriceWithDecimalForContract(minPriceFormatted, fromAssetData.decimals, toAssetData.decimals);
|
|
153
|
+
const offchainDataArray = [
|
|
154
|
+
offchainData.wrapper,
|
|
155
|
+
offchainData.to,
|
|
156
|
+
offchainData.allowanceTarget,
|
|
157
|
+
offchainData.price,
|
|
158
|
+
offchainData.protocolFee,
|
|
159
|
+
offchainData.data,
|
|
160
|
+
];
|
|
161
|
+
const value = offchainData.protocolFee;
|
|
162
|
+
const wrapper = constants_1.ZERO_ADDRESS;
|
|
163
|
+
const wrapperData = `0x${(0, exports.numStringToBytes)(Math.floor(Date.now() / 1000))}`;
|
|
164
|
+
const amountWei = (0, tokens_1.assetAmountInWei)(amount, fromAsset).toString();
|
|
165
|
+
if (offchainData.data === '0x00')
|
|
166
|
+
throw new Error('Offchain data is empty');
|
|
167
|
+
return {
|
|
168
|
+
orderData: [
|
|
169
|
+
fromAssetData.address,
|
|
170
|
+
toAssetData.address,
|
|
171
|
+
amountWei,
|
|
172
|
+
'0',
|
|
173
|
+
minPriceForContract,
|
|
174
|
+
constants_1.STABLE_PAIR_FEE_DIVIDER,
|
|
175
|
+
'0x0000000000000000000000000000000000000000', // set by contract
|
|
176
|
+
wrapper,
|
|
177
|
+
wrapperData,
|
|
178
|
+
offchainDataArray,
|
|
179
|
+
],
|
|
180
|
+
value,
|
|
181
|
+
source,
|
|
182
|
+
price,
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
exports.getExchangeOrder = getExchangeOrder;
|
package/cjs/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import './setup';
|
|
2
2
|
import * as positionData from './positionData';
|
|
3
3
|
import * as marketData from './marketData';
|
|
4
|
+
import * as exchange from './exchange';
|
|
5
|
+
import * as constants from './constants';
|
|
4
6
|
export * from './types';
|
|
5
|
-
export { positionData, marketData, };
|
|
7
|
+
export { positionData, marketData, exchange, constants, };
|
package/cjs/index.js
CHANGED
|
@@ -36,10 +36,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
36
36
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.marketData = exports.positionData = void 0;
|
|
39
|
+
exports.constants = exports.exchange = exports.marketData = exports.positionData = void 0;
|
|
40
40
|
require("./setup");
|
|
41
41
|
const positionData = __importStar(require("./positionData"));
|
|
42
42
|
exports.positionData = positionData;
|
|
43
43
|
const marketData = __importStar(require("./marketData"));
|
|
44
44
|
exports.marketData = marketData;
|
|
45
|
+
const exchange = __importStar(require("./exchange"));
|
|
46
|
+
exports.exchange = exchange;
|
|
47
|
+
const constants = __importStar(require("./constants"));
|
|
48
|
+
exports.constants = constants;
|
|
45
49
|
__exportStar(require("./types"), exports);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { MarketData, NetworkNumber, PositionData } from '../types';
|
|
2
2
|
export declare const getMaxLeverageForSupplyAmount: (marketData: MarketData, supplyAmount: string) => number;
|
|
3
|
-
export declare const getResultingPosition: (marketData: MarketData, supplyAmount: string, leverage: number, rpcUrl: string, network: NetworkNumber) => Promise<PositionData>;
|
|
3
|
+
export declare const getResultingPosition: (marketData: MarketData, supplyAmount: string, leverage: number, userAddress: string, rpcUrl: string, network: NetworkNumber) => Promise<PositionData>;
|
|
@@ -22,10 +22,10 @@ const getMaxLeverageForSupplyAmount = (marketData, supplyAmount) => {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
exports.getMaxLeverageForSupplyAmount = getMaxLeverageForSupplyAmount;
|
|
25
|
-
const getResultingPosition = (marketData, supplyAmount, leverage, rpcUrl, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
+
const getResultingPosition = (marketData, supplyAmount, leverage, userAddress, rpcUrl, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
26
26
|
switch (marketData.market) {
|
|
27
27
|
case types_1.SupportedMarkets.MorphoBlueSUSDeUSDtb_915: {
|
|
28
|
-
return (0, morpho_1.getMorphoResultingPosition)(marketData, supplyAmount, leverage, rpcUrl, network);
|
|
28
|
+
return (0, morpho_1.getMorphoResultingPosition)(marketData, supplyAmount, leverage, userAddress, rpcUrl, network);
|
|
29
29
|
}
|
|
30
30
|
default:
|
|
31
31
|
throw new Error(`Unsupported market: ${marketData.market}`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { NetworkNumber } from '@defisaver/positions-sdk';
|
|
2
2
|
import { MarketData, PositionData } from '../types';
|
|
3
3
|
export declare const getMorphoMaxLeverageForSupplyAmount: (marketData: MarketData, supplyAmount: string) => number;
|
|
4
|
-
export declare const getMorphoResultingPosition: (marketData: MarketData, supplyAmount: string, leverage: number, rpcUrl: string, network: NetworkNumber) => Promise<PositionData>;
|
|
4
|
+
export declare const getMorphoResultingPosition: (marketData: MarketData, supplyAmount: string, leverage: number, userAddress: string, rpcUrl: string, network: NetworkNumber) => Promise<PositionData>;
|
|
@@ -17,6 +17,7 @@ const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
|
17
17
|
const tokens_1 = require("@defisaver/tokens");
|
|
18
18
|
const positions_sdk_1 = require("@defisaver/positions-sdk");
|
|
19
19
|
const viem_1 = require("../services/viem");
|
|
20
|
+
const exchange_1 = require("../exchange");
|
|
20
21
|
const getMaxBoostUsd = (lltv, borrowLimit, debt, targetRatio = 1.01, bufferPercent = 1) => new decimal_js_1.default(targetRatio).mul(debt).sub(borrowLimit)
|
|
21
22
|
.div(new decimal_js_1.default(lltv).sub(targetRatio).toString())
|
|
22
23
|
.mul((100 - bufferPercent) / 100)
|
|
@@ -37,19 +38,19 @@ const getMorphoMaxLeverageForSupplyAmount = (marketData, supplyAmount) => {
|
|
|
37
38
|
return maxLeverage;
|
|
38
39
|
};
|
|
39
40
|
exports.getMorphoMaxLeverageForSupplyAmount = getMorphoMaxLeverageForSupplyAmount;
|
|
40
|
-
const getMorphoResultingPosition = (marketData, supplyAmount, leverage, rpcUrl, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
+
const getMorphoResultingPosition = (marketData, supplyAmount, leverage, userAddress, rpcUrl, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
42
|
const provider = (0, viem_1.getViemProvider)(rpcUrl, network);
|
|
42
43
|
const morphoMarket = positions_sdk_1.markets.MorphoBlueMarkets(network)[positions_sdk_1.MorphoBlueVersions.MorphoBlueSUSDeUSDtb_915];
|
|
43
44
|
const { rate: oracle, assetsData, } = marketData;
|
|
45
|
+
const supplyAsset = Object.values(assetsData).find((asset) => !asset.isDebtAsset);
|
|
46
|
+
const borrowAsset = Object.values(assetsData).find((asset) => asset.isDebtAsset);
|
|
44
47
|
const debtAmount = new decimal_js_1.default(leverage)
|
|
45
48
|
.times(supplyAmount).minus(supplyAmount).times(oracle)
|
|
46
49
|
.toString();
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
const leveragedAmount = new decimal_js_1.default(debtAmount).times(
|
|
50
|
+
const debtAmountWei = (0, tokens_1.assetAmountInWei)(debtAmount, borrowAsset.symbol);
|
|
51
|
+
const { priceWithFee, source } = yield (0, exchange_1.getBestPrice)(borrowAsset.symbol, supplyAsset.symbol, debtAmountWei, userAddress, network);
|
|
52
|
+
const leveragedAmount = new decimal_js_1.default(debtAmount).times(priceWithFee);
|
|
50
53
|
const collIncrease = new decimal_js_1.default(supplyAmount).plus(leveragedAmount).toString();
|
|
51
|
-
const supplyAsset = Object.values(assetsData).find((asset) => !asset.isDebtAsset);
|
|
52
|
-
const borrowAsset = Object.values(assetsData).find((asset) => asset.isDebtAsset);
|
|
53
54
|
const morphoMarketData = yield positions_sdk_1.morphoBlue._getMorphoBlueMarketData(provider, network, morphoMarket);
|
|
54
55
|
const usedAssets = {};
|
|
55
56
|
usedAssets[borrowAsset.symbol] = {
|
|
@@ -73,6 +74,13 @@ const getMorphoResultingPosition = (marketData, supplyAmount, leverage, rpcUrl,
|
|
|
73
74
|
borrowedUsd: '0',
|
|
74
75
|
};
|
|
75
76
|
const aggregatedPosition = positions_sdk_1.helpers.morphoBlueHelpers.getMorphoBlueAggregatedPositionData({ usedAssets, assetsData: morphoMarketData.assetsData, marketInfo: morphoMarketData });
|
|
76
|
-
return Object.assign({
|
|
77
|
+
return Object.assign({ exchangeInfo: {
|
|
78
|
+
price: priceWithFee,
|
|
79
|
+
source,
|
|
80
|
+
sellAsset: borrowAsset.symbol,
|
|
81
|
+
sellAmount: debtAmount,
|
|
82
|
+
buyAsset: supplyAsset.symbol,
|
|
83
|
+
buyAmount: leveragedAmount.toString(),
|
|
84
|
+
}, usedAssets }, aggregatedPosition);
|
|
77
85
|
});
|
|
78
86
|
exports.getMorphoResultingPosition = getMorphoResultingPosition;
|
package/cjs/types/common.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IncentiveData, MMUsedAssets, MorphoBlueAggregatedPositionData, NetworkNumber } from '@defisaver/positions-sdk';
|
|
2
2
|
import { SupportedMarkets } from './markets';
|
|
3
|
+
import { OffchainExchanges } from './exchange';
|
|
3
4
|
export interface AssetData {
|
|
4
5
|
symbol: string;
|
|
5
6
|
address: string;
|
|
@@ -18,7 +19,16 @@ export interface MarketData {
|
|
|
18
19
|
lltv: string;
|
|
19
20
|
rate: string;
|
|
20
21
|
}
|
|
22
|
+
export interface ExchangeInfo {
|
|
23
|
+
price: string;
|
|
24
|
+
source: OffchainExchanges | 'None';
|
|
25
|
+
sellAsset: string;
|
|
26
|
+
sellAmount: string;
|
|
27
|
+
buyAsset: string;
|
|
28
|
+
buyAmount: string;
|
|
29
|
+
}
|
|
21
30
|
export interface PositionData extends MorphoBlueAggregatedPositionData {
|
|
22
31
|
usedAssets: MMUsedAssets;
|
|
32
|
+
exchangeInfo: ExchangeInfo;
|
|
23
33
|
}
|
|
24
34
|
export { NetworkNumber, MMUsedAssets, IncentiveData, };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare enum OffchainExchanges {
|
|
2
|
+
ZeroX = "0x",
|
|
3
|
+
Paraswap = "Paraswap",
|
|
4
|
+
Kyberswap = "Kyberswap",
|
|
5
|
+
OneInch = "1Inch",
|
|
6
|
+
Bebop = "Bebop"
|
|
7
|
+
}
|
|
8
|
+
export interface PriceData {
|
|
9
|
+
price: string;
|
|
10
|
+
priceWithFee: string;
|
|
11
|
+
source: OffchainExchanges | 'None';
|
|
12
|
+
wrapper: string;
|
|
13
|
+
to: string;
|
|
14
|
+
allowanceTarget: string;
|
|
15
|
+
protocolFee: string;
|
|
16
|
+
data: string;
|
|
17
|
+
value: string;
|
|
18
|
+
gas: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OffchainExchanges = void 0;
|
|
4
|
+
var OffchainExchanges;
|
|
5
|
+
(function (OffchainExchanges) {
|
|
6
|
+
OffchainExchanges["ZeroX"] = "0x";
|
|
7
|
+
OffchainExchanges["Paraswap"] = "Paraswap";
|
|
8
|
+
OffchainExchanges["Kyberswap"] = "Kyberswap";
|
|
9
|
+
OffchainExchanges["OneInch"] = "1Inch";
|
|
10
|
+
// Odos = 'Odos',
|
|
11
|
+
OffchainExchanges["Bebop"] = "Bebop";
|
|
12
|
+
})(OffchainExchanges || (exports.OffchainExchanges = OffchainExchanges = {}));
|
package/cjs/types/index.d.ts
CHANGED
package/cjs/types/index.js
CHANGED
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./common"), exports);
|
|
18
18
|
__exportStar(require("./markets"), exports);
|
|
19
|
+
__exportStar(require("./exchange"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NetworkNumber } from '@defisaver/positions-sdk';
|
|
2
|
+
import { OffchainExchanges, PriceData } from '../types';
|
|
3
|
+
export declare const numStringToBytes: (num: number) => string;
|
|
4
|
+
export declare const getBestPrice: (fromAsset: string, toAsset: string, amount: string, userAddress: string, network?: NetworkNumber) => Promise<PriceData>;
|
|
5
|
+
export declare const getExchangeOrder: (fromAsset: string, toAsset: string, amount: string, userAddress: string, minPrice: string, network?: NetworkNumber) => Promise<{
|
|
6
|
+
orderData: (string | string[])[];
|
|
7
|
+
value: string;
|
|
8
|
+
source: OffchainExchanges | "None";
|
|
9
|
+
price: string;
|
|
10
|
+
}>;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import Dec from 'decimal.js';
|
|
11
|
+
import BN from 'bn.js';
|
|
12
|
+
import { NetworkNumber } from '@defisaver/positions-sdk';
|
|
13
|
+
import { assetAmountInWei, getAssetInfo } from '@defisaver/tokens';
|
|
14
|
+
import { OffchainExchanges } from '../types';
|
|
15
|
+
import { DFS_API_URL, SLIPPAGE_PERCENT, STABLE_PAIR_FEE_DIVIDER, ZERO_ADDRESS, } from '../constants';
|
|
16
|
+
const getOffchainEmptyData = (source = 'None') => ({
|
|
17
|
+
wrapper: ZERO_ADDRESS,
|
|
18
|
+
to: ZERO_ADDRESS,
|
|
19
|
+
allowanceTarget: ZERO_ADDRESS,
|
|
20
|
+
price: '0',
|
|
21
|
+
priceWithFee: '0',
|
|
22
|
+
protocolFee: '0',
|
|
23
|
+
data: '0x00',
|
|
24
|
+
value: '0',
|
|
25
|
+
gas: '0',
|
|
26
|
+
source,
|
|
27
|
+
});
|
|
28
|
+
const parsePriceWithDecimals = (price, fromDecimals, toDecimals) => new Dec(price)
|
|
29
|
+
.div(Math.pow(10, toDecimals))
|
|
30
|
+
.div(Math.pow(10, (18 - fromDecimals)))
|
|
31
|
+
.toString();
|
|
32
|
+
const formatPriceWithDecimalForContract = (price, fromDecimals, toDecimals) => new Dec(price)
|
|
33
|
+
.mul(Math.pow(10, toDecimals))
|
|
34
|
+
.mul(Math.pow(10, (18 - fromDecimals)))
|
|
35
|
+
.floor()
|
|
36
|
+
.toString();
|
|
37
|
+
const includeFeeInPrice = (price, from, to, fee) => {
|
|
38
|
+
if (from === to)
|
|
39
|
+
return price;
|
|
40
|
+
return new Dec(price).mul(new Dec(1).sub(fee)).toString();
|
|
41
|
+
};
|
|
42
|
+
const excludeFeeFromPrice = (price, from, to, fee) => {
|
|
43
|
+
if (from === to)
|
|
44
|
+
return price;
|
|
45
|
+
return new Dec(price).mul(new Dec(1).add(fee)).toString();
|
|
46
|
+
};
|
|
47
|
+
const parseOffchainPrice = (fromTokenSymbol, fromTokenDecimals, toTokenSymbol, toTokenDecimals, amount, feeDecimal) => {
|
|
48
|
+
const _price = parsePriceWithDecimals(amount, fromTokenDecimals, toTokenDecimals);
|
|
49
|
+
return includeFeeInPrice(_price, fromTokenSymbol, toTokenSymbol, feeDecimal);
|
|
50
|
+
};
|
|
51
|
+
const getFeeDecimal = () => new Dec(1).div(STABLE_PAIR_FEE_DIVIDER).toString();
|
|
52
|
+
export const numStringToBytes = (num) => {
|
|
53
|
+
const bn = new BN(num.toString()).toTwos(256);
|
|
54
|
+
return bn.toString(16);
|
|
55
|
+
};
|
|
56
|
+
const getPriceFromServer = (fromAsset_1, toAsset_1, amount_1, userAddress_1, ...args_1) => __awaiter(void 0, [fromAsset_1, toAsset_1, amount_1, userAddress_1, ...args_1], void 0, function* (fromAsset, toAsset, amount, userAddress, network = NetworkNumber.Eth, infoOnly = true) {
|
|
57
|
+
const fromAssetData = getAssetInfo(fromAsset, network);
|
|
58
|
+
const toAssetData = getAssetInfo(toAsset, network);
|
|
59
|
+
const feeDecimal = getFeeDecimal();
|
|
60
|
+
const excludedSources = ['Balancer_V2', 'Beethovenx'];
|
|
61
|
+
const allSources = Object.values(OffchainExchanges);
|
|
62
|
+
try {
|
|
63
|
+
const res = yield fetch(`${DFS_API_URL}/api/exchange/get-best-price`, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
},
|
|
68
|
+
body: JSON.stringify({
|
|
69
|
+
fromAsset: fromAssetData.address,
|
|
70
|
+
fromAssetDecimals: fromAssetData.decimals,
|
|
71
|
+
fromAssetSymbol: fromAssetData.symbol,
|
|
72
|
+
toAsset: toAssetData.address,
|
|
73
|
+
toAssetDecimals: toAssetData.decimals,
|
|
74
|
+
toAssetSymbol: toAssetData.symbol,
|
|
75
|
+
sources: [...allSources.map(s => s.toLowerCase())],
|
|
76
|
+
chainId: network,
|
|
77
|
+
amount,
|
|
78
|
+
excludedSources,
|
|
79
|
+
infoOnly,
|
|
80
|
+
takerAddress: userAddress,
|
|
81
|
+
account: userAddress,
|
|
82
|
+
noFee: false,
|
|
83
|
+
feeDecimal,
|
|
84
|
+
// temporary fix for paraswap until old exchange service is removed
|
|
85
|
+
shouldFormatParaswapPrice: true,
|
|
86
|
+
}),
|
|
87
|
+
});
|
|
88
|
+
if (!res.ok)
|
|
89
|
+
throw new Error(yield res.text());
|
|
90
|
+
const data = (yield res.json());
|
|
91
|
+
const formattedData = data.map((d, i) => {
|
|
92
|
+
const source = allSources[i];
|
|
93
|
+
if (typeof d === 'string')
|
|
94
|
+
return getOffchainEmptyData(source);
|
|
95
|
+
return {
|
|
96
|
+
wrapper: d.wrapper || ZERO_ADDRESS,
|
|
97
|
+
to: d.to || ZERO_ADDRESS,
|
|
98
|
+
allowanceTarget: d.allowanceTarget || ZERO_ADDRESS,
|
|
99
|
+
protocolFee: d.protocolFee || '0',
|
|
100
|
+
data: d.data || '0x00',
|
|
101
|
+
value: d.value || '0',
|
|
102
|
+
gas: d.gas || '0',
|
|
103
|
+
source: allSources[i],
|
|
104
|
+
price: d.price,
|
|
105
|
+
priceWithFee: +(d.price || '0') > 0
|
|
106
|
+
? parseOffchainPrice(fromAssetData.symbol, fromAssetData.decimals, toAssetData.symbol, toAssetData.decimals, d.price, feeDecimal)
|
|
107
|
+
: '0',
|
|
108
|
+
};
|
|
109
|
+
}).filter((d) => d.wrapper !== ZERO_ADDRESS && d.price !== '0').sort((a, b) => (new Dec(a.price).gt(b.price) ? -1 : 1));
|
|
110
|
+
return formattedData;
|
|
111
|
+
}
|
|
112
|
+
catch (_a) {
|
|
113
|
+
return allSources.map(source => getOffchainEmptyData(source));
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
export const getBestPrice = (fromAsset_1, toAsset_1, amount_1, userAddress_1, ...args_1) => __awaiter(void 0, [fromAsset_1, toAsset_1, amount_1, userAddress_1, ...args_1], void 0, function* (fromAsset, toAsset, amount, userAddress, network = NetworkNumber.Eth) {
|
|
117
|
+
try {
|
|
118
|
+
const formattedData = yield getPriceFromServer(fromAsset, toAsset, amount, userAddress, network);
|
|
119
|
+
return formattedData[0] || getOffchainEmptyData();
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
console.error('Error fetching best price:', e);
|
|
123
|
+
return getOffchainEmptyData();
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
export const getExchangeOrder = (fromAsset_1, toAsset_1, amount_1, userAddress_1, minPrice_1, ...args_1) => __awaiter(void 0, [fromAsset_1, toAsset_1, amount_1, userAddress_1, minPrice_1, ...args_1], void 0, function* (fromAsset, toAsset, amount, userAddress, minPrice, network = NetworkNumber.Eth) {
|
|
127
|
+
const fromAssetData = getAssetInfo(fromAsset, network);
|
|
128
|
+
const toAssetData = getAssetInfo(toAsset, network);
|
|
129
|
+
const feeDecimal = getFeeDecimal();
|
|
130
|
+
const offchainQuotes = yield getPriceFromServer(fromAsset, toAsset, amount, userAddress, network, false);
|
|
131
|
+
const formattedOffchainQuotes = offchainQuotes.map((quote) => ({
|
|
132
|
+
source: quote.source,
|
|
133
|
+
price: quote.priceWithFee,
|
|
134
|
+
wrapper: quote.wrapper,
|
|
135
|
+
wrapperData: quote.data,
|
|
136
|
+
offchainData: quote,
|
|
137
|
+
}));
|
|
138
|
+
const bestQuote = formattedOffchainQuotes[0];
|
|
139
|
+
const { offchainData, source, price } = bestQuote;
|
|
140
|
+
const minPriceFormatted = new Dec(excludeFeeFromPrice(minPrice, fromAssetData.address, toAssetData.address, feeDecimal))
|
|
141
|
+
.mul(100 - SLIPPAGE_PERCENT)
|
|
142
|
+
.div(100)
|
|
143
|
+
.toString();
|
|
144
|
+
const minPriceForContract = formatPriceWithDecimalForContract(minPriceFormatted, fromAssetData.decimals, toAssetData.decimals);
|
|
145
|
+
const offchainDataArray = [
|
|
146
|
+
offchainData.wrapper,
|
|
147
|
+
offchainData.to,
|
|
148
|
+
offchainData.allowanceTarget,
|
|
149
|
+
offchainData.price,
|
|
150
|
+
offchainData.protocolFee,
|
|
151
|
+
offchainData.data,
|
|
152
|
+
];
|
|
153
|
+
const value = offchainData.protocolFee;
|
|
154
|
+
const wrapper = ZERO_ADDRESS;
|
|
155
|
+
const wrapperData = `0x${numStringToBytes(Math.floor(Date.now() / 1000))}`;
|
|
156
|
+
const amountWei = assetAmountInWei(amount, fromAsset).toString();
|
|
157
|
+
if (offchainData.data === '0x00')
|
|
158
|
+
throw new Error('Offchain data is empty');
|
|
159
|
+
return {
|
|
160
|
+
orderData: [
|
|
161
|
+
fromAssetData.address,
|
|
162
|
+
toAssetData.address,
|
|
163
|
+
amountWei,
|
|
164
|
+
'0',
|
|
165
|
+
minPriceForContract,
|
|
166
|
+
STABLE_PAIR_FEE_DIVIDER,
|
|
167
|
+
'0x0000000000000000000000000000000000000000', // set by contract
|
|
168
|
+
wrapper,
|
|
169
|
+
wrapperData,
|
|
170
|
+
offchainDataArray,
|
|
171
|
+
],
|
|
172
|
+
value,
|
|
173
|
+
source,
|
|
174
|
+
price,
|
|
175
|
+
};
|
|
176
|
+
});
|
package/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import './setup';
|
|
2
2
|
import * as positionData from './positionData';
|
|
3
3
|
import * as marketData from './marketData';
|
|
4
|
+
import * as exchange from './exchange';
|
|
5
|
+
import * as constants from './constants';
|
|
4
6
|
export * from './types';
|
|
5
|
-
export { positionData, marketData, };
|
|
7
|
+
export { positionData, marketData, exchange, constants, };
|
package/esm/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import './setup';
|
|
2
2
|
import * as positionData from './positionData';
|
|
3
3
|
import * as marketData from './marketData';
|
|
4
|
+
import * as exchange from './exchange';
|
|
5
|
+
import * as constants from './constants';
|
|
4
6
|
export * from './types';
|
|
5
|
-
export { positionData, marketData, };
|
|
7
|
+
export { positionData, marketData, exchange, constants, };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { MarketData, NetworkNumber, PositionData } from '../types';
|
|
2
2
|
export declare const getMaxLeverageForSupplyAmount: (marketData: MarketData, supplyAmount: string) => number;
|
|
3
|
-
export declare const getResultingPosition: (marketData: MarketData, supplyAmount: string, leverage: number, rpcUrl: string, network: NetworkNumber) => Promise<PositionData>;
|
|
3
|
+
export declare const getResultingPosition: (marketData: MarketData, supplyAmount: string, leverage: number, userAddress: string, rpcUrl: string, network: NetworkNumber) => Promise<PositionData>;
|
|
@@ -18,10 +18,10 @@ export const getMaxLeverageForSupplyAmount = (marketData, supplyAmount) => {
|
|
|
18
18
|
throw new Error(`Unsupported market: ${marketData.market}`);
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
-
export const getResultingPosition = (marketData, supplyAmount, leverage, rpcUrl, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
export const getResultingPosition = (marketData, supplyAmount, leverage, userAddress, rpcUrl, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
22
|
switch (marketData.market) {
|
|
23
23
|
case SupportedMarkets.MorphoBlueSUSDeUSDtb_915: {
|
|
24
|
-
return getMorphoResultingPosition(marketData, supplyAmount, leverage, rpcUrl, network);
|
|
24
|
+
return getMorphoResultingPosition(marketData, supplyAmount, leverage, userAddress, rpcUrl, network);
|
|
25
25
|
}
|
|
26
26
|
default:
|
|
27
27
|
throw new Error(`Unsupported market: ${marketData.market}`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { NetworkNumber } from '@defisaver/positions-sdk';
|
|
2
2
|
import { MarketData, PositionData } from '../types';
|
|
3
3
|
export declare const getMorphoMaxLeverageForSupplyAmount: (marketData: MarketData, supplyAmount: string) => number;
|
|
4
|
-
export declare const getMorphoResultingPosition: (marketData: MarketData, supplyAmount: string, leverage: number, rpcUrl: string, network: NetworkNumber) => Promise<PositionData>;
|
|
4
|
+
export declare const getMorphoResultingPosition: (marketData: MarketData, supplyAmount: string, leverage: number, userAddress: string, rpcUrl: string, network: NetworkNumber) => Promise<PositionData>;
|
|
@@ -8,9 +8,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import Dec from 'decimal.js';
|
|
11
|
-
import { getAssetInfo } from '@defisaver/tokens';
|
|
11
|
+
import { assetAmountInWei, getAssetInfo } from '@defisaver/tokens';
|
|
12
12
|
import { helpers, markets, morphoBlue, MorphoBlueVersions, } from '@defisaver/positions-sdk';
|
|
13
13
|
import { getViemProvider } from '../services/viem';
|
|
14
|
+
import { getBestPrice } from '../exchange';
|
|
14
15
|
const getMaxBoostUsd = (lltv, borrowLimit, debt, targetRatio = 1.01, bufferPercent = 1) => new Dec(targetRatio).mul(debt).sub(borrowLimit)
|
|
15
16
|
.div(new Dec(lltv).sub(targetRatio).toString())
|
|
16
17
|
.mul((100 - bufferPercent) / 100)
|
|
@@ -30,19 +31,19 @@ export const getMorphoMaxLeverageForSupplyAmount = (marketData, supplyAmount) =>
|
|
|
30
31
|
const maxLeverage = new Dec(supplyAmount).plus(new Dec(maxDebt).times(rate)).div(supplyAmount).toNumber();
|
|
31
32
|
return maxLeverage;
|
|
32
33
|
};
|
|
33
|
-
export const getMorphoResultingPosition = (marketData, supplyAmount, leverage, rpcUrl, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
export const getMorphoResultingPosition = (marketData, supplyAmount, leverage, userAddress, rpcUrl, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
35
|
const provider = getViemProvider(rpcUrl, network);
|
|
35
36
|
const morphoMarket = markets.MorphoBlueMarkets(network)[MorphoBlueVersions.MorphoBlueSUSDeUSDtb_915];
|
|
36
37
|
const { rate: oracle, assetsData, } = marketData;
|
|
38
|
+
const supplyAsset = Object.values(assetsData).find((asset) => !asset.isDebtAsset);
|
|
39
|
+
const borrowAsset = Object.values(assetsData).find((asset) => asset.isDebtAsset);
|
|
37
40
|
const debtAmount = new Dec(leverage)
|
|
38
41
|
.times(supplyAmount).minus(supplyAmount).times(oracle)
|
|
39
42
|
.toString();
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const leveragedAmount = new Dec(debtAmount).times(
|
|
43
|
+
const debtAmountWei = assetAmountInWei(debtAmount, borrowAsset.symbol);
|
|
44
|
+
const { priceWithFee, source } = yield getBestPrice(borrowAsset.symbol, supplyAsset.symbol, debtAmountWei, userAddress, network);
|
|
45
|
+
const leveragedAmount = new Dec(debtAmount).times(priceWithFee);
|
|
43
46
|
const collIncrease = new Dec(supplyAmount).plus(leveragedAmount).toString();
|
|
44
|
-
const supplyAsset = Object.values(assetsData).find((asset) => !asset.isDebtAsset);
|
|
45
|
-
const borrowAsset = Object.values(assetsData).find((asset) => asset.isDebtAsset);
|
|
46
47
|
const morphoMarketData = yield morphoBlue._getMorphoBlueMarketData(provider, network, morphoMarket);
|
|
47
48
|
const usedAssets = {};
|
|
48
49
|
usedAssets[borrowAsset.symbol] = {
|
|
@@ -66,5 +67,12 @@ export const getMorphoResultingPosition = (marketData, supplyAmount, leverage, r
|
|
|
66
67
|
borrowedUsd: '0',
|
|
67
68
|
};
|
|
68
69
|
const aggregatedPosition = helpers.morphoBlueHelpers.getMorphoBlueAggregatedPositionData({ usedAssets, assetsData: morphoMarketData.assetsData, marketInfo: morphoMarketData });
|
|
69
|
-
return Object.assign({
|
|
70
|
+
return Object.assign({ exchangeInfo: {
|
|
71
|
+
price: priceWithFee,
|
|
72
|
+
source,
|
|
73
|
+
sellAsset: borrowAsset.symbol,
|
|
74
|
+
sellAmount: debtAmount,
|
|
75
|
+
buyAsset: supplyAsset.symbol,
|
|
76
|
+
buyAmount: leveragedAmount.toString(),
|
|
77
|
+
}, usedAssets }, aggregatedPosition);
|
|
70
78
|
});
|
package/esm/types/common.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IncentiveData, MMUsedAssets, MorphoBlueAggregatedPositionData, NetworkNumber } from '@defisaver/positions-sdk';
|
|
2
2
|
import { SupportedMarkets } from './markets';
|
|
3
|
+
import { OffchainExchanges } from './exchange';
|
|
3
4
|
export interface AssetData {
|
|
4
5
|
symbol: string;
|
|
5
6
|
address: string;
|
|
@@ -18,7 +19,16 @@ export interface MarketData {
|
|
|
18
19
|
lltv: string;
|
|
19
20
|
rate: string;
|
|
20
21
|
}
|
|
22
|
+
export interface ExchangeInfo {
|
|
23
|
+
price: string;
|
|
24
|
+
source: OffchainExchanges | 'None';
|
|
25
|
+
sellAsset: string;
|
|
26
|
+
sellAmount: string;
|
|
27
|
+
buyAsset: string;
|
|
28
|
+
buyAmount: string;
|
|
29
|
+
}
|
|
21
30
|
export interface PositionData extends MorphoBlueAggregatedPositionData {
|
|
22
31
|
usedAssets: MMUsedAssets;
|
|
32
|
+
exchangeInfo: ExchangeInfo;
|
|
23
33
|
}
|
|
24
34
|
export { NetworkNumber, MMUsedAssets, IncentiveData, };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare enum OffchainExchanges {
|
|
2
|
+
ZeroX = "0x",
|
|
3
|
+
Paraswap = "Paraswap",
|
|
4
|
+
Kyberswap = "Kyberswap",
|
|
5
|
+
OneInch = "1Inch",
|
|
6
|
+
Bebop = "Bebop"
|
|
7
|
+
}
|
|
8
|
+
export interface PriceData {
|
|
9
|
+
price: string;
|
|
10
|
+
priceWithFee: string;
|
|
11
|
+
source: OffchainExchanges | 'None';
|
|
12
|
+
wrapper: string;
|
|
13
|
+
to: string;
|
|
14
|
+
allowanceTarget: string;
|
|
15
|
+
protocolFee: string;
|
|
16
|
+
data: string;
|
|
17
|
+
value: string;
|
|
18
|
+
gas: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export var OffchainExchanges;
|
|
2
|
+
(function (OffchainExchanges) {
|
|
3
|
+
OffchainExchanges["ZeroX"] = "0x";
|
|
4
|
+
OffchainExchanges["Paraswap"] = "Paraswap";
|
|
5
|
+
OffchainExchanges["Kyberswap"] = "Kyberswap";
|
|
6
|
+
OffchainExchanges["OneInch"] = "1Inch";
|
|
7
|
+
// Odos = 'Odos',
|
|
8
|
+
OffchainExchanges["Bebop"] = "Bebop";
|
|
9
|
+
})(OffchainExchanges || (OffchainExchanges = {}));
|
package/esm/types/index.d.ts
CHANGED
package/esm/types/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defisaver/ethena-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "SDK for ethena lev create",
|
|
5
5
|
"main": "./cjs/index.js",
|
|
6
6
|
"module": "./esm/index.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@defisaver/positions-sdk": "^2.1.57",
|
|
29
29
|
"@defisaver/tokens": "^1.7.22",
|
|
30
|
+
"bn.js": "^5.1.3",
|
|
30
31
|
"decimal.js": "^10.6.0",
|
|
31
32
|
"viem": "^2.37.9"
|
|
32
33
|
},
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import Dec from 'decimal.js';
|
|
2
|
+
import BN from 'bn.js';
|
|
3
|
+
import { NetworkNumber } from '@defisaver/positions-sdk';
|
|
4
|
+
import { assetAmountInWei, getAssetInfo } from '@defisaver/tokens';
|
|
5
|
+
import { OffchainExchanges, PriceData } from '../types';
|
|
6
|
+
import {
|
|
7
|
+
DFS_API_URL, SLIPPAGE_PERCENT, STABLE_PAIR_FEE_DIVIDER, ZERO_ADDRESS,
|
|
8
|
+
} from '../constants';
|
|
9
|
+
|
|
10
|
+
const getOffchainEmptyData = (source: OffchainExchanges | 'None' = 'None'): PriceData => ({
|
|
11
|
+
wrapper: ZERO_ADDRESS,
|
|
12
|
+
to: ZERO_ADDRESS,
|
|
13
|
+
allowanceTarget: ZERO_ADDRESS,
|
|
14
|
+
price: '0',
|
|
15
|
+
priceWithFee: '0',
|
|
16
|
+
protocolFee: '0',
|
|
17
|
+
data: '0x00',
|
|
18
|
+
value: '0',
|
|
19
|
+
gas: '0',
|
|
20
|
+
source,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const parsePriceWithDecimals = (price: string, fromDecimals: number, toDecimals: number) => new Dec(price)
|
|
24
|
+
.div(10 ** toDecimals)
|
|
25
|
+
.div(10 ** (18 - fromDecimals))
|
|
26
|
+
.toString();
|
|
27
|
+
|
|
28
|
+
const formatPriceWithDecimalForContract = (price: string, fromDecimals: number, toDecimals: number) => new Dec(price)
|
|
29
|
+
.mul(10 ** toDecimals)
|
|
30
|
+
.mul(10 ** (18 - fromDecimals))
|
|
31
|
+
.floor()
|
|
32
|
+
.toString();
|
|
33
|
+
|
|
34
|
+
const includeFeeInPrice = (price: string, from: string, to: string, fee: string) => {
|
|
35
|
+
if (from === to) return price;
|
|
36
|
+
return new Dec(price).mul(new Dec(1).sub(fee)).toString();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const excludeFeeFromPrice = (price: string, from: string, to: string, fee: string) => {
|
|
40
|
+
if (from === to) return price;
|
|
41
|
+
return new Dec(price).mul(new Dec(1).add(fee)).toString();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const parseOffchainPrice = (
|
|
45
|
+
fromTokenSymbol: string,
|
|
46
|
+
fromTokenDecimals: number,
|
|
47
|
+
toTokenSymbol: string,
|
|
48
|
+
toTokenDecimals: number,
|
|
49
|
+
amount: string,
|
|
50
|
+
feeDecimal: string,
|
|
51
|
+
): string => {
|
|
52
|
+
const _price = parsePriceWithDecimals(amount, fromTokenDecimals, toTokenDecimals);
|
|
53
|
+
return includeFeeInPrice(_price, fromTokenSymbol, toTokenSymbol, feeDecimal);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const getFeeDecimal = () => new Dec(1).div(STABLE_PAIR_FEE_DIVIDER).toString();
|
|
57
|
+
|
|
58
|
+
export const numStringToBytes = (num: number) => {
|
|
59
|
+
const bn = new BN(num.toString()).toTwos(256);
|
|
60
|
+
return bn.toString(16);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const getPriceFromServer = async (fromAsset: string, toAsset: string, amount: string, userAddress: string, network: NetworkNumber = NetworkNumber.Eth, infoOnly: boolean = true) => {
|
|
64
|
+
const fromAssetData = getAssetInfo(fromAsset, network);
|
|
65
|
+
const toAssetData = getAssetInfo(toAsset, network);
|
|
66
|
+
const feeDecimal = getFeeDecimal();
|
|
67
|
+
const excludedSources = ['Balancer_V2', 'Beethovenx'];
|
|
68
|
+
|
|
69
|
+
const allSources = Object.values(OffchainExchanges);
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const res = await fetch(`${DFS_API_URL}/api/exchange/get-best-price`, {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: {
|
|
75
|
+
'Content-Type': 'application/json',
|
|
76
|
+
},
|
|
77
|
+
body: JSON.stringify({
|
|
78
|
+
fromAsset: fromAssetData.address,
|
|
79
|
+
fromAssetDecimals: fromAssetData.decimals,
|
|
80
|
+
fromAssetSymbol: fromAssetData.symbol,
|
|
81
|
+
toAsset: toAssetData.address,
|
|
82
|
+
toAssetDecimals: toAssetData.decimals,
|
|
83
|
+
toAssetSymbol: toAssetData.symbol,
|
|
84
|
+
sources: [...allSources.map(s => s.toLowerCase())],
|
|
85
|
+
chainId: network,
|
|
86
|
+
amount,
|
|
87
|
+
excludedSources,
|
|
88
|
+
infoOnly,
|
|
89
|
+
takerAddress: userAddress,
|
|
90
|
+
account: userAddress,
|
|
91
|
+
noFee: false,
|
|
92
|
+
feeDecimal,
|
|
93
|
+
// temporary fix for paraswap until old exchange service is removed
|
|
94
|
+
shouldFormatParaswapPrice: true,
|
|
95
|
+
}),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!res.ok) throw new Error(await res.text());
|
|
99
|
+
const data = (await res.json());
|
|
100
|
+
|
|
101
|
+
const formattedData: PriceData[] = data.map((d: any, i: number) => {
|
|
102
|
+
const source = allSources[i];
|
|
103
|
+
if (typeof d === 'string') return getOffchainEmptyData(source);
|
|
104
|
+
return {
|
|
105
|
+
wrapper: d.wrapper || ZERO_ADDRESS,
|
|
106
|
+
to: d.to || ZERO_ADDRESS,
|
|
107
|
+
allowanceTarget: d.allowanceTarget || ZERO_ADDRESS,
|
|
108
|
+
protocolFee: d.protocolFee || '0',
|
|
109
|
+
data: d.data || '0x00',
|
|
110
|
+
value: d.value || '0',
|
|
111
|
+
gas: d.gas || '0',
|
|
112
|
+
source: allSources[i],
|
|
113
|
+
price: d.price,
|
|
114
|
+
priceWithFee: +(d.price || '0') > 0
|
|
115
|
+
? parseOffchainPrice(fromAssetData.symbol, fromAssetData.decimals, toAssetData.symbol, toAssetData.decimals, d.price, feeDecimal)
|
|
116
|
+
: '0',
|
|
117
|
+
};
|
|
118
|
+
}).filter((d: PriceData) => d.wrapper !== ZERO_ADDRESS && d.price !== '0').sort((a: PriceData, b: PriceData) => (new Dec(a.price).gt(b.price) ? -1 : 1));
|
|
119
|
+
|
|
120
|
+
return formattedData;
|
|
121
|
+
} catch {
|
|
122
|
+
return allSources.map(source => getOffchainEmptyData(source));
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const getBestPrice = async (fromAsset: string, toAsset: string, amount: string, userAddress: string, network: NetworkNumber = NetworkNumber.Eth): Promise<PriceData> => {
|
|
127
|
+
try {
|
|
128
|
+
const formattedData: PriceData[] = await getPriceFromServer(fromAsset, toAsset, amount, userAddress, network);
|
|
129
|
+
|
|
130
|
+
return formattedData[0] || getOffchainEmptyData();
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.error('Error fetching best price:', e);
|
|
133
|
+
return getOffchainEmptyData();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const getExchangeOrder = async (fromAsset: string, toAsset: string, amount: string, userAddress: string, minPrice: string, network: NetworkNumber = NetworkNumber.Eth) => {
|
|
138
|
+
const fromAssetData = getAssetInfo(fromAsset, network);
|
|
139
|
+
const toAssetData = getAssetInfo(toAsset, network);
|
|
140
|
+
const feeDecimal = getFeeDecimal();
|
|
141
|
+
|
|
142
|
+
const offchainQuotes: PriceData[] = await getPriceFromServer(fromAsset, toAsset, amount, userAddress, network, false);
|
|
143
|
+
|
|
144
|
+
const formattedOffchainQuotes = offchainQuotes.map((quote) => ({
|
|
145
|
+
source: quote.source,
|
|
146
|
+
price: quote.priceWithFee,
|
|
147
|
+
wrapper: quote.wrapper,
|
|
148
|
+
wrapperData: quote.data,
|
|
149
|
+
offchainData: quote,
|
|
150
|
+
}));
|
|
151
|
+
|
|
152
|
+
const bestQuote = formattedOffchainQuotes[0];
|
|
153
|
+
const { offchainData, source, price } = bestQuote;
|
|
154
|
+
|
|
155
|
+
const minPriceFormatted = new Dec(excludeFeeFromPrice(minPrice, fromAssetData.address, toAssetData.address, feeDecimal))
|
|
156
|
+
.mul(100 - SLIPPAGE_PERCENT)
|
|
157
|
+
.div(100)
|
|
158
|
+
.toString();
|
|
159
|
+
const minPriceForContract = formatPriceWithDecimalForContract(minPriceFormatted, fromAssetData.decimals, toAssetData.decimals);
|
|
160
|
+
|
|
161
|
+
const offchainDataArray = [
|
|
162
|
+
offchainData.wrapper,
|
|
163
|
+
offchainData.to,
|
|
164
|
+
offchainData.allowanceTarget,
|
|
165
|
+
offchainData.price,
|
|
166
|
+
offchainData.protocolFee,
|
|
167
|
+
offchainData.data,
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
const value = offchainData.protocolFee;
|
|
171
|
+
|
|
172
|
+
const wrapper = ZERO_ADDRESS;
|
|
173
|
+
const wrapperData = `0x${numStringToBytes(Math.floor(Date.now() / 1000))}`;
|
|
174
|
+
const amountWei = assetAmountInWei(amount, fromAsset).toString();
|
|
175
|
+
|
|
176
|
+
if (offchainData.data === '0x00') throw new Error('Offchain data is empty');
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
orderData: [
|
|
180
|
+
fromAssetData.address,
|
|
181
|
+
toAssetData.address,
|
|
182
|
+
amountWei,
|
|
183
|
+
'0',
|
|
184
|
+
minPriceForContract,
|
|
185
|
+
STABLE_PAIR_FEE_DIVIDER,
|
|
186
|
+
'0x0000000000000000000000000000000000000000', // set by contract
|
|
187
|
+
wrapper,
|
|
188
|
+
wrapperData,
|
|
189
|
+
offchainDataArray,
|
|
190
|
+
],
|
|
191
|
+
value,
|
|
192
|
+
source,
|
|
193
|
+
price,
|
|
194
|
+
};
|
|
195
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -2,10 +2,14 @@ import './setup';
|
|
|
2
2
|
|
|
3
3
|
import * as positionData from './positionData';
|
|
4
4
|
import * as marketData from './marketData';
|
|
5
|
+
import * as exchange from './exchange';
|
|
6
|
+
import * as constants from './constants';
|
|
5
7
|
|
|
6
8
|
export * from './types';
|
|
7
9
|
|
|
8
10
|
export {
|
|
9
11
|
positionData,
|
|
10
12
|
marketData,
|
|
13
|
+
exchange,
|
|
14
|
+
constants,
|
|
11
15
|
};
|
|
@@ -13,10 +13,10 @@ export const getMaxLeverageForSupplyAmount = (marketData: MarketData, supplyAmou
|
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
export const getResultingPosition = async (marketData: MarketData, supplyAmount: string, leverage: number, rpcUrl: string, network: NetworkNumber): Promise<PositionData> => {
|
|
16
|
+
export const getResultingPosition = async (marketData: MarketData, supplyAmount: string, leverage: number, userAddress: string, rpcUrl: string, network: NetworkNumber): Promise<PositionData> => {
|
|
17
17
|
switch (marketData.market) {
|
|
18
18
|
case SupportedMarkets.MorphoBlueSUSDeUSDtb_915: {
|
|
19
|
-
return getMorphoResultingPosition(marketData, supplyAmount, leverage, rpcUrl, network);
|
|
19
|
+
return getMorphoResultingPosition(marketData, supplyAmount, leverage, userAddress, rpcUrl, network);
|
|
20
20
|
}
|
|
21
21
|
default:
|
|
22
22
|
throw new Error(`Unsupported market: ${marketData.market}`);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Dec from 'decimal.js';
|
|
2
|
-
import { getAssetInfo } from '@defisaver/tokens';
|
|
2
|
+
import { assetAmountInWei, getAssetInfo } from '@defisaver/tokens';
|
|
3
3
|
import {
|
|
4
4
|
helpers, markets, MMUsedAssets, morphoBlue, MorphoBlueVersions, NetworkNumber,
|
|
5
5
|
} from '@defisaver/positions-sdk';
|
|
6
6
|
import { AssetData, MarketData, PositionData } from '../types';
|
|
7
7
|
import { getViemProvider } from '../services/viem';
|
|
8
|
+
import { getBestPrice } from '../exchange';
|
|
8
9
|
|
|
9
10
|
const getMaxBoostUsd = (lltv: string, borrowLimit: string, debt: string, targetRatio = 1.01, bufferPercent = 1) => new Dec(targetRatio).mul(debt).sub(borrowLimit)
|
|
10
11
|
.div(new Dec(lltv).sub(targetRatio).toString())
|
|
@@ -38,24 +39,24 @@ export const getMorphoMaxLeverageForSupplyAmount = (marketData: MarketData, supp
|
|
|
38
39
|
return maxLeverage;
|
|
39
40
|
};
|
|
40
41
|
|
|
41
|
-
export const getMorphoResultingPosition = async (marketData: MarketData, supplyAmount: string, leverage: number, rpcUrl: string, network: NetworkNumber): Promise<PositionData> => {
|
|
42
|
+
export const getMorphoResultingPosition = async (marketData: MarketData, supplyAmount: string, leverage: number, userAddress: string, rpcUrl: string, network: NetworkNumber): Promise<PositionData> => {
|
|
42
43
|
const provider = getViemProvider(rpcUrl, network);
|
|
43
44
|
|
|
44
45
|
const morphoMarket = markets.MorphoBlueMarkets(network)[MorphoBlueVersions.MorphoBlueSUSDeUSDtb_915];
|
|
45
46
|
const {
|
|
46
47
|
rate: oracle, assetsData,
|
|
47
48
|
} = marketData;
|
|
49
|
+
const supplyAsset: AssetData = Object.values(assetsData).find((asset) => !asset.isDebtAsset)!;
|
|
50
|
+
const borrowAsset: AssetData = Object.values(assetsData).find((asset) => asset.isDebtAsset)!;
|
|
48
51
|
const debtAmount = new Dec(leverage)
|
|
49
52
|
.times(supplyAmount).minus(supplyAmount).times(oracle)
|
|
50
53
|
.toString();
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
const leveragedAmount = new Dec(debtAmount).times(priceForAmount);
|
|
55
|
-
const collIncrease = new Dec(supplyAmount).plus(leveragedAmount).toString();
|
|
55
|
+
const debtAmountWei = assetAmountInWei(debtAmount, borrowAsset.symbol);
|
|
56
|
+
const { priceWithFee, source } = await getBestPrice(borrowAsset.symbol, supplyAsset.symbol, debtAmountWei, userAddress, network);
|
|
56
57
|
|
|
57
|
-
const
|
|
58
|
-
const
|
|
58
|
+
const leveragedAmount = new Dec(debtAmount).times(priceWithFee);
|
|
59
|
+
const collIncrease = new Dec(supplyAmount).plus(leveragedAmount).toString();
|
|
59
60
|
|
|
60
61
|
const morphoMarketData = await morphoBlue._getMorphoBlueMarketData(provider, network, morphoMarket);
|
|
61
62
|
const usedAssets: MMUsedAssets = {};
|
|
@@ -84,6 +85,14 @@ export const getMorphoResultingPosition = async (marketData: MarketData, supplyA
|
|
|
84
85
|
|
|
85
86
|
const aggregatedPosition = helpers.morphoBlueHelpers.getMorphoBlueAggregatedPositionData({ usedAssets, assetsData: morphoMarketData.assetsData, marketInfo: morphoMarketData });
|
|
86
87
|
return {
|
|
88
|
+
exchangeInfo: {
|
|
89
|
+
price: priceWithFee,
|
|
90
|
+
source,
|
|
91
|
+
sellAsset: borrowAsset.symbol,
|
|
92
|
+
sellAmount: debtAmount,
|
|
93
|
+
buyAsset: supplyAsset.symbol,
|
|
94
|
+
buyAmount: leveragedAmount.toString(),
|
|
95
|
+
},
|
|
87
96
|
usedAssets,
|
|
88
97
|
...aggregatedPosition,
|
|
89
98
|
};
|
package/src/types/common.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
IncentiveData, MMUsedAssets, MorphoBlueAggregatedPositionData, NetworkNumber,
|
|
3
3
|
} from '@defisaver/positions-sdk';
|
|
4
4
|
import { SupportedMarkets } from './markets';
|
|
5
|
+
import { OffchainExchanges } from './exchange';
|
|
5
6
|
|
|
6
7
|
export interface AssetData {
|
|
7
8
|
symbol: string;
|
|
@@ -23,8 +24,18 @@ export interface MarketData {
|
|
|
23
24
|
rate: string;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
export interface ExchangeInfo {
|
|
28
|
+
price: string;
|
|
29
|
+
source: OffchainExchanges | 'None';
|
|
30
|
+
sellAsset: string;
|
|
31
|
+
sellAmount: string;
|
|
32
|
+
buyAsset: string;
|
|
33
|
+
buyAmount: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
export interface PositionData extends MorphoBlueAggregatedPositionData {
|
|
27
37
|
usedAssets: MMUsedAssets;
|
|
38
|
+
exchangeInfo: ExchangeInfo;
|
|
28
39
|
}
|
|
29
40
|
|
|
30
41
|
export {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export enum OffchainExchanges {
|
|
2
|
+
ZeroX = '0x',
|
|
3
|
+
Paraswap = 'Paraswap',
|
|
4
|
+
Kyberswap = 'Kyberswap',
|
|
5
|
+
OneInch = '1Inch',
|
|
6
|
+
// Odos = 'Odos',
|
|
7
|
+
Bebop = 'Bebop',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PriceData {
|
|
11
|
+
price: string;
|
|
12
|
+
priceWithFee: string;
|
|
13
|
+
source: OffchainExchanges | 'None';
|
|
14
|
+
wrapper: string;
|
|
15
|
+
to: string;
|
|
16
|
+
allowanceTarget: string;
|
|
17
|
+
protocolFee: string;
|
|
18
|
+
data: string;
|
|
19
|
+
value: string;
|
|
20
|
+
gas: string;
|
|
21
|
+
}
|
package/src/types/index.ts
CHANGED