Skip to content

Commit 27f6bd1

Browse files
committed
coded in swap calcs locally
1 parent 7a8d9ce commit 27f6bd1

9 files changed

+459
-343
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"test:scripts": "jest -i --verbose ./test-scripts/*.test.ts"
2424
},
2525
"dependencies": {
26-
"@chasevoorhees/osmonauts-math-decimal": "^1.7.1",
2726
"@cosmjs/amino": "^0.31.3",
2827
"@cosmjs/proto-signing": "^0.31.1",
2928
"@cosmjs/stargate": "^0.31.1",
@@ -39,6 +38,7 @@
3938
"@harmony-js/utils": "^0.1.56",
4039
"@improbable-eng/grpc-web": "^0.13.0",
4140
"@injectivelabs/sdk-ts": "^1.10.58",
41+
"@osmonauts/math": "^1.7.0",
4242
"@pancakeswap/sdk": "^2.4.5",
4343
"@pangolindex/sdk": "^1.1.0",
4444
"@perp/sdk-curie": "^1.16.0",

src/chains/osmosis/osmosis.apr.ts

+1-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
1-
// import { Asset } from '@chain-registry/types';
2-
// import { asset_list, assets } from '@chain-registry/osmosis';
3-
import { calcPoolAprs as _calcPoolAprs } from '@chasevoorhees/osmonauts-math-decimal';
1+
import { calcPoolAprs as _calcPoolAprs } from '@osmonauts/math';
42

53
import { CalcPoolAprsParams } from './osmosis.types';
64

7-
// const osmosisAssets: Asset[] = [
8-
// ...assets.assets,
9-
// ...asset_list.assets,
10-
// ];
11-
125
// need to pass this tokenList from osmosis.ts...
136
export const calcPoolAprs = ({
147
activeGauges,

src/chains/osmosis/osmosis.lp.utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
calcPoolLiquidity,
99
getPoolByGammName as _getPoolByGammName,
1010
convertGammTokenToDollarValue,
11-
} from '@chasevoorhees/osmonauts-math-decimal';
11+
} from '@osmonauts/math';
1212

1313
import {
1414
PriceHash,

src/chains/osmosis/osmosis.prices.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Asset } from '@chain-registry/types';
22

33
import {
44
PriceHash,
5-
} from '@chasevoorhees/osmonauts-math-decimal/dist/types';
5+
} from '@osmonauts/math/dist/types';
66
import { CosmosAsset } from '../cosmos/cosmos-base';
77

88
type CoinGeckoId = string;

src/chains/osmosis/osmosis.swap.ts

