Skip to content

Commit

Permalink
Merge pull request #4427 from leather-wallet/release/alex-swaps
Browse files Browse the repository at this point in the history
release: alex swaps
  • Loading branch information
kyranjamie authored Oct 26, 2023
2 parents a05052f + d9bd157 commit 35e4f96
Show file tree
Hide file tree
Showing 91 changed files with 1,247 additions and 757 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
"@typescript-eslint/eslint-plugin": "6.7.4",
"@vkontakte/vk-qr": "2.0.13",
"@zondax/ledger-stacks": "1.0.4",
"alex-sdk": "0.1.22",
"are-passive-events-supported": "1.1.1",
"argon2-browser": "1.18.0",
"assert": "2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/app/common/error-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export enum FormErrorMessages {
InsufficientFunds = 'Insufficient funds',
MemoExceedsLimit = 'Memo must be less than 34-bytes',
MustBeNumber = 'Amount must be a number',
MustBePositive = 'Amount must be positive',
MustBePositive = 'Amount must be greater than zero',
MustSelectAsset = 'Select a valid token to transfer',
SameAddress = 'Cannot send to yourself',
TooMuchPrecision = 'Token can only have {decimals} decimals',
Expand Down
2 changes: 1 addition & 1 deletion src/app/common/hooks/use-bitcoin-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ export function useBitcoinContracts() {
const txMoney = createMoneyFromDecimal(bitcoinValue, 'BTC');
const txFiatValue = i18nFormatCurrency(calculateFiatValue(txMoney)).toString();
const txFiatValueSymbol = bitcoinMarketData.price.symbol;
const txLink = { blockchain: 'bitcoin', txid: txId };
const txLink = { blockchain: 'bitcoin', txId };

return {
txId,
Expand Down
15 changes: 14 additions & 1 deletion src/app/common/hooks/use-convert-to-fiat-amount.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';

import { CryptoCurrencies } from '@shared/models/currencies.model';
import { createMarketData, createMarketPair } from '@shared/models/market.model';
import type { Money } from '@shared/models/money.model';

import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
Expand All @@ -15,3 +16,15 @@ export function useConvertCryptoCurrencyToFiatAmount(currency: CryptoCurrencies)
[cryptoCurrencyMarketData]
);
}

export function useConvertAlexSdkCurrencyToFiatAmount(currency: CryptoCurrencies, price: Money) {
const alexCurrencyMarketData = useMemo(
() => createMarketData(createMarketPair(currency, 'USD'), price),
[currency, price]
);

return useCallback(
(value: Money) => baseCurrencyAmountInQuote(value, alexCurrencyMarketData),
[alexCurrencyMarketData]
);
}
6 changes: 3 additions & 3 deletions src/app/common/hooks/use-explorer-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import { openInNewTab } from '../utils/open-in-new-tab';
export interface HandleOpenTxLinkArgs {
blockchain: Blockchains;
suffix?: string;
txid: string;
txId: string;
}
export function useExplorerLink() {
const { mode } = useCurrentNetworkState();
const handleOpenTxLink = useCallback(
({ blockchain, suffix, txid }: HandleOpenTxLinkArgs) =>
openInNewTab(makeTxExplorerLink({ blockchain, mode, suffix, txid })),
({ blockchain, suffix, txId }: HandleOpenTxLinkArgs) =>
openInNewTab(makeTxExplorerLink({ blockchain, mode, suffix, txId })),
[mode]
);

Expand Down
6 changes: 3 additions & 3 deletions src/app/common/hooks/use-loading.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useLoadingState } from '@app/store/ui/ui.hooks';

export enum LoadingKeys {
CONFIRM_DRAWER = 'loading/CONFIRM_DRAWER',
INCREASE_FEE_DRAWER = 'loading/INCREASE_FEE_DRAWER',
SUBMIT_TRANSACTION = 'loading/SUBMIT_TRANSACTION',
SUBMIT_SIGNATURE = 'loading/SUBMIT_SIGNATURE',
SUBMIT_SEND_FORM_TRANSACTION = 'loading/SUBMIT_SEND_FORM_TRANSACTION',
SUBMIT_SWAP_TRANSACTION = 'loading/SUBMIT_SWAP_TRANSACTION',
SUBMIT_TRANSACTION_REQUEST = 'loading/SUBMIT_TRANSACTION_REQUEST',
}

