Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 30 additions & 1 deletion .github/workflows/update-release-changelog.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# On every push to a release branch (Version-v* or release/*), this workflow rebuilds the matching
# On every push to a release branch (release/x.y.z format), this workflow rebuilds the matching
# changelog branch, re-runs the auto-changelog script, and either updates or recreates the changelog PR.
# Note: This workflow validates the branch name to ensure it matches the semantic versioning pattern
# (release/x.y.z) and skips execution for other branch names like release/x.y.z-Changelog.
name: Update Release Changelog PR

on:
Expand All @@ -12,7 +14,34 @@ concurrency:
cancel-in-progress: false

jobs:
validate-branch:
name: Validate release branch format
runs-on: ubuntu-latest
outputs:
is-valid-release: ${{ steps.check.outputs.is-valid }}
version: ${{ steps.check.outputs.version }}
steps:
- name: Check if branch matches release/x.y.z pattern
id: check
run: |
BRANCH_NAME="${{ github.ref_name }}"
echo "Checking branch: $BRANCH_NAME"

# Validate branch matches release/x.y.z format (semantic versioning)
if [[ "$BRANCH_NAME" =~ ^release/[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
VERSION="${BRANCH_NAME#release/}"
echo "Valid release branch detected: $BRANCH_NAME (version: $VERSION)"
echo "is-valid=true" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
else
echo "Branch '$BRANCH_NAME' does not match release/x.y.z pattern. Skipping changelog update."
echo "is-valid=false" >> "$GITHUB_OUTPUT"
fi

refresh-changelog:
name: Update changelog
needs: validate-branch
if: needs.validate-branch.outputs.is-valid-release == 'true'
permissions:
contents: write
pull-requests: write
Expand Down
9 changes: 9 additions & 0 deletions app/components/Nav/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ const ImportPrivateKeyView = () => (

const ImportSRPView = () => (
<Stack.Navigator
mode="modal"
screenOptions={{
headerShown: false,
}}
Expand All @@ -605,6 +606,14 @@ const ImportSRPView = () => (
name={Routes.MULTI_SRP.IMPORT}
component={ImportNewSecretRecoveryPhrase}
/>
<Stack.Screen name={Routes.QR_TAB_SWITCHER} component={QRTabSwitcher} />
<Stack.Screen
name={Routes.SHEET.SEEDPHRASE_MODAL}
component={SeedphraseModal}
options={{
cardStyle: { backgroundColor: 'transparent' },
}}
/>
</Stack.Navigator>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,14 @@ jest.mock('../../../Rewards/utils', () => ({
(code) => `https://link.metamask.io/rewards?referral=${code}`,
),
}));
jest.mock('../../../Rewards/hooks/useReferralDetails', () => ({
useReferralDetails: jest.fn(),
}));
jest.mock('@metamask/design-tokens', () => ({
brandColor: {
black: '#000000',
white: '#FFFFFF',
},
darkTheme: {
colors: {
background: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import RewardsReferralCodeTag from '../../../Rewards/components/RewardsReferralC
import {
formatPerpsFiat,
parseCurrencyString,
PRICE_RANGES_MINIMAL_VIEW,
PRICE_RANGES_UNIVERSAL,
} from '../../utils/formatUtils';
import MetaMaskLogo from '../../../../../images/branding/metamask-name.png';
Expand All @@ -60,6 +59,7 @@ import {
PerpsHeroCardViewSelectorsIDs,
getPerpsHeroCardViewSelector,
} from '../../../../../../e2e/selectors/Perps/Perps.selectors';
import { useReferralDetails } from '../../../Rewards/hooks/useReferralDetails';

// To add a new card, add the image to the array.
const CARD_IMAGES: { image: ImageSourcePropType; id: number; name: string }[] =
Expand Down Expand Up @@ -87,6 +87,9 @@ const PerpsHeroCardView: React.FC = () => {

const rewardsReferralCode = useSelector(selectReferralCode);

// Fetch referral details to ensure code is available for display
useReferralDetails();

const { track } = usePerpsEventTracking();

const { showToast, PerpsToastOptions } = usePerpsToasts();
Expand Down Expand Up @@ -232,7 +235,7 @@ const PerpsHeroCardView: React.FC = () => {
variant={TextVariant.BodySMMedium}
>
{formatPerpsFiat(data.entryPrice, {
ranges: PRICE_RANGES_MINIMAL_VIEW,
ranges: PRICE_RANGES_UNIVERSAL,
})}
</Text>
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
import {
formatPerpsFiat,
formatTransactionDate,
PRICE_RANGES_UNIVERSAL,
} from '../../utils/formatUtils';
import { styleSheet } from './PerpsPositionTransactionView.styles';

Expand Down Expand Up @@ -103,7 +104,9 @@ const PerpsPositionTransactionView: React.FC = () => {
transaction.fill?.action === 'Closed'
? strings('perps.transactions.position.close_price')
: strings('perps.transactions.position.entry_price'),
value: formatPerpsFiat(transaction.fill.entryPrice),
value: formatPerpsFiat(transaction.fill.entryPrice, {
ranges: PRICE_RANGES_UNIVERSAL,
}),
},
].filter(Boolean);

Expand Down
107 changes: 107 additions & 0 deletions app/components/UI/SrpInputGrid/SrpInputGrid.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { StyleSheet, Platform, TextStyle } from 'react-native';
import { fontStyles, colors as commonColors } from '../../../styles/common';
import { Colors } from '../../../util/theme/models';

/**
* Creates styles for the SrpInputGrid component
* @param colors - Theme colors object
* @returns StyleSheet object with all component styles
*/
export const createStyles = (colors: Colors) =>
StyleSheet.create({
seedPhraseRoot: {
flexDirection: 'column' as const,
gap: 4,
marginBottom: 24,
},
seedPhraseContainer: {
paddingTop: 16,
backgroundColor: colors.background.section,
borderRadius: 10,
marginTop: 16,
minHeight: 264,
maxHeight: 'auto',
},
seedPhraseInnerContainer: {
paddingHorizontal: Platform.select({
ios: 16,
macos: 16,
default: 14,
}),
},
seedPhraseInputContainer: {
flexDirection: 'row' as const,
flexWrap: 'wrap' as const,
width: '100%',
},
seedPhraseDefaultInput: {
borderWidth: 0,
paddingHorizontal: 0,
display: 'flex' as const,
flex: 1,
backgroundColor: commonColors.transparent,
},
seedPhraseInputItem: {
width: '31.33%',
marginRight: '3%',
marginBottom: 8,
flex: 0,
minWidth: 0,
},
seedPhraseInputItemLast: {
marginRight: 0,
},
textAreaInput: {
display: 'flex' as const,
height: 66,
color: colors.text.alternative,
backgroundColor: commonColors.transparent,
...fontStyles.normal,
fontSize: 16,
lineHeight: 20,
paddingTop: Platform.OS === 'ios' ? 12 : 8,
paddingBottom: 12,
} satisfies TextStyle,
inputItem: {
flex: 1,
minWidth: 0,
maxWidth: '100%',
paddingRight: 8,
} satisfies TextStyle,
input: {
paddingVertical: Platform.select({
ios: 4,
macos: 4,
default: 0,
}),
borderRadius: 8,
backgroundColor: colors.background.default,
flexDirection: 'row' as const,
alignItems: 'center' as const,
justifyContent: 'flex-start' as const,
height: 40,
fontSize: 16,
color: colors.text.default,
...fontStyles.normal,
textAlignVertical: 'center' as const,
paddingLeft: 8,
overflow: 'hidden' as const,
} satisfies TextStyle,
inputIndex: {
marginRight: -4,
},
pasteText: {
textAlign: 'right' as const,
paddingTop: 12,
paddingBottom: 16,
alignSelf: 'flex-end' as const,
} satisfies TextStyle,

hiddenInput: {
opacity: 0,
position: 'absolute' as const,
height: 0,
top: 0,
left: 0,
} satisfies TextStyle,
});
46 changes: 46 additions & 0 deletions app/components/UI/SrpInputGrid/SrpInputGrid.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Props for the SrpInputGrid component
* This component provides a reusable Secret Recovery Phrase input grid
* that handles both single textarea and multi-input modes
*/
export interface SrpInputGridProps {
/**
* Array of seed phrase words
*/
seedPhrase: string[];

/**
* Callback when seed phrase array changes
*/
onSeedPhraseChange: React.Dispatch<React.SetStateAction<string[]>>;

/**
* Callback when error state changes
*/
onError?: (error: string) => void;

/**
* External error message to display from parent
*/
externalError?: string;

/**
* Prefix for test IDs (e.g., 'seed-phrase-input' or 'import-from-seed-input')
*/
testIdPrefix: string;

/**
* Placeholder text for the first input (textarea mode)
*/
placeholderText: string;

/**
* Unique ID for key generation (optional, will generate if not provided)
*/
uniqueId?: string;

/**
* Whether the inputs should be disabled
*/
disabled?: boolean;
}
Loading
Loading