diff --git a/sauron/.gitignore b/sauron/.gitignore new file mode 100644 index 000000000..21d0b898f --- /dev/null +++ b/sauron/.gitignore @@ -0,0 +1 @@ +.venv/ diff --git a/sauron/README.md b/sauron/README.md index d02dbe10e..ce023c808 100644 --- a/sauron/README.md +++ b/sauron/README.md @@ -24,6 +24,14 @@ Here is a fully reptilian example running against [blockstream.info](https://blo lightningd --mainnet --disable-plugin bcli --plugin $PWD/sauron.py --sauron-api-endpoint https://blockstream.info/api/ ``` + +Here is an example running against [mutinynet.com](https://mutinynet.com/): + +``` +lightningd --signet --disable-plugin bcli --plugin $PWD/sauron.py --sauron-api-endpoint https://mutinynet.com/api/ +``` + + You can use also proxy your requests through [Tor](https://www.torproject.org/) by specifying a SOCKS proxy to use with the `--sauron-tor-proxy` startup option, in the form `address:port`. diff --git a/sauron/requirements.txt b/sauron/requirements.txt index 1794cb833..7fd22f35e 100644 --- a/sauron/requirements.txt +++ b/sauron/requirements.txt @@ -1,2 +1,2 @@ -pyln-client>=23.2 +pyln-client>=23.2,<=24.5 requests[socks]>=2.23.0 diff --git a/sauron/sauron.py b/sauron/sauron.py index 3e2e34c9a..0ac6b9375 100755 --- a/sauron/sauron.py +++ b/sauron/sauron.py @@ -40,12 +40,29 @@ def fetch(url): @plugin.init() -def init(plugin, options, configuration, **kwargs): - plugin.api_endpoint = options["sauron-api-endpoint"] +def init(plugin, options, **kwargs): + plugin.api_endpoint = options.get("sauron-api-endpoint", None) if not plugin.api_endpoint: raise SauronError("You need to specify the sauron-api-endpoint option.") sys.exit(1) + # Test for Esplora or mempoolspace + try: + # Esplora API + feerate_url = "{}/fee-estimates".format(plugin.api_endpoint) + feerate_req = fetch(feerate_url) + assert feerate_req.status_code == 200 + plugin.is_mempoolspace = False + except AssertionError as e0: + try: + # MutinyNet API + feerate_url = "{}/v1/fees/recommended".format(plugin.api_endpoint) + feerate_req = fetch(feerate_url) + assert feerate_req.status_code == 200 + plugin.is_mempoolspace = True + except AssertionError as e1: + raise Exception("Sauron API cannot be reached") from e1 + if options["sauron-tor-proxy"]: address, port = options["sauron-tor-proxy"].split(":") socks5_proxy = "socks5h://{}:{}".format(address, port) @@ -188,7 +205,12 @@ def getutxout(plugin, txid, vout, **kwargs): @plugin.method("estimatefees") def estimatefees(plugin, **kwargs): - feerate_url = "{}/fee-estimates".format(plugin.api_endpoint) + if plugin.is_mempoolspace: + # MutinyNet API + feerate_url = "{}/v1/fees/recommended".format(plugin.api_endpoint) + else: + # Blockstream API + feerate_url = "{}/fee-estimates".format(plugin.api_endpoint) feerate_req = fetch(feerate_url) assert feerate_req.status_code == 200 @@ -204,7 +226,7 @@ def estimatefees(plugin, **kwargs): urgent = int(feerates["6"] * 10**3) very_urgent = int(feerates["2"] * 10**3) - feerate_floor = int(feerates["1008"] * 10**3) + feerate_floor = int(feerates.get("1008", slow) * 10**3) feerates = [ {"blocks": 2, "feerate": very_urgent}, {"blocks": 6, "feerate": urgent}, @@ -229,7 +251,7 @@ def estimatefees(plugin, **kwargs): plugin.add_option( "sauron-api-endpoint", "", - "The URL of the esplora instance to hit (including '/api').", + "The URL of the esplora or mempool.space instance to hit (including '/api').", ) plugin.add_option(