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

release: v0.28.0 to main #741

Merged
merged 28 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
74394d3
[ENG-3325] chore: refactor workflows (#714)
teebszet Jan 2, 2024
f32e96c
chore: fix build workflow file (#734)
teebszet Jan 3, 2024
f5067a2
ENG-3402 Named classes for styled-components (#721)
jordankzf Jan 4, 2024
50e0667
Merge branch 'develop' into release/v0.27.0
teebszet Jan 5, 2024
2661b33
Merge pull request #732 from secretkeylabs/release/v0.27.0
teebszet Jan 5, 2024
6c8029f
ENG-2630: Remove BRC-20 / SIP-10 token labels (#735)
jordankzf Jan 5, 2024
2b030af
feat: BTC fee UI (#733)
abdulhaseeb4239 Jan 8, 2024
2b1b387
[ENG-3471] feat: use estimated fees for stx transactions (#720)
teebszet Jan 9, 2024
e279511
[ENG-3436] chore: Make some code refactoring for RBF in the extension…
dhriaznov Jan 9, 2024
e30276a
Bug fix/rbf support custom seed handler (#739)
m-aboelenein Jan 10, 2024
e38eb59
feat: add btc consolidation logic and new ui components to psbt and b…
fedeerbes Jan 10, 2024
c5b32b5
[ENG-3496] fix: utxo 500 issue add a fallback option to our api https…
teebszet Jan 11, 2024
2f7a7dc
chore: add new auto lock period values and migrate users if needed (#…
fedeerbes Jan 11, 2024
7898e48
Allow testnet ledger accounts (#688)
victorkirov Jan 11, 2024
73461bf
release: v0.28.0
Jan 11, 2024
1ab7041
Merge branch 'main' into release/v0.28.0
teebszet Jan 11, 2024
748bb29
chore: fix build-rc.yml workflow file
teebszet Jan 11, 2024
18dbcbd
Merge branch 'main' into release/v0.28.0
teebszet Jan 11, 2024
123bae9
Merge branch 'main' into release/v0.28.0
teebszet Jan 11, 2024
5268863
[ENG-3474] feat: Make UI for STX RBF in the extension (#727)
dhriaznov Jan 11, 2024
5b136ec
Merge branch 'develop' into release/v0.28.0
dhriaznov Jan 11, 2024
f009163
Merge branch 'main' into release/v0.28.0
teebszet Jan 11, 2024
01f1b0d
Merge branch 'main' into release/v0.28.0
teebszet Jan 11, 2024
57a50fe
[ENG-3564] fix: Speed up transaction ui issue displaying and loading …
dhriaznov Jan 12, 2024
8f0e3ac
fix: skip server validation of api urls if value didn't change (#752)
teebszet Jan 12, 2024
cd7c798
[END 3565] fix: catch and display failed to broadcast error (#751)
teebszet Jan 12, 2024
497b3b7
[ENG-3563] fix: BTC fee infinite loader when sending ordinals (#748)
dhriaznov Jan 12, 2024
f045814
chore: remove mock data for psbt ui (#753)
fedeerbes Jan 12, 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
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ jobs:
ARTIFACT_URL="https://github.com/$OWNER/$REPO/actions/runs/$WORKFLOW_ID"
echo "ARTIFACT_URL=$ARTIFACT_URL" >> $GITHUB_ENV
- name: Delete old bot comments
env:
PR_ID: ${{ github.event.pull_request.number }}
run: |
gh api \
Expand Down
580 changes: 391 additions & 189 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "xverse-web-extension",
"description": "A Bitcoin wallet for Web3",
"version": "0.27.0",
"version": "0.28.0",
"private": true,
"engines": {
"node": "^18.18.2"
Expand All @@ -10,7 +10,8 @@
"@ledgerhq/hw-transport-webusb": "^6.27.13",
"@phosphor-icons/react": "^2.0.10",
"@react-spring/web": "^9.6.1",
"@secretkeylabs/xverse-core": "7.0.0",
"@scure/btc-signer": "^1.1.1",
"@secretkeylabs/xverse-core": "8.0.1",
"@stacks/connect": "7.4.1",
"@stacks/stacks-blockchain-api-types": "6.1.1",
"@stacks/transactions": "6.9.0",
Expand All @@ -26,6 +27,7 @@
"axios": "^1.1.3",
"bignumber.js": "^9.1.0",
"bip39": "^3.0.3",
"buffer": "6.0.3",
"c32check": "^2.0.0",
"classnames": "^2.3.2",
"crypto-browserify": "^3.12.0",
Expand Down Expand Up @@ -76,8 +78,7 @@
"style": "prettier --write \"src/**/*.{ts,tsx}\"",
"prepare": "husky install"
},
"resolutions": {
"styled-components": "^5",
"overrides": {
"buffer": "6.0.3"
},
"lint-staged": {
Expand Down Expand Up @@ -138,7 +139,8 @@
"tsc-files": "^1.1.4",
"tsconfig-paths-webpack-plugin": "^4.0.0",
"type-fest": "^2.19.0",
"typescript": "^4.8.2",
"typescript": "^5.0.0",
"typescript-plugin-styled-components": "^3.0.0",
"vitest": "^0.34.6",
"webpack": "^5.89.0",
"webpack-cli": "^4.0.0",
Expand Down
34 changes: 29 additions & 5 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import LoadingScreen from '@components/loadingScreen';
import { CheckCircle } from '@phosphor-icons/react';
import { CheckCircle, XCircle } from '@phosphor-icons/react';
import rootStore from '@stores/index';
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
Expand All @@ -11,13 +11,20 @@ import { Toaster } from 'react-hot-toast';
import { Provider } from 'react-redux';
import { RouterProvider } from 'react-router-dom';
import { PersistGate } from 'redux-persist/integration/react';
import { ThemeProvider } from 'styled-components';
import styled, { ThemeProvider } from 'styled-components';
import '../locales';
import Theme from '../theme';
import GlobalStyle from '../theme/global';
import SessionGuard from './components/guards/session';
import router from './routes';

// needed to keep the svg icon scale for toasts over multiple lines
const StyledIcon = styled.div`
display: flex;
align-items: center;
justify-content: center;
`;

function App(): JSX.Element {
useEffect(() => {
if (!MIX_PANEL_TOKEN) {
Expand Down Expand Up @@ -46,16 +53,33 @@ function App(): JSX.Element {
containerStyle={{ bottom: 80 }}
toastOptions={{
success: {
icon: <CheckCircle size={20} weight="bold" />,
icon: (
<StyledIcon>
<CheckCircle size={20} weight="bold" />
</StyledIcon>
),
style: {
...Theme.typography.body_medium_m,
backgroundColor: Theme.colors.success_medium,
borderRadius: Theme.radius(2),
padding: Theme.spacing(4),
paddingLeft: Theme.spacing(6),
padding: Theme.space.s,
color: Theme.colors.elevation0,
},
},
error: {
icon: (
<StyledIcon>
<XCircle size={20} weight="bold" />
</StyledIcon>
),
style: {
...Theme.typography.body_medium_m,
backgroundColor: Theme.colors.danger_dark,
borderRadius: Theme.radius(2),
padding: Theme.space.s,
color: Theme.colors.white_0,
},
},
}}
/>
</ThemeProvider>
Expand Down
10 changes: 5 additions & 5 deletions src/app/components/bottomModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Cross from '@assets/img/dashboard/X.svg';
import Separator from '@components/separator';
import { XCircle } from '@phosphor-icons/react';
import Modal from 'react-modal';
import styled, { useTheme } from 'styled-components';

Expand All @@ -11,9 +11,9 @@ const BottomModalHeaderText = styled.h1((props) => ({
const RowContainer = styled.div((props) => ({
display: 'flex',
flexDirection: 'row',
alignItems: 'space-between',
margin: props.theme.spacing(12),
marginBottom: props.theme.spacing(10),
alignItems: 'center',
justifyContent: 'space-between',
margin: props.theme.space.m,
}));

const ButtonImage = styled.button({
Expand Down Expand Up @@ -87,7 +87,7 @@ function BottomModal({
<RowContainer>
<BottomModalHeaderText>{header}</BottomModalHeaderText>
<ButtonImage onClick={onClose}>
<img src={Cross} alt="cross" />
<XCircle color={theme.colors.white_200} weight="fill" size="28" />
</ButtonImage>
</RowContainer>
{header && <Separator />}
Expand Down
229 changes: 229 additions & 0 deletions src/app/components/confirmBtcTransaction/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
import ledgerConnectDefaultIcon from '@assets/img/ledger/ledger_connect_default.svg';
import ledgerConnectBtcIcon from '@assets/img/ledger/ledger_import_connect_btc.svg';
import { delay } from '@common/utils/ledger';
import BottomModal from '@components/bottomModal';
import ActionButton from '@components/button';
import LedgerConnectionView from '@components/ledger/connectLedgerView';
import useWalletSelector from '@hooks/useWalletSelector';
import TransportFactory from '@ledgerhq/hw-transport-webusb';
import { btcTransaction, Transport } from '@secretkeylabs/xverse-core';
import Callout from '@ui-library/callout';
import { StickyHorizontalSplitButtonContainer, StyledP } from '@ui-library/common.styled';
import { isLedgerAccount } from '@utils/helper';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { MoonLoader } from 'react-spinners';
import styled from 'styled-components';
import SendLayout from '../../layouts/sendLayout';
import TransactionSummary from './transactionSummary';

const LoaderContainer = styled.div(() => ({
display: 'flex',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}));

const ReviewTransactionText = styled(StyledP)`
text-align: left;
margin-bottom: ${(props) => props.theme.space.l};
`;

const BroadcastCallout = styled(Callout)`
margin-bottom: ${(props) => props.theme.space.m};
`;

const SuccessActionsContainer = styled.div((props) => ({
width: '100%',
display: 'flex',
flexDirection: 'column',
gap: props.theme.space.s,
paddingLeft: props.theme.space.m,
paddingRight: props.theme.space.m,
marginBottom: props.theme.space.xxl,
marginTop: props.theme.space.xxl,
}));

type Props = {
inputs: btcTransaction.EnhancedInput[];
outputs: btcTransaction.EnhancedOutput[];
feeOutput?: btcTransaction.TransactionFeeOutput;
isLoading: boolean;
isSubmitting: boolean;
isBroadcast?: boolean;
isError?: boolean;
showAccountHeader?: boolean;
hideBottomBar?: boolean;
cancelText: string;
confirmText: string;
onConfirm: (ledgerTransport?: Transport) => void;
onCancel: () => void;
onBackClick?: () => void;
confirmDisabled?: boolean;
getFeeForFeeRate?: (feeRate: number, useEffectiveFeeRate?: boolean) => Promise<number>;
onFeeRateSet?: (feeRate: number) => void;
};

function ConfirmBtcTransaction({
inputs,
outputs,
feeOutput,
isLoading,
isSubmitting,
isBroadcast,
isError = false,
cancelText,
confirmText,
onConfirm,
onCancel,
onBackClick,
showAccountHeader,
hideBottomBar,
confirmDisabled = false,
getFeeForFeeRate,
onFeeRateSet,
}: Props) {
const [isModalVisible, setIsModalVisible] = useState(false);
const [currentStepIndex, setCurrentStepIndex] = useState(0);
const [isButtonDisabled, setIsButtonDisabled] = useState(false);
const [isConnectSuccess, setIsConnectSuccess] = useState(false);
const [isConnectFailed, setIsConnectFailed] = useState(false);
const [isTxRejected, setIsTxRejected] = useState(false);

const { t } = useTranslation('translation', { keyPrefix: 'CONFIRM_TRANSACTION' });
const { t: signatureRequestTranslate } = useTranslation('translation', {
keyPrefix: 'SIGNATURE_REQUEST',
});
const { selectedAccount } = useWalletSelector();

const hideBackButton = !onBackClick;

const onConfirmPress = async () => {
if (!isLedgerAccount(selectedAccount)) {
return onConfirm();
}

// show ledger connection screens
setIsModalVisible(true);
};

const handleConnectAndConfirm = async () => {
if (!selectedAccount) {
console.error('No account selected');

Check warning on line 112 in src/app/components/confirmBtcTransaction/index.tsx

View workflow job for this annotation

GitHub Actions / test

Unexpected console statement

Check warning on line 112 in src/app/components/confirmBtcTransaction/index.tsx

View workflow job for this annotation

GitHub Actions / test

Unexpected console statement
return;
}
setIsButtonDisabled(true);

const transport = await TransportFactory.create();

if (!transport) {
setIsConnectSuccess(false);
setIsConnectFailed(true);
setIsButtonDisabled(false);
return;
}

setIsConnectSuccess(true);
await delay(1500);
setCurrentStepIndex(1);

try {
onConfirm(transport);
} catch (err) {
console.error(err);

Check warning on line 133 in src/app/components/confirmBtcTransaction/index.tsx

View workflow job for this annotation

GitHub Actions / test

Unexpected console statement

Check warning on line 133 in src/app/components/confirmBtcTransaction/index.tsx

View workflow job for this annotation

GitHub Actions / test

Unexpected console statement
setIsTxRejected(true);
}
};

const handleRetry = async () => {
setIsTxRejected(false);
setIsConnectSuccess(false);
setCurrentStepIndex(0);
};

// TODO: this is a bit naive, but should be correct. We may want to look at the sig hash types of the inputs instead
const isPartialTransaction = !feeOutput;

return isLoading ? (
<LoaderContainer>
<MoonLoader color="white" size={50} />
</LoaderContainer>
) : (
<>
<SendLayout
selectedBottomTab="dashboard"
onClickBack={onBackClick}
hideBackButton={hideBackButton}
showAccountHeader={showAccountHeader}
hideBottomBar={hideBottomBar}
>
<ReviewTransactionText typography="headline_s">
{t('REVIEW_TRANSACTION')}
</ReviewTransactionText>
{!isBroadcast && <BroadcastCallout bodyText={t('PSBT_NO_BROADCAST_DISCLAIMER')} />}
<TransactionSummary
inputs={inputs}
outputs={outputs}
feeOutput={feeOutput}
isPartialTransaction={isPartialTransaction}
getFeeForFeeRate={getFeeForFeeRate}
onFeeRateSet={onFeeRateSet}
isSubmitting={isSubmitting}
/>
{!isLoading && (
<StickyHorizontalSplitButtonContainer>
<ActionButton onPress={onCancel} text={cancelText} transparent />
<ActionButton
onPress={onConfirmPress}
disabled={confirmDisabled}
processing={isSubmitting}
text={confirmText}
warning={isError}
/>
</StickyHorizontalSplitButtonContainer>
)}
</SendLayout>
<BottomModal header="" visible={isModalVisible} onClose={() => setIsModalVisible(false)}>
{currentStepIndex === 0 && (
<LedgerConnectionView
title={signatureRequestTranslate('LEDGER.CONNECT.TITLE')}
text={signatureRequestTranslate('LEDGER.CONNECT.SUBTITLE', { name: 'Bitcoin' })}
titleFailed={signatureRequestTranslate('LEDGER.CONNECT.ERROR_TITLE')}
textFailed={signatureRequestTranslate('LEDGER.CONNECT.ERROR_SUBTITLE')}
imageDefault={ledgerConnectBtcIcon}
isConnectSuccess={isConnectSuccess}
isConnectFailed={isConnectFailed}
/>
)}
{currentStepIndex === 1 && (
<LedgerConnectionView
title={signatureRequestTranslate('LEDGER.CONFIRM.TITLE')}
text={signatureRequestTranslate('LEDGER.CONFIRM.SUBTITLE')}
titleFailed={signatureRequestTranslate('LEDGER.CONFIRM.ERROR_TITLE')}
textFailed={signatureRequestTranslate('LEDGER.CONFIRM.ERROR_SUBTITLE')}
imageDefault={ledgerConnectDefaultIcon}
isConnectSuccess={false}
isConnectFailed={isTxRejected}
/>
)}
<SuccessActionsContainer>
<ActionButton
onPress={isTxRejected || isConnectFailed ? handleRetry : handleConnectAndConfirm}
text={signatureRequestTranslate(
isTxRejected || isConnectFailed ? 'LEDGER.RETRY_BUTTON' : 'LEDGER.CONNECT_BUTTON',
)}
disabled={isButtonDisabled}
processing={isButtonDisabled}
/>
<ActionButton
onPress={onCancel}
text={signatureRequestTranslate('LEDGER.CANCEL_BUTTON')}
transparent
/>
</SuccessActionsContainer>
</BottomModal>
</>
);
}

export default ConfirmBtcTransaction;
Loading
Loading