Add terra ust for quoting
This commit is contained in:
parent
29704b701d
commit
0c50e93dc0
|
@ -1,41 +1,92 @@
|
|||
import { ethers } from "ethers";
|
||||
import { UniEvmToken } from "./uniswap-core";
|
||||
import { QuickswapRouter } from "./quickswap";
|
||||
import { SingleAmmSwapRouter as UniswapV3Router } from "./uniswap-v3";
|
||||
|
||||
import { QuickswapRouter as MaticRouter } from "./quickswap";
|
||||
import { UniswapV3Router as EthRouter } from "./uniswap-v3";
|
||||
import { TerraUstTransfer as UstRouter } from "./terra-ust-transfer";
|
||||
import {
|
||||
ETH_NETWORK_CHAIN_ID,
|
||||
POLYGON_NETWORK_CHAIN_ID,
|
||||
WETH_TOKEN_INFO,
|
||||
WMATIC_TOKEN_INFO,
|
||||
UST_TOKEN_INFO,
|
||||
WORMHOLE_CHAIN_ID_ETHEREUM,
|
||||
WORMHOLE_CHAIN_ID_POLYGON,
|
||||
WORMHOLE_CHAIN_ID_TERRA,
|
||||
} from "../utils/consts";
|
||||
import { addFixedAmounts, subtractFixedAmounts } from "../utils/math";
|
||||
import { UstLocation } from "./generic";
|
||||
import {
|
||||
ExactInParameters,
|
||||
ExactOutParameters,
|
||||
makeExactInParameters,
|
||||
makeExactOutParameters,
|
||||
} from "./uniswap-core";
|
||||
import { ChainId } from "@certusone/wormhole-sdk";
|
||||
|
||||
export { PROTOCOL as PROTOCOL_UNISWAP_V2 } from "./uniswap-v2";
|
||||
export { PROTOCOL as PROTOCOL_UNISWAP_V3 } from "./uniswap-v3";
|
||||
export { PROTOCOL as PROTOCOL_TERRA_UST_TRANSFER } from "./terra-ust-transfer";
|
||||
|
||||
export const TERRA_UST = UST_TOKEN_INFO.address;
|
||||
|
||||
export enum QuoteType {
|
||||
ExactIn = 1,
|
||||
ExactOut,
|
||||
}
|
||||
|
||||
function makeRouter(provider: ethers.providers.Provider, id: number) {
|
||||
switch (id) {
|
||||
case ETH_NETWORK_CHAIN_ID: {
|
||||
return new UniswapV3Router(provider);
|
||||
export function makeEvmProviderFromAddress(tokenAddress: string) {
|
||||
switch (tokenAddress) {
|
||||
case WETH_TOKEN_INFO.address: {
|
||||
const url = process.env.REACT_APP_GOERLI_PROVIDER;
|
||||
if (!url) {
|
||||
throw new Error("Could not find REACT_APP_GOERLI_PROVIDER");
|
||||
}
|
||||
return new ethers.providers.StaticJsonRpcProvider(url);
|
||||
}
|
||||
case POLYGON_NETWORK_CHAIN_ID: {
|
||||
return new QuickswapRouter(provider);
|
||||
case WMATIC_TOKEN_INFO.address: {
|
||||
const url = process.env.REACT_APP_MUMBAI_PROVIDER;
|
||||
if (!url) {
|
||||
throw new Error("Could not find REACT_APP_MUMBAI_PROVIDER");
|
||||
}
|
||||
return new ethers.providers.StaticJsonRpcProvider(url);
|
||||
}
|
||||
default: {
|
||||
throw Error("unrecognized chain id");
|
||||
throw Error("unrecognized evm token address");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getUstAddress(id: number): string {
|
||||
switch (id) {
|
||||
case ETH_NETWORK_CHAIN_ID: {
|
||||
return "0x36Ed51Afc79619b299b238898E72ce482600568a";
|
||||
export function getChainIdFromAddress(tokenAddress: string) {
|
||||
switch (tokenAddress) {
|
||||
case WETH_TOKEN_INFO.address: {
|
||||
return WORMHOLE_CHAIN_ID_ETHEREUM;
|
||||
}
|
||||
case POLYGON_NETWORK_CHAIN_ID: {
|
||||
return "0xe3a1c77e952b57b5883f6c906fc706fcc7d4392c";
|
||||
case WMATIC_TOKEN_INFO.address: {
|
||||
return WORMHOLE_CHAIN_ID_POLYGON;
|
||||
}
|
||||
case UST_TOKEN_INFO.address: {
|
||||
return WORMHOLE_CHAIN_ID_TERRA;
|
||||
}
|
||||
default: {
|
||||
throw Error("unrecognized evm token address");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function makeRouter(tokenAddress: string, loc: UstLocation) {
|
||||
switch (tokenAddress) {
|
||||
case WETH_TOKEN_INFO.address: {
|
||||
const provider = makeEvmProviderFromAddress(tokenAddress);
|
||||
const router = new EthRouter(provider);
|
||||
await router.initialize(loc);
|
||||
return router;
|
||||
}
|
||||
case WMATIC_TOKEN_INFO.address: {
|
||||
const provider = makeEvmProviderFromAddress(tokenAddress);
|
||||
const router = new MaticRouter(provider);
|
||||
await router.initialize(loc);
|
||||
return router;
|
||||
}
|
||||
case UST_TOKEN_INFO.address: {
|
||||
return new UstRouter();
|
||||
}
|
||||
default: {
|
||||
throw Error("unrecognized chain id");
|
||||
|
@ -51,123 +102,105 @@ function splitSlippageInHalf(totalSlippage: string): string {
|
|||
.toString();
|
||||
}
|
||||
|
||||
interface RelayerFee {
|
||||
amount: ethers.BigNumber;
|
||||
export interface RelayerFee {
|
||||
amount: string;
|
||||
tokenAddress: string;
|
||||
}
|
||||
|
||||
export interface ExactInParameters {
|
||||
protocol: string;
|
||||
amountIn: ethers.BigNumber;
|
||||
minAmountOut: ethers.BigNumber;
|
||||
deadline: ethers.BigNumber;
|
||||
poolFee: string;
|
||||
path: [string, string];
|
||||
}
|
||||
|
||||
export interface ExactInCrossParameters {
|
||||
amountIn: string;
|
||||
minAmountOut: string;
|
||||
src: ExactInParameters;
|
||||
dst: ExactInParameters;
|
||||
relayerFee: RelayerFee;
|
||||
}
|
||||
|
||||
export interface ExactOutParameters {
|
||||
protocol: string;
|
||||
amountOut: ethers.BigNumber;
|
||||
maxAmountIn: ethers.BigNumber;
|
||||
deadline: ethers.BigNumber;
|
||||
poolFee: string;
|
||||
path: [string, string];
|
||||
}
|
||||
|
||||
export interface ExactOutCrossParameters {
|
||||
amountOut: string;
|
||||
maxAmountIn: string;
|
||||
src: ExactOutParameters;
|
||||
dst: ExactOutParameters;
|
||||
relayerFee: RelayerFee;
|
||||
}
|
||||
|
||||
export class UniswapToUniswapQuoter {
|
||||
// providers
|
||||
srcProvider: ethers.providers.Provider;
|
||||
dstProvider: ethers.providers.Provider;
|
||||
|
||||
// networks
|
||||
srcNetwork: ethers.providers.Network;
|
||||
dstNetwork: ethers.providers.Network;
|
||||
// tokens
|
||||
tokenInAddress: string;
|
||||
tokenOutAddress: string;
|
||||
|
||||
// routers
|
||||
srcRouter: UniswapV3Router | QuickswapRouter;
|
||||
dstRouter: UniswapV3Router | QuickswapRouter;
|
||||
srcRouter: UstRouter | EthRouter | MaticRouter;
|
||||
dstRouter: UstRouter | EthRouter | MaticRouter;
|
||||
|
||||
// tokens
|
||||
srcTokenIn: UniEvmToken;
|
||||
srcTokenOut: UniEvmToken;
|
||||
dstTokenIn: UniEvmToken;
|
||||
dstTokenOut: UniEvmToken;
|
||||
constructor() {}
|
||||
|
||||
constructor(
|
||||
srcProvider: ethers.providers.Provider,
|
||||
dstProvider: ethers.providers.Provider
|
||||
) {
|
||||
this.srcProvider = srcProvider;
|
||||
this.dstProvider = dstProvider;
|
||||
}
|
||||
async initialize(
|
||||
tokenInAddress: string,
|
||||
tokenOutAddress: string
|
||||
): Promise<void> {
|
||||
if (tokenInAddress !== this.tokenInAddress) {
|
||||
this.tokenInAddress = tokenInAddress;
|
||||
this.srcRouter = await makeRouter(tokenInAddress, UstLocation.Out);
|
||||
}
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
[this.srcNetwork, this.dstNetwork] = await Promise.all([
|
||||
this.srcProvider.getNetwork(),
|
||||
this.dstProvider.getNetwork(),
|
||||
]);
|
||||
|
||||
this.srcRouter = makeRouter(this.srcProvider, this.srcNetwork.chainId);
|
||||
this.dstRouter = makeRouter(this.dstProvider, this.dstNetwork.chainId);
|
||||
if (tokenOutAddress != this.tokenOutAddress) {
|
||||
this.tokenOutAddress = tokenOutAddress;
|
||||
this.dstRouter = await makeRouter(tokenOutAddress, UstLocation.In);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sameChain(): boolean {
|
||||
return this.srcNetwork.chainId === this.dstNetwork.chainId;
|
||||
}
|
||||
|
||||
async makeSrcTokens(
|
||||
tokenInAddress: string
|
||||
): Promise<[UniEvmToken, UniEvmToken]> {
|
||||
const ustOutAddress = getUstAddress(this.srcNetwork.chainId);
|
||||
|
||||
const router = this.srcRouter;
|
||||
|
||||
[this.srcTokenIn, this.srcTokenOut] = await Promise.all([
|
||||
router.makeToken(tokenInAddress),
|
||||
router.makeToken(ustOutAddress),
|
||||
]);
|
||||
return [this.srcTokenIn, this.srcTokenOut];
|
||||
}
|
||||
|
||||
async makeDstTokens(
|
||||
tokenOutAddress: string
|
||||
): Promise<[UniEvmToken, UniEvmToken]> {
|
||||
const ustInAddress = getUstAddress(this.dstNetwork.chainId);
|
||||
|
||||
const router = this.dstRouter;
|
||||
|
||||
[this.dstTokenIn, this.dstTokenOut] = await Promise.all([
|
||||
router.makeToken(ustInAddress),
|
||||
router.makeToken(tokenOutAddress),
|
||||
]);
|
||||
return [this.dstTokenIn, this.dstTokenOut];
|
||||
}
|
||||
|
||||
async computeAndVerifySrcPoolAddress(): Promise<string> {
|
||||
return this.srcRouter.computeAndVerifyPoolAddress(
|
||||
this.srcTokenIn,
|
||||
this.srcTokenOut
|
||||
);
|
||||
return this.srcRouter.computeAndVerifyPoolAddress();
|
||||
}
|
||||
|
||||
async computeAndVerifyDstPoolAddress(): Promise<string> {
|
||||
return this.dstRouter.computeAndVerifyPoolAddress(
|
||||
this.dstTokenIn,
|
||||
this.dstTokenOut
|
||||
);
|
||||
return this.dstRouter.computeAndVerifyPoolAddress();
|
||||
}
|
||||
|
||||
computeSwapSlippage(slippage): string {
|
||||
if (this.isSrcUst() || this.isDstUst()) {
|
||||
return slippage;
|
||||
}
|
||||
|
||||
return splitSlippageInHalf(slippage);
|
||||
}
|
||||
|
||||
getRelayerFee(amount: string): RelayerFee {
|
||||
if (this.isSrcUst()) {
|
||||
return {
|
||||
amount: this.srcRouter.computeUnitAmountOut(amount),
|
||||
tokenAddress: TERRA_UST, // TODO: make sure this is the right address for bridge transfer?
|
||||
};
|
||||
}
|
||||
|
||||
const relayerFee: RelayerFee = {
|
||||
amount: this.srcRouter.computeUnitAmountOut(amount),
|
||||
tokenAddress: this.srcRouter.getTokenOutAddress(),
|
||||
};
|
||||
return relayerFee;
|
||||
}
|
||||
|
||||
makeSrcExactInParameters(
|
||||
amountIn: string,
|
||||
minAmountOut: string
|
||||
): ExactInParameters {
|
||||
if (this.isSrcUst()) {
|
||||
return undefined;
|
||||
}
|
||||
// @ts-ignore
|
||||
return makeExactInParameters(this.srcRouter, amountIn, minAmountOut);
|
||||
}
|
||||
|
||||
makeDstExactInParameters(
|
||||
amountIn: string,
|
||||
minAmountOut: string
|
||||
): ExactInParameters {
|
||||
if (this.isDstUst()) {
|
||||
return undefined;
|
||||
}
|
||||
// @ts-ignore
|
||||
return makeExactInParameters(this.dstRouter, amountIn, minAmountOut);
|
||||
}
|
||||
|
||||
async computeExactInParameters(
|
||||
|
@ -175,71 +208,68 @@ export class UniswapToUniswapQuoter {
|
|||
slippage: string,
|
||||
relayerFeeUst: string
|
||||
): Promise<ExactInCrossParameters> {
|
||||
const singleSlippage = splitSlippageInHalf(slippage);
|
||||
const singleSlippage = this.computeSwapSlippage(slippage);
|
||||
|
||||
// src quote
|
||||
const srcRouter = this.srcRouter;
|
||||
const srcTokenIn = this.srcTokenIn;
|
||||
const srcTokenOut = this.srcTokenOut;
|
||||
const srcMinAmountOut = await srcRouter.fetchQuoteAmountOut(
|
||||
srcTokenIn,
|
||||
srcTokenOut,
|
||||
const srcMinAmountOut = await srcRouter.fetchExactInQuote(
|
||||
amountIn,
|
||||
singleSlippage
|
||||
);
|
||||
|
||||
// dst quote
|
||||
const dstRouter = this.dstRouter;
|
||||
const dstAmountIn = this.srcTokenOut.formatAmount(srcMinAmountOut);
|
||||
const dstAmountIn = srcMinAmountOut; //srcRouter.formatAmountOut(srcMinAmountOut);
|
||||
if (Number(dstAmountIn) < Number(relayerFeeUst)) {
|
||||
throw Error(
|
||||
`srcAmountOut <= relayerFeeUst. ${dstAmountIn} vs ${relayerFeeUst}`
|
||||
);
|
||||
}
|
||||
|
||||
const dstTokenIn = this.dstTokenIn;
|
||||
const dstTokenOut = this.dstTokenOut;
|
||||
const dstAmountInAfterFee = dstTokenIn.subtractAmounts(
|
||||
const dstAmountInAfterFee = subtractFixedAmounts(
|
||||
dstAmountIn,
|
||||
relayerFeeUst
|
||||
relayerFeeUst,
|
||||
dstRouter.getTokenInDecimals()
|
||||
);
|
||||
|
||||
const dstMinAmountOut = await dstRouter.fetchQuoteAmountOut(
|
||||
dstTokenIn,
|
||||
dstTokenOut,
|
||||
const dstMinAmountOut = await dstRouter.fetchExactInQuote(
|
||||
dstAmountInAfterFee,
|
||||
singleSlippage
|
||||
);
|
||||
|
||||
const srcParameters: ExactInParameters = {
|
||||
protocol: srcRouter.getProtocol(),
|
||||
amountIn: srcTokenIn.computeUnitAmount(amountIn),
|
||||
minAmountOut: srcMinAmountOut,
|
||||
poolFee: srcRouter.getPoolFee(),
|
||||
deadline: srcRouter.getTradeDeadline(),
|
||||
path: [srcTokenIn.getAddress(), srcTokenOut.getAddress()],
|
||||
};
|
||||
|
||||
const dstParameters: ExactInParameters = {
|
||||
protocol: dstRouter.getProtocol(),
|
||||
amountIn: dstTokenIn.computeUnitAmount(dstAmountInAfterFee),
|
||||
minAmountOut: dstMinAmountOut,
|
||||
poolFee: dstRouter.getPoolFee(),
|
||||
deadline: dstRouter.getTradeDeadline(),
|
||||
path: [dstTokenIn.getAddress(), dstTokenOut.getAddress()],
|
||||
};
|
||||
|
||||
// organize parameters
|
||||
const params: ExactInCrossParameters = {
|
||||
src: srcParameters,
|
||||
dst: dstParameters,
|
||||
relayerFee: {
|
||||
amount: dstTokenIn.computeUnitAmount(relayerFeeUst),
|
||||
tokenAddress: this.dstTokenIn.getAddress(),
|
||||
},
|
||||
amountIn: amountIn,
|
||||
minAmountOut: dstMinAmountOut,
|
||||
src: this.makeSrcExactInParameters(amountIn, srcMinAmountOut),
|
||||
dst: this.makeDstExactInParameters(dstAmountInAfterFee, dstMinAmountOut),
|
||||
relayerFee: this.getRelayerFee(relayerFeeUst),
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
makeSrcExactOutParameters(
|
||||
amountOut: string,
|
||||
maxAmountIn: string
|
||||
): ExactOutParameters {
|
||||
if (this.isSrcUst()) {
|
||||
return null;
|
||||
}
|
||||
// @ts-ignore
|
||||
return makeExactOutParameters(this.srcRouter, amountOut, maxAmountIn);
|
||||
}
|
||||
|
||||
makeDstExactOutParameters(
|
||||
amountOut: string,
|
||||
maxAmountIn: string
|
||||
): ExactOutParameters {
|
||||
if (this.isDstUst()) {
|
||||
return null;
|
||||
}
|
||||
// @ts-ignore
|
||||
return makeExactOutParameters(this.dstRouter, amountOut, maxAmountIn);
|
||||
}
|
||||
|
||||
async computeExactOutParameters(
|
||||
amountOut: string,
|
||||
slippage: string,
|
||||
|
@ -249,69 +279,85 @@ export class UniswapToUniswapQuoter {
|
|||
|
||||
// dst quote first
|
||||
const dstRouter = this.dstRouter;
|
||||
const dstTokenIn = this.dstTokenIn;
|
||||
const dstTokenOut = this.dstTokenOut;
|
||||
const dstMaxAmountIn = await dstRouter.fetchQuoteAmountIn(
|
||||
dstTokenIn,
|
||||
dstTokenOut,
|
||||
const dstMaxAmountIn = await dstRouter.fetchExactOutQuote(
|
||||
amountOut,
|
||||
singleSlippage
|
||||
);
|
||||
|
||||
// src quote
|
||||
const srcRouter = this.srcRouter;
|
||||
const srcAmountOut = this.dstTokenIn.formatAmount(dstMaxAmountIn);
|
||||
const srcAmountOut = dstMaxAmountIn;
|
||||
if (Number(srcAmountOut) < Number(relayerFeeUst)) {
|
||||
throw Error(
|
||||
`dstAmountIn <= relayerFeeUst. ${srcAmountOut} vs ${relayerFeeUst}`
|
||||
);
|
||||
}
|
||||
|
||||
const srcTokenIn = this.srcTokenIn;
|
||||
const srcTokenOut = this.srcTokenOut;
|
||||
const srcAmountOutBeforeFee = srcTokenOut.addAmounts(
|
||||
const srcAmountOutBeforeFee = addFixedAmounts(
|
||||
srcAmountOut,
|
||||
relayerFeeUst
|
||||
relayerFeeUst,
|
||||
srcRouter.getTokenOutDecimals()
|
||||
);
|
||||
|
||||
const srcMaxAmountIn = await srcRouter.fetchQuoteAmountIn(
|
||||
srcTokenIn,
|
||||
srcTokenOut,
|
||||
const srcMaxAmountIn = await srcRouter.fetchExactOutQuote(
|
||||
srcAmountOutBeforeFee,
|
||||
singleSlippage
|
||||
);
|
||||
|
||||
const srcParameters: ExactOutParameters = {
|
||||
protocol: srcRouter.getProtocol(),
|
||||
amountOut: srcTokenOut.computeUnitAmount(srcAmountOutBeforeFee),
|
||||
maxAmountIn: srcMaxAmountIn,
|
||||
poolFee: srcRouter.getPoolFee(),
|
||||
deadline: srcRouter.getTradeDeadline(),
|
||||
path: [srcTokenIn.getAddress(), srcTokenOut.getAddress()],
|
||||
};
|
||||
|
||||
const dstParameters: ExactOutParameters = {
|
||||
protocol: dstRouter.getProtocol(),
|
||||
amountOut: dstTokenOut.computeUnitAmount(amountOut),
|
||||
maxAmountIn: dstMaxAmountIn,
|
||||
poolFee: dstRouter.getPoolFee(),
|
||||
deadline: dstRouter.getTradeDeadline(),
|
||||
path: [dstTokenIn.getAddress(), dstTokenOut.getAddress()],
|
||||
};
|
||||
|
||||
// organize parameters
|
||||
const params: ExactOutCrossParameters = {
|
||||
src: srcParameters,
|
||||
dst: dstParameters,
|
||||
relayerFee: {
|
||||
amount: dstTokenIn.computeUnitAmount(relayerFeeUst),
|
||||
tokenAddress: this.dstTokenIn.getAddress(),
|
||||
},
|
||||
amountOut: amountOut,
|
||||
maxAmountIn: srcMaxAmountIn,
|
||||
src: this.makeSrcExactOutParameters(
|
||||
srcAmountOutBeforeFee,
|
||||
srcMaxAmountIn
|
||||
),
|
||||
dst: this.makeDstExactOutParameters(amountOut, dstMaxAmountIn),
|
||||
relayerFee: this.getRelayerFee(relayerFeeUst),
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
setDeadlines(deadline: string): void {
|
||||
this.srcRouter.setDeadline(deadline);
|
||||
this.dstRouter.setDeadline(deadline);
|
||||
if (!this.isSrcUst()) {
|
||||
// @ts-ignore
|
||||
this.srcRouter.setDeadline(deadline);
|
||||
}
|
||||
if (!this.isDstUst()) {
|
||||
// @ts-ignore
|
||||
this.dstRouter.setDeadline(deadline);
|
||||
}
|
||||
}
|
||||
|
||||
isSrcUst(): boolean {
|
||||
return this.tokenInAddress === TERRA_UST;
|
||||
}
|
||||
|
||||
isDstUst(): boolean {
|
||||
return this.tokenOutAddress === TERRA_UST;
|
||||
}
|
||||
|
||||
getSrcEvmProvider(): ethers.providers.Provider {
|
||||
if (this.isSrcUst()) {
|
||||
return undefined;
|
||||
}
|
||||
// @ts-ignore
|
||||
return this.srcRouter.getProvider();
|
||||
}
|
||||
|
||||
getDstEvmProvider(): ethers.providers.Provider {
|
||||
if (this.isDstUst()) {
|
||||
return undefined;
|
||||
}
|
||||
// @ts-ignore
|
||||
return this.dstRouter.getProvider();
|
||||
}
|
||||
|
||||
getSrcChainId(): ChainId {
|
||||
return getChainIdFromAddress(this.tokenInAddress);
|
||||
}
|
||||
|
||||
getDstChainId(): ChainId {
|
||||
return getChainIdFromAddress(this.tokenOutAddress);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { ethers } from "ethers";
|
|||
import { GenericToken } from "./generic";
|
||||
|
||||
// erc20 spec
|
||||
import { abi as Erc20Abi } from "../abi/erc20.json";
|
||||
import { abi as Erc20Abi } from "../../abi/erc20.json";
|
||||
import {
|
||||
TransactionReceipt,
|
||||
TransactionRequest,
|
||||
|
|
|
@ -1,7 +1,40 @@
|
|||
export abstract class DexRouter {
|
||||
abstract makeToken(tokenAddress: string): any;
|
||||
abstract quoteLot(tokenA: any, tokenB: any, amount: string): Promise<any>;
|
||||
abstract setSlippage(slippage: string): void;
|
||||
import { FixedNumber } from "ethers";
|
||||
|
||||
export enum UstLocation {
|
||||
In = 1,
|
||||
Out,
|
||||
}
|
||||
|
||||
export abstract class RouterCore {
|
||||
abstract computeAndVerifyPoolAddress(): Promise<string>;
|
||||
|
||||
abstract computePoolAddress(): string;
|
||||
|
||||
//abstract computeUnitAmountIn(amount: string): string;
|
||||
|
||||
abstract computeUnitAmountOut(amount: string): string;
|
||||
|
||||
abstract fetchExactInQuote(
|
||||
amountOut: string,
|
||||
slippage: string
|
||||
): Promise<string>;
|
||||
|
||||
abstract fetchExactOutQuote(
|
||||
amountOut: string,
|
||||
slippage: string
|
||||
): Promise<string>;
|
||||
|
||||
abstract formatAmountIn(amount: string): string;
|
||||
|
||||
abstract formatAmountOut(amount: string): string;
|
||||
|
||||
abstract getProtocol(): string;
|
||||
|
||||
abstract getTokenInDecimals(): number;
|
||||
|
||||
abstract getTokenOutDecimals(): number;
|
||||
|
||||
abstract getTokenOutAddress(): string;
|
||||
}
|
||||
|
||||
export abstract class GenericToken {
|
||||
|
@ -9,16 +42,3 @@ export abstract class GenericToken {
|
|||
|
||||
abstract getDecimals(): number;
|
||||
}
|
||||
|
||||
// TODO: wrap SwapRoute and other routes
|
||||
export class GenericRoute {
|
||||
route: any;
|
||||
|
||||
constructor(route: any) {
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
getRoute(): any {
|
||||
return this.route;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
import { ethers } from "ethers";
|
||||
import { QUICKSWAP_FACTORY_ADDRESS } from "../utils/consts";
|
||||
import { SingleAmmSwapRouter } from "./uniswap-v2";
|
||||
import { QUICKSWAP_FACTORY_ADDRESS, WMATIC_TOKEN_INFO } from "../utils/consts";
|
||||
import { UstLocation } from "./generic";
|
||||
import { UniswapV2Router } from "./uniswap-v2";
|
||||
|
||||
export { PROTOCOL } from "./uniswap-v2";
|
||||
|
||||
export class QuickswapRouter extends SingleAmmSwapRouter {
|
||||
export class QuickswapRouter extends UniswapV2Router {
|
||||
constructor(provider: ethers.providers.Provider) {
|
||||
super(provider);
|
||||
super.setFactoryAddress(QUICKSWAP_FACTORY_ADDRESS);
|
||||
}
|
||||
|
||||
async initialize(ustLocation: UstLocation): Promise<void> {
|
||||
await super.initializeTokens(WMATIC_TOKEN_INFO, ustLocation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { Dec, Int } from "@terra-money/terra.js";
|
||||
|
||||
import { UST_TOKEN_INFO } from "../utils/consts";
|
||||
import { RouterCore } from "./generic";
|
||||
|
||||
export const PROTOCOL = "TerraUstTransfer";
|
||||
|
||||
const UST_DECIMALS = 6;
|
||||
|
||||
const UST_AMOUNT_MULTIPLIER = "1000000";
|
||||
|
||||
export class TerraUstTransfer extends RouterCore {
|
||||
computePoolAddress(): string {
|
||||
return UST_TOKEN_INFO.address;
|
||||
}
|
||||
|
||||
computeAndVerifyPoolAddress(): Promise<string> {
|
||||
return new Promise<string>((resolve) => {
|
||||
return resolve(this.computePoolAddress());
|
||||
});
|
||||
}
|
||||
|
||||
formatAmountIn(amount: string): string {
|
||||
const formatted = new Dec(amount).div(UST_AMOUNT_MULTIPLIER);
|
||||
return formatted.toString();
|
||||
}
|
||||
|
||||
formatAmountOut(amount: string): string {
|
||||
return this.formatAmountIn(amount);
|
||||
}
|
||||
|
||||
computeUnitAmountIn(amount: string): string {
|
||||
const unitified = new Dec(amount).mul(UST_AMOUNT_MULTIPLIER);
|
||||
return new Int(unitified.toString()).toString();
|
||||
}
|
||||
|
||||
computeUnitAmountOut(amount: string): string {
|
||||
return this.computeUnitAmountIn(amount);
|
||||
}
|
||||
|
||||
getProtocol(): string {
|
||||
return PROTOCOL;
|
||||
}
|
||||
|
||||
async fetchExactInQuote(amountIn: string, slippage: string): Promise<string> {
|
||||
return amountIn;
|
||||
}
|
||||
|
||||
async fetchExactOutQuote(
|
||||
amountOut: string,
|
||||
slippage: string
|
||||
): Promise<string> {
|
||||
return amountOut;
|
||||
}
|
||||
|
||||
getTokenInDecimals(): number {
|
||||
return UST_DECIMALS;
|
||||
}
|
||||
|
||||
getTokenOutDecimals(): number {
|
||||
return UST_DECIMALS;
|
||||
}
|
||||
|
||||
getTokenOutAddress(): string {
|
||||
return this.computePoolAddress();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ import { ethers } from "ethers";
|
|||
import { CurrencyAmount, Token } from "@uniswap/sdk-core";
|
||||
|
||||
import { EvmToken } from "./evm";
|
||||
import { RouterCore, UstLocation } from "./generic";
|
||||
import { TokenInfo } from "../utils/consts";
|
||||
|
||||
export function computeTradeDeadline(deadline: string): ethers.BigNumber {
|
||||
return ethers.BigNumber.from(Math.floor(Date.now() / 1000)).add(deadline);
|
||||
|
@ -78,46 +80,112 @@ export async function makeUniEvmToken(
|
|||
return new UniEvmToken(chainId, erc20);
|
||||
}
|
||||
|
||||
export abstract class UniswapRouterCore {
|
||||
function stringToBigNumber(value: string): ethers.BigNumber {
|
||||
return ethers.BigNumber.from(value);
|
||||
}
|
||||
|
||||
export interface ExactInParameters {
|
||||
protocol: string;
|
||||
amountIn: ethers.BigNumber;
|
||||
minAmountOut: ethers.BigNumber;
|
||||
deadline: ethers.BigNumber;
|
||||
poolFee: string;
|
||||
path: [string, string];
|
||||
}
|
||||
|
||||
export interface ExactOutParameters {
|
||||
protocol: string;
|
||||
amountOut: ethers.BigNumber;
|
||||
maxAmountIn: ethers.BigNumber;
|
||||
deadline: ethers.BigNumber;
|
||||
poolFee: string;
|
||||
path: [string, string];
|
||||
}
|
||||
|
||||
export function makeExactInParameters(
|
||||
router: UniswapRouterCore,
|
||||
amountIn: string,
|
||||
minAmountOut: string
|
||||
): ExactInParameters {
|
||||
const params: ExactInParameters = {
|
||||
protocol: router.getProtocol(),
|
||||
amountIn: router.tokenIn.computeUnitAmount(amountIn),
|
||||
minAmountOut: router.tokenOut.computeUnitAmount(minAmountOut),
|
||||
poolFee: router.getPoolFee(),
|
||||
deadline: router.getTradeDeadline(),
|
||||
path: [router.tokenIn.getAddress(), router.tokenOut.getAddress()],
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
export function makeExactOutParameters(
|
||||
router: UniswapRouterCore,
|
||||
amountOut: string,
|
||||
maxAmountIn: string
|
||||
): ExactOutParameters {
|
||||
const params: ExactOutParameters = {
|
||||
protocol: router.getProtocol(),
|
||||
amountOut: router.tokenOut.computeUnitAmount(amountOut),
|
||||
maxAmountIn: router.tokenIn.computeUnitAmount(maxAmountIn),
|
||||
poolFee: router.getPoolFee(),
|
||||
deadline: router.getTradeDeadline(),
|
||||
path: [router.tokenIn.getAddress(), router.tokenOut.getAddress()],
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
export abstract class UniswapRouterCore extends RouterCore {
|
||||
provider: ethers.providers.Provider;
|
||||
network: ethers.providers.Network;
|
||||
|
||||
// wormhole
|
||||
chainId: number;
|
||||
|
||||
// tokens
|
||||
tokenIn: UniEvmToken;
|
||||
tokenOut: UniEvmToken;
|
||||
|
||||
// params
|
||||
deadline: string = "";
|
||||
|
||||
constructor(provider: ethers.providers.Provider) {
|
||||
super();
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public async makeToken(tokenAddress: string): Promise<UniEvmToken> {
|
||||
const network = await this.provider.getNetwork();
|
||||
return makeUniEvmToken(this.provider, network.chainId, tokenAddress);
|
||||
public getProvider(): ethers.providers.Provider {
|
||||
return this.provider;
|
||||
}
|
||||
|
||||
abstract computePoolAddress(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken
|
||||
): string;
|
||||
public async initializeTokens(
|
||||
tokenInfo: TokenInfo,
|
||||
ustLocation: UstLocation
|
||||
): Promise<void> {
|
||||
this.network = await this.provider.getNetwork();
|
||||
|
||||
abstract computeAndVerifyPoolAddress(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken
|
||||
): Promise<string>;
|
||||
const network = this.network;
|
||||
|
||||
abstract fetchQuoteAmountOut(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken,
|
||||
amountOut: string,
|
||||
slippage: string
|
||||
): Promise<ethers.BigNumber>;
|
||||
|
||||
abstract fetchQuoteAmountIn(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken,
|
||||
amountOut: string,
|
||||
slippage: string
|
||||
): Promise<ethers.BigNumber>;
|
||||
|
||||
abstract getProtocol(): string;
|
||||
if (ustLocation == UstLocation.Out) {
|
||||
[this.tokenIn, this.tokenOut] = await Promise.all([
|
||||
makeUniEvmToken(this.provider, network.chainId, tokenInfo.address),
|
||||
makeUniEvmToken(
|
||||
this.provider,
|
||||
network.chainId,
|
||||
tokenInfo.ustPairedAddress
|
||||
),
|
||||
]);
|
||||
} else {
|
||||
[this.tokenIn, this.tokenOut] = await Promise.all([
|
||||
makeUniEvmToken(
|
||||
this.provider,
|
||||
network.chainId,
|
||||
tokenInfo.ustPairedAddress
|
||||
),
|
||||
makeUniEvmToken(this.provider, network.chainId, tokenInfo.address),
|
||||
]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public getPoolFee(): string {
|
||||
return "";
|
||||
|
@ -130,4 +198,36 @@ export abstract class UniswapRouterCore {
|
|||
public getTradeDeadline(): ethers.BigNumber {
|
||||
return computeTradeDeadline(this.deadline);
|
||||
}
|
||||
|
||||
/*
|
||||
public computeUnitAmountIn(amount: string): string {
|
||||
return this.tokenIn.computeUnitAmount(amount).toString();
|
||||
}
|
||||
*/
|
||||
|
||||
public computeUnitAmountOut(amount: string): string {
|
||||
return this.tokenOut.computeUnitAmount(amount).toString();
|
||||
}
|
||||
|
||||
public formatAmountIn(amount: string): string {
|
||||
return this.tokenIn.formatAmount(stringToBigNumber(amount));
|
||||
}
|
||||
|
||||
public formatAmountOut(amount: string): string {
|
||||
return this.tokenOut.formatAmount(stringToBigNumber(amount));
|
||||
}
|
||||
|
||||
public getTokenInDecimals(): number {
|
||||
return this.tokenIn.getDecimals();
|
||||
}
|
||||
|
||||
public getTokenOutDecimals(): number {
|
||||
return this.tokenOut.getDecimals();
|
||||
}
|
||||
|
||||
public getTokenOutAddress(): string {
|
||||
return this.tokenOut.getAddress();
|
||||
}
|
||||
|
||||
abstract getProtocol(): string;
|
||||
}
|
||||
|
|
|
@ -3,11 +3,19 @@ import { CurrencyAmount, TradeType } from "@uniswap/sdk-core";
|
|||
import { abi as IUniswapV2PairABI } from "@uniswap/v2-core/build/UniswapV2Pair.json";
|
||||
import { computePairAddress, Pair, Route, Trade } from "@uniswap/v2-sdk";
|
||||
|
||||
import { UniEvmToken, UniswapRouterCore } from "./uniswap-core";
|
||||
import { UniswapRouterCore } from "./uniswap-core";
|
||||
|
||||
export const PROTOCOL = "UniswapV2";
|
||||
|
||||
export class SingleAmmSwapRouter extends UniswapRouterCore {
|
||||
// uniswap v3 (ethereum)
|
||||
//export const UNISWAP_V3_FACTORY_ADDRESS = '0x1F98431c8aD98523631AE4a59f267346ea31F984';
|
||||
//export const UNISWAP_V3_ROUTER_ADDRESS = '0xE592427A0AEce92De3Edee1F18E0157C05861564';
|
||||
|
||||
// quickswap (polygon)
|
||||
export const QUICKSWAP_V2_ROUTER_ADDRESS =
|
||||
"0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff";
|
||||
|
||||
export class UniswapV2Router extends UniswapRouterCore {
|
||||
factoryAddress: string;
|
||||
pairContract: ethers.Contract;
|
||||
pair: Pair;
|
||||
|
@ -17,23 +25,20 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
return;
|
||||
}
|
||||
|
||||
computePoolAddress(tokenIn: UniEvmToken, tokenOut: UniEvmToken): string {
|
||||
computePoolAddress(): string {
|
||||
if (this.factoryAddress === undefined) {
|
||||
throw Error("factoryAddress is undefined. use setFactoryAddress");
|
||||
}
|
||||
|
||||
return computePairAddress({
|
||||
factoryAddress: this.factoryAddress,
|
||||
tokenA: tokenIn.getUniToken(),
|
||||
tokenB: tokenOut.getUniToken(),
|
||||
tokenA: this.tokenIn.getUniToken(),
|
||||
tokenB: this.tokenOut.getUniToken(),
|
||||
});
|
||||
}
|
||||
|
||||
async computeAndVerifyPoolAddress(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken
|
||||
): Promise<string> {
|
||||
const pairAddress = this.computePoolAddress(tokenIn, tokenOut);
|
||||
async computeAndVerifyPoolAddress(): Promise<string> {
|
||||
const pairAddress = this.computePoolAddress();
|
||||
|
||||
// verify by attempting to call factory()
|
||||
const poolContract = new ethers.Contract(
|
||||
|
@ -46,8 +51,8 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
return pairAddress;
|
||||
}
|
||||
|
||||
async createPool(tokenIn: UniEvmToken, tokenOut: UniEvmToken): Promise<Pair> {
|
||||
const pairAddress = this.computePoolAddress(tokenIn, tokenOut);
|
||||
async createPool(): Promise<Pair> {
|
||||
const pairAddress = this.computePoolAddress();
|
||||
|
||||
const pairContract = new ethers.Contract(
|
||||
pairAddress,
|
||||
|
@ -63,6 +68,9 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
const reserve0 = reserves._reserve0.toString();
|
||||
const reserve1 = reserves._reserve1.toString();
|
||||
|
||||
const tokenIn = this.tokenIn;
|
||||
const tokenOut = this.tokenOut;
|
||||
|
||||
if (token0.toLowerCase() === tokenIn.getAddress().toLowerCase()) {
|
||||
return new Pair(
|
||||
CurrencyAmount.fromRawAmount(tokenIn.getUniToken(), reserve0),
|
||||
|
@ -76,15 +84,13 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
);
|
||||
}
|
||||
|
||||
async fetchQuoteAmountOut(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken,
|
||||
amountIn: string,
|
||||
slippage: string
|
||||
): Promise<ethers.BigNumber> {
|
||||
async fetchExactInQuote(amountIn: string, slippage: string): Promise<string> {
|
||||
// create pool
|
||||
const pair = await this.createPool(tokenIn, tokenOut);
|
||||
const pair = await this.createPool();
|
||||
|
||||
// let's get that quote
|
||||
const tokenIn = this.tokenIn;
|
||||
const tokenOut = this.tokenOut;
|
||||
|
||||
const route = new Route(
|
||||
[pair],
|
||||
|
@ -108,18 +114,24 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
.mulUnsafe(slippageMultiplier)
|
||||
.round(decimals);
|
||||
|
||||
return tokenOut.computeUnitAmount(minAmountOutWithSlippage.toString());
|
||||
/*
|
||||
return tokenOut
|
||||
.computeUnitAmount(minAmountOutWithSlippage.toString())
|
||||
.toString();
|
||||
*/
|
||||
return minAmountOutWithSlippage.toString();
|
||||
}
|
||||
|
||||
async fetchQuoteAmountIn(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken,
|
||||
async fetchExactOutQuote(
|
||||
amountOut: string,
|
||||
slippage: string
|
||||
): Promise<ethers.BigNumber> {
|
||||
): Promise<string> {
|
||||
// create pool
|
||||
const pair = await this.createPool(tokenIn, tokenOut);
|
||||
const pair = await this.createPool();
|
||||
|
||||
// let's get that quote
|
||||
const tokenIn = this.tokenIn;
|
||||
const tokenOut = this.tokenOut;
|
||||
|
||||
const route = new Route(
|
||||
[pair],
|
||||
|
@ -142,7 +154,12 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
.divUnsafe(slippageDivisor)
|
||||
.round(decimals);
|
||||
|
||||
return tokenIn.computeUnitAmount(maxAmountInWithSlippage.toString());
|
||||
/*
|
||||
return tokenIn
|
||||
.computeUnitAmount(maxAmountInWithSlippage.toString())
|
||||
.toString();
|
||||
*/
|
||||
return maxAmountInWithSlippage.toString();
|
||||
}
|
||||
|
||||
getProtocol(): string {
|
||||
|
|
|
@ -14,11 +14,12 @@ import {
|
|||
} from "@uniswap/v3-sdk";
|
||||
|
||||
import { UniEvmToken, UniswapRouterCore } from "./uniswap-core";
|
||||
import { UNISWAP_V3_FACTORY_ADDRESS } from "../utils/consts";
|
||||
import { WETH_TOKEN_INFO, UNISWAP_V3_FACTORY_ADDRESS } from "../utils/consts";
|
||||
import { UstLocation } from "./generic";
|
||||
|
||||
export const PROTOCOL = "UniswapV3";
|
||||
|
||||
export class SingleAmmSwapRouter extends UniswapRouterCore {
|
||||
export class UniswapV3Router extends UniswapRouterCore {
|
||||
poolContract: ethers.Contract;
|
||||
pool: Pool;
|
||||
poolFee: FeeAmount;
|
||||
|
@ -30,24 +31,26 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
this.poolFee = FeeAmount.MEDIUM;
|
||||
}
|
||||
|
||||
async initialize(ustLocation: UstLocation): Promise<void> {
|
||||
await this.initializeTokens(WETH_TOKEN_INFO, ustLocation);
|
||||
return;
|
||||
}
|
||||
|
||||
getPoolFee(): string {
|
||||
return this.poolFee.toString();
|
||||
}
|
||||
|
||||
computePoolAddress(tokenIn: UniEvmToken, tokenOut: UniEvmToken): string {
|
||||
computePoolAddress(): string {
|
||||
return computePoolAddress({
|
||||
factoryAddress: UNISWAP_V3_FACTORY_ADDRESS,
|
||||
fee: this.poolFee,
|
||||
tokenA: tokenIn.getUniToken(),
|
||||
tokenB: tokenOut.getUniToken(),
|
||||
tokenA: this.tokenIn.getUniToken(),
|
||||
tokenB: this.tokenOut.getUniToken(),
|
||||
});
|
||||
}
|
||||
|
||||
async computeAndVerifyPoolAddress(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken
|
||||
): Promise<string> {
|
||||
const pairAddress = this.computePoolAddress(tokenIn, tokenOut);
|
||||
async computeAndVerifyPoolAddress(): Promise<string> {
|
||||
const pairAddress = this.computePoolAddress();
|
||||
|
||||
// verify by attempting to call factory()
|
||||
const poolContract = new ethers.Contract(
|
||||
|
@ -60,8 +63,8 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
return pairAddress;
|
||||
}
|
||||
|
||||
async createPool(tokenIn: UniEvmToken, tokenOut: UniEvmToken): Promise<Pool> {
|
||||
const poolAddress = this.computePoolAddress(tokenIn, tokenOut);
|
||||
async createPool(): Promise<Pool> {
|
||||
const poolAddress = this.computePoolAddress();
|
||||
|
||||
const poolContract = new ethers.Contract(
|
||||
poolAddress,
|
||||
|
@ -103,8 +106,8 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
];
|
||||
|
||||
return new Pool(
|
||||
tokenIn.getUniToken(),
|
||||
tokenOut.getUniToken(),
|
||||
this.tokenIn.getUniToken(),
|
||||
this.tokenOut.getUniToken(),
|
||||
this.poolFee,
|
||||
sqrtPriceX96.toString(), //note the description discrepancy - sqrtPriceX96 and sqrtRatioX96 are interchangable values
|
||||
liquidity,
|
||||
|
@ -114,13 +117,15 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
}
|
||||
|
||||
async computeTradeExactIn(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken,
|
||||
amount: string
|
||||
): Promise<Trade<Token, Token, TradeType.EXACT_INPUT>> {
|
||||
// create pool
|
||||
const pool = await this.createPool(tokenIn, tokenOut);
|
||||
const pool = await this.createPool();
|
||||
|
||||
// let's get that quote
|
||||
const tokenIn = this.tokenIn;
|
||||
const tokenOut = this.tokenOut;
|
||||
|
||||
const amountIn = tokenIn.computeUnitAmount(amount);
|
||||
|
||||
const route = new Route(
|
||||
|
@ -136,13 +141,15 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
}
|
||||
|
||||
async computeTradeExactOut(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken,
|
||||
amount: string
|
||||
): Promise<Trade<Token, Token, TradeType.EXACT_OUTPUT>> {
|
||||
// create pool
|
||||
const pool = await this.createPool(tokenIn, tokenOut);
|
||||
const pool = await this.createPool();
|
||||
|
||||
// let's get that quote
|
||||
const tokenIn = this.tokenIn;
|
||||
const tokenOut = this.tokenOut;
|
||||
|
||||
const amountOut = tokenOut.computeUnitAmount(amount);
|
||||
|
||||
const route = new Route(
|
||||
|
@ -160,15 +167,11 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
);
|
||||
}
|
||||
|
||||
async fetchQuoteAmountOut(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken,
|
||||
amountIn: string,
|
||||
slippage: string
|
||||
): Promise<ethers.BigNumber> {
|
||||
async fetchExactInQuote(amountIn: string, slippage: string): Promise<string> {
|
||||
// get the quote
|
||||
const trade = await this.computeTradeExactIn(tokenIn, tokenOut, amountIn);
|
||||
const trade = await this.computeTradeExactIn(amountIn);
|
||||
|
||||
const tokenOut = this.tokenOut;
|
||||
const decimals = tokenOut.getDecimals();
|
||||
|
||||
// calculate output amount with slippage
|
||||
|
@ -183,18 +186,22 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
.mulUnsafe(slippageMultiplier)
|
||||
.round(decimals);
|
||||
|
||||
return tokenOut.computeUnitAmount(minAmountOutWithSlippage.toString());
|
||||
/*
|
||||
return tokenOut
|
||||
.computeUnitAmount(minAmountOutWithSlippage.toString())
|
||||
.toString();
|
||||
*/
|
||||
return minAmountOutWithSlippage.toString();
|
||||
}
|
||||
|
||||
async fetchQuoteAmountIn(
|
||||
tokenIn: UniEvmToken,
|
||||
tokenOut: UniEvmToken,
|
||||
async fetchExactOutQuote(
|
||||
amountOut: string,
|
||||
slippage: string
|
||||
): Promise<ethers.BigNumber> {
|
||||
): Promise<string> {
|
||||
// get the quote
|
||||
const trade = await this.computeTradeExactOut(tokenIn, tokenOut, amountOut);
|
||||
const trade = await this.computeTradeExactOut(amountOut);
|
||||
|
||||
const tokenIn = this.tokenIn;
|
||||
const decimals = tokenIn.getDecimals();
|
||||
|
||||
// calculate output amount with slippage
|
||||
|
@ -209,7 +216,12 @@ export class SingleAmmSwapRouter extends UniswapRouterCore {
|
|||
.divUnsafe(slippageDivisor)
|
||||
.round(decimals);
|
||||
|
||||
return tokenIn.computeUnitAmount(maxAmountInWithSlippage.toString());
|
||||
/*
|
||||
return tokenIn
|
||||
.computeUnitAmount(maxAmountInWithSlippage.toString())
|
||||
.toString();
|
||||
*/
|
||||
return maxAmountInWithSlippage.toString();
|
||||
}
|
||||
|
||||
getProtocol(): string {
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import { ethers } from "ethers";
|
||||
import { TransactionReceipt } from "@ethersproject/abstract-provider";
|
||||
import {
|
||||
CHAIN_ID_POLYGON as WORMHOLE_CHAIN_ID_POLYGON,
|
||||
CHAIN_ID_ETH as WORMHOLE_CHAIN_ID_ETHEREUM,
|
||||
ChainId,
|
||||
getEmitterAddressEth,
|
||||
hexToUint8Array,
|
||||
nativeToHexString,
|
||||
parseSequenceFromLogEth,
|
||||
getSignedVAAWithRetry,
|
||||
//getSignedVAAWithRetry,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import getSignedVAAWithRetry from "@certusone/wormhole-sdk/lib/cjs/rpc/getSignedVAAWithRetry";
|
||||
import { grpc } from "@improbable-eng/grpc-web";
|
||||
import { UniEvmToken } from "../route/uniswap-core";
|
||||
import {
|
||||
|
@ -21,15 +20,22 @@ import {
|
|||
UniswapToUniswapQuoter,
|
||||
} from "../route/cross-quote";
|
||||
import {
|
||||
TOKEN_BRIDGE_ADDRESS_ETHEREUM,
|
||||
TOKEN_BRIDGE_ADDRESS_POLYGON,
|
||||
TOKEN_BRIDGE_ADDRESS_TERRA,
|
||||
CORE_BRIDGE_ADDRESS_ETHEREUM,
|
||||
CORE_BRIDGE_ADDRESS_POLYGON,
|
||||
TOKEN_BRIDGE_ADDRESS_ETHEREUM,
|
||||
CORE_BRIDGE_ADDRESS_TERRA,
|
||||
WORMHOLE_CHAIN_ID_ETHEREUM,
|
||||
WORMHOLE_CHAIN_ID_POLYGON,
|
||||
WORMHOLE_CHAIN_ID_TERRA,
|
||||
WORMHOLE_RPC_HOSTS,
|
||||
POLYGON_NETWORK_CHAIN_ID,
|
||||
ETH_NETWORK_CHAIN_ID,
|
||||
//ETH_NETWORK_CHAIN_ID,
|
||||
//POLYGON_NETWORK_CHAIN_ID,
|
||||
//TERRA_NETWORK_CHAIN_ID,
|
||||
WETH_TOKEN_INFO,
|
||||
WMATIC_TOKEN_INFO,
|
||||
UST_TOKEN_INFO,
|
||||
} from "../utils/consts";
|
||||
import {
|
||||
CROSSCHAINSWAP_GAS_PARAMETERS,
|
||||
|
@ -38,10 +44,13 @@ import {
|
|||
swapExactOutFromVaaNative,
|
||||
swapExactOutFromVaaToken,
|
||||
} from "./util";
|
||||
import { abi as SWAP_CONTRACT_V2_ABI } from "../abi/contracts/CrossChainSwapV2.json";
|
||||
import { abi as SWAP_CONTRACT_V3_ABI } from "../abi/contracts/CrossChainSwapV3.json";
|
||||
import { SWAP_CONTRACT_ADDRESS as CROSSCHAINSWAP_CONTRACT_ADDRESS_ETHEREUM } from "../addresses/goerli";
|
||||
import { SWAP_CONTRACT_ADDRESS as CROSSCHAINSWAP_CONTRACT_ADDRESS_POLYGON } from "../addresses/mumbai";
|
||||
import { abi as SWAP_CONTRACT_V2_ABI } from "../../abi/contracts/CrossChainSwapV2.json";
|
||||
import { abi as SWAP_CONTRACT_V3_ABI } from "../../abi/contracts/CrossChainSwapV3.json";
|
||||
import { SWAP_CONTRACT_ADDRESS as CROSSCHAINSWAP_CONTRACT_ADDRESS_ETHEREUM } from "../../scripts/contract-addresses/goerli";
|
||||
import { SWAP_CONTRACT_ADDRESS as CROSSCHAINSWAP_CONTRACT_ADDRESS_POLYGON } from "../../scripts/contract-addresses/mumbai";
|
||||
|
||||
// placeholders
|
||||
const CROSSCHAINSWAP_CONTRACT_ADDRESS_TERRA = "";
|
||||
|
||||
interface SwapContractParameters {
|
||||
address: string;
|
||||
|
@ -80,21 +89,35 @@ const EXECUTION_PARAMETERS_POLYGON: ExecutionParameters = {
|
|||
},
|
||||
};
|
||||
|
||||
function makeExecutionParameters(id: number): ExecutionParameters {
|
||||
switch (id) {
|
||||
case ETH_NETWORK_CHAIN_ID: {
|
||||
const EXECUTION_PARAMETERS_TERRA: ExecutionParameters = {
|
||||
crossChainSwap: {
|
||||
address: CROSSCHAINSWAP_CONTRACT_ADDRESS_TERRA,
|
||||
},
|
||||
wormhole: {
|
||||
chainId: WORMHOLE_CHAIN_ID_TERRA,
|
||||
coreBridgeAddress: CORE_BRIDGE_ADDRESS_TERRA,
|
||||
tokenBridgeAddress: TOKEN_BRIDGE_ADDRESS_TERRA,
|
||||
},
|
||||
};
|
||||
|
||||
function makeExecutionParameters(chainId: ChainId): ExecutionParameters {
|
||||
switch (chainId) {
|
||||
case WORMHOLE_CHAIN_ID_ETHEREUM: {
|
||||
return EXECUTION_PARAMETERS_ETHEREUM;
|
||||
}
|
||||
case POLYGON_NETWORK_CHAIN_ID: {
|
||||
case WORMHOLE_CHAIN_ID_POLYGON: {
|
||||
return EXECUTION_PARAMETERS_POLYGON;
|
||||
}
|
||||
case WORMHOLE_CHAIN_ID_TERRA: {
|
||||
return EXECUTION_PARAMETERS_TERRA;
|
||||
}
|
||||
default: {
|
||||
throw Error("unrecognized chain id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function approveContractTokenSpend(
|
||||
async function evmApproveContractTokenSpend(
|
||||
provider: ethers.providers.Provider,
|
||||
signer: ethers.Signer,
|
||||
tokenContract: ethers.Contract,
|
||||
|
@ -140,7 +163,7 @@ function makeCrossChainSwapV2Contract(
|
|||
return new ethers.Contract(contractAddress, SWAP_CONTRACT_V2_ABI, provider);
|
||||
}
|
||||
|
||||
function makeCrossChainSwapContract(
|
||||
function makeCrossChainSwapEvmContract(
|
||||
provider: ethers.providers.Provider,
|
||||
protocol: string,
|
||||
contractAddress: string
|
||||
|
@ -163,7 +186,7 @@ function addressToBytes32(
|
|||
return hexToUint8Array(hexString);
|
||||
}
|
||||
|
||||
async function approveAndSwapExactIn(
|
||||
async function evmApproveAndSwapExactIn(
|
||||
srcProvider: ethers.providers.Provider,
|
||||
srcWallet: ethers.Signer,
|
||||
srcTokenIn: UniEvmToken,
|
||||
|
@ -175,7 +198,7 @@ async function approveAndSwapExactIn(
|
|||
const swapContractParams = srcExecutionParams.crossChainSwap;
|
||||
|
||||
const protocol = quoteParams.src.protocol;
|
||||
const swapContract = makeCrossChainSwapContract(
|
||||
const swapContract = makeCrossChainSwapEvmContract(
|
||||
srcProvider,
|
||||
protocol,
|
||||
swapContractParams.address
|
||||
|
@ -187,18 +210,19 @@ async function approveAndSwapExactIn(
|
|||
|
||||
const address = await srcWallet.getAddress();
|
||||
|
||||
const dstWormholeChainId = dstExecutionParams.wormhole.chainId;
|
||||
|
||||
const swapParams = [
|
||||
amountIn,
|
||||
quoteParams.src.minAmountOut,
|
||||
quoteParams.dst.minAmountOut,
|
||||
address,
|
||||
addressToBytes32(address, dstWormholeChainId),
|
||||
quoteParams.src.deadline,
|
||||
quoteParams.dst.poolFee || quoteParams.src.poolFee,
|
||||
];
|
||||
|
||||
const pathArray = quoteParams.src.path.concat(quoteParams.dst.path);
|
||||
|
||||
const dstWormholeChainId = dstExecutionParams.wormhole.chainId;
|
||||
const dstContractAddress = addressToBytes32(
|
||||
dstExecutionParams.crossChainSwap.address,
|
||||
dstWormholeChainId
|
||||
|
@ -227,7 +251,7 @@ async function approveAndSwapExactIn(
|
|||
return tx.wait();
|
||||
} else {
|
||||
console.info("approving contract to spend token in");
|
||||
await approveContractTokenSpend(
|
||||
await evmApproveContractTokenSpend(
|
||||
srcProvider,
|
||||
srcWallet,
|
||||
srcTokenIn.getContract(),
|
||||
|
@ -249,7 +273,7 @@ async function approveAndSwapExactIn(
|
|||
}
|
||||
}
|
||||
|
||||
async function approveAndSwapExactOut(
|
||||
async function evmApproveAndSwapExactOut(
|
||||
srcProvider: ethers.providers.Provider,
|
||||
srcWallet: ethers.Signer,
|
||||
srcTokenIn: UniEvmToken,
|
||||
|
@ -261,7 +285,7 @@ async function approveAndSwapExactOut(
|
|||
const swapContractParams = srcExecutionParams.crossChainSwap;
|
||||
|
||||
const protocol = quoteParams.src.protocol;
|
||||
const swapContract = makeCrossChainSwapContract(
|
||||
const swapContract = makeCrossChainSwapEvmContract(
|
||||
srcProvider,
|
||||
protocol,
|
||||
swapContractParams.address
|
||||
|
@ -274,17 +298,18 @@ async function approveAndSwapExactOut(
|
|||
|
||||
const address = await srcWallet.getAddress();
|
||||
|
||||
const dstWormholeChainId = dstExecutionParams.wormhole.chainId;
|
||||
|
||||
const swapParams = [
|
||||
amountOut,
|
||||
maxAmountIn,
|
||||
quoteParams.dst.amountOut,
|
||||
address,
|
||||
addressToBytes32(address, dstWormholeChainId),
|
||||
quoteParams.src.deadline,
|
||||
quoteParams.dst.poolFee || quoteParams.src.poolFee,
|
||||
];
|
||||
const pathArray = quoteParams.src.path.concat(quoteParams.dst.path);
|
||||
|
||||
const dstWormholeChainId = dstExecutionParams.wormhole.chainId;
|
||||
const dstContractAddress = addressToBytes32(
|
||||
dstExecutionParams.crossChainSwap.address,
|
||||
dstWormholeChainId
|
||||
|
@ -313,7 +338,7 @@ async function approveAndSwapExactOut(
|
|||
return tx.wait();
|
||||
} else {
|
||||
console.info("approving contract to spend token in");
|
||||
await approveContractTokenSpend(
|
||||
await evmApproveContractTokenSpend(
|
||||
srcProvider,
|
||||
srcWallet,
|
||||
srcTokenIn.getContract(),
|
||||
|
@ -345,7 +370,7 @@ async function swapExactInFromVaa(
|
|||
): Promise<TransactionReceipt> {
|
||||
const swapContractParams = dstExecutionParams.crossChainSwap;
|
||||
|
||||
const swapContract = makeCrossChainSwapContract(
|
||||
const swapContract = makeCrossChainSwapEvmContract(
|
||||
dstProvider,
|
||||
dstProtocol,
|
||||
swapContractParams.address
|
||||
|
@ -371,7 +396,7 @@ async function swapExactOutFromVaa(
|
|||
): Promise<TransactionReceipt> {
|
||||
const swapContractParams = dstExecutionParams.crossChainSwap;
|
||||
|
||||
const swapContract = makeCrossChainSwapContract(
|
||||
const swapContract = makeCrossChainSwapEvmContract(
|
||||
dstProvider,
|
||||
dstProtocol,
|
||||
swapContractParams.address
|
||||
|
@ -399,7 +424,7 @@ interface VaaSearchParams {
|
|||
emitterAddress: string;
|
||||
}
|
||||
|
||||
export function makeProvider(tokenAddress: string) {
|
||||
export function makeEvmProvider(tokenAddress: string) {
|
||||
switch (tokenAddress) {
|
||||
case WETH_TOKEN_INFO.address: {
|
||||
const url = process.env.REACT_APP_GOERLI_PROVIDER;
|
||||
|
@ -416,6 +441,7 @@ export function makeProvider(tokenAddress: string) {
|
|||
return new ethers.providers.StaticJsonRpcProvider(url);
|
||||
}
|
||||
default: {
|
||||
console.log("huh?", tokenAddress);
|
||||
throw Error("unrecognized token address");
|
||||
}
|
||||
}
|
||||
|
@ -440,8 +466,16 @@ export class UniswapToUniswapExecutor {
|
|||
transportFactory: grpc.TransportFactory;
|
||||
vaaSearchParams: VaaSearchParams;
|
||||
vaaBytes: Uint8Array;
|
||||
srcReceipt: TransactionReceipt;
|
||||
dstReceipt: TransactionReceipt;
|
||||
|
||||
// receipts
|
||||
srcEvmReceipt: TransactionReceipt;
|
||||
dstEvmReceipt: TransactionReceipt;
|
||||
srcTerraReceipt: any;
|
||||
dstTerraReceipt: any;
|
||||
|
||||
constructor() {
|
||||
this.quoter = new UniswapToUniswapQuoter();
|
||||
}
|
||||
|
||||
async initialize(
|
||||
tokenInAddress: string,
|
||||
|
@ -450,20 +484,14 @@ export class UniswapToUniswapExecutor {
|
|||
): Promise<void> {
|
||||
this.isNative = isNative;
|
||||
|
||||
const srcProvider = makeProvider(tokenInAddress);
|
||||
const dstProvider = makeProvider(tokenOutAddress);
|
||||
|
||||
this.quoter = new UniswapToUniswapQuoter(srcProvider, dstProvider);
|
||||
await this.quoter.initialize();
|
||||
|
||||
await this.makeTokens(tokenInAddress, tokenOutAddress);
|
||||
await this.quoter.initialize(tokenInAddress, tokenOutAddress);
|
||||
|
||||
// now that we have a chain id for each network, get contract info for each chain
|
||||
this.srcExecutionParams = makeExecutionParameters(
|
||||
this.quoter.srcNetwork.chainId
|
||||
this.quoter.getSrcChainId()
|
||||
);
|
||||
this.dstExecutionParams = makeExecutionParameters(
|
||||
this.quoter.dstNetwork.chainId
|
||||
this.quoter.getDstChainId()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -483,6 +511,7 @@ export class UniswapToUniswapExecutor {
|
|||
this.quoter.setDeadlines(deadline);
|
||||
}
|
||||
|
||||
/*
|
||||
async makeTokens(
|
||||
tokenInAddress: string,
|
||||
tokenOutAddress: string
|
||||
|
@ -507,7 +536,7 @@ export class UniswapToUniswapExecutor {
|
|||
getTokens(): CrossChainSwapTokens {
|
||||
return this.tokens;
|
||||
}
|
||||
|
||||
*/
|
||||
async computeAndVerifySrcPoolAddress(): Promise<string> {
|
||||
return this.quoter.computeAndVerifySrcPoolAddress();
|
||||
}
|
||||
|
@ -546,19 +575,19 @@ export class UniswapToUniswapExecutor {
|
|||
return this.cachedExactOutParams;
|
||||
}
|
||||
|
||||
getSrcProvider(): ethers.providers.Provider {
|
||||
return this.quoter.srcProvider;
|
||||
getSrcEvmProvider(): ethers.providers.Provider {
|
||||
return this.quoter.getSrcEvmProvider();
|
||||
}
|
||||
|
||||
getDstProvider(): ethers.providers.Provider {
|
||||
return this.quoter.dstProvider;
|
||||
getDstEvmProvider(): ethers.providers.Provider {
|
||||
return this.quoter.getDstEvmProvider();
|
||||
}
|
||||
|
||||
async approveAndSwapExactIn(
|
||||
async evmApproveAndSwapExactIn(
|
||||
wallet: ethers.Signer
|
||||
): Promise<TransactionReceipt> {
|
||||
return approveAndSwapExactIn(
|
||||
this.getSrcProvider(),
|
||||
return evmApproveAndSwapExactIn(
|
||||
this.getSrcEvmProvider(),
|
||||
wallet,
|
||||
this.tokens.srcIn,
|
||||
this.cachedExactInParams,
|
||||
|
@ -568,11 +597,11 @@ export class UniswapToUniswapExecutor {
|
|||
);
|
||||
}
|
||||
|
||||
async approveAndSwapExactOut(
|
||||
async evmApproveAndSwapExactOut(
|
||||
wallet: ethers.Signer
|
||||
): Promise<TransactionReceipt> {
|
||||
return approveAndSwapExactOut(
|
||||
this.getSrcProvider(),
|
||||
return evmApproveAndSwapExactOut(
|
||||
this.getSrcEvmProvider(),
|
||||
wallet,
|
||||
this.tokens.srcIn,
|
||||
this.cachedExactOutParams,
|
||||
|
@ -582,23 +611,40 @@ export class UniswapToUniswapExecutor {
|
|||
);
|
||||
}
|
||||
|
||||
async approveAndSwap(wallet: ethers.Signer): Promise<TransactionReceipt> {
|
||||
srcIsUst(): boolean {
|
||||
return (
|
||||
this.quoter.tokenInAddress === UST_TOKEN_INFO.address &&
|
||||
this.cachedExactInParams.src === undefined
|
||||
);
|
||||
}
|
||||
|
||||
async evmApproveAndSwap(wallet: ethers.Signer): Promise<TransactionReceipt> {
|
||||
const quoteType = this.quoteType;
|
||||
|
||||
if (quoteType === QuoteType.ExactIn) {
|
||||
this.srcReceipt = await this.approveAndSwapExactIn(wallet);
|
||||
this.srcEvmReceipt = await this.evmApproveAndSwapExactIn(wallet);
|
||||
} else if (quoteType === QuoteType.ExactOut) {
|
||||
this.srcReceipt = await this.approveAndSwapExactOut(wallet);
|
||||
this.srcEvmReceipt = await this.evmApproveAndSwapExactOut(wallet);
|
||||
} else {
|
||||
throw Error("no quote found");
|
||||
}
|
||||
|
||||
this.fetchAndSetEmitterAndSequence();
|
||||
return this.srcReceipt;
|
||||
return this.srcEvmReceipt;
|
||||
}
|
||||
|
||||
fetchAndSetEmitterAndSequence(): void {
|
||||
const receipt = this.srcReceipt;
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
|
||||
fetchAndSetTerraEmitterAndSequence(): void {
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
|
||||
fetchAndSetEvmEmitterAndSequence(): void {
|
||||
const receipt = this.srcEvmReceipt;
|
||||
if (receipt === undefined) {
|
||||
throw Error("no swap receipt found");
|
||||
}
|
||||
|
@ -623,11 +669,15 @@ export class UniswapToUniswapExecutor {
|
|||
const emitterAddress = vaaSearchParams.emitterAddress;
|
||||
console.info(`sequence: ${sequence}, emitterAddress: ${emitterAddress}`);
|
||||
// wait for VAA to be signed
|
||||
|
||||
const vaaResponse = await getSignedVAAWithRetry(
|
||||
WORMHOLE_RPC_HOSTS,
|
||||
this.srcExecutionParams.wormhole.chainId,
|
||||
vaaSearchParams.emitterAddress,
|
||||
vaaSearchParams.sequence
|
||||
vaaSearchParams.sequence,
|
||||
{
|
||||
transport: this.transportFactory,
|
||||
}
|
||||
);
|
||||
// grab vaaBytes
|
||||
this.vaaBytes = vaaResponse.vaaBytes;
|
||||
|
@ -636,22 +686,27 @@ export class UniswapToUniswapExecutor {
|
|||
async fetchVaaAndSwap(wallet: ethers.Signer): Promise<TransactionReceipt> {
|
||||
await this.fetchSignedVaaFromSwap();
|
||||
|
||||
// check if Terra transaction
|
||||
// TODO: change return as something else (not evm TransactionReceipt)
|
||||
|
||||
const quoteType = this.quoteType;
|
||||
|
||||
if (quoteType === QuoteType.ExactIn) {
|
||||
this.dstReceipt = await this.swapExactInFromVaa(wallet);
|
||||
this.dstEvmReceipt = await this.evmSwapExactInFromVaa(wallet);
|
||||
} else if (quoteType === QuoteType.ExactOut) {
|
||||
this.dstReceipt = await this.swapExactOutFromVaa(wallet);
|
||||
this.dstEvmReceipt = await this.evmSwapExactOutFromVaa(wallet);
|
||||
} else {
|
||||
throw Error("no quote found");
|
||||
}
|
||||
|
||||
return this.dstReceipt;
|
||||
return this.dstEvmReceipt;
|
||||
}
|
||||
|
||||
async swapExactInFromVaa(wallet: ethers.Signer): Promise<TransactionReceipt> {
|
||||
async evmSwapExactInFromVaa(
|
||||
wallet: ethers.Signer
|
||||
): Promise<TransactionReceipt> {
|
||||
return swapExactInFromVaa(
|
||||
this.getDstProvider(),
|
||||
this.getDstEvmProvider(),
|
||||
wallet,
|
||||
this.dstExecutionParams,
|
||||
this.cachedExactInParams.dst.protocol,
|
||||
|
@ -660,11 +715,11 @@ export class UniswapToUniswapExecutor {
|
|||
);
|
||||
}
|
||||
|
||||
async swapExactOutFromVaa(
|
||||
async evmSwapExactOutFromVaa(
|
||||
wallet: ethers.Signer
|
||||
): Promise<TransactionReceipt> {
|
||||
return swapExactOutFromVaa(
|
||||
this.getDstProvider(),
|
||||
this.getDstEvmProvider(),
|
||||
wallet,
|
||||
this.dstExecutionParams,
|
||||
this.cachedExactOutParams.dst.protocol,
|
||||
|
@ -673,6 +728,10 @@ export class UniswapToUniswapExecutor {
|
|||
);
|
||||
}
|
||||
|
||||
setTransport(transportFactory: grpc.TransportFactory) {
|
||||
this.transportFactory = transportFactory;
|
||||
}
|
||||
|
||||
//getSwapResult(
|
||||
// walletAddress: string,
|
||||
// onSwapResult: (result: boolean) => void
|
||||
|
@ -680,7 +739,7 @@ export class UniswapToUniswapExecutor {
|
|||
// console.log(this.cachedExactInParams.dst.protocol);
|
||||
// console.log(this.dstExecutionParams.crossChainSwap.address);
|
||||
// const contract = makeCrossChainSwapContract(
|
||||
// this.getDstProvider(),
|
||||
// this.getDstEvmProvider(),
|
||||
// this.quoteType === QuoteType.ExactIn
|
||||
// ? this.cachedExactInParams.dst.protocol
|
||||
// : this.cachedExactOutParams.dst.protocol,
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
import {
|
||||
ChainId,
|
||||
CHAIN_ID_ETH,
|
||||
CHAIN_ID_POLYGON,
|
||||
CHAIN_ID_ETH as WORMHOLE_CHAIN_ID_ETHEREUM,
|
||||
CHAIN_ID_POLYGON as WORMHOLE_CHAIN_ID_POLYGON,
|
||||
CHAIN_ID_TERRA as WORMHOLE_CHAIN_ID_TERRA,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import ethIcon from "../icons/eth.svg";
|
||||
import polygonIcon from "../icons/polygon.svg";
|
||||
//import ethIcon from "../icons/eth.svg";
|
||||
//import polygonIcon from "../icons/polygon.svg";
|
||||
|
||||
const ethIcon = undefined;
|
||||
const polygonIcon = undefined;
|
||||
const ustIcon = undefined;
|
||||
|
||||
export {
|
||||
WORMHOLE_CHAIN_ID_ETHEREUM,
|
||||
WORMHOLE_CHAIN_ID_POLYGON,
|
||||
WORMHOLE_CHAIN_ID_TERRA,
|
||||
};
|
||||
|
||||
export interface TokenInfo {
|
||||
name: string;
|
||||
|
@ -13,42 +24,57 @@ export interface TokenInfo {
|
|||
logo: string;
|
||||
isNative: boolean;
|
||||
maxAmount: number;
|
||||
ustPairedAddress: string;
|
||||
}
|
||||
|
||||
export const MATIC_TOKEN_INFO: TokenInfo = {
|
||||
name: "MATIC",
|
||||
address: "0x9c3c9283d3e44854697cd22d3faa240cfb032889", // used to compute quote
|
||||
chainId: CHAIN_ID_POLYGON,
|
||||
chainId: WORMHOLE_CHAIN_ID_POLYGON,
|
||||
logo: polygonIcon,
|
||||
isNative: true,
|
||||
maxAmount: 0.1,
|
||||
ustPairedAddress: "0xe3a1c77e952b57b5883f6c906fc706fcc7d4392c",
|
||||
};
|
||||
|
||||
export const WMATIC_TOKEN_INFO: TokenInfo = {
|
||||
name: "WMATIC",
|
||||
address: "0x9c3c9283d3e44854697cd22d3faa240cfb032889",
|
||||
chainId: CHAIN_ID_POLYGON,
|
||||
chainId: WORMHOLE_CHAIN_ID_POLYGON,
|
||||
logo: polygonIcon,
|
||||
isNative: false,
|
||||
maxAmount: 0.1,
|
||||
ustPairedAddress: "0xe3a1c77e952b57b5883f6c906fc706fcc7d4392c",
|
||||
};
|
||||
|
||||
export const ETH_TOKEN_INFO: TokenInfo = {
|
||||
name: "ETH",
|
||||
address: "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6", // used to compute quote
|
||||
chainId: CHAIN_ID_ETH,
|
||||
chainId: WORMHOLE_CHAIN_ID_ETHEREUM,
|
||||
logo: ethIcon,
|
||||
isNative: true,
|
||||
maxAmount: 0.01,
|
||||
ustPairedAddress: "0x36Ed51Afc79619b299b238898E72ce482600568a",
|
||||
};
|
||||
|
||||
export const WETH_TOKEN_INFO: TokenInfo = {
|
||||
name: "WETH",
|
||||
address: "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6",
|
||||
chainId: CHAIN_ID_ETH,
|
||||
chainId: WORMHOLE_CHAIN_ID_ETHEREUM,
|
||||
logo: ethIcon,
|
||||
isNative: false,
|
||||
maxAmount: 0.01,
|
||||
ustPairedAddress: "0x36Ed51Afc79619b299b238898E72ce482600568a",
|
||||
};
|
||||
|
||||
export const UST_TOKEN_INFO: TokenInfo = {
|
||||
name: "UST",
|
||||
address: "uusd",
|
||||
chainId: WORMHOLE_CHAIN_ID_TERRA,
|
||||
logo: ustIcon,
|
||||
isNative: false,
|
||||
maxAmount: 10.0,
|
||||
ustPairedAddress: undefined,
|
||||
};
|
||||
|
||||
export const TOKEN_INFOS = [
|
||||
|
@ -56,19 +82,21 @@ export const TOKEN_INFOS = [
|
|||
WMATIC_TOKEN_INFO,
|
||||
ETH_TOKEN_INFO,
|
||||
WETH_TOKEN_INFO,
|
||||
UST_TOKEN_INFO,
|
||||
];
|
||||
|
||||
export const ETH_NETWORK_CHAIN_ID = 5;
|
||||
|
||||
export const POLYGON_NETWORK_CHAIN_ID = 80001;
|
||||
// evm handling
|
||||
export const EVM_ETH_NETWORK_CHAIN_ID = 5;
|
||||
export const EVM_POLYGON_NETWORK_CHAIN_ID = 80001;
|
||||
|
||||
export const getEvmChainId = (chainId: ChainId) =>
|
||||
chainId === CHAIN_ID_ETH
|
||||
? ETH_NETWORK_CHAIN_ID
|
||||
: chainId === CHAIN_ID_POLYGON
|
||||
? POLYGON_NETWORK_CHAIN_ID
|
||||
chainId === WORMHOLE_CHAIN_ID_ETHEREUM
|
||||
? EVM_ETH_NETWORK_CHAIN_ID
|
||||
: chainId === WORMHOLE_CHAIN_ID_POLYGON
|
||||
? EVM_POLYGON_NETWORK_CHAIN_ID
|
||||
: undefined;
|
||||
|
||||
// misc
|
||||
export const RELAYER_FEE_UST = "0.25";
|
||||
|
||||
export const WORMHOLE_RPC_HOSTS = [
|
||||
|
@ -81,12 +109,16 @@ export const CORE_BRIDGE_ADDRESS_ETHEREUM =
|
|||
export const CORE_BRIDGE_ADDRESS_POLYGON =
|
||||
"0x0CBE91CF822c73C2315FB05100C2F714765d5c20";
|
||||
|
||||
export const CORE_BRIDGE_ADDRESS_TERRA = undefined;
|
||||
|
||||
export const TOKEN_BRIDGE_ADDRESS_ETHEREUM =
|
||||
"0xF890982f9310df57d00f659cf4fd87e65adEd8d7";
|
||||
|
||||
export const TOKEN_BRIDGE_ADDRESS_POLYGON =
|
||||
"0x377D55a7928c046E18eEbb61977e714d2a76472a";
|
||||
|
||||
export const TOKEN_BRIDGE_ADDRESS_TERRA = undefined;
|
||||
|
||||
export const QUICKSWAP_FACTORY_ADDRESS =
|
||||
"0x5757371414417b8C6CAad45bAeF941aBc7d3Ab32";
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { FixedNumber } from "ethers";
|
||||
|
||||
export function addFixedAmounts(
|
||||
left: string,
|
||||
right: string,
|
||||
decimals: number
|
||||
): string {
|
||||
const sum = FixedNumber.from(left).addUnsafe(FixedNumber.from(right));
|
||||
return sum.round(this.getDecimals()).toString();
|
||||
}
|
||||
|
||||
export function subtractFixedAmounts(
|
||||
left: string,
|
||||
right: string,
|
||||
decimals: number
|
||||
): string {
|
||||
const diff = FixedNumber.from(left).subUnsafe(FixedNumber.from(right));
|
||||
return diff.round(decimals).toString();
|
||||
}
|
Loading…
Reference in New Issue