Skip to content

Commit

Permalink
feat: calc minimum receive
Browse files Browse the repository at this point in the history
  • Loading branch information
trung2891 committed Oct 4, 2024
1 parent 40e9135 commit fa54662
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 35 deletions.
24 changes: 24 additions & 0 deletions packages/universal-swap/src/msg/chains/chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Path } from "../../types";
import { validatePath, validateReceiver } from "../common";

export class ChainMsg {
constructor(
protected path: Path,
protected minimumReceive: string,
protected receiver: string,
protected currentChainAddress: string,
protected memo: string = ""
) {
// validate path
validatePath(path);
validateReceiver(receiver, currentChainAddress, path.chainId);
}

setMinimumReceive(minimumReceive: string) {
this.minimumReceive = minimumReceive;
}

getMinimumReceive() {
return this.minimumReceive;
}
}
29 changes: 18 additions & 11 deletions packages/universal-swap/src/msg/chains/cosmos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,31 @@ import { ActionType, Path } from "../../types";
import { Action } from "@oraichain/osor-api-contracts-sdk/src/EntryPoint.types";
import { validatePath, validateReceiver } from "../common";
import {
BigDecimal,
calculateTimeoutTimestamp,
generateError,
IBC_TRANSFER_TIMEOUT,
NetworkChainId
} from "@oraichain/oraidex-common";

import { EncodeObject } from "@cosmjs/proto-signing";
import { ChainMsg } from "./chain";

