Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4987a3c
chore: removed unused subscription actions
lwin-kyaw Dec 2, 2025
c67beb1
feat: get rewardsSubscriptionId for shield subscribed account
lwin-kyaw Dec 2, 2025
0ee67f0
feat: link reward to subscription
lwin-kyaw Dec 3, 2025
3380903
feat: link reward to crypto subs and refactor
lwin-kyaw Dec 3, 2025
1e7fcf1
Merge remote-tracking branch 'origin/main' into feat/shield-rewards-link
lwin-kyaw Dec 3, 2025
45fd45e
Update LavaMoat policies
metamaskbot Dec 3, 2025
b174e08
feat: updated privacy-snapshot for rewards APIs
lwin-kyaw Dec 3, 2025
b270f2c
fix: fixed lint
lwin-kyaw Dec 3, 2025
943a3d1
chore: refactoring and error handling
lwin-kyaw Dec 3, 2025
c88a95d
Merge remote-tracking branch 'origin/main' into feat/shield-rewards-link
lwin-kyaw Dec 3, 2025
109ed5a
feat: updated crypto subscription to link with payer rewards if avail…
lwin-kyaw Dec 3, 2025
8e088be
Merge remote-tracking branch 'origin/main' into feat/shield-rewards-link
lwin-kyaw Dec 3, 2025
04a700a
chore: bump subscription-controller to 5.3.0
lwin-kyaw Dec 3, 2025
2268d2e
chore: yarn dedupe
lwin-kyaw Dec 3, 2025
093ce32
Update LavaMoat policies
metamaskbot Dec 3, 2025
af5b29f
Merge branch 'main' into feat/shield-rewards-link
lwin-kyaw Dec 4, 2025
6665f65
feat: bump subscription-controller to 5.3.1
lwin-kyaw Dec 4, 2025
e66115d
Merge remote-tracking branch 'origin/feat/shield-rewards-link' into f…
lwin-kyaw Dec 4, 2025
04c7a7a
feat: metrics for rewards-shield
lwin-kyaw Dec 4, 2025
c77d016
chore: resolved conflicts
lwin-kyaw Dec 4, 2025
17ede8d
feat: integrated link-reward with shield in Reward Onboarding Modal
lwin-kyaw Dec 4, 2025
3b2ca55
Merge remote-tracking branch 'origin/main' into feat/shield-rewards-m…
lwin-kyaw Dec 4, 2025
178c8f6
feat: link-rewards metrics
lwin-kyaw Dec 4, 2025
67ea5a6
chore: added missing deps array
lwin-kyaw Dec 4, 2025
82bf23e
chore: error handling
lwin-kyaw Dec 5, 2025
131a4a7
chore: removed refresh optin status
lwin-kyaw Dec 5, 2025
f0cac6a
feat: check optin status before linking to shield
lwin-kyaw Dec 5, 2025
548fa92
feat: handle reward linking failed and retry
lwin-kyaw Dec 5, 2025
5ac21dc
resolved conflicts
lwin-kyaw Dec 5, 2025
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
3 changes: 3 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions app/_locales/en_GB/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion ui/hooks/rewards/useOptIn.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback, useState, useContext, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { AccountGroupId, AccountWalletId } from '@metamask/account-api';
import log from 'loglevel';
import {
getMultichainAccountsByWalletId,
getWalletIdAndNameByAccountAddress,
Expand Down Expand Up @@ -173,8 +174,9 @@ export const useOptIn = (options?: UseOptInOptions): UseOptinResult => {
options.rewardPoints,
),
);
} catch {
} catch (error) {
// Silently fail - reward linking should not block opt-in
log.warn('Failed to link reward to shield subscription', error);
}
}
}
Expand Down
42 changes: 40 additions & 2 deletions ui/pages/settings/transaction-shield-tab/transaction-shield.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Product,
PRODUCT_TYPES,
RECURRING_INTERVALS,
Subscription,
SUBSCRIPTION_STATUSES,
} from '@metamask/subscription-controller';
import { useLocation, useNavigate } from 'react-router-dom-v5-compat';
Expand All @@ -17,6 +18,7 @@ import {
IconSize,
} from '@metamask/design-system-react';
import { useDispatch, useSelector } from 'react-redux';
import log from 'loglevel';
import {
BannerAlert,
BannerAlertSeverity,
Expand Down Expand Up @@ -83,6 +85,7 @@ import { useHandlePayment } from '../../../hooks/subscription/useHandlePayment';
import { MetaMaskReduxDispatch } from '../../../store/store';
import { setOnboardingModalOpen } from '../../../ducks/rewards';
import { getIntlLocale } from '../../../ducks/locale/locale';
import { linkRewardToShieldSubscription } from '../../../store/actions';
import CancelMembershipModal from './cancel-membership-modal';
import { isCardPaymentMethod, isCryptoPaymentMethod } from './types';
import ShieldBannerAnimation from './shield-banner-animation';
Expand Down Expand Up @@ -126,8 +129,9 @@ const TransactionShield = () => {
lastSubscription,
);
// show current active shield subscription or last subscription if no active subscription
const displayedShieldSubscription =
currentShieldSubscription ?? lastShieldSubscription;
const displayedShieldSubscription:
| (Subscription & { rewardAccountId?: string }) // TODO: fix this type once we have controller released.
| undefined = currentShieldSubscription ?? lastShieldSubscription;

const [timeoutCancelled, setTimeoutCancelled] = useState(false);
useEffect(() => {
Expand Down Expand Up @@ -280,6 +284,20 @@ const TransactionShield = () => {
padding: 4,
};

const handleLinkRewardToShieldSubscription = useCallback(
async (subscriptionId: string, rewardPoints: number) => {
// link to shield only coz already opted in to rewards
try {
await dispatch(
linkRewardToShieldSubscription(subscriptionId, rewardPoints),
);
} catch (error) {
log.warn('Failed to link reward to shield subscription', error);
}
},
[dispatch],
);

const buttonRow = (label: string, onClick: () => void, id?: string) => {
return (
<Box
Expand Down Expand Up @@ -682,6 +700,26 @@ const TransactionShield = () => {
</Button>
</Box>
)}
{hasOptedIntoRewards &&
displayedShieldSubscription?.id &&
claimedRewardsPoints &&
!displayedShieldSubscription?.rewardAccountId && (
<Box className="flex-shrink-0">
<Button
className="px-3"
variant={ButtonVariant.Secondary}
size={ButtonSize.Sm}
onClick={async () =>
handleLinkRewardToShieldSubscription(
displayedShieldSubscription?.id,
claimedRewardsPoints,
)
}
>
{t('shieldTxDetails3DescriptionLinkReward')}
</Button>
</Box>
)}
</Box>
)}
</Box>
Expand Down
Loading