Skip to content

Commit

Permalink
feat: Bundle wugnot wrap/unwrap transaction into a single multi msg (#…
Browse files Browse the repository at this point in the history
…337)

* feat: add withStaking options in add position

* feat: [GSW-752] Implement oneclick staking

* chore: Update build cache

* refactor: remove unused codes

* feat: Add Approve message to WUGNOT when calling MintAndStake function

* chore: Change gas wanted to 100_000_00

* feat: [GSW-1068] Bundle wugnot wrap/unwrap transaction into a single multi msg

* feat: Add swap router API

* feat: Add swap router API

* fix: Fix a test

* fix: Fix a insufficient balance condition

* feat: Handle token amount input

* fix: Fix a estimate swap parameters

* fix: Fix a estimate swap parameters

* fix: Fix a swap interaction

* feat: Apply swap router in reposition

* feat: Improve swap interaction (#353)

* feat: Improve swap interaction

* feat: Check minimum gnot amount condition

* chore: Update build cache

* feat: Add router api error handling
  • Loading branch information
jinoosss authored May 27, 2024
1 parent 8052769 commit 3b6e633
Show file tree
Hide file tree
Showing 33 changed files with 993 additions and 1,089 deletions.
2 changes: 1 addition & 1 deletion packages/swap-router/.ultra.cache.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"files":{"build":"1713170489386.185",".eslintignore":"7de3bd702df2dee92c033c49abbedd0b0f7452e6",".eslintrc.js":"ca4815a5cf5cffa1d3fb4a014c8c602f852b002a",".gitignore":"c87c9b392c0200d9c9dafc444386ad3e15a85c64",".prettierignore":"47bb4656eb55860a075be7799cba7fa955b68141",".prettierrc":"fe5f744c7a08b128c935d1e1aed3e8a577e74507","jest.config.json":"2e496ee6bd64eb237161dcd69a6957eff2df584d","package.json":"4dda70ca76fb6022f6cb20852ecd8d2d95d638d2","src/common/array.util.ts":"9482ab121d34cc7e08a0cd33b49173b0b85823d8","src/common/bigint.util.ts":"343f4c85ca1f6c840ade68c259ed82bf5b159fb0","src/common/index.ts":"861a3167cddfc93e9eb1b6a4ae8229bb9dc2f8fd","src/common/mapper.ts":"f7d7b491dff443911a978b34e4cb378bee46c2b7","src/common/queue.ts":"ad096fefbe1c5a7339b536b0b8d39dba661b520e","src/common/test.util.ts":"3e500df6ec27ba98606acbfcaec9243e22862e43","src/constants/index.ts":"9605b149deb525c25f6e93420bbc433ff1c75cd0","src/constants/math.constant.ts":"b617851527cabcc9c3bce2c8e39208001d379ad6","src/constants/swap.constant.ts":"53e280147c68acfba490bc1f9a0b7bb1580e7280","src/index.ts":"691efb21a28bd3f0e6437edcb16192789dbbb7f6","src/swap-router/index.ts":"effaf28a826bdf1441437643e8343e7fbd8026b1","src/swap-router/swap-router-default.spec.ts":"e78d6591f15c38821bd701796c5281a5000a98ce","src/swap-router/swap-router-multi-higher-range-position-pool.spec.ts":"683ce3a82d73e915018e772723700905c3ff7c92","src/swap-router/swap-router-multi-lower-range-position-pool.spec.ts":"93bfd18d0a297f3c66743cddcf2fe10c3764e250","src/swap-router/swap-router-multi-pair-pools.spec.ts":"642a9f24dc06b4ef5fb6f099b21b1dbec7f09d8f","src/swap-router/swap-router-multi-route.spec.ts":"2b37b87049e38971482716b93be7eb2d739ed135","src/swap-router/swap-router-single-pair-pools.spec.ts":"8508da991d741ce394e663680b87f56a5c9af30d","src/swap-router/swap-router.ts":"97c4ee1a2cb563be921352b60bbd7bff9535fb21","src/swap-router/swap-router.types.ts":"2a48987217df238256a0721d227952142a37ce08","src/swap-router/utility/index.ts":"4973874904dd9d77d037d72b1ec8aed397716a38","src/swap-router/utility/route.util.ts":"d492418c9184e42d3ef29d7760eb18fa013f54c6","src/swap-simulator/index.ts":"ef493c5977bdf1123d1197b804f2344ee463870c","src/swap-simulator/swap-simulator-default.spec.ts":"867788b12ccc70abe676010aeed5d6b2b58e8036","src/swap-simulator/swap-simulator.ts":"48cc4c90a2622d806659fa2f8c4f48d600a2b2db","src/swap-simulator/swap-simulator.types.ts":"11d929d55a895b0305375b3b69ac27c49a985ce0","src/swap-simulator/utility/cache.util.ts":"c5af86d350610a80a6690846657a35635bbc752a","src/swap-simulator/utility/index.ts":"7272f5d23dfa7af2895fca9bb0b17985234ab6e1","src/swap-simulator/utility/math.util.ts":"96fbe38cbabe344f6f58220f46c20103e6df4225","src/swap-simulator/utility/swap-util.spec.ts":"b7fe082f3fef7e5a912959925924f56f8c36e020","src/swap-simulator/utility/swap.util.ts":"f49236f0d22f72b9283244e870d34401d42fe009","src/swap-simulator/utility/tick.util.ts":"01d1fc86a1cfcf81aa8932c52bca9738916feab5","tsconfig.json":"55467bd5c5eb1b501abe50b952d5f2d9fa0a0d69"},"deps":{}}
{"files":{".vscode":"1700971955685.2515","build":"1713516446907.2502","node_modules":"1700891704503.8325",".eslintignore":"7de3bd702df2dee92c033c49abbedd0b0f7452e6",".eslintrc.js":"ca4815a5cf5cffa1d3fb4a014c8c602f852b002a",".gitignore":"c87c9b392c0200d9c9dafc444386ad3e15a85c64",".prettierignore":"47bb4656eb55860a075be7799cba7fa955b68141",".prettierrc":"fe5f744c7a08b128c935d1e1aed3e8a577e74507","jest.config.json":"2e496ee6bd64eb237161dcd69a6957eff2df584d","package.json":"4dda70ca76fb6022f6cb20852ecd8d2d95d638d2","src/common/array.util.ts":"9482ab121d34cc7e08a0cd33b49173b0b85823d8","src/common/bigint.util.ts":"343f4c85ca1f6c840ade68c259ed82bf5b159fb0","src/common/index.ts":"861a3167cddfc93e9eb1b6a4ae8229bb9dc2f8fd","src/common/mapper.ts":"f7d7b491dff443911a978b34e4cb378bee46c2b7","src/common/queue.ts":"ad096fefbe1c5a7339b536b0b8d39dba661b520e","src/common/test.util.ts":"3e500df6ec27ba98606acbfcaec9243e22862e43","src/constants/index.ts":"9605b149deb525c25f6e93420bbc433ff1c75cd0","src/constants/math.constant.ts":"b617851527cabcc9c3bce2c8e39208001d379ad6","src/constants/swap.constant.ts":"53e280147c68acfba490bc1f9a0b7bb1580e7280","src/index.ts":"691efb21a28bd3f0e6437edcb16192789dbbb7f6","src/swap-router/index.ts":"effaf28a826bdf1441437643e8343e7fbd8026b1","src/swap-router/swap-router-default.spec.ts":"e78d6591f15c38821bd701796c5281a5000a98ce","src/swap-router/swap-router-multi-higher-range-position-pool.spec.ts":"683ce3a82d73e915018e772723700905c3ff7c92","src/swap-router/swap-router-multi-lower-range-position-pool.spec.ts":"93bfd18d0a297f3c66743cddcf2fe10c3764e250","src/swap-router/swap-router-multi-pair-pools.spec.ts":"642a9f24dc06b4ef5fb6f099b21b1dbec7f09d8f","src/swap-router/swap-router-multi-route.spec.ts":"2b37b87049e38971482716b93be7eb2d739ed135","src/swap-router/swap-router-single-pair-pools.spec.ts":"8508da991d741ce394e663680b87f56a5c9af30d","src/swap-router/swap-router.ts":"97c4ee1a2cb563be921352b60bbd7bff9535fb21","src/swap-router/swap-router.types.ts":"2a48987217df238256a0721d227952142a37ce08","src/swap-router/utility/index.ts":"4973874904dd9d77d037d72b1ec8aed397716a38","src/swap-router/utility/route.util.ts":"d492418c9184e42d3ef29d7760eb18fa013f54c6","src/swap-simulator/index.ts":"ef493c5977bdf1123d1197b804f2344ee463870c","src/swap-simulator/swap-simulator-default.spec.ts":"867788b12ccc70abe676010aeed5d6b2b58e8036","src/swap-simulator/swap-simulator.ts":"48cc4c90a2622d806659fa2f8c4f48d600a2b2db","src/swap-simulator/swap-simulator.types.ts":"11d929d55a895b0305375b3b69ac27c49a985ce0","src/swap-simulator/utility/cache.util.ts":"c5af86d350610a80a6690846657a35635bbc752a","src/swap-simulator/utility/index.ts":"7272f5d23dfa7af2895fca9bb0b17985234ab6e1","src/swap-simulator/utility/math.util.ts":"96fbe38cbabe344f6f58220f46c20103e6df4225","src/swap-simulator/utility/swap-util.spec.ts":"b7fe082f3fef7e5a912959925924f56f8c36e020","src/swap-simulator/utility/swap.util.ts":"f49236f0d22f72b9283244e870d34401d42fe009","src/swap-simulator/utility/tick.util.ts":"01d1fc86a1cfcf81aa8932c52bca9738916feab5","tsconfig.json":"55467bd5c5eb1b501abe50b952d5f2d9fa0a0d69"},"deps":{}}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const isPreview = ENVIRONMENT === "preview";
const PREVIEW_ENV_VARIABLES = {
DEFAULT_CHAIN_ID: "dev.gnoswap",
API_URL: "https://dev.api.gnoswap.io/v1",
ROUTER_API_URL: "https://gnoswap-route-api.in.onbloc.xyz",
PACKAGE_ROUTER_PATH: "gno.land/r/demo/router",
PACKAGE_POOL_PATH: "gno.land/r/demo/pool",
PACKAGE_POSITION_PATH: "gno.land/r/demo/position",
Expand All @@ -26,6 +27,7 @@ const PREVIEW_ENV_VARIABLES = {
const ENV_VARIABLES = {
DEFAULT_CHAIN_ID: process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID || "",
API_URL: process.env.NEXT_PUBLIC_API_URL || "",
ROUTER_API_URL: process.env.NEXT_PUBLIC_ROUTER_API_URL || "",
PACKAGE_ROUTER_PATH: process.env.NEXT_PUBLIC_PACKAGE_ROUTER_PATH || "",
PACKAGE_POOL_PATH: process.env.NEXT_PUBLIC_PACKAGE_POOL_PATH || "",
PACKAGE_POSITION_PATH: process.env.NEXT_PUBLIC_PACKAGE_POSITION_PATH || "",
Expand All @@ -48,6 +50,7 @@ const currentEnvVariables = isPreview ? PREVIEW_ENV_VARIABLES : ENV_VARIABLES;

export const DEFAULT_CHAIN_ID = currentEnvVariables.DEFAULT_CHAIN_ID;
export const API_URL = currentEnvVariables.API_URL;
export const ROUTER_API_URL = currentEnvVariables.ROUTER_API_URL;
export const PACKAGE_ROUTER_PATH = currentEnvVariables.PACKAGE_ROUTER_PATH;
export const PACKAGE_POOL_PATH = currentEnvVariables.PACKAGE_POOL_PATH;
export const PACKAGE_POSITION_PATH = currentEnvVariables.PACKAGE_POSITION_PATH;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
makeGNOTSendAmount,
makeTransactionMessage,
PACKAGE_POOL_ADDRESS,
PACKAGE_ROUTER_ADDRESS,
PACKAGE_STAKER_ADDRESS,
PACKAGE_STAKER_PATH,
} from "./common";
Expand All @@ -19,6 +20,18 @@ export function makePoolTokenApproveMessage(
);
}

export function makeRouterTokenApproveMessage(
packagePath: string,
amount: string,
caller: string,
) {
return makeApproveMessage(
packagePath,
[PACKAGE_ROUTER_ADDRESS, amount],
caller,
);
}

export function makeCreateIncentiveMessage(
poolPath: string,
rewardTokenPath: string,
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/common/values/data-constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ export const DEFAULT_GAS_FEE = 1 as const;
export const DEFAULT_GAS_WANTED = 100_000_000 as const;

export const SCANNER_URL = "https://gnoscan.io";

export const MINIMUM_GNOT_SWAP_AMOUNT = 0.001;
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ interface Props {
priceRangeSummary: IPriceRange;
aprFee: number;
currentAmounts: { amountA: number; amountB: number } | null;
repositionAmounts: { amountA: number; amountB: number } | null;
repositionAmounts: { amountA: number | null; amountB: number | null } | null;
removePosition: () => Promise<WalletResponse | null>;
swapRemainToken: () => Promise<WalletResponse<SwapRouteResponse> | null>;
addPosition: () => Promise<WalletResponse<AddLiquidityResponse> | null>;
addPosition: (
swapToken: TokenModel,
swapAmount: string,
) => Promise<WalletResponse<AddLiquidityResponse> | null>;
}

const RepositionModal: React.FC<Props> = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,14 @@ export const BalanceChangeWrapper = styled.div<Props>`
width: 133px;
}
&.new-balance {
display: flex;
align-items: center;
justify-content: flex-end;
color: ${({ theme }) => theme.color.text03};
.loading-skeleton {
align-self: flex-end;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import { BalanceChangeWrapper } from "./BalanceChange.styles";
import { useWindowSize } from "@hooks/common/use-window-size";
import { DEVICE_TYPE } from "@styles/media";
import { numberToFormat } from "@utils/string-utils";
import { pulseSkeletonStyle } from "@constants/skeleton.constant";

export interface BalanceChangeProps {
tokenA: TokenModel;
tokenB: TokenModel;
title?: string;
isHiddenCurrentBalance?: boolean;
currentAmounts: { amountA: number; amountB: number } | null;
repositionAmounts: { amountA: number; amountB: number } | null;
repositionAmounts: { amountA: number | null; amountB: number | null } | null;
}

const BalanceChange: React.FC<BalanceChangeProps> = ({
Expand Down Expand Up @@ -50,6 +51,11 @@ const BalanceChange: React.FC<BalanceChangeProps> = ({
if (!repositionAmounts) {
return "-";
}

if (repositionAmounts.amountA === null) {
return null;
}

return numberToFormat(repositionAmounts.amountA, {
decimals: 2,
forceDecimals: true,
Expand All @@ -60,6 +66,11 @@ const BalanceChange: React.FC<BalanceChangeProps> = ({
if (!repositionAmounts) {
return "-";
}

if (repositionAmounts.amountB === null) {
return null;
}

return numberToFormat(repositionAmounts.amountB, {
decimals: 2,
forceDecimals: true,
Expand Down Expand Up @@ -120,7 +131,16 @@ const BalanceChange: React.FC<BalanceChangeProps> = ({
{tokenA?.symbol}
</p>
<p className="label">{currentTokenAAmount}</p>
<p className="label new-balance">{repositionTokenAAmount}</p>
<p className="label new-balance">
{repositionTokenAAmount !== null ? (
repositionTokenAAmount
) : (
<div
css={pulseSkeletonStyle({ w: 80, h: 18 })}
className="loading-skeleton"
/>
)}
</p>
</div>
<div className="table-balance-change">
<p className="value">
Expand All @@ -132,7 +152,16 @@ const BalanceChange: React.FC<BalanceChangeProps> = ({
{tokenB?.symbol}
</p>
<p className="label">{currentTokenBAmount}</p>
<p className="label new-balance">{repositionTokenBAmount}</p>
<p className="label new-balance">
{repositionTokenBAmount !== null ? (
repositionTokenBAmount
) : (
<div
css={pulseSkeletonStyle({ w: 80, h: 18 })}
className="loading-skeleton"
/>
)}
</p>
</div>
</div>
</BalanceChangeWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,25 @@ import IconAddPositionCircle from "@components/common/icons/IconAddPositionCircl
import { WalletResponse } from "@common/clients/wallet-client/protocols";
import { SwapRouteResponse } from "@repositories/swap/response/swap-route-response";
import { AddLiquidityResponse } from "@repositories/pool/response/add-liquidity-response";
import { TokenModel } from "@models/token/token-model";

export interface RepositionBroadcastProgressProps {
removePosition: () => Promise<WalletResponse | null>;
swapRemainToken: () => Promise<WalletResponse<SwapRouteResponse> | null>;
addPosition: () => Promise<WalletResponse<AddLiquidityResponse> | null>;
addPosition: (
swapToken: TokenModel,
swapAmount: string,
) => Promise<WalletResponse<AddLiquidityResponse> | null>;
closeModal: () => void;
}

const RepositionBroadcastProgress: React.FC<
RepositionBroadcastProgressProps
> = ({ removePosition, addPosition, closeModal }) => {
> = ({ removePosition, addPosition, swapRemainToken, closeModal }) => {
const [removePositionState, setRemovePositionState] =
useState<ProgressStateType>("NONE");
const [swapState, setSwapState] = useState<ProgressStateType>("NONE");
const [swapResult, setSwapResult] = useState<SwapRouteResponse | null>(null);
const [addPositionState, setAddPositionState] =
useState<ProgressStateType>("NONE");

Expand Down Expand Up @@ -65,10 +70,8 @@ const RepositionBroadcastProgress: React.FC<
}

setRemovePositionState("BROADCAST");
wait(async () => {
wait(async () => true, 1000).then(() => {
setRemovePositionState("SUCCESS");
return true;
}, 1000).then(() => {
callback();
});
});
Expand All @@ -79,68 +82,72 @@ const RepositionBroadcastProgress: React.FC<
return;
}

setSwapResult(null);
setSwapState("WAIT");

wait(async () => {
swapRemainToken().then(result => {
if (!result) {
setSwapState("FAIL");
return;
}
if (result.code === 4000) {
setSwapState("REJECTED");
return;
}

if (result.code !== 0 || result.data === null) {
setSwapState("INSUFFICIENT_LIQUIDITY");
return;
}

setSwapState("BROADCAST");
return true;
}, 1000).then(() => {
wait(async () => {

wait(async () => true, 1000).then(() => {
setSwapState("SUCCESS");
return true;
}, 1000).then(() => {
setSwapResult(result.data);
callback();
});
});

// XXX: Not yet apply swap router
// swapRemainToken().then(succeed => {
// if (succeed) {
// setSwapState("BROADCAST");

// wait(async () => {
// setSwapState("SUCCESS");
// return true;
// }, 1000).then(() => {
// callback();
// });
// } else {
// setSwapState("FAIL");
// }
// });
};

const processAddPosition = (callback: () => void) => {
const processAddPosition = async (callback: () => void) => {
if (addPositionState !== "INIT") {
return;
}

setAddPositionState("WAIT");

addPosition().then(response => {
if (!response) {
setAddPositionState("FAIL");
return;
}

if (response.code === 4000) {
setAddPositionState("REJECTED");
return;
}

if (response.code !== 0 || response.data === null) {
setAddPositionState("FAIL");
return;
}

setAddPositionState("BROADCAST");
wait(async () => {
setAddPositionState("SUCCESS");
return true;
}, 1000).then(() => {
callback();
if (!swapResult) {
wait(async () => true, 500).then(() => {
setAddPositionState("INIT");
});
});
return;
}

addPosition(swapResult.resultToken, swapResult.resultAmount).then(
response => {
if (!response) {
setAddPositionState("FAIL");
return;
}

if (response.code === 4000) {
setAddPositionState("REJECTED");
return;
}

if (response.code !== 0 || response.data === null) {
setAddPositionState("FAIL");
return;
}

setAddPositionState("BROADCAST");
wait(async () => true, 1000).then(() => {
setAddPositionState("SUCCESS");
callback();
});
},
);
};

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface RepositionContentProps {
priceRange: AddLiquidityPriceRage;
changePriceRange: (priceRange: AddLiquidityPriceRage) => void;
currentAmounts: { amountA: number; amountB: number } | null;
repositionAmounts: { amountA: number; amountB: number } | null;
repositionAmounts: { amountA: number | null; amountB: number | null } | null;
}

const RepositionContent: React.FC<RepositionContentProps> = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,34 @@ export const ConfirmSwapModalBackground = styled.div`
bottom: 0px;
left: 0px;
right: 0px;
width: 100%;
height: 100%;
width: 100vw;
height: 100vh;
pointer-events: none;
`;

export const ConfirmModal = styled.div`
position: relative;
pointer-events: initial;
${mixins.flexbox("column", "flex-start", "flex-start")};
overflow: hidden;
display: flex;
flex-direction: column;
width: 460px;
padding: 23px;
height: auto;
padding: 23px 0px;
gap: 16px;
${mixins.positionCenter}
border-radius: 8px;
box-shadow: 10px 14px 48px 0px rgba(0, 0, 0, 0.12);
border: 1px solid ${({ theme }) => theme.color.border02};
background-color: ${({ theme }) => theme.color.background06};
&.modal-body-wrapper {
gap: 24px;
${media.mobile} {
${mixins.positionCenter}
padding: 12px 0px;
}
}
${media.mobile} {
width: 328px;
${mixins.positionCenter}
padding: 15px 0px;
}
Expand Down Expand Up @@ -186,8 +187,10 @@ export const ConfirmModal = styled.div`
border: 1px solid ${({ theme }) => theme.color.border02};
.coin-info {
${mixins.flexbox("row", "center", "flex-start")};
width: 100%;
gap: 4px;
.gnos-price {
display: flex;
${fonts.body12};
${media.mobile} {
${fonts.p2};
Expand Down
Loading

0 comments on commit 3b6e633

Please sign in to comment.