Skip to content

Commit

Permalink
Release v0.3.17
Browse files Browse the repository at this point in the history
  • Loading branch information
dash-yuga committed Nov 20, 2024
1 parent c18abee commit 00a2c25
Show file tree
Hide file tree
Showing 16 changed files with 289 additions and 138 deletions.
4 changes: 4 additions & 0 deletions lib/classes/BridgeTransactionData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ export class BridgeTransactionData {

applicationFee: number = 0;
applicationFeeUsd: number = 0;
/** Gas as a decimal amount for the native token, eg. 1gwei = 0.000000001 gasFee */
gasFee: number = 0;
gasFeeUsd: number = 0;
/** Gas as a raw/uint8 amount for the native token, eg. 1gwei = 1000000000 gasFeeWei */
gasFeeWei: bigint = 0n;
timeWarning: string | undefined;
priceImpactWarning: string | undefined;
_slippagePercentage: number = 1;
Expand All @@ -29,6 +32,7 @@ export class BridgeTransactionData {
this.applicationFeeUsd = 0;
this.gasFee = 0;
this.gasFeeUsd = 0;
this.gasFeeWei = 0n;
this.timeWarning = undefined;
this.priceImpactWarning = undefined;
}
Expand Down
11 changes: 10 additions & 1 deletion lib/components/buy/buy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export function Buy({
const { setError } = useErrorStore();
const wasHallidayLoaded = useRef<boolean>(false);
const [isIframePresent, setIsIframePresent] = useState(false);
const launchAddress = useRef<undefined | string>();

// Check if the iframe is present. So if the user closes the iframe,
// we can show the "launch onramp" button
Expand All @@ -57,6 +58,7 @@ export function Buy({
console.error('Onramp: Address or signer not available');
return;
}
launchAddress.current = address;
void openHalliday({
apiKey,
destinationChainId: apeChain.id,
Expand All @@ -70,7 +72,14 @@ export function Buy({
}, [address, destinationAddress, signer]);

useEffect(() => {
if (wasHallidayLoaded.current) return;
if (wasHallidayLoaded.current) {
if (launchAddress.current === address) {
return;
} else {
// User address changed, re-instantiating iframe with new address
void launchHalliday();
}
}
if (isTabHosted && portalType !== PortalType.OnRamp) return;
if (!address || !signer || !enableOnramp) return;
void launchHalliday();
Expand Down
36 changes: 18 additions & 18 deletions lib/components/ui/SolanaModule.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { motion } from 'framer-motion';
import { BaseButton } from './buttons/BaseButton.tsx';
import { useEffect, useState } from 'react';
import { handler } from 'tailwindcss-animate';
import { useEffect } from 'react';
import { useApeContext } from '../../providers/ape/apeProvider.context.ts';
import { usePortalStore } from '../../store/usePortalStore.ts';

export const SolanaModule = () => {
const { solanaRedirectUrl } = useApeContext();
const [count, setCount] = useState(3);
useEffect(() => {
if (count === 0) {
if (solanaRedirectUrl) {
window.location.href = solanaRedirectUrl;
}
return;
}
const { setSolanaSelected } = usePortalStore((state) => ({
setSolanaSelected: state.setSolanaSelected,
}));

const intervalId = setInterval(() => {
setCount((prevCount) => prevCount - 1);
}, 1000);
const handleRedirect = () => {
if (typeof solanaRedirectUrl === 'string') {
window.location.href = solanaRedirectUrl;
}
};

return () => clearInterval(intervalId);
}, [count, solanaRedirectUrl]);
useEffect(() => {
return () => {
setSolanaSelected(false);
};
}, [setSolanaSelected]);

return (
<motion.div
Expand All @@ -36,23 +36,23 @@ export const SolanaModule = () => {
'aw-font-dmsans aw-font-medium aw-leading-normal aw-tracking-wide'
}
>
2. Redirecting to Solana Bridge
2. Redirect to Solana Bridge
</p>
<div
className={
'aw-flex aw-w-full aw-flex-col aw-items-center aw-justify-center aw-gap-y-3 aw-py-3'
}
>
<BaseButton
onClick={handler}
onClick={handleRedirect}
className={'aw-bg-gradient-lavender-coral-sunset'}
>
<div
className={
'aw-relative aw-inline-flex aw-size-full aw-w-full aw-items-center aw-justify-center aw-overflow-hidden aw-rounded-[5px] aw-bg-apeCtaBlue aw-text-center aw-font-dmmono aw-text-[16px] aw-font-medium aw-text-white md:aw-text-[18px]'
}
>
Redirecting {count}
Go To Solana Bridge
</div>
</BaseButton>
</div>
Expand Down
52 changes: 43 additions & 9 deletions lib/hooks/useBalanceSufficient.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useEffect, useRef } from 'react';
import { useEffect, useMemo, useRef } from 'react';
import { BoxActionResponse } from '@decent.xyz/box-common';
import { useAccount, useBalance, useReadContract } from 'wagmi';
import { useBridgeStore } from '../store/useBridgeStore';
import { Address, erc20Abi } from 'viem';
import { useChainConfig } from './useChainConfig';
import { usePortalStore } from '../store/usePortalStore';

export const useBalanceSufficient = (
preparedTransaction: BoxActionResponse | undefined,
Expand All @@ -13,6 +14,9 @@ export const useBalanceSufficient = (
const { setBridgeError } = useBridgeStore((state) => ({
setBridgeError: state.setBridgeError,
}));
const bridgeTransactionData = usePortalStore(
(state) => state.bridgeTransactionData,
);
const { chains } = useChainConfig();
const chainId = preparedTransaction?.tokenPayment?.chainId;
const isValidChain = chainId !== undefined && chains.includes(chainId);
Expand All @@ -28,28 +32,50 @@ export const useBalanceSufficient = (
preparedTransaction?.tokenPayment?.isNative,
},
});
// Monitor for changes to sourceNativeTokenBalance and manage balanceSufficient state accordingly

/** Total amount of fees required in the native token, in the smallest unit (wei). */
const totalFeesNativeWei = useMemo(() => {
return (
(preparedTransaction?.applicationFee?.amount ?? 0n) +
(preparedTransaction?.protocolFee?.amount ?? 0n) +
(preparedTransaction?.bridgeFee?.amount ?? 0n) +
bridgeTransactionData.gasFeeWei
);
}, [
preparedTransaction?.applicationFee?.amount,
preparedTransaction?.protocolFee?.amount,
preparedTransaction?.bridgeFee?.amount,
bridgeTransactionData.gasFeeWei,
]);

// Monitors balance sufficiency for swaps using the native token as the source
useEffect(() => {
// TODO: This logic could get more complex and consider the `preparedTransaction?.tx?.value` as well, since
// that could be sent separately (and greater than) the tokenPayment.
if (!preparedTransaction?.tokenPayment?.isNative) {
if (
!preparedTransaction?.tokenPayment ||
!preparedTransaction.tokenPayment.isNative ||
nativeTokenBalance.data?.value === undefined
) {
return;
}
const totalNativePaymentWithFees =
preparedTransaction.tokenPayment.amount + totalFeesNativeWei;
if (
nativeTokenBalance.data?.value !== undefined &&
preparedTransaction?.tokenPayment?.amount !== undefined &&
nativeTokenBalance.data.value < preparedTransaction.tokenPayment.amount
) {
balanceSufficient.current = false;
setBridgeError('INSUFFICIENT_FUNDS');
} else if (nativeTokenBalance.data?.value < totalNativePaymentWithFees) {
balanceSufficient.current = false;
setBridgeError('INSUFFICIENT_FUNDS_FOR_FEES');
} else {
balanceSufficient.current = true;
}
}, [
totalFeesNativeWei,
nativeTokenBalance.data?.value,
preparedTransaction?.tokenPayment?.amount,
preparedTransaction?.tokenPayment?.isNative,
preparedTransaction,
setBridgeError,
bridgeTransactionData.gasFeeWei,
]);

// Non-native (ERC-20) token balance monitor.
Expand Down Expand Up @@ -80,13 +106,21 @@ export const useBalanceSufficient = (
) {
balanceSufficient.current = false;
setBridgeError('INSUFFICIENT_FUNDS');
} else if (
nativeTokenBalance.data?.value !== undefined &&
nativeTokenBalance.data.value < totalFeesNativeWei
) {
balanceSufficient.current = false;
setBridgeError('INSUFFICIENT_FUNDS_FOR_FEES');
} else {
balanceSufficient.current = true;
}
}, [
tokenBalance,
preparedTransaction?.tokenPayment?.amount,
preparedTransaction?.tokenPayment?.isNative,
nativeTokenBalance.data?.value,
totalFeesNativeWei,
setBridgeError,
]);

Expand Down
8 changes: 6 additions & 2 deletions lib/hooks/useEthersSigner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BrowserProvider, JsonRpcSigner } from 'ethers';
import { useMemo } from 'react';
import type { Account, Chain, Client, Transport } from 'viem';
import { type Config, useConnectorClient } from 'wagmi';
import { type Config, useAccount, useConnectorClient } from 'wagmi';

/**
* wagmi to ethers.js signer
Expand All @@ -21,6 +21,10 @@ export function clientToSigner(client: Client<Transport, Chain, Account>) {

/** Hook to convert a viem Wallet Client to an ethers.js Signer. */
export function useEthersSigner({ chainId }: { chainId?: number } = {}) {
const { data: client } = useConnectorClient<Config>({ chainId });
const { address } = useAccount();
const { data: client } = useConnectorClient<Config>({
account: address,
chainId,
});
return useMemo(() => (client ? clientToSigner(client) : undefined), [client]);
}
6 changes: 5 additions & 1 deletion lib/hooks/usePreparedTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,10 @@ export const usePreparedTransaction = (useBoxActionArgs: UseBoxActionArgs) => {
if (
InsufficientFundsError.nodeMessage.test(
gasEstimateErrorData.cause.details,
) ||
)
) {
setBridgeError('INSUFFICIENT_FUNDS_FOR_FEES');
} else if (
/amount exceeds balance/.test(gasEstimateErrorData.cause.details)
) {
setBridgeError('INSUFFICIENT_FUNDS');
Expand Down Expand Up @@ -311,6 +314,7 @@ export const usePreparedTransaction = (useBoxActionArgs: UseBoxActionArgs) => {
amountOutStr,
totalAppFeesStr,
gasFeeStr,
totalGasWei,
);
const { estimatedTxTime } = preparedTransaction;
if (estimatedTxTime) {
Expand Down
3 changes: 3 additions & 0 deletions lib/store/usePortalStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ interface PortalActions {
destAmount: string,
bridgeFee: string,
gasFee: string,
gasFeeWei: bigint,
) => void;
setSlippagePercentage: (slippage: number) => void;
resetSlippage: () => void;
Expand Down Expand Up @@ -160,6 +161,7 @@ export const usePortalStore = create<PortalStore>()((set) => ({
destAmount: string,
bridgeFee: string,
gasFee: string,
gasFeeWei: bigint,
) =>
set(
produce((state: PortalStore) => {
Expand All @@ -171,6 +173,7 @@ export const usePortalStore = create<PortalStore>()((set) => ({
state.bridgeTransactionData.setApplicationFeeUsd = Number(bridgeFee);
state.bridgeTransactionData.gasFee = Number(gasFee);
state.bridgeTransactionData.setGasFeeUsd = Number(gasFee);
state.bridgeTransactionData.gasFeeWei = gasFeeWei;
}),
),
setSourceChainGasTokenUsdValue: (value: number) =>
Expand Down
2 changes: 2 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ export type DecentBridgeStatus = {

export type BridgeError =
| 'INSUFFICIENT_FUNDS'
| 'INSUFFICIENT_FUNDS_FOR_FEES'
| 'WRONG_NETWORK'
| 'UNKNOWN_ERROR';
export type BridgeErrorDescriptions = {
[key in BridgeError]: string;
};
export const humanReadableBridgeError: BridgeErrorDescriptions = {
INSUFFICIENT_FUNDS: 'Insufficient funds',
INSUFFICIENT_FUNDS_FOR_FEES: 'Insufficient funds for fees',
UNKNOWN_ERROR: 'Something went wrong',
WRONG_NETWORK: 'Bad from or to chains',
};
Expand Down
Loading

0 comments on commit 00a2c25

Please sign in to comment.