Skip to content
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
e82c697
feat: Add MPB bridge widget with cross-chain bridging
romeoscript Jul 28, 2025
28b610f
feat: Add bridge provider selection and improved transaction history UI
romeoscript Jul 28, 2025
c812b66
fix: Replace hardcoded transaction history with real SDK data
romeoscript Jul 28, 2025
c430e59
feat: Add bridging status and real-time transaction feedback
romeoscript Jul 28, 2025
629cd7b
feat: integrate GoodDollar Bridge API for real-time fees
romeoscript Aug 5, 2025
1756d36
refactor: remove redundant MPBBridgeController component
romeoscript Aug 5, 2025
0b37dd0
feat: implement MPB (Main Bridge) UI and SDK for cross-chain G$ trans…
romeoscript Aug 8, 2025
dab3ac2
fix source chain attribute
romeoscript Aug 8, 2025
c14a198
update price impact on mpb
romeoscript Aug 20, 2025
c24371c
fix: Set MPBBridge minimum amount to 1000 G$ and fix validation
romeoscript Aug 20, 2025
3586a9c
fix(mpb-bridge): validate against chain-decimal limits and use BigNumber
romeoscript Aug 20, 2025
99d21e1
fix:bridge fees
romeoscript Aug 20, 2025
3ade989
fix:change mpbbridge transaction card
romeoscript Aug 20, 2025
e7ecf97
feat: replace fake MPB transaction history with real blockchain events
romeoscript Sep 4, 2025
1da5276
fix(mpbridge): increase Celo gas fees to 100 gwei
romeoscript Sep 5, 2025
fe8b76d
fix: resolve TypeScript errors and fee routing in MPB bridge
romeoscript Sep 7, 2025
0d10a29
fix: update onBridgeStart prop type to accept chain parameters
romeoscript Sep 7, 2025
589e005
feat: add bridge transaction debug logging for gas estimation trouble…
romeoscript Sep 9, 2025
5a48b42
feat: use transferAndCall for MPB bridge and dynamic API fees
romeoscript Sep 13, 2025
d1cc2e2
feat: use transferAndCall for MPB bridge with dynamic API fees
romeoscript Sep 13, 2025
845340a
feat: improve balance display UX in MPB bridge interface
romeoscript Sep 13, 2025
5790bf4
refactor: break down large MPB bridge file into focused modules
romeoscript Sep 13, 2025
5c5eafb
refactor: break down large MPBBridge component into focused modules
romeoscript Sep 13, 2025
bd63322
fix: resolve SDK build conflicts and restore transaction history
romeoscript Sep 13, 2025
d331f70
refactor: replace hardcoded MPB contract data with @gooddollar/bridg…
romeoscript Sep 13, 2025
ad0d72b
feat: enhance MPB bridge transaction UI with full-width cards and cus…
romeoscript Sep 18, 2025
0291ad2
feat: enhance MPB bridge transaction modal with custom styling
romeoscript Sep 18, 2025
3bc7612
Merge branch 'master' into feature/mpb-bridge-widget
romeoscript Sep 18, 2025
3c70c24
feat: update MPB bridge widget components and SDK integration
romeoscript Sep 30, 2025
4b5ff40
perf(mpb-bridge): reduce re-renders, debounce input, cache fees, remo…
romeoscript Sep 30, 2025
5602f93
refactor: consolidate mpbridge files and apply DRY principles
romeoscript Sep 30, 2025
4be4ec6
Merge branch 'feature/mpb-bridge-widget' of https://github.com/romeos…
romeoscript Sep 30, 2025
ff4f5b8
Simplify getContractIcon function to always return GoodDollar
romeoscript Oct 6, 2025
2c99e4a
Fix MPBridge loading issue caused by API rate limiting
romeoscript Oct 6, 2025
27ecab9
Clean up MPBridge code and remove debug stories
romeoscript Oct 6, 2025
cbd1791
fix: use dynamic minimum amount from contract instead of hardcoded value
romeoscript Oct 13, 2025
355e5c8
refactor: centralize contract ABIs and improve bridge code quality
romeoscript Oct 15, 2025
be55e2a
fix: resolve bridge amount issues and improve dropdown UX
romeoscript Oct 15, 2025
e727e3a
refactor: remove hardcoded bridge fees and improve error handling
romeoscript Oct 20, 2025
8bb5652
fix(bridge): resolve transaction state issues and improve UX
romeoscript Oct 20, 2025
4970aed
feat(bridge): replace hardcoded values with contract calls
romeoscript Oct 28, 2025
5c00b83
feat(bridge): de-duplicate provider routes and auto-adjust on provide…
romeoscript Oct 30, 2025
2b986d3
fix: MPB bridge contract integration - use mpb.json and approve+bridg…
romeoscript Nov 6, 2025
d57a289
Merge branch 'master' of https://github.com/GoodDollar/GoodWeb3-Mono …
L03TJ3 Nov 18, 2025
731642e
feat(mpbridge): add error decoding and improved error logging
romeoscript Nov 17, 2025
17fbdd7
feat(mpbridge): add comprehensive pre-flight validation checks
romeoscript Nov 18, 2025
e0d812a
fix(mpbridge): use correct proxy contract and production G$ token
romeoscript Nov 24, 2025
2663ba8
fix(mpbridge): allow automatic approval flow when allowance is insuff…
romeoscript Nov 24, 2025
fbd0e3f
fix: revert the brige service mapping to use the correct values
romeoscript Nov 24, 2025
31a36f0
fix: MPB bridge transaction history - amounts, source chain, status, …
romeoscript Nov 24, 2025
b16ff66
fix: executed transaction history
romeoscript Nov 25, 2025
a85cd0c
fix(mpbridge): improve error handling and ui feedback
romeoscript Nov 25, 2025
6d5cc91
Merge branch 'master' of https://github.com/GoodDollar/GoodWeb3-Mono …
L03TJ3 Nov 26, 2025
10ef07d
fix(sdk-v2): correct relative import paths in MPBridge hooks
romeoscript Nov 27, 2025
2b56448
feat(mpbridge): optimize approval flow and fix error handling
romeoscript Nov 27, 2025
cda8caa
chore: remove console logs from MPBridge for production
romeoscript Nov 27, 2025
78f0047
Merge branch 'master' of https://github.com/GoodDollar/GoodWeb3-Mono …
L03TJ3 Nov 27, 2025
d5c75bd
fix: explorer link base-env destructure
L03TJ3 Nov 27, 2025
c79031a
remove duplicate comment
romeoscript Nov 27, 2025
32d8bc2
feat(mpbridge): add success modal for bridge transactions
romeoscript Dec 3, 2025
c94100d
fix(good-design): show bridge success modal immediately after transac…
romeoscript Dec 11, 2025
fdcaed4
fix: linting and formatting issues in bridge components
romeoscript Dec 11, 2025
3ea80e3
fix: correct balance fetching for MPBBridge with chain-specific G$ ad…
romeoscript Dec 18, 2025
9d069d4
refactor: improve MPBBridge UI and code organization
romeoscript Dec 22, 2025
90f399f
feat: separate transaction history into own card with improved styling
romeoscript Dec 22, 2025
6eb0b3a
fix: improve transaction status detection and display consistency
romeoscript Dec 22, 2025
dbe82c0
fix: reduce block ranges to comply with RPC provider 10k limit
romeoscript Dec 22, 2025
4a102b3
fix(mpbridge): use selected route for validation and show pre-executi…
romeoscript Feb 3, 2026
e186658
fix:modify constants
romeoscript Feb 5, 2026
f4d4e56
fix(mpbridge): chain switching, min amount validation, and env backen…
romeoscript Feb 5, 2026
d3eea0b
fix(mpbridge): remove no-op allowance check in useBridgeValidators
romeoscript Feb 5, 2026
92654de
refactor(sdk-v2): useBridgeValidators early checks, single bridgeLimi…
romeoscript Feb 5, 2026
3fc4299
refactor(sdk-v2): use shared normalizeAmountTo18 and useG in mpbridge
romeoscript Feb 5, 2026
74604f3
feat(good-design): MPB bridge network icons (Celo dark, Fuse, Mainnet)
romeoscript Feb 5, 2026
f6b514d
feat(good-design): simpler transaction details copy and align styling…
romeoscript Feb 5, 2026
0d4a423
fix(good-design): avoid using current time as fallback when tx date i…
romeoscript Feb 5, 2026
d576a68
fix: Transaction Details modal styling and progress line
romeoscript Feb 5, 2026
68d9803
fix: prevent double bridgeTo execution after approval
romeoscript Feb 5, 2026
e2c3b20
refactor: centralize MPBBridge via useGetContract, remove useGetMPBCo…
romeoscript Feb 5, 2026
8a7ae9d
Merge upstream/master into feature/mpb-bridge-widget
romeoscript Feb 5, 2026
1ed512a
fix(mpbridge): prevent duplicate bridgeTo execution with single lock
romeoscript Feb 6, 2026
82d6956
fix: resolve MPBBridge contract key mismatch and add loading state gu…
romeoscript Feb 18, 2026
9e82973
refactor: remove verbose comments, split static/dynamic data fetching…
romeoscript Feb 18, 2026
66e08f4
perf: remove canBridge polling from useGetMPBBridgeData
romeoscript Feb 18, 2026
5761e5f
fix: address PR review - remove wrapper, fix default chain, remove ha…
romeoscript Feb 18, 2026
077810f
refactor(MPBBridgeTransactionCard): wrap helper functions in useCallb…
romeoscript Feb 19, 2026
8a7b7f8
revert: remove unrelated formatting and config changes from MPBBridge PR
romeoscript Feb 19, 2026
157695b
fix: surface bridge exceptions to user and fix typechain import path
romeoscript Mar 3, 2026
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
5 changes: 1 addition & 4 deletions packages/good-design/src/apps/bridge/MicroBridge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,7 @@ export const MicroBridge = ({
}
}, [relayStatus, bridgeStatus, selfRelayStatus, onBridgeSuccess, onBridgeFailed]);

