Skip to content

Commit

Permalink
feat: swap routing WIP🚧
Browse files Browse the repository at this point in the history
- implement swap curve, un/wrap OETH
- add swap route display and selection
- add loading states
- add estimation logging
  • Loading branch information
toniocodo committed Sep 7, 2023
1 parent 747b7a5 commit 51672e4
Show file tree
Hide file tree
Showing 16 changed files with 557 additions and 168 deletions.
31 changes: 16 additions & 15 deletions libs/oeth/swap/src/actions/defaultApi.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { isNilOrEmpty } from '@origin/shared/utils';

import type {
EstimateAmount,
EstimateGas,
Expand All @@ -12,17 +10,18 @@ const estimateAmount: EstimateAmount = async (
_tokenOut,
amountIn,
) => {
if (amountIn === 0n) {
return 0n;
}
console.log('Amount estimation not implemented');

return amountIn;
};

const estimateGas: EstimateGas = async (_tokenIn, _tokenOut, amountIn) => {
if (amountIn === 0n) {
return 0n;
}
const estimateGas: EstimateGas = async (
_tokenIn,
_tokenOut,
_amountIn,
_slippage,
) => {
console.log('Gas estimation not implemented');

return 0n;
};
Expand All @@ -32,20 +31,22 @@ const estimateRoute: EstimateRoute = async (
tokenOut,
amountIn,
route,
slippage,
) => {
if (amountIn === 0n) {
return { ...route, estimatedAmount: 0n, gas: 0n, rate: 0 };
}

const estimatedAmount = await estimateAmount(tokenIn, tokenOut, amountIn);
const [estimatedAmount, gas] = await Promise.all([
estimateAmount(tokenIn, tokenOut, amountIn),
estimateGas(tokenIn, tokenOut, amountIn, slippage),
]);

return { ...route, estimatedAmount, gas: 0n, rate: 0 };
return { ...route, estimatedAmount, gas, rate: 0 };
};

const swap: Swap = async (_tokenIn, _tokenOut, amountIn, route) => {
if (amountIn === 0n || isNilOrEmpty(route)) {
return;
}
const swap: Swap = async (_tokenIn, _tokenOut, _amountIn, _route) => {
console.log('Route swap operation not implemented');
};

export default {
Expand Down
82 changes: 80 additions & 2 deletions libs/oeth/swap/src/actions/mintVault.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,91 @@
import { contracts } from '@origin/shared/contracts';
import { isNilOrEmpty } from '@origin/shared/utils';
import { getAccount, getPublicClient, readContract } from '@wagmi/core';
import { formatUnits } from 'viem';

import type { EstimateGas, EstimateRoute } from '../types';
import type { EstimateAmount } from '../types';

const estimateAmount: EstimateAmount = async (tokenIn, tokenOut, amountIn) => {
const estimateAmount: EstimateAmount = async (tokenIn, _tokenOut, amountIn) => {
if (amountIn === 0n) {
return 0n;
}

return amountIn * 2n;
const data = await readContract({
address: contracts.mainnet.OETHVaultCore.address,
abi: contracts.mainnet.OETHVaultCore.abi,
functionName: 'priceUnitMint',
args: [tokenIn.address],
});

return amountIn * data;
};

const estimateGas: EstimateGas = async (
_tokenIn,
_tokenOut,
amountIn,
slippage,
) => {
let gasEstimate = 0n;

const publicClient = getPublicClient();

if (amountIn === 0n) {
return gasEstimate;
}

const { address } = getAccount();

if (!isNilOrEmpty(address)) {
try {
gasEstimate = await publicClient.estimateContractGas({
address: contracts.mainnet.WOETH.address,
abi: contracts.mainnet.WOETH.abi,
functionName: 'deposit',
args: [amountIn, address],
account: address,
});

return gasEstimate;
} catch {}
}

try {
gasEstimate = 0n;
} catch {}

return gasEstimate;
};

const estimateRoute: EstimateRoute = async (
tokenIn,
tokenOut,
amountIn,
route,
slippage,
) => {
if (amountIn === 0n) {
return { ...route, estimatedAmount: 0n, gas: 0n, rate: 0 };
}

const [estimatedAmount, gas] = await Promise.all([
estimateAmount(tokenIn, tokenOut, amountIn),
estimateGas(tokenIn, tokenOut, amountIn, slippage),
]);

return {
...route,
estimatedAmount,
gas,
rate:
+formatUnits(amountIn, tokenIn.decimals) /
+formatUnits(estimatedAmount, tokenOut.decimals),
};
};

export default {
estimateAmount,
estimateGas,
estimateRoute,
};
98 changes: 95 additions & 3 deletions libs/oeth/swap/src/actions/swapCurve.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import curve from '@curvefi/api';
import { tokens } from '@origin/shared/contracts';
import { waitForTransaction } from '@wagmi/core';
import { formatUnits, parseUnits } from 'viem';

import type { EstimateAmount, EstimateRoute } from '../types';
import type { HexAddress } from '@origin/shared/utils';

import type {
EstimateAmount,
EstimateGas,
EstimateRoute,
Swap,
} from '../types';

const ETH = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';

Expand All @@ -28,22 +37,105 @@ const estimateAmount: EstimateAmount = async (tokenIn, tokenOut, amountIn) => {
return parseUnits(routes.output, tokenOut.decimals);
};

const estimateGas: EstimateGas = async (
tokenIn,
tokenOut,
amountIn,
_slippage,
) => {
let gasEstimate = 0n;

if (amountIn === 0n) {
return gasEstimate;
}

try {
console.time('curve gas estimate');
const res = await curve.router.estimateGas.swap(
tokenIn?.address ?? ETH,
tokenOut?.address ?? ETH,
formatUnits(amountIn, tokenIn.decimals),
);
gasEstimate = parseUnits(res.toString(), tokens.mainnet.ETH.decimals);
console.timeEnd('curve gas estimate');
} catch {}

return gasEstimate;
};

const estimateRoute: EstimateRoute = async (
tokenIn,
tokenOut,
amountIn,
route,
slippage,
) => {
if (amountIn === 0n) {
return { ...route, estimatedAmount: 0n, gas: 0n, rate: 0 };
}

const estimatedAmount = await estimateAmount(tokenIn, tokenOut, amountIn);
const [estimatedAmount, gas] = await Promise.all([
estimateAmount(tokenIn, tokenOut, amountIn),
estimateGas(tokenIn, tokenOut, amountIn, slippage),
]);

return {
...route,
estimatedAmount,
gas,
rate:
+formatUnits(amountIn, tokenIn.decimals) /
+formatUnits(estimatedAmount, tokenOut.decimals),
};
};

const swap: Swap = async (tokenIn, tokenOut, amountIn) => {
if (amountIn === 0n) {
return;
}

return { ...route, estimatedAmount, gas: 0n, rate: 0 };
let isApproved = false;
try {
isApproved = await curve.router.isApproved(
tokenIn?.address ?? ETH,
formatUnits(amountIn, tokenIn.decimals),
);
} catch (e) {
console.log(`swap curve isApproved error!\n${e.message}`);
}

if (!isApproved) {
try {
const [hash] = await curve.router.approve(
tokenIn?.address ?? ETH,
formatUnits(amountIn, tokenIn.decimals),
);
await waitForTransaction({ hash: hash as HexAddress });
// TODO trigger notification
console.log('swap curve approval done!');
} catch (e) {
console.log(`swap curve approve error!\n${e.message}`);
return;
}
}

try {
const { hash } = await curve.router.swap(
tokenIn?.address ?? ETH,
tokenOut?.address ?? ETH,
formatUnits(amountIn, tokenIn.decimals),
);
await waitForTransaction({ hash: hash as HexAddress });
// TODO trigger notification
console.log(`swap curve done!`);
} catch (e) {
// TODO trigger notification
console.log(`swap curve error!\n${e.message}`);
}
};

export default {
estimateAmount,
estimateRoute,
swap,
};
Loading

0 comments on commit 51672e4

Please sign in to comment.