export function useLoading(key: string) {
Expand Down
7 changes: 5 additions & 2 deletions src/app/common/math/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import BigNumber from 'bignumber.js';

export function initBigNumber(num: string | number | BigNumber) {
return BigNumber.isBigNumber(num) ? num : new BigNumber(num);
import { isBigInt } from '@shared/utils';

export function initBigNumber(num: string | number | BigNumber | bigint) {
if (BigNumber.isBigNumber(num)) return num;
return isBigInt(num) ? new BigNumber(num.toString()) : new BigNumber(num);
}

export function sumNumbers(nums: number[]) {
Expand Down
12 changes: 10 additions & 2 deletions src/app/common/money/calculate-money.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { BigNumber } from 'bignumber.js';

import { MarketData, formatMarketPair } from '@shared/models/market.model';
import { Money, createMoney } from '@shared/models/money.model';
import { Money, NumType, createMoney } from '@shared/models/money.model';
import { isNumber } from '@shared/utils';

import { sumNumbers } from '../math/helpers';
import { initBigNumber, sumNumbers } from '../math/helpers';
import { formatMoney } from './format-money';
import { isMoney } from './is-money';

Expand All @@ -31,6 +31,14 @@ export function convertAmountToFractionalUnit(num: Money | BigNumber, decimals?:
return num.shiftedBy(decimals);
}

export function convertToMoneyTypeWithDefaultOfZero(
symbol: string,
num?: NumType,
decimals?: number
) {
return createMoney(initBigNumber(num ?? 0), symbol.toUpperCase(), decimals);
}

// ts-unused-exports:disable-next-line
export function convertAmountToBaseUnit(num: Money | BigNumber, decimals?: number) {
if (isMoney(num)) return num.amount.shiftedBy(-num.decimals);
Expand Down
14 changes: 14 additions & 0 deletions src/app/common/transactions/stacks/transaction.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { bytesToHex } from '@stacks/common';
import { TransactionTypes } from '@stacks/connect';
import {
CoinbaseTransaction,
NetworkBlockTimesResponse,
TransactionEventFungibleAsset,
} from '@stacks/stacks-blockchain-api-types';
import {
Expand Down Expand Up @@ -126,3 +127,16 @@ export function getTxSenderAddress(tx: StacksTransaction): string | undefined {
);
return txSender;
}

export function getEstimatedConfirmationTime(
isTestnet: boolean,
blockTime?: NetworkBlockTimesResponse
) {
const arrivesIn = isTestnet
? blockTime?.testnet.target_block_time
: blockTime?.mainnet.target_block_time;

if (!arrivesIn) return '~10 – 20 min';

return `~${arrivesIn / 60} min`;
}
8 changes: 4 additions & 4 deletions src/app/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,19 @@ interface MakeTxExplorerLinkArgs {
blockchain: Blockchains;
mode: BitcoinNetworkModes;
suffix?: string;
txid: string;
txId: string;
}
export function makeTxExplorerLink({
blockchain,
mode,
suffix = '',
txid,
txId,
}: MakeTxExplorerLinkArgs) {
switch (blockchain) {
case 'bitcoin':
return `https://mempool.space/${mode !== 'mainnet' ? mode + '/' : ''}tx/${txid}`;
return `https://mempool.space/${mode !== 'mainnet' ? mode + '/' : ''}tx/${txId}`;
case 'stacks':
return `https://explorer.hiro.so/txid/${txid}?chain=${mode}${suffix}`;
return `https://explorer.hiro.so/txid/${txId}?chain=${mode}${suffix}`;
default:
return '';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Flag } from '@app/components/layout/flag';
import { Tooltip } from '@app/components/tooltip';
import { Caption, Text } from '@app/components/typography';

import { SmallLoadingSpinner } from '../loading-spinner';
import { LoadingSpinner } from '../loading-spinner';

interface BitcoinContractEntryPointLayoutProps extends StackProps {
balance: Money;
Expand Down Expand Up @@ -48,7 +48,7 @@ export const BitcoinContractEntryPointLayout = forwardRefWithAs(
fontVariantNumeric="tabular-nums"
textAlign="right"
>
{isLoading ? <SmallLoadingSpinner /> : formattedBalance.value}
{isLoading ? <LoadingSpinner size="sm" /> : formattedBalance.value}
</Text>
</Tooltip>
</HStack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function BitcoinTransactionItem({ transaction, ...rest }: BitcoinTransact
}
handleOpenTxLink({
blockchain: 'bitcoin',
txid: transaction?.txid || '',
txId: transaction?.txid || '',
});
};

Expand Down
41 changes: 15 additions & 26 deletions src/app/components/generic-error/generic-error.layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ReactNode } from 'react';

import GenericError from '@assets/images/generic-error.png';
import { Box, Text, color } from '@stacks/ui';
import { Flex, FlexProps, HStack, styled } from 'leather-styles/jsx';

import { openInNewTab } from '@app/common/utils/open-in-new-tab';
Expand All @@ -22,16 +21,8 @@ export function GenericErrorLayout(props: GenericErrorProps) {
const { body, helpTextList, onClose, title, ...rest } = props;

return (
<Flex
alignItems="center"
flexDirection="column"
px={['space.05', 'space.05', 'unset']}
width="100%"
{...rest}
>
<Box mt="loose">
<img src={GenericError} width="106px" />
</Box>
<Flex alignItems="center" flexDirection="column" px="space.05" width="100%" {...rest}>
<styled.img src={GenericError} width="106px" height="72px" alt="Error" mt="space.06" />
<styled.h1 mt="space.05" textStyle="heading.04">
{title}
</styled.h1>
Expand All @@ -44,32 +35,30 @@ export function GenericErrorLayout(props: GenericErrorProps) {
>
{body}
</styled.h2>
<Box
as="ul"
border="2px solid #EFEFF2"
borderRadius="12px"
color={color('text-caption')}
<styled.ul
border="default"
borderRadius="10px"
fontSize="14px"
lineHeight="1.6"
listStyleType="circle"
mt="extra-loose"
pb="loose"
mt="space.06"
pb="space.05"
pl="40px"
pr="loose"
pt="tight"
pr="space.05"
pt="space.02"
textAlign="left"
width="100%"
>
{helpTextList}
<Box as="li" mt="base" textAlign="left">
<styled.li mt="space.04" textAlign="left">
<HStack alignItems="center">
<Text>Reach out to our support team</Text>
<Box as="button" onClick={() => openInNewTab(supportUrl)}>
<styled.span textStyle="label.02">Reach out to our support team</styled.span>
<styled.button onClick={() => openInNewTab(supportUrl)}>
<ExternalLinkIcon />
</Box>
</styled.button>
</HStack>
</Box>
</Box>
</styled.li>
</styled.ul>
<LeatherButton fontSize="14px" mt="space.05" onClick={onClose} variant="link">
Close window
</LeatherButton>
Expand Down
14 changes: 11 additions & 3 deletions src/app/components/generic-error/generic-error.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
import { ReactNode } from 'react';

import { FlexProps } from 'leather-styles/jsx';

import { closeWindow } from '@shared/utils';

import { useRouteHeader } from '@app/common/hooks/use-route-header';
import { Header } from '@app/components/header';

import { GenericErrorLayout } from './generic-error.layout';

interface GenericErrorProps {
interface GenericErrorProps extends FlexProps {
body: string;
helpTextList: ReactNode[];
onClose?(): void;
title: string;
}
export function GenericError(props: GenericErrorProps) {
const { body, helpTextList, onClose = () => closeWindow(), title } = props;
const { body, helpTextList, onClose = () => closeWindow(), title, ...rest } = props;

useRouteHeader(<Header hideActions />);

return (
<GenericErrorLayout body={body} helpTextList={helpTextList} onClose={onClose} title={title} />
<GenericErrorLayout
body={body}
helpTextList={helpTextList}
onClose={onClose}
title={title}
{...rest}
/>
);
}
14 changes: 0 additions & 14 deletions src/app/components/icons/dot-icon.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/app/components/icons/swap-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function SwapIcon(props: React.SVGProps<SVGSVGElement>) {
<g clipPath="url(#clip0_5842_83269)">
<path
d="M1.94727 4.50229H13.2596M10.7086 7.59746L13.7987 4.50229L10.7086 1.41211M13.9934 11.4964H2.756M5.30702 8.4012L2.21185 11.4964L5.30702 14.5865"
stroke="#12100F"
stroke="currentColor"
strokeWidth="2"
strokeMiterlimit="10"
/>
Expand Down
17 changes: 6 additions & 11 deletions src/app/components/loading-spinner.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { Flex, FlexProps, Spinner, color } from '@stacks/ui';
import { Spinner, SpinnerSize } from '@stacks/ui';
import { Flex, FlexProps } from 'leather-styles/jsx';
import { token } from 'leather-styles/tokens';

export function LoadingSpinner(props: FlexProps) {
export function LoadingSpinner(props: { size?: SpinnerSize } & FlexProps) {
const { size = 'lg' } = props;
return (
<Flex alignItems="center" flexGrow={1} justifyContent="center" width="100%" {...props}>
<Spinner color={color('text-caption')} opacity={0.5} size="lg" />
</Flex>
);
}

export function SmallLoadingSpinner(props: FlexProps) {
return (
<Flex alignItems="center" flexGrow={1} justifyContent="center" width="100%" {...props}>
<Spinner color={color('text-caption')} opacity={0.5} size="sm" />
<Spinner color={token('colors.accent.text-subdued')} size={size} />
</Flex>
);
}
Expand Down
10 changes: 5 additions & 5 deletions src/app/components/nonce-setter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useAsync } from 'react-async-hook';

import { useFormikContext } from 'formik';

Expand All @@ -12,10 +12,10 @@ export function NonceSetter() {
>();
const { data: nextNonce } = useNextNonce();

useEffect(() => {
if (nextNonce && !touched.nonce && values.nonce !== nextNonce.nonce)
setFieldValue('nonce', nextNonce.nonce);
// eslint-disable-next-line react-hooks/exhaustive-deps
useAsync(async () => {
if (nextNonce?.nonce && !touched.nonce && values.nonce !== nextNonce.nonce)
return await setFieldValue('nonce', nextNonce?.nonce);
return;
}, [nextNonce?.nonce]);

return <></>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export function StacksTransactionItem({
void analytics.track('view_transaction');
handleOpenTxLink({
blockchain: 'stacks',
txid: transaction?.tx_id || transferDetails?.link || '',
txId: transaction?.tx_id || transferDetails?.link || '',
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function SubmittedTransactionItem(props: SubmittedTransactionItemProps) {
handleOpenTxLink({
blockchain: 'stacks',
suffix: `&submitted=true`,
txid: txId,
txId,
})
}
position="relative"
Expand Down
Loading

0 comments on commit 35e4f96

Please sign in to comment.