export class CosmosMsg {
constructor(
protected path: Path,
protected minimumReceive: string,
protected receiver: string,
protected currentChainAddress: string,
protected memo: string = ""
) {
// validate path
validatePath(path);
validateReceiver(receiver, currentChainAddress, path.chainId);
export class CosmosMsg extends ChainMsg {
constructor(path: Path, minimumReceive: string, receiver: string, currentChainAddress: string, memo: string = "") {
super(path, minimumReceive, receiver, currentChainAddress, memo);
}

setMinimumReceiveForSwap(slippage: number = 0.01) {
if (slippage > 1) {
throw generateError("Slippage must be less than 1");
}
let bridgeInfo = this.getBridgeInfo();
let minimumReceive = new BigDecimal(1 - slippage).mul(bridgeInfo.amount).toString();
if (minimumReceive.includes(".")) {
minimumReceive = minimumReceive.split(".")[0];
}
this.minimumReceive = minimumReceive;
}

/**
Expand All @@ -34,6 +40,7 @@ export class CosmosMsg {
switch (action.type) {
case ActionType.Bridge: {
bridgeInfo = {
amount: action.tokenInAmount,
sourceChannel: action.bridgeInfo.channel,
sourcePort: action.bridgeInfo.port,
memo: this.memo,
Expand Down
34 changes: 25 additions & 9 deletions packages/universal-swap/src/msg/chains/oraichain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SwapOperation } from "@oraichain/osor-api-contracts-sdk/src/types";
import { Action, ExecuteMsg } from "@oraichain/osor-api-contracts-sdk/src/EntryPoint.types";
import { isCw20Token, validatePath, validateReceiver } from "../common";
import {
BigDecimal,
calculateTimeoutTimestamp,
CONVERTER_CONTRACT,
generateError,
Expand All @@ -17,28 +18,42 @@ import { EncodeObject } from "@cosmjs/proto-signing";
import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx";
import { TransferBackMsg } from "@oraichain/common-contracts-sdk/build/CwIcs20Latest.types";
import { toUtf8 } from "@cosmjs/encoding";
import { ChainMsg } from "./chain";

export class OraichainMsg {
export class OraichainMsg extends ChainMsg {
SWAP_VENUE_NAME = "oraidex";
ENTRY_POINT_CONTRACT = "orai13mgxn93pjvd7eermj4ghet8assxdqttxugwk25rasuuqq2g5nczq43eesn"; // FIXME: use mainnet

constructor(
protected path: Path,
protected minimumReceive: string,
protected receiver: string,
protected currentChainAddress: string,
protected memo: string = "",
path: Path,
minimumReceive: string,
receiver: string,
currentChainAddress: string,
memo: string = "",
protected destPrefix: string = undefined,
protected obridgeAddress: string = undefined
) {
super(path, minimumReceive, receiver, currentChainAddress, memo);
// check chainId = "Oraichain"
if (path.chainId !== "Oraichain") {
throw generateError("This path must be on Oraichain");
}
// validate path
validatePath(path);
validateReceiver(receiver, currentChainAddress, path.chainId);
}

setMinimumReceiveForSwap(slippage: number = 0.01) {
if (slippage > 1) {
throw generateError("Slippage must be less than 1");
}
let [_, bridgeInfo] = this.getSwapAndBridgeInfo();

let returnAmount = bridgeInfo ? bridgeInfo.amount : this.path.tokenOutAmount;
let minimumReceive = new BigDecimal(1 - slippage).mul(returnAmount).toString();
if (minimumReceive.includes(".")) {
minimumReceive = minimumReceive.split(".")[0];
}
this.minimumReceive = minimumReceive;
}

/**
* Converts the given input and output tokens to a pool ID using the converter contract in the Oraichain ecosystem.
* @param tokenIn The input token to be converted
Expand Down Expand Up @@ -109,6 +124,7 @@ export class OraichainMsg {
}
case ActionType.Bridge: {
bridgeInfo = {
amount: action.tokenInAmount,
sourceChannel: action.bridgeInfo.channel,
sourcePort: action.bridgeInfo.port,
memo: this.memo,
Expand Down
31 changes: 20 additions & 11 deletions packages/universal-swap/src/msg/chains/osmosis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SwapOperation } from "@oraichain/osor-api-contracts-sdk/src/types";
import { Swap, Action, ExecuteMsg } from "@oraichain/osor-api-contracts-sdk/src/EntryPoint.types";
import { isCw20Token, validatePath, validateReceiver } from "../common";
import {
BigDecimal,
calculateTimeoutTimestamp,
generateError,
IBC_TRANSFER_TIMEOUT,
Expand All @@ -13,25 +14,32 @@ import { toBinary } from "@cosmjs/cosmwasm-stargate";
import { EncodeObject } from "@cosmjs/proto-signing";
import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx";
import { toUtf8 } from "@cosmjs/encoding";
import { ChainMsg } from "./chain";

export class OsmosisMsg {
export class OsmosisMsg extends ChainMsg {
SWAP_VENUE_NAME = "osmosis-poolmanager";
ENTRY_POINT_CONTRACT = "osmo1h3jkejkcpthl45xrrm5geed3eq75p5rgfce9taufkwfr89k63muqweu2y7";

constructor(
protected path: Path,
protected minimumReceive: string,
protected receiver: string,
protected currentChainAddress: string,
protected memo: string = ""
) {
constructor(path: Path, minimumReceive: string, receiver: string, currentChainAddress: string, memo: string = "") {
super(path, minimumReceive, receiver, currentChainAddress, memo);
// check chainId = "osmosis-1"
if (path.chainId !== "osmosis-1") {
throw generateError("This path must be on Osmosis");
}
// validate path
validatePath(path);
validateReceiver(receiver, currentChainAddress, path.chainId);
}

setMinimumReceiveForSwap(slippage: number = 0.01) {
if (slippage > 1) {
throw generateError("Slippage must be less than 1");
}
let [_, bridgeInfo] = this.getSwapAndBridgeInfo();

let returnAmount = bridgeInfo ? bridgeInfo.amount : this.path.tokenOutAmount;
let minimumReceive = new BigDecimal(1 - slippage).mul(returnAmount).toString();
if (minimumReceive.includes(".")) {
minimumReceive = minimumReceive.split(".")[0];
}
this.minimumReceive = minimumReceive;
}

/**
Expand Down Expand Up @@ -61,6 +69,7 @@ export class OsmosisMsg {
}
case ActionType.Bridge: {
bridgeInfo = {
amount: action.tokenInAmount,
sourceChannel: action.bridgeInfo.channel,
sourcePort: action.bridgeInfo.port,
memo: this.memo,
Expand Down
16 changes: 12 additions & 4 deletions packages/universal-swap/src/msg/msgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ const buildMemoSwap = (
path: Path,
receiver: string,
memo: string,
addresses: { [chainId: string]: string }
addresses: { [chainId: string]: string },
slippage: number = 0.01
): MiddleWareResponse => {
let currentChain = path.chainId;
let currentAddress = addresses[currentChain];
Expand All @@ -38,6 +39,7 @@ const buildMemoSwap = (
let prefix = getDestPrefixForBridgeToEvmOnOrai(path.tokenOutChainId);
let oBridgeAddress = addresses["OraiBridge"];
let oraichainMsg = new OraichainMsg(path, "1", receiver, currentAddress, memo, prefix, oBridgeAddress);
oraichainMsg.setMinimumReceiveForSwap(slippage);
let previousChain = path.chainId;
// we have 2 cases:
// - Previous chain use IBC bridge to Oraichain (noble)
Expand All @@ -47,6 +49,7 @@ const buildMemoSwap = (
}
case "osmosis-1": {
let cosmosMsg = new OsmosisMsg(path, "1", receiver, currentAddress, memo);
cosmosMsg.setMinimumReceiveForSwap(slippage);
let msgInfo = cosmosMsg.genMemoAsMiddleware();
return msgInfo;
}
Expand All @@ -58,6 +61,7 @@ const buildMemoSwap = (
throw generateError("Don't support universal swap in EVM");
}
let cosmosMsg = new CosmosMsg(path, "1", receiver, currentAddress, memo);
cosmosMsg.setMinimumReceiveForSwap(slippage);
let msgInfo = cosmosMsg.genMemoAsMiddleware();
return msgInfo;
}
Expand All @@ -69,7 +73,8 @@ const buildExecuteMsg = (
path: Path,
receiver: string,
memo: string,
addresses: { [chainId: string]: string }
addresses: { [chainId: string]: string },
slippage: number = 0.01
): EncodeObject => {
let currentChain = path.chainId;
let currentAddress = addresses[currentChain];
Expand All @@ -78,10 +83,12 @@ const buildExecuteMsg = (
let prefix = getDestPrefixForBridgeToEvmOnOrai(path.tokenOutChainId);
let oBridgeAddress = addresses["OraiBridge"];
let oraichainMsg = new OraichainMsg(path, "1", receiver, currentAddress, memo, prefix, oBridgeAddress);
oraichainMsg.setMinimumReceiveForSwap(slippage);
return oraichainMsg.genExecuteMsg();
}
case "osmosis-1": {
let cosmosMsg = new OsmosisMsg(path, "1", receiver, currentAddress, memo);
cosmosMsg.setMinimumReceiveForSwap(slippage);
return cosmosMsg.genExecuteMsg();
}

Expand All @@ -92,6 +99,7 @@ const buildExecuteMsg = (
throw generateError("Don't support universal swap in EVM");
}
let cosmosMsg = new CosmosMsg(path, "1", receiver, currentAddress, memo);
cosmosMsg.setMinimumReceiveForSwap(slippage);
return cosmosMsg.genExecuteMsg();
}
}
Expand All @@ -106,12 +114,12 @@ export const generateMsgSwap = (route: Route, slippage: number = 0.01, addresses

// generate memo for univeral swap
for (let i = route.paths.length - 1; i > 0; i--) {
let swapInfo = buildMemoSwap(route.paths[i], receiver, memo, addresses);
let swapInfo = buildMemoSwap(route.paths[i], receiver, memo, addresses, slippage);
memo = swapInfo.memo;
receiver = swapInfo.receiver;
}

return buildExecuteMsg(route.paths[0], receiver, memo, addresses);
return buildExecuteMsg(route.paths[0], receiver, memo, addresses, slippage);

// generate execute msg
};
1 change: 1 addition & 0 deletions packages/universal-swap/src/msg/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface SwapMsgInfo {
}

export interface BridgeMsgInfo {
amount: string;
sourceChannel: string;
sourcePort: string;
receiver: string;
Expand Down

0 comments on commit fa54662

Please sign in to comment.