+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
import { Asset } from "@chain-registry/types";
2+
import { Decimal } from "decimal.js";
3+
import { BigNumber } from "bignumber.js";
4+
import { CoinDenom, Trade, PrettyPair } from "@osmonauts/math/dist/types";
5+
import { symbolToOsmoDenom } from "@osmonauts/math/dist/utils";
6+
import { SwapAmountInRoute } from "osmojs/dist/codegen/osmosis/poolmanager/v1beta1/swap_route";
7+
import { Pool } from "osmojs/dist/codegen/osmosis/gamm/pool-models/balancer/balancerPool";
8+
import { Coin } from "osmojs/dist/codegen/cosmos/base/v1beta1/coin";
9+
10+
export const routesThroughPools = ({
11+
denom,
12+
trade,
13+
pairs,
14+
}: {
15+
denom: CoinDenom;
16+
trade: Trade;
17+
pairs: PrettyPair[];
18+
}): SwapAmountInRoute[] => {
19+
const sellPool = pairs.find(
20+
(pair) =>
21+
(pair.baseAddress == trade.sell.denom && pair.quoteAddress == denom) ||
22+
(pair.quoteAddress == trade.sell.denom && pair.baseAddress == denom)
23+
);
24+
25+
const buyPool = pairs.find(
26+
(pair) =>
27+
(pair.baseAddress == denom && pair.quoteAddress == trade.buy.denom) ||
28+
(pair.quoteAddress == denom && pair.baseAddress == trade.buy.denom)
29+
);
30+
31+
if (sellPool && buyPool) {
32+
const routes = [
33+
{
34+
poolId: BigInt(sellPool.poolId),
35+
tokenOutDenom: denom,
36+
},
37+
{
38+
poolId: BigInt(buyPool.poolId),
39+
tokenOutDenom: trade.buy.denom,
40+
},
41+
];
42+
43+
return routes;
44+
}
45+
46+
return [];
47+
};
48+
49+
export const getRoutesForTrade = (
50+
assets: Asset[],
51+
{
52+
trade,
53+
pairs,
54+
}: {
55+
trade: Trade;
56+
pairs: PrettyPair[];
57+
}
58+
): SwapAmountInRoute[] => {
59+
const directPool = pairs.find(
60+
(pair) =>
61+
(pair.baseAddress == trade.sell.denom &&
62+
pair.quoteAddress == trade.buy.denom) ||
63+
(pair.quoteAddress == trade.sell.denom &&
64+
pair.baseAddress == trade.buy.denom)
65+
);
66+
67+
if (directPool) {
68+
return [
69+
{
70+
poolId: BigInt(directPool.poolId),
71+
tokenOutDenom: trade.buy.denom,
72+
},
73+
];
74+
}
75+
76+
const osmoRoutes = routesThroughPools({
77+
denom: "uosmo",
78+
trade,
79+
pairs,
80+
});
81+
82+
if (osmoRoutes.length === 2) return osmoRoutes;
83+
84+
const atomRoutes = routesThroughPools({
85+
denom: symbolToOsmoDenom(assets, "ATOM"),
86+
trade,
87+
pairs,
88+
});
89+
90+
if (atomRoutes.length === 2) return atomRoutes;
91+
92+
return [];
93+
};
94+
95+
export const calcAmountWithSlippage = (
96+
amount: string,
97+
slippage: number | string
98+
) => {
99+
const remainingPercentage = new BigNumber(100).minus(slippage).div(100);
100+
return new BigNumber(amount).multipliedBy(remainingPercentage).toString();
101+
};
102+
103+
const one = new BigNumber(1);
104+
105+
const getPoolAsset = (pool: Pool, denom: string) => {
106+
const poolAsset = pool.poolAssets.find(
107+
(asset) => asset?.token && asset.token.denom === denom
108+
);
109+
if (!poolAsset) {
110+
throw new Error(
111+
`Pool ${pool.id} doesn't have the pool asset for ${denom}`
112+
);
113+
}
114+
return { denom, weight: poolAsset.weight, amount: poolAsset.token!.amount };
115+
};
116+
117+
export const calcSpotPrice = (
118+
tokenBalanceIn: BigNumber,
119+
tokenWeightIn: BigNumber,
120+
tokenBalanceOut: BigNumber,
121+
tokenWeightOut: BigNumber,
122+
swapFee: BigNumber
123+
): BigNumber => {
124+
const number = tokenBalanceIn.div(tokenWeightIn);
125+
const denom = tokenBalanceOut.div(tokenWeightOut);
126+
const scale = one.div(one.minus(swapFee));
127+
128+
return number.div(denom).multipliedBy(scale);
129+
};
130+
131+
export const calcOutGivenIn = (
132+
tokenBalanceIn: BigNumber,
133+
tokenWeightIn: BigNumber,
134+
tokenBalanceOut: BigNumber,
135+
tokenWeightOut: BigNumber,
136+
tokenAmountIn: BigNumber,
137+
swapFee: BigNumber
138+
): BigNumber => {
139+
const weightRatio = tokenWeightIn.div(tokenWeightOut);
140+
let adjustedIn = one.minus(swapFee);
141+
adjustedIn = tokenAmountIn.multipliedBy(adjustedIn);
142+
const y = tokenBalanceIn.div(tokenBalanceIn.plus(adjustedIn));
143+
const foo = new BigNumber(new Decimal(y.toString()).pow(new Decimal(weightRatio.toString())).toString());
144+
const bar = one.minus(foo);
145+
return tokenBalanceOut.multipliedBy(bar);
146+
};
147+
148+
export const calcInGivenOut = (
149+
tokenBalanceIn: BigNumber,
150+
tokenWeightIn: BigNumber,
151+
tokenBalanceOut: BigNumber,
152+
tokenWeightOut: BigNumber,
153+
tokenAmountOut: BigNumber,
154+
swapFee: BigNumber
155+
): BigNumber => {
156+
const weightRatio = tokenWeightOut.div(tokenWeightIn);
157+
const diff = tokenBalanceOut.minus(tokenAmountOut);
158+
const y = tokenBalanceOut.div(diff);
159+
let foo = new BigNumber(new Decimal(y.toString()).pow(new Decimal(weightRatio.toString())).toString());
160+
foo = foo.minus(one);
161+
const tokenAmountIn = one.minus(swapFee);
162+
return tokenBalanceIn.multipliedBy(foo).div(tokenAmountIn);
163+
};
164+
165+
export const calcPriceImpactGivenIn = (
166+
tokenIn: Coin,
167+
tokenOutDenom: string,
168+
pool: Pool
169+
) => {
170+
const inPoolAsset = getPoolAsset(pool, tokenIn.denom);
171+
const outPoolAsset = getPoolAsset(pool, tokenOutDenom);
172+
173+
const swapFee = new BigNumber(pool.poolParams?.swapFee || 0).shiftedBy(-18);
174+
175+
const beforeSpotPriceInOverOut = calcSpotPrice(
176+
new BigNumber(inPoolAsset.amount),
177+
new BigNumber(inPoolAsset.weight),
178+
new BigNumber(outPoolAsset.amount),
179+
new BigNumber(outPoolAsset.weight),
180+
swapFee
181+
);
182+
183+
const tokenOutAmount = calcOutGivenIn(
184+
new BigNumber(inPoolAsset.amount),
185+
new BigNumber(inPoolAsset.weight),
186+
new BigNumber(outPoolAsset.amount),
187+
new BigNumber(outPoolAsset.weight),
188+
new BigNumber(tokenIn.amount),
189+
swapFee
190+
).decimalPlaces(0);
191+
192+
const effectivePrice = new BigNumber(tokenIn.amount).div(tokenOutAmount);
193+
const priceImpact = effectivePrice.div(beforeSpotPriceInOverOut).minus(one);
194+
195+
return priceImpact.toString();
196+
};
197+
198+
export const calcPriceImpactGivenOut = (
199+
tokenOut: Coin,
200+
tokenInDenom: string,
201+
pool: Pool
202+
) => {
203+
const inPoolAsset = getPoolAsset(pool, tokenInDenom);
204+
const outPoolAsset = getPoolAsset(pool, tokenOut.denom);
205+
206+
const swapFee = new BigNumber(pool.poolParams?.swapFee || 0).shiftedBy(-18);
207+
208+
const beforeSpotPriceInOverOut = calcSpotPrice(
209+
new BigNumber(inPoolAsset.amount),
210+
new BigNumber(inPoolAsset.weight),
211+
new BigNumber(outPoolAsset.amount),
212+
new BigNumber(outPoolAsset.weight),
213+
swapFee
214+
);
215+
216+
const tokenInAmount = calcInGivenOut(
217+
new BigNumber(inPoolAsset.amount),
218+
new BigNumber(inPoolAsset.weight),
219+
new BigNumber(outPoolAsset.amount),
220+
new BigNumber(outPoolAsset.weight),
221+
new BigNumber(tokenOut.amount),
222+
swapFee
223+
).decimalPlaces(0);
224+
225+
const effectivePrice = new BigNumber(tokenInAmount).div(tokenOut.amount);
226+
const priceImpact = effectivePrice.div(beforeSpotPriceInOverOut).minus(one);
227+
228+
return priceImpact.toString();
229+
};

