diff --git a/assets/logos/plasma_on_black.svg b/assets/logos/plasma_on_black.svg new file mode 100644 index 0000000..58aa104 --- /dev/null +++ b/assets/logos/plasma_on_black.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/logos/plasma_on_white.svg b/assets/logos/plasma_on_white.svg new file mode 100644 index 0000000..c89b4d6 --- /dev/null +++ b/assets/logos/plasma_on_white.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart index b55686f..acab2de 100644 --- a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart +++ b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal.dart @@ -556,7 +556,11 @@ class _PreviewDepositModalState extends State fit: FlexFit.loose, child: _fieldColumn( title: S.of(context).previewDepositModalNetwork, - image: SizedBox(width: 30, height: 30, child: widget.currentYield.network.icon), + image: SizedBox( + width: 30, + height: 30, + child: widget.currentYield.network.icon(context.brightness), + ), value: widget.currentYield.network.label, ), ), diff --git a/lib/core/enums/networks.dart b/lib/core/enums/networks.dart index 9ec707c..b50bacd 100644 --- a/lib/core/enums/networks.dart +++ b/lib/core/enums/networks.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:web3kit/web3kit.dart'; import 'package:zup_app/gen/assets.gen.dart'; +import 'package:zup_core/zup_core.dart'; enum AppNetworks { allNetworks, @@ -12,6 +13,7 @@ enum AppNetworks { // bnb, unichain, scroll, + plasma, sepolia; static List get testnets => @@ -41,6 +43,7 @@ enum AppNetworks { base => false, unichain => false, hyperEvm => false, + plasma => false, // bnb => false }; @@ -52,10 +55,11 @@ enum AppNetworks { base => "Base", unichain => "Unichain", hyperEvm => "HyperEVM", + plasma => "Plasma", // bnb => "BNB Chain", }; - Widget get icon => switch (this) { + Widget icon(Brightness brightness) => switch (this) { sepolia => Assets.logos.ethereum.svg(), mainnet => Assets.logos.ethereum.svg(), scroll => Assets.logos.scroll.svg(), @@ -63,6 +67,7 @@ enum AppNetworks { unichain => Assets.logos.unichain.svg(), allNetworks => Assets.icons.all.svg(), hyperEvm => Assets.logos.hyperliquid.svg(), + plasma => brightness.isDark ? Assets.logos.plasmaOnBlack.svg() : Assets.logos.plasmaOnWhite.svg(), // bnb => Assets.logos.bnbChain.svg() }; @@ -110,6 +115,13 @@ enum AppNetworks { nativeCurrency: NativeCurrencies.hype.currencyInfo, rpcUrls: [rpcUrl], ), + plasma => ChainInfo( + hexChainId: "0x2611", + chainName: label, + blockExplorerUrls: const ["https://plasmascan.to"], + nativeCurrency: NativeCurrencies.xpl.currencyInfo, + rpcUrls: [rpcUrl], + ), // bnb => ChainInfo( // hexChainId => "0x38", // chainName => label, @@ -127,6 +139,7 @@ enum AppNetworks { base => "0x4200000000000000000000000000000000000006", unichain => "0x4200000000000000000000000000000000000006", hyperEvm => "0x5555555555555555555555555555555555555555", + plasma => "0x6100E367285b01F48D07953803A2d8dCA5D19873", // bnb => "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", }; @@ -138,6 +151,7 @@ enum AppNetworks { base => "https://base-rpc.publicnode.com", unichain => "https://unichain-rpc.publicnode.com", hyperEvm => "https://rpc.hyperliquid.xyz/evm", + plasma => "https://rpc.plasma.to", // bnb => "https://bsc-rpc.publicnode.com" }; diff --git a/lib/widgets/app_header/app_header.dart b/lib/widgets/app_header/app_header.dart index 0291a6c..3942ebc 100644 --- a/lib/widgets/app_header/app_header.dart +++ b/lib/widgets/app_header/app_header.dart @@ -135,7 +135,7 @@ class _AppHeaderState extends State with DeviceInfoMixin { currentModeNetworks.length, (index) => NetworkSwitcherItem( title: currentModeNetworks[index].label, - icon: currentModeNetworks[index].icon, + icon: currentModeNetworks[index].icon(context.brightness), chainInfo: currentModeNetworks[index].isAllNetworks ? null : currentModeNetworks[index].chainInfo, ), ), diff --git a/lib/widgets/yield_card.dart b/lib/widgets/yield_card.dart index 5d33386..2caf27c 100644 --- a/lib/widgets/yield_card.dart +++ b/lib/widgets/yield_card.dart @@ -67,7 +67,7 @@ class _YieldCardState extends State { top: 2, child: ZupTooltip.text( message: S.of(context).yieldCardThisPoolIsAtNetwork(network: widget.currentYield.network.label), - trailingIcon: widget.currentYield.network.icon, + trailingIcon: widget.currentYield.network.icon(context.brightness), child: Container( height: 40, padding: const EdgeInsets.all(6), @@ -78,7 +78,7 @@ class _YieldCardState extends State { : (context.brightness.isDark ? ZupColors.black2 : ZupColors.gray6), borderRadius: BorderRadius.circular(8), ), - child: widget.currentYield.network.icon, + child: widget.currentYield.network.icon(context.brightness), ), ), ), diff --git a/pubspec.lock b/pubspec.lock index c7ba2cc..2d1f5e9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1281,7 +1281,7 @@ packages: description: path: "." ref: main - resolved-ref: "9a51f58425d80bd29886286a68571d653b4995d5" + resolved-ref: "0f6c0f2a93e858209109c9f436f53bbc7c5e3659" url: "https://github.com/Zup-Protocol/web3kit.git" source: git version: "0.0.1" diff --git a/pubspec.yaml b/pubspec.yaml index 40e560b..18ff89d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -55,12 +55,12 @@ dependencies: async: ^2.13.0 # dependency_overrides: -# zup_core: -# path: ../zup-core -# web3kit: -# path: ../web3kit -# zup_ui_kit: -# path: ../zup-ui-kit + # zup_core: + # path: ../zup-core + # web3kit: + # path: ../web3kit + # zup_ui_kit: + # path: ../zup-ui-kit dev_dependencies: flutter_test: diff --git a/test/core/enums/goldens/plasma_network_icon_dark_mode.png b/test/core/enums/goldens/plasma_network_icon_dark_mode.png new file mode 100644 index 0000000..c45b14b Binary files /dev/null and b/test/core/enums/goldens/plasma_network_icon_dark_mode.png differ diff --git a/test/core/enums/goldens/plasma_network_icon_light_mode.png b/test/core/enums/goldens/plasma_network_icon_light_mode.png new file mode 100644 index 0000000..a8bbe6b Binary files /dev/null and b/test/core/enums/goldens/plasma_network_icon_light_mode.png differ diff --git a/test/core/enums/goldens/unichain_network_icon.png b/test/core/enums/goldens/unichain_network_icon.png index 33e339e..0ff0cbd 100644 Binary files a/test/core/enums/goldens/unichain_network_icon.png and b/test/core/enums/goldens/unichain_network_icon.png differ diff --git a/test/core/enums/networks_test.dart b/test/core/enums/networks_test.dart index 968848e..fbfd0d9 100644 --- a/test/core/enums/networks_test.dart +++ b/test/core/enums/networks_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter/src/widgets/basic.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:golden_toolkit/golden_toolkit.dart'; import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; @@ -10,10 +10,11 @@ import '../../golden_config.dart'; import '../../mocks.dart'; void main() { - UrlLauncherPlatform urlLauncherPlatform; + late UrlLauncherPlatform urlLauncherPlatform; setUp(() { urlLauncherPlatform = UrlLauncherPlatformCustomMock(); + UrlLauncherPlatform.instance = urlLauncherPlatform; }); @@ -25,6 +26,7 @@ void main() { expect(AppNetworks.fromValue("base"), AppNetworks.base, reason: "Base should match"); expect(AppNetworks.fromValue("hyperEvm"), AppNetworks.hyperEvm, reason: "HyperEVM should match"); expect(AppNetworks.fromValue("unichain"), AppNetworks.unichain, reason: "Unichain should match"); + expect(AppNetworks.fromValue("plasma"), AppNetworks.plasma, reason: "Plasma should match"); // expect(AppNetworks.fromValue("bnb"), AppNetworks.bnb, reason: "BNB should match"); }); @@ -36,6 +38,7 @@ void main() { expect(AppNetworks.base.label, "Base", reason: "Base Label should match"); expect(AppNetworks.hyperEvm.label, "HyperEVM", reason: "HyperEVM Label should match"); expect(AppNetworks.unichain.label, "Unichain", reason: "Unichain Label should match"); + expect(AppNetworks.plasma.label, "Plasma", reason: "Plasma Label should match"); // expect(AppNetworks.bnb.label, "BNB Chain", reason: "BNB Chain Label should match"); }); @@ -53,6 +56,7 @@ void main() { AppNetworks.base, AppNetworks.hyperEvm, AppNetworks.unichain, + AppNetworks.plasma, // AppNetworks.bnb ]), ); @@ -82,6 +86,10 @@ void main() { expect(AppNetworks.unichain.isTestnet, false); }); + test("`isTestnet` method should return false for plasma", () { + expect(AppNetworks.plasma.isTestnet, false); + }); + test("`isTestnet` method should return false for bnb", () { // expect(AppNetworks.bnb.isTestnet, false); }); @@ -158,6 +166,18 @@ void main() { reason: "HyperEVM ChainInfo should match", ); + expect( + AppNetworks.plasma.chainInfo, + ChainInfo( + hexChainId: "0x2611", + chainName: "Plasma", + blockExplorerUrls: const ["https://plasmascan.to"], + nativeCurrency: NativeCurrencies.xpl.currencyInfo, + rpcUrls: const ["https://rpc.plasma.to"], + ), + reason: "Plasma ChainInfo should match", + ); + // expect( // AppNetworks.bnb.chainInfo, // ChainInfo( @@ -190,17 +210,29 @@ void main() { reason: "Scroll wrapped native token address should match", ); - // expect( - // AppNetworks.base.wrappedNativeTokenAddress, - // "0x4200000000000000000000000000000000000006", - // reason: "Base wrapped native token address should match", - // ); + expect( + AppNetworks.base.wrappedNativeTokenAddress, + "0x4200000000000000000000000000000000000006", + reason: "Base wrapped native token address should match", + ); expect( AppNetworks.unichain.wrappedNativeTokenAddress, "0x4200000000000000000000000000000000000006", reason: "Unichain wrapped native token address should match", ); + + expect( + AppNetworks.plasma.wrappedNativeTokenAddress, + "0x6100E367285b01F48D07953803A2d8dCA5D19873", + reason: "Plasma wrapped native token address should match", + ); + + expect( + AppNetworks.hyperEvm.wrappedNativeTokenAddress, + "0x5555555555555555555555555555555555555555", + reason: "HyperEVM wrapped native token address should match", + ); }); test("RpcUrl extension should return the correct rpc url", () { @@ -214,14 +246,14 @@ void main() { expect(AppNetworks.scroll.rpcUrl, "https://scroll-rpc.publicnode.com", reason: "Scroll rpc url should match"); - // expect( - // AppNetworks.base.rpcUrl, - // "https://base-rpc.publicnode.com", - // reason: "Base rpc url should match", - // ); + expect(AppNetworks.base.rpcUrl, "https://base-rpc.publicnode.com", reason: "Base rpc url should match"); expect(AppNetworks.unichain.rpcUrl, "https://unichain-rpc.publicnode.com", reason: "Unichain rpc url should match"); + expect(AppNetworks.hyperEvm.rpcUrl, "https://rpc.hyperliquid.xyz/evm", reason: "HyperEVM rpc url should match"); + + expect(AppNetworks.plasma.rpcUrl, "https://rpc.plasma.to", reason: "Plasma rpc url should match"); + // expect( // AppNetworks.bnb.rpcUrl, // "https://bsc-rpc.publicnode.com", @@ -275,38 +307,103 @@ void main() { }); zGoldenTest("Sepolia network icon should match", goldenFileName: "sepolia_network_icon", (tester) async { - await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.sepolia.icon, device: GoldenDevice.square)); + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder( + SizedBox(height: 100, width: 100, child: AppNetworks.sepolia.icon(Brightness.light)), + device: GoldenDevice.square, + ), + ); }); zGoldenTest("hyperEVM network icon should match", goldenFileName: "hyperEVM_network_icon", (tester) async { await tester.pumpDeviceBuilder( await goldenDeviceBuilder( - SizedBox(height: 100, child: Center(child: AppNetworks.hyperEvm.icon)), + SizedBox(height: 100, child: Center(child: AppNetworks.hyperEvm.icon(Brightness.light))), device: GoldenDevice.square, ), ); }); zGoldenTest("Ethereum network icon should match", goldenFileName: "ethereum_network_icon", (tester) async { - await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.mainnet.icon, device: GoldenDevice.square)); + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder( + SizedBox(width: 100, height: 100, child: AppNetworks.mainnet.icon(Brightness.light)), + device: GoldenDevice.square, + ), + ); }); zGoldenTest("Base network icon should match", goldenFileName: "base_network_icon", (tester) async { - await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.base.icon, device: GoldenDevice.square)); + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder( + SizedBox(height: 100, width: 100, child: AppNetworks.base.icon(Brightness.light)), + device: GoldenDevice.square, + ), + ); }); zGoldenTest("Scroll network icon should match", goldenFileName: "scroll_network_icon", (tester) async { - await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.scroll.icon, device: GoldenDevice.square)); + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder( + SizedBox(height: 100, width: 100, child: AppNetworks.scroll.icon(Brightness.light)), + device: GoldenDevice.square, + ), + ); }); zGoldenTest("Unichain network icon should match", goldenFileName: "unichain_network_icon", (tester) async { - await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.unichain.icon, device: GoldenDevice.square)); + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder( + SizedBox(width: 100, height: 100, child: AppNetworks.unichain.icon(Brightness.light)), + device: GoldenDevice.square, + ), + ); }); + zGoldenTest( + "Plasma network icon should be correct for light mode (Dark icon)", + goldenFileName: "plasma_network_icon_light_mode", + (tester) async { + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder( + SizedBox(height: 100, width: 100, child: AppNetworks.plasma.icon(Brightness.light)), + device: GoldenDevice.square, + darkMode: false, + ), + ); + }, + ); + autoUpdateGoldenFiles = true; + zGoldenTest( + "Plasma network icon should be correct for dark mode (light icon)", + goldenFileName: "plasma_network_icon_dark_mode", + (tester) async { + await tester.pumpDeviceBuilder( + await goldenDeviceBuilder( + Container(height: 100, width: 100, color: Colors.black, child: AppNetworks.plasma.icon(Brightness.dark)), + device: GoldenDevice.square, + darkMode: false, + ), + ); + }, + ); + // zGoldenTest("BNB network icon should match", goldenFileName: "bnb_network_icon", (tester) async { // await tester.pumpDeviceBuilder(await goldenDeviceBuilder( // AppNetworks.bnb.icon, // device: GoldenDevice.square, // )); // }); + + test("The block explorer url of any network, should not end with a slash", () { + for (final network in AppNetworks.values) { + if (network.isAllNetworks) continue; + + expect( + network.chainInfo.blockExplorerUrls?.first.endsWith("/"), + false, + reason: "The ${network.label} block explorer url should not end with a slash", + ); + } + }); } diff --git a/test/golden_config.dart b/test/golden_config.dart index 1b99865..c4f4165 100644 --- a/test/golden_config.dart +++ b/test/golden_config.dart @@ -39,7 +39,7 @@ class GoldenConfig { static final scrollController = ScrollController(); static final navigatorKey = GlobalKey(); - static Future builder(Widget child) async { + static Future builder(Widget child, {bool darkMode = false}) async { await loadAppFonts(); return MaterialApp( @@ -57,7 +57,7 @@ class GoldenConfig { slivers: [SliverFillRemaining(hasScrollBody: false, child: child)], ), ), - theme: AppTheme.lightTheme, + theme: darkMode ? AppTheme.darkTheme : AppTheme.lightTheme, ); } @@ -81,10 +81,13 @@ class GoldenConfig { } } -Future goldenDeviceBuilder(Widget child, {GoldenDevice device = GoldenDevice.pc}) async => - DeviceBuilder() - ..overrideDevicesForAllScenarios(devices: device.devices) - ..addScenario(widget: await GoldenConfig.builder(child)); +Future goldenDeviceBuilder( + Widget child, { + GoldenDevice device = GoldenDevice.pc, + bool darkMode = false, +}) async => DeviceBuilder() + ..overrideDevicesForAllScenarios(devices: device.devices) + ..addScenario(widget: await GoldenConfig.builder(child, darkMode: darkMode)); @isTest void zGoldenTest( diff --git a/web/index.html b/web/index.html index 4e97fa2..daf4388 100644 --- a/web/index.html +++ b/web/index.html @@ -82,6 +82,6 @@ inject(); - +