From 56e576a7f3da1d69d67c5113437b532ee5ffa87a Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Tue, 4 Jun 2024 16:39:35 +1000 Subject: [PATCH] feat: use mutinynet faucet --- mobile/lib/common/init_service.dart | 2 +- .../wallet/application/faucet_service.dart | 69 +++++++++++++------ .../lib/features/wallet/receive_screen.dart | 11 +-- 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/mobile/lib/common/init_service.dart b/mobile/lib/common/init_service.dart index f772f2984..1edac48e3 100644 --- a/mobile/lib/common/init_service.dart +++ b/mobile/lib/common/init_service.dart @@ -64,7 +64,7 @@ List createProviders() { Provider(create: (context) => pollService), Provider(create: (context) => memeService) ]; - if (config.network == "regtest") { + if (config.network == "regtest" || config.network == "signet") { providers.add(Provider(create: (context) => FaucetService())); } diff --git a/mobile/lib/features/wallet/application/faucet_service.dart b/mobile/lib/features/wallet/application/faucet_service.dart index 4eabe5f70..c6c2fee8b 100644 --- a/mobile/lib/features/wallet/application/faucet_service.dart +++ b/mobile/lib/features/wallet/application/faucet_service.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:math'; import 'package:get_10101/common/domain/model.dart'; import 'package:get_10101/logger/logger.dart'; @@ -6,7 +7,7 @@ import 'package:http/http.dart' as http; class FaucetService { /// Pay the provided invoice with our faucet - Future payInvoiceWithFaucet(String bip21Uri, Amount? invoiceAmount) async { + Future payInvoiceWithFaucet(String bip21Uri, Amount? invoiceAmount, String network) async { final split = bip21Uri.split(":"); final addressAndMaybeAmount = split[1].split("?"); logger.i("Funding $addressAndMaybeAmount"); @@ -14,16 +15,32 @@ class FaucetService { final amount = invoiceAmount?.btc ?? 1.0; logger.i("Funding $address with $amount"); - // Default to the faucet on the 10101 server, but allow to override it - // locally if needed for dev testing - // It's not populated in Config struct, as it's not used in production + + switch (network) { + case "regtest": + await payWith10101Faucet(address, amount); + break; + case "signet": + await payWithMutinyFaucet(address, amount); + break; + default: + throw Exception("Invalid network provided $network. Only regtest or signet supported"); + } + } + + Future payWith10101Faucet(String address, double amountBtc) async { + // Faucet env variable needs to be set for local testing, otherwise we will fail here + if (!const bool.hasEnvironment("REGTEST_FAUCET")) { + throw Exception("Could not fund address. REGTEST_FAUCET not set"); + } + String faucet = - const String.fromEnvironment("REGTEST_FAUCET", defaultValue: "http://34.32.62.120:8080"); + const String.fromEnvironment("REGTEST_FAUCET", defaultValue: "http://localhost:8080"); final data = { 'jsonrpc': '1.0', 'method': 'sendtoaddress', - 'params': [address, "$amount"], + 'params': [address, "$amountBtc"], }; final encodedData = json.encode(data); @@ -63,24 +80,32 @@ class FaucetService { } } -// Pay the generated invoice with maker faucet - Future payInvoiceWithMakerFaucet(String invoice) async { - // Default to the faucet on the 10101 server, but allow to override it - // locally if needed for dev testing - // It's not populated in Config struct, as it's not used in production - String faucet = const String.fromEnvironment("REGTEST_MAKER_FAUCET", - defaultValue: "http://34.32.62.120:80/maker/faucet"); - - final response = await http.post( - Uri.parse('$faucet/$invoice'), - ); + Future payWithMutinyFaucet(String address, double amountBtc) async { + final url = Uri.parse('https://faucet.mutinynet.com/api/onchain'); + final headers = { + 'Content-Type': 'application/json', + 'Origin': 'https://faucet.mutinynet.com', + }; + final body = jsonEncode({ + 'sats': min(amountBtc * 100000000, 10000000).toInt(), + 'address': address, + }); - logger.i("Response ${response.body}${response.statusCode}"); + try { + final response = await http.post( + url, + headers: headers, + body: body, + ); - if (response.statusCode != 200) { - throw Exception("Payment failed: Received ${response.statusCode}. ${response.body}"); - } else { - logger.i("Paying invoice succeeded: ${response.body}"); + if (response.statusCode == 200) { + logger.i('Funding successful ${response.body}'); + } else { + logger.e('Request failed with status: ${response.statusCode} ${response.body}'); + throw Exception("Failed funding address ${response.statusCode} ${response.body}"); + } + } catch (e) { + throw Exception("Failed funding address ${e.toString()}"); } } } diff --git a/mobile/lib/features/wallet/receive_screen.dart b/mobile/lib/features/wallet/receive_screen.dart index da31dfaf3..67ab63a9b 100644 --- a/mobile/lib/features/wallet/receive_screen.dart +++ b/mobile/lib/features/wallet/receive_screen.dart @@ -84,8 +84,9 @@ class _ReceiveScreenState extends State { Container( margin: const EdgeInsets.fromLTRB(0, 10, 0, 0), child: GestureDetector( - onDoubleTap: - config.network == "regtest" ? () => setState(() => _faucet = !_faucet) : null, + onDoubleTap: config.network == "regtest" || config.network == "signet" + ? () => setState(() => _faucet = !_faucet) + : null, child: Center( child: _faucet ? Column( @@ -98,7 +99,7 @@ class _ReceiveScreenState extends State { setState(() => _isPayInvoiceButtonDisabled = true); final faucetService = context.read(); faucetService - .payInvoiceWithFaucet(rawInvoice(), amount) + .payInvoiceWithFaucet(rawInvoice(), amount, config.network) .catchError((error) { setState(() => _isPayInvoiceButtonDisabled = false); showSnackBar(ScaffoldMessenger.of(context), error.toString()); @@ -108,7 +109,9 @@ class _ReceiveScreenState extends State { shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(5.0))), ), - child: const Text("Pay with 10101 faucet"), + child: config.network == "regtest" + ? const Text("Pay with 10101 faucet") + : const Text("Pay with Mutinynet faucet"), ), const SizedBox(height: 125), ],