Skip to content

Commit

Permalink
Release v0.3.11
Browse files Browse the repository at this point in the history
  • Loading branch information
dash-yuga committed Nov 8, 2024
1 parent 527c2ea commit 84edd97
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 56 deletions.
2 changes: 2 additions & 0 deletions lib/classes/BridgeTransactionData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export class BridgeTransactionData {
[immerable] = true;

static DEFAULT_SLIPPAGE: number = 1;
/** Amount of slippage to use when swapping between stables (stable coins). */
static STABLE_SWAP_SLIPPAGE: number = 0.1;
static MINIMUM_SLIPPAGE: number = 0.1;
static MAXIMUM_SLIPPAGE: number = 50;

Expand Down
15 changes: 1 addition & 14 deletions lib/components/ui/ApeStableDisclosure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@ import AdaptiveTooltip from './tooltip/AdaptiveTooltip';
import { useMemo } from 'react';
import { InfoIcon } from '../icons/InfoIcon';

const isPositiveMoney = (str: string): boolean => {
// Strip all characters except digits and a decimal, convert to number
// eslint-disable-next-line unicorn/prefer-string-replace-all
const num = Number(str.replace(/[^\d.]/g, ''));
return !Number.isNaN(num) && num > 0;
};

type ApeStableDisclosureProps = {
isSourceToken: boolean;
tokenAddress: Address;
Expand All @@ -28,7 +21,6 @@ type ApeStableDisclosureProps = {
export const ApeStableDisclosure = ({
isSourceToken,
tokenAddress,
tokenUsdValue,
}: ApeStableDisclosureProps) => {
const isApeUsd = isAddressEqual(tokenAddress, ApeUsdOmnichainContract);
const isApeEth = isAddressEqual(tokenAddress, ApeEthOmnichainContract);
Expand All @@ -43,12 +35,7 @@ export const ApeStableDisclosure = ({
}
}, [isApeEth, isApeUsd]);

if (
isSourceToken ||
!isApeStable ||
!isPositiveMoney(tokenUsdValue) ||
!tooltipContent
) {
if (isSourceToken || !isApeStable || !tooltipContent) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion lib/components/ui/SlippageInputModule.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PencilIcon } from '../icons/PencilIcon.tsx';
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/react';
import { usePortalStore } from '../../store/usePortalStore.ts';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { cn } from '../../utils/utils.ts';
import { BridgeTransactionData } from '../../classes/BridgeTransactionData.ts';
import { WarningIcon } from '../icons/WarningIcon.tsx';
Expand All @@ -19,6 +19,14 @@ export const SlippageInputModule = () => {
);
const [error, setError] = useState<string | undefined>();

useEffect(() => {
setCustomSlippageEnabled(
bridgeTransactionData.slippagePercentage !==
BridgeTransactionData.DEFAULT_SLIPPAGE,
);
setInputValue(bridgeTransactionData.slippagePercentage);
}, [bridgeTransactionData.slippagePercentage]);

const handlePercentChange = (rawValue: string) => {
setError(undefined);
// Clamp maximum and minimum values
Expand Down
21 changes: 14 additions & 7 deletions lib/components/ui/modal/ChainTokenSelectModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ import {
ApeEthOmnichainContract,
ApeUsdOmnichainContract,
createApeCoinTokenInfo,
DaiArbMainnetContract,
DaiEthMainnetContract,
StethEthMainnetContract,
UsdcArbMainnetContract,
UsdcEthMainnetContract,
UsdtArbMainnetContract,
UsdtEthMainnetContract,
} from '../../../utils/utils.ts';
import { Address, isAddressEqual, zeroAddress } from 'viem';

Expand All @@ -31,20 +38,20 @@ const activeTokens = {
ApeEthOmnichainContract,
ApeCoinMainnetEthereumContract,
zeroAddress,
'0x6B175474E89094C44Da98b954EedeAC495271d0F', // ETH-DAI
'0xdAC17F958D2ee523a2206206994597C13D831ec7', // ETH-USDT
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // ETH-USDC
'0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84', // ETH-stETH
DaiEthMainnetContract, // ETH-DAI
UsdtEthMainnetContract, // ETH-USDT
UsdcEthMainnetContract, // ETH-USDC
StethEthMainnetContract, // ETH-stETH
],
[ChainId.ARBITRUM]: [
ApeUsdOmnichainContract,
ApeEthOmnichainContract,
ApeCoinMainnetArbitrumContract,
zeroAddress,
'0x912CE59144191C1204E64559FE8253a0e49E6548', // ARB-ARB
'0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // ARB-DAI
'0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', // ARB-USDT
'0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // ARB-USDC
DaiArbMainnetContract, // ARB-DAI
UsdtArbMainnetContract, // ARB-USDT
UsdcArbMainnetContract, // ARB-USDC
],
[ChainId.APE]: [
ApeUsdOmnichainContract,
Expand Down
102 changes: 78 additions & 24 deletions lib/store/usePortalStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@decent.xyz/box-common';
import {
ApeCoinMainnetEthereum,
isTokenPairStable,
secondsToReadableTime,
} from '../utils/utils.ts';
import { BridgeTransactionData } from '../classes/BridgeTransactionData.ts';
Expand All @@ -28,6 +29,8 @@ interface PortalState {
hasUserUpdatedTokens: boolean;
/* Input State */
lastChanged: InputType;
/** Holds the value of slippage that is used for swaps other than stables. */
nonStableSlippage: number;
}

interface PortalActions {
Expand Down Expand Up @@ -70,13 +73,36 @@ export const defaultSwapSourceToken = getNativeTokenInfoOrFail(
);
export const defaultSwapDestinationToken: TokenInfo = ApeCoinMainnetEthereum;

export const usePortalStore = create<PortalState & PortalActions>()((set) => ({
/** Set slippage to minimum to accommodate stable coin swaps. */
function setSlippageForStableSwap(
state: PortalStore,
shouldStoreSlippage: boolean,
) {
if (shouldStoreSlippage) {
state.nonStableSlippage = state.bridgeTransactionData.slippagePercentage;
}
state.bridgeTransactionData.slippagePercentage =
BridgeTransactionData.STABLE_SWAP_SLIPPAGE;
}

/** Reset slippage to the value before stable coin swap. */
function setSlippageForNonStableSwap(state: PortalStore) {
if (
state.nonStableSlippage &&
state.bridgeTransactionData.slippagePercentage !== state.nonStableSlippage
) {
state.bridgeTransactionData.slippagePercentage = state.nonStableSlippage;
}
}

type PortalStore = PortalState & PortalActions;
export const usePortalStore = create<PortalStore>()((set) => ({
sourceToken: new TokenTransactionData(defaultBridgeSourceToken),
destinationToken: new TokenTransactionData(defaultBridgeDestinationToken),
stashedToken: undefined,
setStashedToken: (token: TokenTransactionData | undefined) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.stashedToken = token;
}),
),
Expand All @@ -88,14 +114,14 @@ export const usePortalStore = create<PortalState & PortalActions>()((set) => ({
hasUserUpdatedTokens: false,
setHasUserUpdatedTokens: () =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.hasUserUpdatedTokens = true;
}),
),
/** Reset warnings, gas prices and fees, and only the last touched token amount. */
resetTransactionData: () =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.bridgeTransactionData.resetTransactionData();
// Reset amount for the "non touched" field to zero out the quote
if (state.lastChanged == InputType.Source) {
Expand All @@ -108,7 +134,7 @@ export const usePortalStore = create<PortalState & PortalActions>()((set) => ({
/** Reset warnings, gas prices and fees, and both source/dest token amounts. */
resetTransactionDataAndAmounts: () =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.bridgeTransactionData.resetTransactionData();
state.sourceToken.amount = '';
state.destinationToken.amount = '';
Expand All @@ -121,38 +147,39 @@ export const usePortalStore = create<PortalState & PortalActions>()((set) => ({
gasFee: string,
) =>
set(
produce((state) => {
produce((state: PortalStore) => {
if (state.lastChanged !== InputType.Source) {
state.sourceToken.amount = sourceAmount;
}
state.destinationToken.amount = destAmount;
state.bridgeTransactionData.applicationFee = bridgeFee;
state.bridgeTransactionData.setApplicationFeeUsd = bridgeFee;
state.bridgeTransactionData.gasFee = gasFee;
state.bridgeTransactionData.setGasFeeUsd = gasFee;
state.bridgeTransactionData.applicationFee = Number(bridgeFee);
state.bridgeTransactionData.setApplicationFeeUsd = Number(bridgeFee);
state.bridgeTransactionData.gasFee = Number(gasFee);
state.bridgeTransactionData.setGasFeeUsd = Number(gasFee);
}),
),
setSourceChainGasTokenUsdValue: (value: number) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.bridgeTransactionData.sourceChainGasTokenUsdValue = value;
}),
),
setSlippagePercentage: (slippage: number) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.bridgeTransactionData.slippagePercentage = slippage;
state.nonStableSlippage = slippage;
}),
),
resetSlippage: () =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.bridgeTransactionData.resetSlippage();
}),
),
setPriceImpactWarning: (priceImpact?: number) =>
set(
produce((state) => {
produce((state: PortalStore) => {
if (!priceImpact || priceImpact < WARNING_THRESHOLD_PRICE_IMPACT) {
state.bridgeTransactionData.priceImpactWarning = undefined;
return;
Expand All @@ -163,7 +190,7 @@ export const usePortalStore = create<PortalState & PortalActions>()((set) => ({
),
setTxTimeWarning: (estimatedTxTime?: number) => {
set(
produce((state) => {
produce((state: PortalStore) => {
state.bridgeTransactionData.estimatedTxTime = estimatedTxTime;
if (
!estimatedTxTime ||
Expand All @@ -179,57 +206,83 @@ export const usePortalStore = create<PortalState & PortalActions>()((set) => ({
},
setTokenApprovalTxHash: (txHash: string) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.tokenApprovalTxHash = txHash;
}),
),
setSourceTokenAmount: (amount: string) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.sourceToken.amount = amount;
state.lastChanged = InputType.Source;
}),
),
setSourceTokenAmountUsd: (amount: string) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.sourceToken.amountUsd = amount;
}),
),
setDestinationTokenAmount: (amount: string) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.destinationToken.amount = amount;
state.lastChanged = InputType.Destination;
}),
),
setDestinationTokenAmountUsd: (amount: string) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.destinationToken.amountUsd = amount;
}),
),
setSourceToken: (token: TokenInfo) =>
set(
produce((state) => {
produce<PortalStore>((state) => {
const previousSourceTokenAddress = state.sourceToken.token.address;
state.sourceToken = new TokenTransactionData(
token,
state.sourceToken.amount,
);
// Apply slippage for stable swaps
if (
isTokenPairStable(token.address, state.destinationToken.token.address)
) {
// Only store slippage if the previous tokens were not stable
const wasPreviousPairStable = isTokenPairStable(
previousSourceTokenAddress,
state.destinationToken.token.address,
);
setSlippageForStableSwap(state, !wasPreviousPairStable);
} else {
setSlippageForNonStableSwap(state);
}
}),
),
setDestinationToken: (token: TokenInfo) =>
set(
produce((state) => {
produce((state: PortalStore) => {
const previousDestTokenAddress = state.destinationToken.token.address;
state.destinationToken = new TokenTransactionData(
token,
state.destinationToken.amount,
);
// Apply slippage for stable swaps
if (isTokenPairStable(token.address, state.sourceToken.token.address)) {
// Only store slippage if the previous tokens were not stable
const wasPreviousPairStable = isTokenPairStable(
previousDestTokenAddress,
state.sourceToken.token.address,
);
setSlippageForStableSwap(state, !wasPreviousPairStable);
} else {
setSlippageForNonStableSwap(state);
}
}),
),
swapSourceDestination: () => {
set(
produce((state) => {
produce((state: PortalStore) => {
const currentSource = state.sourceToken;
state.sourceToken = state.destinationToken;
state.destinationToken = currentSource;
Expand All @@ -239,9 +292,10 @@ export const usePortalStore = create<PortalState & PortalActions>()((set) => ({
},
maxOutSourceToken: (userBalance: string) =>
set(
produce((state) => {
produce((state: PortalStore) => {
state.sourceToken.amount = userBalance;
state.lastChanged = InputType.Source;
}),
),
nonStableSlippage: BridgeTransactionData.DEFAULT_SLIPPAGE,
}));
Loading

0 comments on commit 84edd97

Please sign in to comment.