Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENG-3594] feature: Send Max STX #767

Closed
wants to merge 80 commits into from
Closed
Show file tree
Hide file tree
Changes from 75 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
d6df19b
Add btc send screen skeleton
victorkirov Jan 15, 2024
4ccd4dd
Implement MAX
victorkirov Jan 15, 2024
76c9f31
extract amount selector to component
victorkirov Jan 15, 2024
63f2bb4
Add max dust filtered callout
victorkirov Jan 15, 2024
2ea224a
Fix minor styling
victorkirov Jan 15, 2024
5207c5d
Add fee display
victorkirov Jan 16, 2024
ed664f4
Implement fee selection
victorkirov Jan 17, 2024
de83299
Add insufficient funds on fee selector
victorkirov Jan 17, 2024
b20e4b6
add insufficient funds message on custom fee selector
victorkirov Jan 17, 2024
002dc58
Add insufficient funds gate
victorkirov Jan 17, 2024
b7e4ded
fix some todos
victorkirov Jan 17, 2024
4d1b558
Add min and max fee rate
victorkirov Jan 17, 2024
e2b0b1a
fix container styling
victorkirov Jan 17, 2024
5f79616
Merge branch 'develop' into victor/eng-3548-ext-send-btc-integrate-tx…
victorkirov Jan 18, 2024
f304895
fix styling
victorkirov Jan 18, 2024
a14b8d4
Fix fee summary on confirm page
victorkirov Jan 18, 2024
225f1bd
fix some component interactions
victorkirov Jan 18, 2024
23dd157
fix a few minor bugs
victorkirov Jan 19, 2024
75fa52d
fix rbf typing
victorkirov Jan 19, 2024
b92ad64
Merge branch 'develop' into victor/eng-3548-ext-send-btc-integrate-tx…
victorkirov Jan 19, 2024
cf3cc1f
Close window if ledger
victorkirov Jan 19, 2024
aecf750
Update src/app/ui-library/input.tsx
victorkirov Jan 23, 2024
38223d4
Update src/app/ui-library/input.tsx
victorkirov Jan 23, 2024
0d0409c
Add address editable field
victorkirov Jan 23, 2024
d2925dd
Merge branch 'develop' into victor/eng-3548-ext-send-btc-integrate-tx…
victorkirov Jan 23, 2024
bbd6829
chore: package-lock exact version
teebszet Jan 31, 2024
5a56cd8
refactor: use classnames for variants in ui-library button
teebszet Jan 31, 2024
24d429f
refactor: use css classnames in ui input
teebszet Jan 31, 2024
bc45210
fix: edit and pencil icon row
teebszet Jan 31, 2024
06b4efa
fix: recipient input next should be disabled when error
teebszet Jan 31, 2024
1a36ad9
fix: confirm/cancel translation keys
teebszet Jan 31, 2024
c04c058
Update core
victorkirov Jan 31, 2024
d9c0d67
Merge branch 'develop' into victor/eng-3548-ext-send-btc-integrate-tx…
victorkirov Jan 31, 2024
fe42aaf
Remove unneeded toNumbers
victorkirov Jan 31, 2024
cde4e39
Move error text to feedback
victorkirov Jan 31, 2024
fa243f8
add new for BigNumber
victorkirov Jan 31, 2024
636aa49
Make sats/vByte consistent
victorkirov Jan 31, 2024
a750d7b
Fix fee select styling
victorkirov Jan 31, 2024
38a9c9a
Fix input styling
victorkirov Jan 31, 2024
e2d094c
Merge branch 'develop' into victor/eng-3548-ext-send-btc-integrate-tx…
teebszet Feb 1, 2024
b753ca2
switch to new spinner
victorkirov Feb 1, 2024
b4e4e59
Factor out InputScreen from RecipientSelector
jordankzf Jan 23, 2024
bcb34f0
Update InputScreen to accept ReactNode
jordankzf Jan 23, 2024
c8efcaa
Step 1: Select Recipient
jordankzf Jan 23, 2024
1cdaa9f
[WIP] Step 2: Select Amount
jordankzf Jan 23, 2024
7389ff3
stxAmountSelector bug fixes
jordankzf Jan 23, 2024
a2a58ef
[WIP] Step 3
jordankzf Jan 24, 2024
8374e59
Forward AND reverse BNS lookup
jordankzf Jan 30, 2024
df955c3
Indented feedback
jordankzf Jan 31, 2024
2724c60
send async
jordankzf Jan 31, 2024
47607e9
Step3Confirm adapter
jordankzf Feb 1, 2024
3583bc6
wip send max
jordankzf Feb 1, 2024
305df4c
chore: bump core version
teebszet Feb 2, 2024
45f881d
Merge branch 'develop' into victor/eng-3548-ext-send-btc-integrate-tx…
victorkirov Feb 2, 2024
bbcb677
fix: rotate faders icon
teebszet Feb 2, 2024
d2c60d0
Revert "Fix fee select styling"
teebszet Feb 2, 2024
5e00bbb
fix: minor spacing, styling, and colour fixes
teebszet Feb 2, 2024
3e08755
fix: react key warning fix
teebszet Feb 2, 2024
b67d1cc
fees
jordankzf Feb 2, 2024
8282c07
bump core
victorkirov Feb 2, 2024
11395ba
Fix api
victorkirov Feb 2, 2024
3fe3c7d
fees
jordankzf Feb 4, 2024
eacc169
apply fee
jordankzf Feb 4, 2024
ecc0056
remove feeoverride
jordankzf Feb 4, 2024
341f852
Merge branch 'victor/eng-3548-ext-send-btc-integrate-tx-consolidation…
jordankzf Feb 4, 2024
4929264
Merge branch 'develop' of https://github.com/secretkeylabs/xverse-web…
victorkirov Feb 13, 2024
6702d63
Don't log insufficient funds message
victorkirov Feb 13, 2024
0d6d8b2
Fix insufficient amount on load
victorkirov Feb 13, 2024
c14f289
Enable rbf on txns
victorkirov Feb 13, 2024
3e8353a
Merge branch 'victor/eng-3548-ext-send-btc-integrate-tx-consolidation…
jordankzf Feb 14, 2024
cf11c64
Remove comments
jordankzf Feb 14, 2024
b79f6b5
avoid calling setState twice
jordankzf Feb 14, 2024
88d39b5
Merge branch 'develop' of https://github.com/secretkeylabs/xverse-web…
jordankzf Feb 17, 2024
441bf77
Rename btcRecipientSelector
jordankzf Feb 17, 2024
7425a8c
Address Vic feedback
jordankzf Feb 20, 2024
1b30168
address PR comments
abdulhaseeb4239 Feb 28, 2024
77346dd
fix: change variant name according to zeroheight
abdulhaseeb4239 Feb 28, 2024
d24473c
fix: use the correct variant for memo
abdulhaseeb4239 Feb 28, 2024
51ec511
feat: apply stx fee cap logic
abdulhaseeb4239 Mar 1, 2024
2b6e22f
fix: setting recipient address
abdulhaseeb4239 Apr 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/app/components/confirmStxTransactionComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ interface Props {
title?: string;
subTitle?: string;
hasSignatures?: boolean;
feeOverride?: BigNumber;
}