src/chains/osmosis/osmosis.ts

+28-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @ts-nocheck
1+
@ts-nocheck
22
// OSMO message composer classes don't quite match up with what the RPC/Go backend actually accepts.
33

44
import axios from 'axios';
@@ -33,18 +33,20 @@ import {
3333

3434
import { OsmosisConfig } from './osmosis.config';
3535
import {
36-
convertDollarValueToCoins,
37-
convertDollarValueToShares,
38-
calcShareOutAmount,
39-
makePoolPairs,
4036
getRoutesForTrade,
4137
calcAmountWithSlippage,
4238
calcPriceImpactGivenIn,
4339
calcPriceImpactGivenOut
44-
} from '@chasevoorhees/osmonauts-math-decimal';
40+
} from './osmosis.swap';
41+
import {
42+
convertDollarValueToCoins,
43+
convertDollarValueToShares,
44+
calcShareOutAmount,
45+
makePoolPairs,
46+
} from '@osmonauts/math';
4547
import type {
4648
PrettyPair,
47-
} from "@chasevoorhees/osmonauts-math-decimal/dist/types";
49+
} from "@osmonauts/math/dist/types";
4850
import NodeCache from 'node-cache';
4951
import { TradeInfo } from './osmosis.controllers';
5052
import { PoolAsset } from 'osmojs/dist/codegen/osmosis/gamm/pool-models/balancer/balancerPool';
@@ -55,7 +57,7 @@ import { getCoinGeckoPrices, getImperatorPriceHash } from './osmosis.prices';
5557
import { GasPrice, IndexedTx, calculateFee, setupIbcExtension } from '@cosmjs/stargate';
5658
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
5759
import { TokensRequest, TokensResponse } from '../../network/network.requests';
58-
import { TransferRequest } from '../../chains/injective/injective.requests';
60+
import { TransferRequest } from '../../services/common-interfaces';
5961
import { ConfigManagerCertPassphrase } from '../../services/config-manager-cert-passphrase';
6062

