{"id":13832511,"url":"https://github.com/Kukks/NNostr","last_synced_at":"2025-07-09T19:30:30.389Z","repository":{"id":44729319,"uuid":"373964795","full_name":"Kukks/NNostr","owner":"Kukks","description":"A Nostr Relay and Client written in C#","archived":false,"fork":false,"pushed_at":"2024-11-05T14:18:00.000Z","size":1045,"stargazers_count":115,"open_issues_count":2,"forks_count":32,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-11-20T12:38:07.388Z","etag":null,"topics":["nostr"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kukks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["kukks"],"custom":["https://donate.kukks.org"]}},"created_at":"2021-06-04T21:38:43.000Z","updated_at":"2024-11-13T00:19:13.000Z","dependencies_parsed_at":"2023-02-14T08:15:27.811Z","dependency_job_id":"bbb129f2-469f-415f-ae02-5bf8a94afd62","html_url":"https://github.com/Kukks/NNostr","commit_stats":null,"previous_names":[],"tags_count":74,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kukks%2FNNostr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kukks%2FNNostr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kukks%2FNNostr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kukks%2FNNostr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kukks","download_url":"https://codeload.github.com/Kukks/NNostr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225581771,"owners_count":17491788,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nostr"],"created_at":"2024-08-04T11:00:21.543Z","updated_at":"2024-11-20T15:30:46.528Z","avatar_url":"https://github.com/Kukks.png","language":"C#","funding_links":["https://github.com/sponsors/kukks","https://donate.kukks.org"],"categories":["Install from Source","Relays"],"sub_categories":["Nostr","Implementations"],"readme":"# NNostr\nA Nostr Relay and Client written in C#\n\n# Client\n\n## Installation\n\n```dotnet add package NNostr.Client```\n\n## Usage\n\n1.) Initiate a new client\n```csharp\nvar client = new NostrClient(new Uri(\"wss://your-relay-url.com\"));\n```\n2.) Connect to the relay\n```csharp\n_ = client.Connect();\n```\n3.) Wait for the connection to be established\n```csharp\nawait client.WaitUntilConnected();\n```\n4.) Listen in for events\n```csharp\nvoid OnClientOnEventsReceived(object sender, (string subscriptionId, NostrEvent[] events) args)\n    {\n        if (args.subscriptionId == \"my-subscription-id\")\n        {\n            foreach (var nostrEvent in args.events)\n            {\n                Console.WriteLine(nostrEvent.Content);\n            }\n        }\n    }\nclient.EventsReceived += OnClientOnEventsReceived;\n```\n\n5.) Subscribe to events\n```csharp\n//subscribe to all kind 1 events under the subscription id of \"my-subscription-id\"\nclient.CreateSubscription(\"my-subscription-id\", new []\n        {\n            new NostrSubscriptionFilter()\n            {\n                Kinds = new []{1}\n            }\n})\n```\n6.) Send events\n```csharp\n// create a private key:\nvar key = ECPrivKey.Create(RandomUtils.GetBytes(32));\n// or else load a private key from a hex string\nkey = Context.Instance.CreateECPrivKey(Convert.FromHexString(\"7f4c11a9742721d66e40e321ca50b682c27f7422190c14a187525e69e604836a\"));\n// or load from an nsec string\nkey = \"nsec1vl029mgpspedva04g90vltkh6fvh240zqtv9k0t9af8935ke9laqsnlfe5\".FromNIP19Nsec();\n\n// create a new event\nvar newEvent = new NostrEvent()\n{\n    Kind = 1,\n    Content = \"Hello World!\"\n};\n// sign the event\nawait newEvent.ComputeIdAndSignAsync(key);\n// send the event\nawait client.SendEventsAndWaitUntilReceived(new[] {evt}, CancellationToken.None);\n```\n\n\n\n# Relay\n* Install BTCPay Server through docker deployment https://docs.btcpayserver.org/Docker/#full-installation-for-technical-users\n* run the following ssh commands\n```bash\ncd btcpayserver-docker\nBTCPAYGEN_ADDITIONAL_FRAGMENTS=\"$BTCPAYGEN_ADDITIONAL_FRAGMENTS;opt-add-nostr-relay\"\n. ./btcpay-setup.sh -i\n```\n* your relay will be available at your btcpay url `/nostr`\n\n\nAlternatively, you can configure a docker compose with the following service definition (it is missing nginx, ssl, postgres)\n```yml\nservices:\n  nnostr-relay:\n    restart: unless-stopped\n    image: kukks/nnostr-relay:v0.0.10-1\n    container_name: nnostr-relay\n    environment:\n      NOSTR_CONNECTIONSTRINGS__RelayDatabase: User ID=postgres;Host=postgres;Port=5432;Database=nnostr\n      ASPNETCORE_URLS: \"http://0.0.0.0:80\"\n    links:\n      - postgres\n      - btcpayserver\n    volumes:\n      - \"nnostr_datadir:/datadir\"\nvolumes:\n  nnostr_datadir:\n```\n\nAlternatively, you can go to `/Relay`, configure `appsettings.json` and `dotnet run` ( you need dotnet runtime installed)\n\n## Configure the relay\nThe relay is now running, great! DO NOT SHARE THE URL JUST YET! As there is no UI, one must first connect to the relay using a nostr client, and wait for a Notice event from the relay, that states that the relay is not yet configured and a temporary nostr private key has been created that you can use to configure. Simply login using that key, send a DM to yourself with the message `/admin config` to get the confougration options, and then send it back with `/admin update {CONFIG}`. Please note that the admin key (`AdminKey`) MUST be hex format, not `nsec`.\n\nThe BTCPay Server integration uses the BTCPay Server Greenfield API. You can generate a new API key by going to `Account =\u003e API Keys`, and the only permissions needed are `CanViewInvoices` and `CanCreateInvoice`.The mandatory ones for payments are `BTCPayServerUri`, `BTCPayServerApiKey`, and `BTCPayServerStoreId`. \n\nOptionally, you can configure BTCPayServer to send a webhook (`Store-Settings-\u003eWebhooks`) to `your relay url.com/nostr/btcpay/webhook` for the specific event of `An invoice has been settled`. You are highly recommended to also configure a secret and then to configure it in the relay with `BTCPayServerWebhookSecret` configuration to reduce spam attacks.\n### Payment options\nThe relay allows you to charge a fee per event if wanted using the `EventCost` configuration. This is always in sats. You may also configure the relay to make the cost of an event dynamic, to charge based on the size of the event (1byte = eventcost) by setting `EventCostPerByte` to true.\n\nYou can charge pubkeys to be whitelisted on the server by setting `PubKeyCost` to the number of sats to charge.\n\n### Commands\nAs an admin (the key saved in `AdminKey`), you can DM yourself with the commands `/admin update {config}`, `/admin factory-reset`, `/admin config`\n\nAny user can send a DM to the admin's public key, with the commands `/topup` and `/balance`. \n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FKukks%2FNNostr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FKukks%2FNNostr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FKukks%2FNNostr/lists"}