function ConfirmStxTransactionComponent({
Expand All @@ -144,6 +145,7 @@ function ConfirmStxTransactionComponent({
onCancelClick,
skipModal = false,
hasSignatures = false,
feeOverride,
}: Props) {
const { t } = useTranslation('translation', { keyPrefix: 'CONFIRM_TRANSACTION' });
const { t: signatureRequestTranslate } = useTranslation('translation', {
Expand Down Expand Up @@ -255,6 +257,12 @@ function ConfirmStxTransactionComponent({
setOpenTransactionSettingModal(false);
};

useEffect(() => {
if (feeOverride) {
applyTxSettings({ fee: microstacksToStx(feeOverride).toString() });
}
}, [feeOverride]);

const handleConnectAndConfirm = async () => {
if (!selectedAccount) {
console.error('No account selected');
Expand Down
38 changes: 38 additions & 0 deletions src/app/components/inputScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import styled from 'styled-components';

const Container = styled.div`
flex: 1 1 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
`;

const ButtonsContainer = styled.div`
margin: ${(props) => props.theme.spacing(12)}px 0;
`;

const InputsContainer = styled.div`
display: flex;
flex-direction: column;
`;

type InputScreenProps = {
inputs: React.ReactNode;
buttons: React.ReactNode;
header?: React.ReactNode;
};

function InputScreen({ inputs, buttons, header }: InputScreenProps) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% convinced this component is needed. It's currently used in 1 place with a single input and single button. Do we foresee it being used elsewhere?

Copy link
Member

@teebszet teebszet Feb 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda agree with @victorkirov here. I get the intent is to abstract away some of the layout logic to make it consistent, but IMO a better abstraction is to store well-defined styled components into ui-library/common.styled.ts.

because in this case, i'm not sure if this InputScreen will work for stx with the memo input.

return (
<Container>
<div>
{header}
<InputsContainer>{inputs}</InputsContainer>
</div>
<ButtonsContainer>{buttons}</ButtonsContainer>
</Container>
);
}

export default InputScreen;
21 changes: 17 additions & 4 deletions src/app/screens/confirmStxTransaction/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
getStxFiatEquivalent,
isMultiSig,
microstacksToStx,
stxToMicrostacks,
} from '@secretkeylabs/xverse-core';
import { MultiSigSpendingCondition, deserializeTransaction } from '@stacks/transactions';
import { useMutation } from '@tanstack/react-query';
Expand All @@ -38,7 +39,6 @@ const AlertContainer = styled.div((props) => ({

function ConfirmStxTransaction() {
const { t } = useTranslation('translation');
const [fee, setStateFee] = useState(new BigNumber(0));
const [amount, setAmount] = useState(new BigNumber(0));
const [fiatAmount, setFiatAmount] = useState(new BigNumber(0));
const [total, setTotal] = useState(new BigNumber(0));
Expand All @@ -53,7 +53,18 @@ function ConfirmStxTransaction() {
const { refetch } = useStxWalletData();

const location = useLocation();
const { unsignedTx: stringHex, sponsored, isBrowserTx, tabId, requestToken } = location.state;
const {
unsignedTx: stringHex,
sponsored,
isBrowserTx,
tabId,
requestToken,
fee: stateFee,
} = location.state;
const [fee, setStateFee] = useState(
stateFee ? stxToMicrostacks(new BigNumber(stateFee)) : new BigNumber(0),
);

const unsignedTx = useMemo(() => deserializeTransaction(stringHex), [stringHex]);

// SignTransaction Params
Expand Down Expand Up @@ -123,7 +134,7 @@ function ConfirmStxTransaction() {
}

const txAmount = new BigNumber(txPayload.amount.toString(10));
jordankzf marked this conversation as resolved.
Show resolved Hide resolved
const txFee = new BigNumber(unsignedTx.auth.spendingCondition.fee.toString());
const txFee = new BigNumber(fee.toString() ?? unsignedTx.auth.spendingCondition.fee.toString());
jordankzf marked this conversation as resolved.
Show resolved Hide resolved
const txTotal = amount.plus(fee);
const txFiatAmount = getStxFiatEquivalent(
amount,
Expand All @@ -137,7 +148,7 @@ function ConfirmStxTransaction() {
const modifiedMemoString = txMemo.content.split('\u0000').join('');

setAmount(txAmount);
setStateFee(txFee);
if (!fee) setStateFee(txFee);
jordankzf marked this conversation as resolved.
Show resolved Hide resolved
setFiatAmount(txFiatAmount);
setTotal(txTotal);
setFiatTotal(txFiatTotal);
Expand Down Expand Up @@ -194,6 +205,7 @@ function ConfirmStxTransaction() {
recipientAddress: recipient,
amountToSend: getAmount().toString(),
stxMemo: memo,
fee: fee.toString(),
},
});
}
Expand All @@ -214,6 +226,7 @@ function ConfirmStxTransaction() {
isSponsored={sponsored}
skipModal={isLedgerAccount(selectedAccount)}
hasSignatures={hasSignatures}
feeOverride={fee}
>
<RecipientComponent
address={recipient}
Expand Down
7 changes: 5 additions & 2 deletions src/app/screens/ordinals/ordinalImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,13 @@ function OrdinalImage({
if (contentType.includes('image')) {
return renderImage(t('ORDINAL'), `${XVERSE_ORDIVIEW_URL(network.type)}/content/${ordinal.id}`);
}

// if content type is undefined or "", we fall back to ordiview thumbnail
if (!contentType) {
return renderImage(t('ORDINAL'), `${XVERSE_ORDIVIEW_URL(network.type)}/thumbnail/${ordinal.id}`);
return renderImage(
t('ORDINAL'),
`${XVERSE_ORDIVIEW_URL(network.type)}/thumbnail/${ordinal.id}`,
);
}

if (textContent?.includes('brc-721e')) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,31 @@
import InputScreen from '@components/inputScreen';
import useWalletSelector from '@hooks/useWalletSelector';
import { validateBtcAddress } from '@secretkeylabs/xverse-core';
import Button from '@ui-library/button';
import Input from '@ui-library/input';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import styled from 'styled-components';

const Container = styled.div`
flex: 1 1 100%;

display: flex;
flex-direction: column;
justify-content: space-between;
`;

const Buttons = styled.div`
margin: ${(props) => props.theme.spacing(12)}px 0;
`;

type Props = {
type BtcRecipientScreenProps = {
recipientAddress: string;
setRecipientAddress: (address: string) => void;
onNext: () => void;
isLoading: boolean;
header?: React.ReactNode;
};

// TODO: this could be extracted into a component for reuse
function RecipientSelector({
type InputFeedback = {
variant: 'danger';
message: string;
}

function BtcRecipientScreen({
recipientAddress,
setRecipientAddress,
onNext,
isLoading,
header,
}: Props) {
}: BtcRecipientScreenProps) {
const { t } = useTranslation('translation', { keyPrefix: 'SEND' });
const { network } = useWalletSelector();
const [addressIsValid, setAddressIsValid] = useState(true);
Expand All @@ -51,41 +43,39 @@ function RecipientSelector({
setAddressIsValid(true);
};

const inputFeedback = useMemo(() => {
const inputFeedback: InputFeedback[] = useMemo(() => {
if (addressIsValid) {
return [];
}
return [
{
variant: 'danger' as const,
variant: 'danger',
message: t('ERRORS.ADDRESS_INVALID'),
},
];
}, [addressIsValid]);
}, [addressIsValid, t]);

const inputElement = (
<Input
title={t('RECIPIENT')}
placeholder={t('BTC.RECIPIENT_PLACEHOLDER')}
value={recipientAddress}
onChange={handleAddressChange}
variant={addressIsValid ? 'default' : 'danger'}
feedback={inputFeedback}
/>
);

return (
<Container>
<div>
{header}
<Input
title={t('RECIPIENT')}
placeholder={t('BTC.RECIPIENT_PLACEHOLDER')}
value={recipientAddress}
onChange={handleAddressChange}
variant={addressIsValid ? 'default' : 'danger'}
feedback={inputFeedback}
/>
</div>
<Buttons>
<Button
title={t('NEXT')}
onClick={handleNext}
disabled={!recipientAddress || !addressIsValid}
loading={isLoading}
/>
</Buttons>
</Container>
const buttonElement = (
<Button
title={t('NEXT')}
onClick={handleNext}
disabled={!recipientAddress || !addressIsValid}
loading={isLoading}
/>
);

return <InputScreen inputs={inputElement} buttons={buttonElement} header={header} />;
}

export default RecipientSelector;
export default BtcRecipientScreen;
4 changes: 2 additions & 2 deletions src/app/screens/sendBtc/stepDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useTranslation } from 'react-i18next';
import styled from 'styled-components';
import SendLayout from '../../layouts/sendLayout';
import AmountSelector from './amountSelector';
import BtcRecipientSelector from './btcRecipientSelector';
import { TransactionSummary } from './helpers';
import RecipientSelector from './recipientSelector';
import { Step, getNextStep } from './steps';

const TitleContainer = styled.div`
Expand Down Expand Up @@ -83,7 +83,7 @@ function StepDisplay({
return (
<SendLayout selectedBottomTab="dashboard" onClickBack={onBack}>
<Container>
<RecipientSelector
<BtcRecipientSelector
header={header}
recipientAddress={recipientAddress}
setRecipientAddress={setRecipientAddress}
Expand Down
Loading
Loading