6163
const crypto = require('crypto').webcrypto;
@@ -91,7 +93,7 @@ export class Osmosis {
9193
private signingClient?: any;
9294
public chainId: string;
9395
protected tokenList: CosmosAsset[] = [];
94-
protected tokenMap: Record<string, CosmosAsset> = {}; // all the other connectors are using this instead of/as tokenMap - so changing in cosmos-base too
96+
protected tokenMap: Record<string, CosmosAsset> = {};
9597
public chainName: string;
9698
public rpcURL: string;
9799

@@ -548,7 +550,7 @@ export class Osmosis {
548550
}
549551
}
550552
} catch (err) {
551-
//console.debug(err);
553+
//can skip this - will be added by raw denom
552554
}
553555

554556
// Not all tokens are added in the registry so we use the denom if the token doesn't exist
@@ -700,6 +702,7 @@ export class Osmosis {
700702

701703
// so far we have pools, routes, and token info...
702704
let route_length_1_pool_swapFee = '';
705+
// leaving some unreads in here in case they want to be delivered later
703706
let priceImpact = '';
704707

705708
if (new BigNumber(tokenIn.amount).isEqualTo(0)) {
@@ -881,7 +884,21 @@ export class Osmosis {
881884
'tokenOutMinAmount': tokenOutMinAmount.toString(),
882885
});
883886

884-
const fee = FEES.osmosis.swapExactAmountIn(this.feeTier);
887+
const fee = FEES.osmosis.swapExactAmountIn(feeTier);
888+
889+
const gasEstimation = await this.signingClient.simulate(
890+
address,
891+
[msg],
892+
);
893+
if (!gasEstimation) {
894+
throw new Error('estimate gas error');
895+
}
896+
897+
const calcedFee = calculateFee(
898+
Math.round(gasEstimation * (gasAdjustment || 1.5)),
899+
GasPrice.fromString(this.manualGasPrice)
900+
);
901+
if (calcedFee){}
885902

886903
try {
887904
const res = await this.signingClient.signAndBroadcast(address, [msg], fee);

0 commit comments

Comments
 (0)