Skip to content

Commit

Permalink
fix: nwc auth docs, husky commit (#325)
Browse files Browse the repository at this point in the history
  • Loading branch information
rolznz authored Feb 21, 2025
1 parent 2be1bbf commit 672213b
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 30 deletions.
3 changes: 0 additions & 3 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

yarn commitlint --edit
3 changes: 0 additions & 3 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

yarn lint-staged
19 changes: 6 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ There are two interfaces you can use to access NWC:
- `walletPubkey`: pubkey of the Nostr Wallet Connect app
- `secret`: secret key to sign the request event (if not available window.nostr will be used)

#### `static newClientFromAuthorizationUrl()`
#### `static fromAuthorizationUrl()`

Initialized a new `NWCClient` instance but generates a new random secret. The pubkey of that secret then needs to be authorized by the user (this can be initiated by redirecting the user to the `getAuthorizationUrl()` URL or calling `fromAuthorizationUrl()` to open an authorization popup.

Expand All @@ -71,6 +71,8 @@ const nwcClient = await nwc.NWCClient.fromAuthorizationUrl(
);
```

The same options can be provided to getAuthorizationUrl() as fromAuthorizationUrl() - see [Manual Auth example](./examples/nwc/client/auth_manual.html)

#### Quick start example

```js
Expand Down Expand Up @@ -232,18 +234,7 @@ nwc.close(); // close the websocket connection
#### Generate a new NWC connect url using a locally-generated secret

```js
// same options can be provided to .withNewSecret() as creating a new NostrWebLNProvider()
const webln = webln.NostrWebLNProvider.withNewSecret();

// get the connect URL to the interface where the user has to enable the connection
webln.getConnectUrl({ name: `My app name` });
// an optional return_to parameter can be passed in
webln.getConnectUrl({
name: `My app name`,
returnTo: document.location.toString(),
});

// or use the `fromAuthorizationUrl` helper which opens a popup to initiate the connection flow.
// use the `fromAuthorizationUrl` helper which opens a popup to initiate the connection flow.
// the promise resolves once the NWC app returned.
const nwc = await webln.NostrWebLNProvider.fromAuthorizationUrl(
"https://my.albyhub.com/apps/new",
Expand All @@ -258,6 +249,8 @@ const nwc = await webln.NostrWebLNProvider.fromAuthorizationUrl(
// const nostrWalletConnectUrl nwc.getNostrWalletConnectUrl(true)
```

The same options can be provided to getAuthorizationUrl() as fromAuthorizationUrl() - see [Manual Auth example](./examples/nwc/auth_manual.html)

## OAuth API Documentation

Please have a look a the Alby OAuth2 Wallet API:
Expand Down
81 changes: 81 additions & 0 deletions examples/nwc/auth_manual.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<button id="connect-button" onclick="window.launchNwc()">Connect NWC</button>
<button id="reset-button" onclick="window.resetNwc()">Reset</button>

<script type="module">
import { webln, nwc } from "https://esm.sh/@getalby/[email protected]"; // jsdelivr.net, skypack.dev also work
import {
generateSecretKey,
getPublicKey,
} from "https://esm.sh/[email protected]"; // jsdelivr.net, skypack.dev also work
import {
bytesToHex,
hexToBytes,
} from "https://esm.sh/@noble/[email protected]/utils"; // jsdelivr.net, skypack.dev also work

const params = new URL(window.location.href).searchParams;
const walletPubkey = params.get("pubkey");
const relayUrl = params.get("relay");
const lud16 = params.get("lud16");
const secret = window.localStorage.getItem("demo_secret");

if (walletPubkey && relayUrl) {
try {
if (!secret) {
throw new Error("No secret saved locally");
}
window.document.getElementById("connect-button").remove();
const nwcClient = new nwc.NWCClient({
secret,
walletPubkey,
relayUrl,
lud16,
});
const weblnProvider = new webln.NostrWebLNProvider({
client: nwcClient,
});
await weblnProvider.enable();
const result = await weblnProvider.getInfo();
alert("Info response: " + JSON.stringify(result) + " lud16: " + lud16);
} catch (error) {
console.error(error);
alert("Something went wrong: " + error);
}
} else {
window.document.getElementById("reset-button").remove();
}

window.resetNwc = async () => {
window.localStorage.removeItem("demo_secret");
window.location.href = window.origin;
};

window.launchNwc = async () => {
try {
if (!window.origin.startsWith("http")) {
alert(
"Please use a webserver from this directory e.g. python3 -m http.server",
);
}

const secret = bytesToHex(generateSecretKey());
const pubkey = getPublicKey(hexToBytes(secret));
window.localStorage.setItem("demo_secret", secret);
const authorizationBasePath = prompt(
"Auth URL",
"https://my.albyhub.com/apps/new",
);
const authUrl = await nwc.NWCClient.getAuthorizationUrl(
authorizationBasePath,
{
name: "Deeplink " + Date.now(),
returnTo: window.location.href,
},
pubkey,
);
window.location = authUrl;
} catch (error) {
console.error(error);
alert("Something went wrong: " + error);
}
};
</script>
77 changes: 77 additions & 0 deletions examples/nwc/client/auth_manual.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<button id="connect-button" onclick="window.launchNwc()">Connect NWC</button>
<button id="reset-button" onclick="window.resetNwc()">Reset</button>

<script type="module">
import { nwc } from "https://esm.sh/@getalby/[email protected]"; // jsdelivr.net, skypack.dev also work
import {
generateSecretKey,
getPublicKey,
} from "https://esm.sh/[email protected]"; // jsdelivr.net, skypack.dev also work
import {
bytesToHex,
hexToBytes,
} from "https://esm.sh/@noble/[email protected]/utils"; // jsdelivr.net, skypack.dev also work

const params = new URL(window.location.href).searchParams;
const walletPubkey = params.get("pubkey");
const relayUrl = params.get("relay");
const lud16 = params.get("lud16");
const secret = window.localStorage.getItem("demo_secret");

if (walletPubkey && relayUrl) {
try {
if (!secret) {
throw new Error("No secret saved locally");
}
window.document.getElementById("connect-button").remove();
const nwcClient = new nwc.NWCClient({
secret,
walletPubkey,
relayUrl,
lud16,
});
const result = await nwcClient.getInfo();
alert("Info response: " + JSON.stringify(result) + " lud16: " + lud16);
} catch (error) {
console.error(error);
alert("Something went wrong: " + error);
}
} else {
window.document.getElementById("reset-button").remove();
}

window.resetNwc = async () => {
window.localStorage.removeItem("demo_secret");
window.location.href = window.origin;
};

window.launchNwc = async () => {
try {
if (!window.origin.startsWith("http")) {
alert(
"Please use a webserver from this directory e.g. python3 -m http.server",
);
}

const secret = bytesToHex(generateSecretKey());
const pubkey = getPublicKey(hexToBytes(secret));
window.localStorage.setItem("demo_secret", secret);
const authorizationBasePath = prompt(
"Auth URL",
"https://my.albyhub.com/apps/new",
);
const authUrl = await nwc.NWCClient.getAuthorizationUrl(
authorizationBasePath,
{
name: "Deeplink " + Date.now(),
returnTo: window.location.href,
},
pubkey,
);
window.location = authUrl;
} catch (error) {
console.error(error);
alert("Something went wrong: " + error);
}
};
</script>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"clean": "rm -rf dist",
"build": "microbundle --no-sourcemap",
"dev": "microbundle watch",
"prepare": "husky install"
"prepare": "husky"
},
"dependencies": {
"nostr-tools": "2.9.4"
Expand Down
11 changes: 1 addition & 10 deletions src/webln/NostrWeblnProvider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Event, UnsignedEvent, generateSecretKey } from "nostr-tools";
import { bytesToHex } from "@noble/hashes/utils";
import { Event, UnsignedEvent } from "nostr-tools";
import {
GetBalanceResponse,
KeysendArgs,
Expand Down Expand Up @@ -93,14 +92,6 @@ export class NostrWebLNProvider implements WebLNProvider, Nip07Provider {
return this.client.options;
}

static withNewSecret(
options?: ConstructorParameters<typeof NostrWebLNProvider>[0],
) {
options = options || {};
options.secret = bytesToHex(generateSecretKey());
return new NostrWebLNProvider(options);
}

static async fromAuthorizationUrl(
authorizationBasePath: string,
options: NWCAuthorizationUrlOptions = {},
Expand Down

0 comments on commit 672213b

Please sign in to comment.