const reasonMinAmount =
reason === "minAmount"
? " Minimum amount is " + Number(minimumAmount) / (sourceChain === "fuse" ? 1e2 : 1e18) + "G$"
: undefined;
const reasonMinAmount = reason === "minAmount" ? " Minimum amount is 1000G$" : undefined;

const getActiveColor = useCallback(
(chain: string) => {
Expand Down
50 changes: 50 additions & 0 deletions packages/good-design/src/apps/bridge/mpbridge/AmountInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";
import { HStack, Text, VStack } from "native-base";
import { TokenInput } from "../../../core";
import { CurrencyValue } from "@usedapp/core";

interface AmountInputProps {
wei: string;
gdValue: CurrencyValue;
bridgeWeiAmount: string;
setBridgeAmount: (amount: string) => void;
minimumAmount: CurrencyValue;
isValid: boolean;
reason: string;
balance: CurrencyValue;
}

export const AmountInput: React.FC<AmountInputProps> = ({
wei,
gdValue,
bridgeWeiAmount,
setBridgeAmount,
minimumAmount,
isValid,
reason,
balance
}) => {
return (
<VStack space={3}>
<HStack justifyContent="space-between" alignItems="center">
<Text fontFamily="subheading" fontSize="md" color="goodGrey.600" fontWeight="600">
Amount to send
</Text>
<Text color="goodGrey.500" fontSize="sm" fontWeight="400">
Balance: {balance.format()}
</Text>
</HStack>
<TokenInput
balanceWei={wei}
onChange={setBridgeAmount}
gdValue={gdValue}
minAmountWei={minimumAmount?.toString()}
/>
{!isValid && bridgeWeiAmount && (
<Text color="red.500" fontSize="sm" fontWeight="500">
{reason === "minAmount" ? " Minimum amount is 1000 G$" : undefined}
</Text>
)}
</VStack>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from "react";
import { HStack, Pressable, Text, VStack } from "native-base";
import type { BridgeProvider } from "./types";

interface BridgeProviderSelectorProps {
bridgeProvider: BridgeProvider;
onProviderChange: (provider: BridgeProvider) => void;
}

export const BridgeProviderSelector: React.FC<BridgeProviderSelectorProps> = ({ bridgeProvider, onProviderChange }) => {
return (
<VStack space={4}>
<Text fontFamily="heading" fontSize="xl" fontWeight="700" color="goodGrey.800">
Select Bridge Provider
</Text>
<HStack space={4}>
<Pressable
flex={1}
onPress={() => onProviderChange("axelar")}
bg={bridgeProvider === "axelar" ? "rgb(59, 130, 246)" : "goodGrey.100"}
borderRadius="lg"
padding={5}
alignItems="center"
borderWidth={bridgeProvider === "axelar" ? 2 : 1}
borderColor={bridgeProvider === "axelar" ? "rgb(59, 130, 246)" : "goodGrey.300"}
>
<Text color={bridgeProvider === "axelar" ? "white" : "goodGrey.700"} fontWeight="600" fontSize="lg">
Axelar
</Text>
</Pressable>
<Pressable
flex={1}
onPress={() => onProviderChange("layerzero")}
bg={bridgeProvider === "layerzero" ? "rgb(59, 130, 246)" : "goodGrey.100"}
borderRadius="lg"
padding={5}
alignItems="center"
borderWidth={bridgeProvider === "layerzero" ? 2 : 1}
borderColor={bridgeProvider === "layerzero" ? "rgb(59, 130, 246)" : "goodGrey.300"}
>
<Text color={bridgeProvider === "layerzero" ? "white" : "goodGrey.700"} fontWeight="600" fontSize="lg">
LayerZero
</Text>
</Pressable>
</HStack>
</VStack>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
import { Box, HStack, Spinner, Text } from "native-base";

interface BridgingStatusBannerProps {
isBridging: boolean;
bridgingStatus: string;
}

export const BridgingStatusBanner: React.FC<BridgingStatusBannerProps> = ({ isBridging, bridgingStatus }) => {
if (!isBridging) return null;

return (
<Box borderRadius="lg" padding={4} backgroundColor="goodBlue.100" borderWidth="1" borderColor="goodBlue.300">
<HStack space={3} alignItems="center">
<Spinner size="sm" color="goodBlue.500" />
<Text color="goodBlue.700" fontSize="sm" fontWeight="500">
{bridgingStatus}
</Text>
</HStack>
</Box>
);
};
207 changes: 207 additions & 0 deletions packages/good-design/src/apps/bridge/mpbridge/ChainSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import React, { memo, useMemo } from "react";
import { Box, HStack, Pressable, ChevronDownIcon, Text, VStack } from "native-base";
import { getChainIcon, getChainColor, getChainLabel, getValidTargetChains } from "./utils";

// Style objects defined outside component for reusability and cleaner renders
const chainContainerStyles = {
flex: 1,
bg: "white",
borderRadius: "lg",
padding: 2,
borderWidth: "1",
borderColor: "goodGrey.300",
position: "relative",
style: { overflow: "visible" }
} as const;

const chainIconStyles = {
borderRadius: "full",
width: "8",
height: "8",
alignItems: "center",
justifyContent: "center",
shadow: "sm"
} as const;

const chainPressableStyles = {
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between"
} as const;

const dropdownStyles = {
position: "absolute",
top: "100%",
left: 0,
right: 0,
bg: "white",
borderRadius: "lg",
borderWidth: "1",
borderColor: "goodGrey.300",
shadow: "xl",
zIndex: 999999,
mt: 1,
minWidth: "200px",
maxWidth: "300px"
} as const;

const dropdownItemStyles = {
padding: 4,
borderBottomWidth: 1,
borderBottomColor: "goodGrey.200",
_pressed: { bg: "goodGrey.100" }
} as const;

const swapButtonStyles = {
bg: "goodGrey.200",
borderRadius: "full",
width: "8",
height: "8",
alignItems: "center",
justifyContent: "center",
shadow: "sm",
_pressed: { bg: "goodGrey.300" }
} as const;

interface ChainSelectorProps {
sourceChain: string;
targetChain: string;
showSourceDropdown: boolean;
showTargetDropdown: boolean;
bridgeFees: any;
bridgeProvider: string;
feesLoading: boolean;
onSourceChainSelect: (chain: string) => void;
onTargetChainSelect: (chain: string) => void;
onSwap: () => void;
onSourceDropdownToggle: () => void;
onTargetDropdownToggle: () => void;
}

export const ChainSelector: React.FC<ChainSelectorProps> = memo(
({
sourceChain,
targetChain,
showSourceDropdown,
showTargetDropdown,
bridgeFees,
bridgeProvider,
feesLoading,
onSourceChainSelect,
onTargetChainSelect,
onSwap,
onSourceDropdownToggle,
onTargetDropdownToggle
}) => {
const availableChains = useMemo(() => ["fuse", "celo", "mainnet"], []);

const validTargetChains = useMemo(
() => getValidTargetChains(sourceChain, bridgeFees, bridgeProvider, feesLoading),
[sourceChain, bridgeFees, bridgeProvider, feesLoading]
);

return (
<HStack space={4} alignItems="center" zIndex={1000}>
{/* Source Chain */}
<VStack {...chainContainerStyles}>
<HStack space={3} alignItems="center">
<Box bg={getChainColor(sourceChain)} {...chainIconStyles}>
<Text color="white" fontSize="sm" fontWeight="bold">
{getChainIcon(sourceChain)}
</Text>
</Box>
<Pressable onPress={onSourceDropdownToggle} {...chainPressableStyles}>
<Text color="goodGrey.700" fontSize="md" fontWeight="600">
{getChainLabel(sourceChain)}
</Text>
<Box style={{ transform: [{ rotate: showSourceDropdown ? "180deg" : "0deg" }] }}>
<ChevronDownIcon size="sm" color="goodGrey.400" />
</Box>
</Pressable>
</HStack>

{/* Source Chain Dropdown */}
{showSourceDropdown && (
<Box {...dropdownStyles}>
{availableChains.map(chain => (
<Pressable
key={chain}
onPress={() => onSourceChainSelect(chain)}
{...dropdownItemStyles}
borderBottomWidth={chain === availableChains[availableChains.length - 1] ? 0 : 1}
>
<HStack space={3} alignItems="center">
<Box bg={getChainColor(chain)} {...chainIconStyles} width="6" height="6">
<Text color="white" fontSize="xs" fontWeight="bold">
{getChainIcon(chain)}
</Text>
</Box>
<Text color="goodGrey.700" fontSize="md" fontWeight="500">
{getChainLabel(chain)}
</Text>
</HStack>
</Pressable>
))}
</Box>
)}
</VStack>

{/* Swap Arrow */}
<Pressable onPress={onSwap} {...swapButtonStyles}>
<Text fontSize="xl" color="goodGrey.600" fontWeight="bold">
</Text>
</Pressable>

{/* Target Chain */}
<VStack {...chainContainerStyles}>
<HStack space={3} alignItems="center">
<Box bg={getChainColor(targetChain)} {...chainIconStyles}>
<Text color="white" fontSize="sm" fontWeight="bold">
{getChainIcon(targetChain)}
</Text>
</Box>
<Pressable onPress={onTargetDropdownToggle} {...chainPressableStyles}>
<Text color="goodGrey.700" fontSize="md" fontWeight="600">
{getChainLabel(targetChain)}
</Text>
<Box style={{ transform: [{ rotate: showTargetDropdown ? "180deg" : "0deg" }] }}>
<ChevronDownIcon size="sm" color="goodGrey.400" />
</Box>
</Pressable>
</HStack>

{/* Target Chain Dropdown */}
{showTargetDropdown && (
<Box {...dropdownStyles}>
{validTargetChains.map(chain => {
const isLastItem = chain === validTargetChains[validTargetChains.length - 1];

return (
<Pressable
key={chain}
onPress={() => onTargetChainSelect(chain)}
{...dropdownItemStyles}
borderBottomWidth={isLastItem ? 0 : 1}
>
<HStack space={3} alignItems="center">
<Box bg={getChainColor(chain)} {...chainIconStyles} width="6" height="6">
<Text color="white" fontSize="xs" fontWeight="bold">
{getChainIcon(chain)}
</Text>
</Box>
<Text color="goodGrey.700" fontSize="md" fontWeight="500">
{getChainLabel(chain)}
</Text>
</HStack>
</Pressable>
);
})}
</Box>
)}
</VStack>
</HStack>
);
}
);
34 changes: 34 additions & 0 deletions packages/good-design/src/apps/bridge/mpbridge/ExpectedOutput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";
import { HStack, Text, VStack, Input } from "native-base";
import { CurrencyValue } from "@usedapp/core";

interface ExpectedOutputProps {
expectedToReceive: CurrencyValue;
targetChain: string;
balance: CurrencyValue;
}

export const ExpectedOutput: React.FC<ExpectedOutputProps> = ({ expectedToReceive, targetChain, balance }) => {
return (
<VStack space={3}>
<HStack justifyContent="space-between" alignItems="center">
<Text fontFamily="subheading" fontSize="md" color="goodGrey.600" fontWeight="600">
You will receive on {targetChain.toUpperCase()}
</Text>
<Text color="goodGrey.500" fontSize="sm" fontWeight="400">
Balance: {balance.format()}
</Text>
</HStack>
<Input
value={expectedToReceive ? expectedToReceive.format() : "0"}
isReadOnly
borderRadius="lg"
borderColor="goodGrey.300"
bg="goodGrey.50"
fontSize="md"
padding={2}
fontWeight="500"
/>
</VStack>
);
};
Loading