diff --git a/README.md b/README.md index b81a215..a7bbb36 100644 --- a/README.md +++ b/README.md @@ -85,10 +85,16 @@ Coordinators act as a mediator between digital signers and wallets. The coordin ``` ./start_coordinator.py ``` +Possible arguments: + +- `--show`: Show active relays via [nostr watch](https://nostr.watch/relays/find) +- `--add`: Add new relays ex: ``` ./start_coordinator --add [relay1] [relay2] ...``` ### Running a signer -`./start_signer.py` +``` +./start_signer.py +``` Possible arguments: @@ -96,6 +102,8 @@ Possible arguments: - `--wallet_id`: The coordinator persists wallets by ID with some associated information. Default is none. - `--key_seed`: An optional seed to use when initializing the signer's keys. Not recommended for anything other than testing. - `--nonce_seed`: An optional seed to use when creating nonces. Not recommended for anything other than testing. +- `--show`: Show active relays via [nostr watch](https://nostr.watch/relays/find) +- `--add`: Add new relays ex: ``` ./start_signer -add [relay1] [relay2] ...``` ### Completing an end-to-end test diff --git a/requirements.txt b/requirements.txt index 1f28e8e..08a8268 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,5 @@ bip32 nostr colorama python-bitcoinlib +requests +random \ No newline at end of file diff --git a/src/coordinator/coordinator.py b/src/coordinator/coordinator.py index 9c4a5c5..f4aacc7 100644 --- a/src/coordinator/coordinator.py +++ b/src/coordinator/coordinator.py @@ -4,7 +4,7 @@ from colorama import Fore -from src.utils.nostr_utils import add_relays, construct_and_publish_event, generate_nostr_message, init_relay_manager, read_nsec, read_public_keys +from src.utils.nostr_utils import show_relays, add_relays, construct_and_publish_event, generate_nostr_message, init_relay_manager, read_nsec, read_public_keys from src.utils.payload import is_valid_json, is_valid_payload, PayloadKeys from src.coordinator.wallet import add_xpub, create_wallet, is_valid_command, get_address, save_nonce, start_spend, save_signature from src.coordinator.db import DB @@ -37,13 +37,18 @@ def setup_logging(): logging.getLogger().setLevel(logging.INFO) logging.info(Fore.GREEN + header) -def run(): +def run(show, relays): setup_logging() # start up the db db = DB('src/coordinator/db.json') - relay_manager = add_relays() + if show: + print("----- ACTIVE RELAYS -----\n") + show_relays() + exit() + + relay_manager = add_relays(relays) nostr_private_key, nostr_public_key = read_nsec('src/coordinator/nsec.txt') # get the public keys for the signers so we can subscribe to messages from them diff --git a/src/signer/signer.py b/src/signer/signer.py index d599a00..fdbc1d4 100644 --- a/src/signer/signer.py +++ b/src/signer/signer.py @@ -1,7 +1,7 @@ from colorama import Fore from src.signer.wallet import Wallet -from src.utils.nostr_utils import generate_nostr_message, add_relays, construct_and_publish_event, init_relay_manager, read_nsec, read_public_keys +from src.utils.nostr_utils import show_relays, generate_nostr_message, add_relays, construct_and_publish_event, init_relay_manager, read_nsec, read_public_keys from src.utils.payload import is_valid_json, is_valid_payload from enum import Enum @@ -223,10 +223,16 @@ def setup_logging(): logging.getLogger().setLevel(logging.INFO) logging.info(Fore.RED + header) -def run_signer(wallet_id=None, key_pair_seed=None, nonce_seed=None): +def run_signer(show, relays, wallet_id=None, key_pair_seed=None, nonce_seed=None): + setup_logging() - relay_manager = add_relays() + if show: + print("----- ACTIVE RELAYS -----\n") + show_relays() + exit() + + relay_manager = add_relays(relays) nostr_private_key, nostr_public_key = read_nsec('src/signer/nsec.txt') # get the public keys for the coordinator so we can subscribe to messages from them diff --git a/src/utils/nostr_utils.py b/src/utils/nostr_utils.py index 2de9690..fc60064 100644 --- a/src/utils/nostr_utils.py +++ b/src/utils/nostr_utils.py @@ -3,6 +3,9 @@ import ssl import time import uuid +import requests +import sys +import random from nostr.event import Event, EventKind from nostr.filter import Filter, Filters @@ -13,8 +16,26 @@ from src.utils.payload import PayloadKeys NOSTR_RELAYS = ["wss://nostr-pub.wellorder.net", "wss://relay.damus.io"] +NOSTR_WATCH = "https://api.nostr.watch/v1/online" +NEW_RELAYS = 20 + +def show_relays(): + try: + r = (requests.get(NOSTR_WATCH, {})).json() + except Exception as e: + print(f"nostr_watch API error: {e}\nOption not available at the moment.") + exit() + new_relays = [x for x in r[:NEW_RELAYS] if 'damus' not in x and 'nostr-pub.wellorder' not in x] + new_relays_rows = [[new_relays[i+k] for i in range(4)] for k in range(0,len(new_relays)-4,4)] + col_width = max(len(word) for row in new_relays_rows for word in row) + 2 + for row in new_relays_rows: + print("".join(word.ljust(col_width) for word in row)) + +def add_relays(relays): + if relays is not None: + for r in relays: + NOSTR_RELAYS.append(r) -def add_relays(): relay_manager = RelayManager() [relay_manager.add_relay(relay) for relay in NOSTR_RELAYS] @@ -77,7 +98,7 @@ def read_nsec(nsec_file_name): public_key = private_key.public_key.hex() logging.info("[nostr] My public key: %s", public_key) return private_key, public_key - except(error): + except Exception: logging.error("[nostr] Unexpected error reading nsec from %s", nsec_file_name) sys.exit(1) @@ -87,7 +108,7 @@ def read_public_keys(file_name): try: lines = f.readlines() return [line.strip() for line in lines] - except(error): + except Exception: logging.error("[nostr] Unexpected error reading public keys from %s", file_name) sys.exit(1) diff --git a/start_coordinator.py b/start_coordinator.py index 317cee1..0bdc82a 100755 --- a/start_coordinator.py +++ b/start_coordinator.py @@ -1,8 +1,15 @@ #!/usr/bin/env python3 from src.coordinator.coordinator import run -def main(): - run() +import argparse + +def main(show:bool, relays=None): + run(show, relays) if __name__ == "__main__": - main() + parser = argparse.ArgumentParser() + parser.add_argument("-s", "--show", help="Display active relays", default=False, action='store_true') + parser.add_argument("-a", "--add", help="Add new relays before running", default=None, nargs="+") + args = parser.parse_args() + + main(args.show, args.add) diff --git a/start_signer.py b/start_signer.py index 20d75fc..fc8a9c8 100755 --- a/start_signer.py +++ b/start_signer.py @@ -5,16 +5,24 @@ import argparse -def main(wallet_id=None, key_pair_seed=None, nonce_seed=None): - run_signer(wallet_id=wallet_id, key_pair_seed=key_pair_seed, nonce_seed=nonce_seed) +def main(show,relays, wallet_id=None, key_pair_seed=None, nonce_seed=None): + run_signer(show, relays, wallet_id=wallet_id, key_pair_seed=key_pair_seed, nonce_seed=nonce_seed) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--wallet_id", help="Wallet ID", default=None) parser.add_argument("--key_seed", help="Key seed") parser.add_argument("--nonce_seed", help="Nonce seed") + parser.add_argument("-s", "--show", help="Display active relays", default=False, action='store_true') + parser.add_argument("-a", "--add", help="Add new relays before running", default=None, nargs="+") + args = parser.parse_args() # Call the main function with the command line arguments - main(args.wallet_id, args.key_seed, args.nonce_seed) - + main( + args.show, + args.add, + args.wallet_id, + args.key_seed, + args.nonce_seed + ) \ No newline at end of file