applesauce-wallet-connect 0.0.0-next-20250930093922 → 0.0.0-next-20251009095925
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -41,10 +41,10 @@ Create a wallet service that handles NIP-47 requests:
|
|
|
41
41
|
|
|
42
42
|
```typescript
|
|
43
43
|
import { WalletService } from "applesauce-wallet-connect";
|
|
44
|
-
import {
|
|
44
|
+
import { PrivateKeySigner } from "applesauce-signers";
|
|
45
45
|
|
|
46
46
|
// Create a signer for the service
|
|
47
|
-
const signer = new
|
|
47
|
+
const signer = new PrivateKeySigner();
|
|
48
48
|
|
|
49
49
|
// Define method handlers
|
|
50
50
|
const handlers = {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { EventBlueprint } from "applesauce-factory";
|
|
2
2
|
import { WalletSupport } from "../helpers/support.js";
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Creates a wallet info event
|
|
5
|
+
* @param info - The wallet support information
|
|
6
|
+
* @param client - The client pubkey
|
|
7
|
+
* @param overrideRelay - An optional relay to tell the client which relay to use (for nostr+walletauth URI connections)
|
|
8
|
+
*/
|
|
9
|
+
export declare function WalletSupportBlueprint(info: WalletSupport, client?: string, overrideRelay?: string): EventBlueprint;
|
|
@@ -2,9 +2,14 @@ import { blueprint } from "applesauce-factory";
|
|
|
2
2
|
import { setContent } from "applesauce-factory/operations/content";
|
|
3
3
|
import { includeSingletonTag } from "applesauce-factory/operations";
|
|
4
4
|
import { WALLET_INFO_KIND } from "../helpers/support.js";
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Creates a wallet info event
|
|
7
|
+
* @param info - The wallet support information
|
|
8
|
+
* @param client - The client pubkey
|
|
9
|
+
* @param overrideRelay - An optional relay to tell the client which relay to use (for nostr+walletauth URI connections)
|
|
10
|
+
*/
|
|
11
|
+
export function WalletSupportBlueprint(info, client, overrideRelay) {
|
|
7
12
|
return blueprint(WALLET_INFO_KIND, setContent(info.methods.join(" ")), info.encryption ? includeSingletonTag(["encryption", info.encryption.join(" ")]) : undefined, info.notifications ? includeSingletonTag(["notifications", info.notifications.join(" ")]) : undefined,
|
|
8
13
|
// An optional client pubkey to notify the service is created (used for nostr+walletauth URI connections)
|
|
9
|
-
client ? includeSingletonTag(["p", client]) : undefined);
|
|
14
|
+
client ? includeSingletonTag(overrideRelay ? ["p", client, overrideRelay] : ["p", client]) : undefined);
|
|
10
15
|
}
|
package/dist/wallet-connect.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export type WalletConnectOptions = NostrConnectionMethodsOptions & {
|
|
|
14
14
|
service?: string;
|
|
15
15
|
/** Default timeout for RPC requests in milliseconds */
|
|
16
16
|
timeout?: number;
|
|
17
|
+
/** Whether to accept the relay hint from the wallet service */
|
|
18
|
+
acceptRelayHint?: boolean;
|
|
17
19
|
};
|
|
18
20
|
export declare class WalletConnect {
|
|
19
21
|
/** A fallback method to use for subscriptionMethod if none is passed in when creating the client */
|
|
@@ -30,7 +32,10 @@ export declare class WalletConnect {
|
|
|
30
32
|
readonly secret: Uint8Array;
|
|
31
33
|
protected readonly signer: EventSigner;
|
|
32
34
|
/** The relays to use for the connection */
|
|
33
|
-
|
|
35
|
+
protected relays$: BehaviorSubject<string[]>;
|
|
36
|
+
get relays(): string[];
|
|
37
|
+
/** Whether to accept the relay hint from the wallet service */
|
|
38
|
+
acceptRelayHint: boolean;
|
|
34
39
|
/** The wallet service public key ( unset if waiting for service ) */
|
|
35
40
|
service$: BehaviorSubject<string | undefined>;
|
|
36
41
|
get service(): string | undefined;
|
package/dist/wallet-connect.js
CHANGED
|
@@ -2,7 +2,7 @@ import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
|
|
|
2
2
|
import { simpleTimeout } from "applesauce-core";
|
|
3
3
|
import { create } from "applesauce-factory";
|
|
4
4
|
import { finalizeEvent, getPublicKey, nip04, nip44, verifyEvent } from "nostr-tools";
|
|
5
|
-
import { BehaviorSubject, defer, filter, firstValueFrom, from, fromEvent, identity, ignoreElements, lastValueFrom, map, merge, mergeMap, repeat, ReplaySubject, retry, share, switchMap, takeUntil, tap, timer, toArray, } from "rxjs";
|
|
5
|
+
import { BehaviorSubject, combineLatest, defer, filter, firstValueFrom, from, fromEvent, identity, ignoreElements, lastValueFrom, map, merge, mergeMap, of, repeat, ReplaySubject, retry, share, switchMap, take, takeUntil, tap, timer, toArray, } from "rxjs";
|
|
6
6
|
import { WalletRequestBlueprint } from "./blueprints/index.js";
|
|
7
7
|
import { createWalletError } from "./helpers/error.js";
|
|
8
8
|
import { createWalletAuthURI, getPreferredEncryption, getWalletRequestEncryption, getWalletResponseRequestId, getWalletSupport, isValidWalletNotification, isValidWalletResponse, parseWalletConnectURI, supportsMethod, supportsNotifications, supportsNotificationType, unlockWalletNotification, unlockWalletResponse, WALLET_INFO_KIND, WALLET_LEGACY_NOTIFICATION_KIND, WALLET_NOTIFICATION_KIND, WALLET_RESPONSE_KIND, } from "./helpers/index.js";
|
|
@@ -22,7 +22,12 @@ export class WalletConnect {
|
|
|
22
22
|
secret;
|
|
23
23
|
signer;
|
|
24
24
|
/** The relays to use for the connection */
|
|
25
|
-
relays;
|
|
25
|
+
relays$ = new BehaviorSubject([]);
|
|
26
|
+
get relays() {
|
|
27
|
+
return this.relays$.value;
|
|
28
|
+
}
|
|
29
|
+
/** Whether to accept the relay hint from the wallet service */
|
|
30
|
+
acceptRelayHint;
|
|
26
31
|
/** The wallet service public key ( unset if waiting for service ) */
|
|
27
32
|
service$ = new BehaviorSubject(undefined);
|
|
28
33
|
get service() {
|
|
@@ -42,7 +47,8 @@ export class WalletConnect {
|
|
|
42
47
|
waitForService$;
|
|
43
48
|
constructor(options) {
|
|
44
49
|
this.secret = options.secret;
|
|
45
|
-
this.relays
|
|
50
|
+
this.relays$.next(options.relays);
|
|
51
|
+
this.acceptRelayHint = options.acceptRelayHint ?? true;
|
|
46
52
|
this.service$.next(options.service);
|
|
47
53
|
this.defaultTimeout = options.timeout || 30000; // 30 second default timeout
|
|
48
54
|
// Create a signer for the factory
|
|
@@ -64,18 +70,18 @@ export class WalletConnect {
|
|
|
64
70
|
this.subscriptionMethod = (relays, filters) => subscriptionMethod(relays, filters);
|
|
65
71
|
this.publishMethod = (relays, event) => publishMethod(relays, event);
|
|
66
72
|
// Create shared observable for all wallet events
|
|
67
|
-
this.events$ = this.service
|
|
73
|
+
this.events$ = combineLatest([this.service$, this.relays$]).pipe(switchMap(([service, relays]) => {
|
|
68
74
|
const client = getPublicKey(this.secret);
|
|
69
75
|
// If the service is not known yet, subscribe to a wallet info event tagging the client
|
|
70
76
|
if (!service)
|
|
71
|
-
return from(this.subscriptionMethod(
|
|
77
|
+
return from(this.subscriptionMethod(relays, [{ kinds: [WALLET_INFO_KIND], "#p": [client] }])).pipe(
|
|
72
78
|
// Keep the connection open indefinitely
|
|
73
79
|
repeat(),
|
|
74
80
|
// Retry on connection failure
|
|
75
81
|
retry(),
|
|
76
82
|
// Ignore strings (support for applesauce-relay)
|
|
77
83
|
filter((event) => typeof event !== "string"));
|
|
78
|
-
return from(this.subscriptionMethod(
|
|
84
|
+
return from(this.subscriptionMethod(relays, [
|
|
79
85
|
// Subscribe to response events
|
|
80
86
|
{
|
|
81
87
|
kinds: [WALLET_RESPONSE_KIND, WALLET_NOTIFICATION_KIND, WALLET_LEGACY_NOTIFICATION_KIND],
|
|
@@ -104,18 +110,29 @@ export class WalletConnect {
|
|
|
104
110
|
}));
|
|
105
111
|
this.encryption$ = this.support$.pipe(map((info) => (info ? getPreferredEncryption(info) : "nip04")));
|
|
106
112
|
this.notifications$ = this.events$.pipe(filter((event) => isValidWalletNotification(event)), mergeMap((event) => this.handleNotificationEvent(event)));
|
|
107
|
-
this.waitForService$ =
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
this.waitForService$ = defer(() =>
|
|
114
|
+
// If service is already set, return it
|
|
115
|
+
this.service$.value
|
|
116
|
+
? of(this.service$.value)
|
|
117
|
+
: // Otherwise listen for new wallet info events
|
|
118
|
+
this.events$.pipe(
|
|
119
|
+
// Only listen for wallet info events
|
|
120
|
+
filter((event) => event.kind === WALLET_INFO_KIND),
|
|
121
|
+
// Set the service to the pubkey of the wallet info event
|
|
122
|
+
tap((event) => {
|
|
123
|
+
// Set the service to the pubkey of the wallet info event
|
|
124
|
+
this.service$.next(event.pubkey);
|
|
125
|
+
// Switch to the relay from the service if its set
|
|
126
|
+
if (this.acceptRelayHint) {
|
|
127
|
+
const relay = event.tags.find((t) => t[0] === "p" && t[2])?.[2];
|
|
128
|
+
if (relay)
|
|
129
|
+
this.relays$.next([relay]);
|
|
130
|
+
}
|
|
131
|
+
}),
|
|
132
|
+
// Get the service pubkey from the event
|
|
133
|
+
map((event) => event.pubkey),
|
|
134
|
+
// Complete after the first value
|
|
135
|
+
take(1))).pipe(
|
|
119
136
|
// Only create a single subscription to avoid multiple side effects
|
|
120
137
|
share());
|
|
121
138
|
}
|
|
@@ -144,7 +161,7 @@ export class WalletConnect {
|
|
|
144
161
|
request(request, options = {}) {
|
|
145
162
|
if (!this.service)
|
|
146
163
|
throw new Error("WalletConnect is not connected to a service");
|
|
147
|
-
// Create the request
|
|
164
|
+
// Create the request event
|
|
148
165
|
return defer(async () => {
|
|
149
166
|
// Get the preferred encryption method for the wallet
|
|
150
167
|
const encryption = await firstValueFrom(this.encryption$);
|
package/dist/wallet-service.d.ts
CHANGED
|
@@ -115,5 +115,8 @@ export declare class WalletService {
|
|
|
115
115
|
/** Send a response event */
|
|
116
116
|
protected sendResponse(requestEvent: WalletRequestEvent, response: WalletResponse): Promise<void>;
|
|
117
117
|
/** Creates a service for a nostr+walletauth URI */
|
|
118
|
-
static fromAuthURI(uri: string | WalletAuthURI, options: Omit<WalletServiceOptions, "relays">
|
|
118
|
+
static fromAuthURI(uri: string | WalletAuthURI, options: Omit<WalletServiceOptions, "relays"> & {
|
|
119
|
+
/** A relay or method to select a single relay for the client and service to communicate over */
|
|
120
|
+
overrideRelay?: string | ((relays: string[]) => string);
|
|
121
|
+
}): WalletService;
|
|
119
122
|
}
|
package/dist/wallet-service.js
CHANGED
|
@@ -162,7 +162,9 @@ export class WalletService {
|
|
|
162
162
|
/** Publish the wallet support event */
|
|
163
163
|
async publishSupportEvent() {
|
|
164
164
|
try {
|
|
165
|
-
|
|
165
|
+
// Tell the client which relay to use if there is only one (for nostr+walletauth URI connections)
|
|
166
|
+
const overrideRelay = this.relays.length === 1 ? this.relays[0] : undefined;
|
|
167
|
+
const draft = await create({ signer: this.signer }, WalletSupportBlueprint, this.support, this.client, overrideRelay);
|
|
166
168
|
const event = await this.signer.signEvent(draft);
|
|
167
169
|
await this.publishMethod(this.relays, event);
|
|
168
170
|
}
|
|
@@ -284,10 +286,13 @@ export class WalletService {
|
|
|
284
286
|
}
|
|
285
287
|
/** Creates a service for a nostr+walletauth URI */
|
|
286
288
|
static fromAuthURI(uri, options) {
|
|
287
|
-
const
|
|
289
|
+
const authURI = typeof uri === "string" ? parseWalletAuthURI(uri) : uri;
|
|
290
|
+
const relays = options.overrideRelay
|
|
291
|
+
? [typeof options.overrideRelay === "function" ? options.overrideRelay(authURI.relays) : options.overrideRelay]
|
|
292
|
+
: authURI.relays;
|
|
288
293
|
return new WalletService({
|
|
289
294
|
...options,
|
|
290
|
-
client,
|
|
295
|
+
client: authURI.client,
|
|
291
296
|
relays,
|
|
292
297
|
});
|
|
293
298
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "applesauce-wallet-connect",
|
|
3
|
-
"version": "0.0.0-next-
|
|
3
|
+
"version": "0.0.0-next-20251009095925",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@noble/hashes": "^1.7.1",
|
|
62
|
-
"applesauce-core": "
|
|
63
|
-
"applesauce-factory": "
|
|
62
|
+
"applesauce-core": "^4.0.0",
|
|
63
|
+
"applesauce-factory": "^4.0.0",
|
|
64
64
|
"nostr-tools": "~2.17",
|
|
65
65
|
"rxjs": "^7.8.1"
|
|
66
66
|
},
|