applesauce-wallet-connect 3.1.0 → 4.0.0
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/dist/helpers/notification.d.ts +12 -4
- package/dist/helpers/notification.js +18 -12
- package/dist/helpers/request.d.ts +12 -4
- package/dist/helpers/request.js +19 -14
- package/dist/helpers/response.d.ts +15 -5
- package/dist/helpers/response.js +20 -14
- package/dist/wallet-connect.d.ts +3 -3
- package/dist/wallet-connect.js +23 -26
- package/dist/wallet-service.d.ts +8 -9
- package/dist/wallet-service.js +13 -9
- package/package.json +7 -5
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { HiddenContentSigner } from "applesauce-core/helpers";
|
|
1
|
+
import { HiddenContentSigner, KnownEvent, UnlockedHiddenContent } from "applesauce-core/helpers";
|
|
2
2
|
import { NostrEvent } from "nostr-tools";
|
|
3
3
|
import { Transaction } from "./response.js";
|
|
4
4
|
export declare const WALLET_NOTIFICATION_KIND = 23197;
|
|
5
5
|
export declare const WALLET_LEGACY_NOTIFICATION_KIND = 23196;
|
|
6
|
+
/** A type for validated wallet notification events */
|
|
7
|
+
export type WalletNotificationEvent = KnownEvent<typeof WALLET_NOTIFICATION_KIND> | KnownEvent<typeof WALLET_LEGACY_NOTIFICATION_KIND>;
|
|
6
8
|
/** A symbol used to cache the wallet notification on the event */
|
|
7
9
|
export declare const WalletNotificationSymbol: unique symbol;
|
|
10
|
+
/** A type for unlocked notifications events */
|
|
11
|
+
export type UnlockedWalletNotification = UnlockedHiddenContent & {
|
|
12
|
+
[WalletNotificationSymbol]: WalletNotification;
|
|
13
|
+
};
|
|
8
14
|
/** Supported notification types */
|
|
9
15
|
export type NotificationType = "payment_received" | "payment_sent";
|
|
10
16
|
/** Base notification structure */
|
|
@@ -21,8 +27,10 @@ export type PaymentSentNotification = BaseNotification<"payment_sent", Transacti
|
|
|
21
27
|
/** Union type for all NIP-47 notification types */
|
|
22
28
|
export type WalletNotification = PaymentReceivedNotification | PaymentSentNotification;
|
|
23
29
|
/** Checks if a kind 23196 or 23197 event is locked */
|
|
24
|
-
export declare function
|
|
30
|
+
export declare function isWalletNotificationUnlocked(notification: any): notification is UnlockedWalletNotification;
|
|
25
31
|
/** Unlocks a kind 23196 or 23197 event */
|
|
26
|
-
export declare function unlockWalletNotification(notification: NostrEvent, signer: HiddenContentSigner): Promise<WalletNotification | undefined
|
|
32
|
+
export declare function unlockWalletNotification(notification: NostrEvent, signer: HiddenContentSigner): Promise<WalletNotification | undefined>;
|
|
27
33
|
/** Gets the wallet notification from a kind 23196 or 23197 event */
|
|
28
|
-
export declare function getWalletNotification(notification: NostrEvent): WalletNotification | undefined
|
|
34
|
+
export declare function getWalletNotification(notification: NostrEvent): WalletNotification | undefined;
|
|
35
|
+
/** Checks if an event is a valid wallet notification event */
|
|
36
|
+
export declare function isValidWalletNotification(notification: NostrEvent): notification is WalletNotificationEvent;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isHiddenContentUnlocked, notifyEventUpdate, setHiddenContentEncryptionMethod, unlockHiddenContent, } from "applesauce-core/helpers";
|
|
2
2
|
export const WALLET_NOTIFICATION_KIND = 23197;
|
|
3
3
|
export const WALLET_LEGACY_NOTIFICATION_KIND = 23196;
|
|
4
4
|
/** A symbol used to cache the wallet notification on the event */
|
|
@@ -7,22 +7,28 @@ export const WalletNotificationSymbol = Symbol("wallet-notification");
|
|
|
7
7
|
setHiddenContentEncryptionMethod(WALLET_NOTIFICATION_KIND, "nip44");
|
|
8
8
|
setHiddenContentEncryptionMethod(WALLET_LEGACY_NOTIFICATION_KIND, "nip04");
|
|
9
9
|
/** Checks if a kind 23196 or 23197 event is locked */
|
|
10
|
-
export function
|
|
11
|
-
return
|
|
10
|
+
export function isWalletNotificationUnlocked(notification) {
|
|
11
|
+
return isHiddenContentUnlocked(notification) && Reflect.has(notification, WalletNotificationSymbol) === true;
|
|
12
12
|
}
|
|
13
13
|
/** Unlocks a kind 23196 or 23197 event */
|
|
14
14
|
export async function unlockWalletNotification(notification, signer) {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (isWalletNotificationUnlocked(notification))
|
|
16
|
+
return notification[WalletNotificationSymbol];
|
|
17
|
+
const content = await unlockHiddenContent(notification, signer);
|
|
18
|
+
const parsed = JSON.parse(content);
|
|
19
|
+
// Save the parsed content
|
|
20
|
+
Reflect.set(notification, WalletNotificationSymbol, parsed);
|
|
21
|
+
notifyEventUpdate(notification);
|
|
22
|
+
return parsed;
|
|
17
23
|
}
|
|
18
24
|
/** Gets the wallet notification from a kind 23196 or 23197 event */
|
|
19
25
|
export function getWalletNotification(notification) {
|
|
20
|
-
if (
|
|
26
|
+
if (isWalletNotificationUnlocked(notification))
|
|
27
|
+
return notification[WalletNotificationSymbol];
|
|
28
|
+
else
|
|
21
29
|
return undefined;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return JSON.parse(content);
|
|
27
|
-
});
|
|
30
|
+
}
|
|
31
|
+
/** Checks if an event is a valid wallet notification event */
|
|
32
|
+
export function isValidWalletNotification(notification) {
|
|
33
|
+
return notification.kind === WALLET_NOTIFICATION_KIND || notification.kind === WALLET_LEGACY_NOTIFICATION_KIND;
|
|
28
34
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { HiddenContentSigner } from "applesauce-core/helpers";
|
|
1
|
+
import { HiddenContentSigner, KnownEvent, UnlockedHiddenContent } from "applesauce-core/helpers";
|
|
2
2
|
import { NostrEvent } from "nostr-tools";
|
|
3
3
|
import { WalletConnectEncryptionMethod } from "./encryption.js";
|
|
4
4
|
import { WalletMethod } from "./support.js";
|
|
5
5
|
export declare const WALLET_REQUEST_KIND = 23194;
|
|
6
|
+
export type WalletRequestEvent = KnownEvent<typeof WALLET_REQUEST_KIND>;
|
|
6
7
|
/** A symbol used to cache the wallet request on the event */
|
|
7
8
|
export declare const WalletRequestSymbol: unique symbol;
|
|
9
|
+
/** Type for events with unlocked hidden content */
|
|
10
|
+
export type UnlockedWalletRequest = UnlockedHiddenContent & {
|
|
11
|
+
[WalletRequestSymbol]: WalletRequest;
|
|
12
|
+
};
|
|
8
13
|
/** TLV record for keysend payments */
|
|
9
14
|
export interface TLVRecord {
|
|
10
15
|
/** TLV type */
|
|
@@ -116,12 +121,13 @@ export type GetInfoRequest = BaseWalletRequest<"get_info", GetInfoParams>;
|
|
|
116
121
|
/** Union type for all NIP-47 request types */
|
|
117
122
|
export type WalletRequest = PayInvoiceRequest | MultiPayInvoiceRequest | PayKeysendRequest | MultiPayKeysendRequest | MakeInvoiceRequest | LookupInvoiceRequest | ListTransactionsRequest | GetBalanceRequest | GetInfoRequest;
|
|
118
123
|
/** Checks if a kind 23194 event is locked */
|
|
119
|
-
export declare function
|
|
124
|
+
export declare function isWalletRequestUnlocked(request: any): request is UnlockedWalletRequest;
|
|
120
125
|
/** Unlocks a kind 23194 event */
|
|
121
|
-
export declare function unlockWalletRequest(request: NostrEvent, signer: HiddenContentSigner): Promise<WalletRequest | undefined
|
|
126
|
+
export declare function unlockWalletRequest(request: NostrEvent, signer: HiddenContentSigner): Promise<WalletRequest | undefined>;
|
|
122
127
|
/** Gets the wallet request from a kind 23194 event */
|
|
123
|
-
export declare function getWalletRequest(request: NostrEvent): WalletRequest | undefined
|
|
128
|
+
export declare function getWalletRequest(request: NostrEvent): WalletRequest | undefined;
|
|
124
129
|
/** Returns the wallet service pubkey from a request */
|
|
130
|
+
export declare function getWalletRequestServicePubkey(request: WalletRequestEvent): string;
|
|
125
131
|
export declare function getWalletRequestServicePubkey(request: NostrEvent): string | undefined;
|
|
126
132
|
/** Returns the expiration timestamp from a request */
|
|
127
133
|
export declare function getWalletRequestExpiration(request: NostrEvent): number | undefined;
|
|
@@ -129,3 +135,5 @@ export declare function getWalletRequestExpiration(request: NostrEvent): number
|
|
|
129
135
|
export declare function isWalletRequestExpired(request: NostrEvent): boolean;
|
|
130
136
|
/** Gets the encryption method used for a request */
|
|
131
137
|
export declare function getWalletRequestEncryption(request: NostrEvent): WalletConnectEncryptionMethod;
|
|
138
|
+
/** Checks if an event is a valid wallet request event */
|
|
139
|
+
export declare function isValidWalletRequest(request: NostrEvent): request is WalletRequestEvent;
|
package/dist/helpers/request.js
CHANGED
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getTagValue, isHiddenContentUnlocked, isNIP04Encrypted, notifyEventUpdate, setHiddenContentEncryptionMethod, unixNow, unlockHiddenContent, } from "applesauce-core/helpers";
|
|
2
2
|
export const WALLET_REQUEST_KIND = 23194;
|
|
3
3
|
// Set the encryption method to use for request kind
|
|
4
4
|
setHiddenContentEncryptionMethod(WALLET_REQUEST_KIND, "nip44");
|
|
5
5
|
/** A symbol used to cache the wallet request on the event */
|
|
6
6
|
export const WalletRequestSymbol = Symbol("wallet-request");
|
|
7
7
|
/** Checks if a kind 23194 event is locked */
|
|
8
|
-
export function
|
|
9
|
-
return
|
|
8
|
+
export function isWalletRequestUnlocked(request) {
|
|
9
|
+
return isHiddenContentUnlocked(request) && Reflect.has(request, WalletRequestSymbol) === true;
|
|
10
10
|
}
|
|
11
11
|
/** Unlocks a kind 23194 event */
|
|
12
12
|
export async function unlockWalletRequest(request, signer) {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
if (isWalletRequestUnlocked(request))
|
|
14
|
+
return request[WalletRequestSymbol];
|
|
15
|
+
const content = await unlockHiddenContent(request, signer);
|
|
16
|
+
const parsed = JSON.parse(content);
|
|
17
|
+
// Save the parsed content
|
|
18
|
+
Reflect.set(request, WalletRequestSymbol, parsed);
|
|
19
|
+
notifyEventUpdate(request);
|
|
20
|
+
return parsed;
|
|
15
21
|
}
|
|
16
22
|
/** Gets the wallet request from a kind 23194 event */
|
|
17
23
|
export function getWalletRequest(request) {
|
|
18
|
-
if (
|
|
24
|
+
if (isWalletRequestUnlocked(request))
|
|
25
|
+
return request[WalletRequestSymbol];
|
|
26
|
+
else
|
|
19
27
|
return undefined;
|
|
20
|
-
|
|
21
|
-
const content = getHiddenContent(request);
|
|
22
|
-
if (!content)
|
|
23
|
-
return null;
|
|
24
|
-
return JSON.parse(content);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
/** Returns the wallet service pubkey from a request */
|
|
28
|
+
}
|
|
28
29
|
export function getWalletRequestServicePubkey(request) {
|
|
29
30
|
return getTagValue(request, "p");
|
|
30
31
|
}
|
|
@@ -49,3 +50,7 @@ export function getWalletRequestEncryption(request) {
|
|
|
49
50
|
? "nip04"
|
|
50
51
|
: "nip44_v2";
|
|
51
52
|
}
|
|
53
|
+
/** Checks if an event is a valid wallet request event */
|
|
54
|
+
export function isValidWalletRequest(request) {
|
|
55
|
+
return request.kind === WALLET_REQUEST_KIND && getWalletRequestServicePubkey(request) !== undefined;
|
|
56
|
+
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import { EncryptionMethod, HiddenContentSigner } from "applesauce-core/helpers";
|
|
1
|
+
import { EncryptionMethod, HiddenContentSigner, KnownEvent, UnlockedHiddenContent } from "applesauce-core/helpers";
|
|
2
2
|
import { NostrEvent } from "nostr-tools";
|
|
3
3
|
import { WalletErrorCode } from "./error.js";
|
|
4
|
-
import { WalletMethod } from "./support.js";
|
|
5
4
|
import { NotificationType } from "./notification.js";
|
|
5
|
+
import { WalletMethod } from "./support.js";
|
|
6
6
|
export declare const WALLET_RESPONSE_KIND = 23195;
|
|
7
7
|
/** A symbol used to cache the wallet response on the event */
|
|
8
8
|
export declare const WalletResponseSymbol: unique symbol;
|
|
9
|
+
/** Type for events with unlocked hidden content */
|
|
10
|
+
export type UnlockedWalletResponse = UnlockedHiddenContent & {
|
|
11
|
+
[WalletResponseSymbol]: WalletResponse;
|
|
12
|
+
};
|
|
13
|
+
/** Type for validated wallet response events */
|
|
14
|
+
export type WalletResponseEvent = KnownEvent<typeof WALLET_RESPONSE_KIND>;
|
|
9
15
|
/** Error object for wallet responses */
|
|
10
16
|
export interface WalletResponseError {
|
|
11
17
|
type: WalletErrorCode;
|
|
@@ -127,12 +133,16 @@ export type GetInfoResponse = BaseWalletResponse<"get_info", GetInfoResult>;
|
|
|
127
133
|
/** Union type for all NIP-47 response types */
|
|
128
134
|
export type WalletResponse = PayInvoiceResponse | MultiPayInvoiceResponse | PayKeysendResponse | MultiPayKeysendResponse | MakeInvoiceResponse | LookupInvoiceResponse | ListTransactionsResponse | GetBalanceResponse | GetInfoResponse;
|
|
129
135
|
/** Checks if a kind 23195 event is locked */
|
|
130
|
-
export declare function
|
|
136
|
+
export declare function isWalletResponseUnlocked(response: any): response is UnlockedWalletResponse;
|
|
131
137
|
/** Unlocks a kind 23195 event */
|
|
132
|
-
export declare function unlockWalletResponse(response: NostrEvent, signer: HiddenContentSigner, override?: EncryptionMethod): Promise<WalletResponse | undefined
|
|
138
|
+
export declare function unlockWalletResponse(response: NostrEvent, signer: HiddenContentSigner, override?: EncryptionMethod): Promise<WalletResponse | undefined>;
|
|
133
139
|
/** Gets the wallet response from a kind 23195 event */
|
|
134
|
-
export declare function getWalletResponse(response: NostrEvent): WalletResponse | undefined
|
|
140
|
+
export declare function getWalletResponse(response: NostrEvent): WalletResponse | undefined;
|
|
135
141
|
/** Returns the client pubkey of client this response is for */
|
|
142
|
+
export declare function getWalletResponseClientPubkey(response: WalletResponseEvent): string;
|
|
136
143
|
export declare function getWalletResponseClientPubkey(response: NostrEvent): string | undefined;
|
|
137
144
|
/** Returns the request id of the request this response is for */
|
|
145
|
+
export declare function getWalletResponseRequestId(response: WalletResponseEvent): string;
|
|
138
146
|
export declare function getWalletResponseRequestId(response: NostrEvent): string | undefined;
|
|
147
|
+
/** Checks if event is a valid wallet response event */
|
|
148
|
+
export declare function isValidWalletResponse(response: NostrEvent): response is WalletResponseEvent;
|
package/dist/helpers/response.js
CHANGED
|
@@ -1,35 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getTagValue, isHiddenContentUnlocked, isNIP04Encrypted, notifyEventUpdate, setHiddenContentEncryptionMethod, unlockHiddenContent, } from "applesauce-core/helpers";
|
|
2
2
|
export const WALLET_RESPONSE_KIND = 23195;
|
|
3
3
|
// Set the encryption method to use for response kind
|
|
4
4
|
setHiddenContentEncryptionMethod(WALLET_RESPONSE_KIND, "nip04");
|
|
5
5
|
/** A symbol used to cache the wallet response on the event */
|
|
6
6
|
export const WalletResponseSymbol = Symbol("wallet-response");
|
|
7
7
|
/** Checks if a kind 23195 event is locked */
|
|
8
|
-
export function
|
|
9
|
-
return
|
|
8
|
+
export function isWalletResponseUnlocked(response) {
|
|
9
|
+
return isHiddenContentUnlocked(response) && Reflect.has(response, WalletResponseSymbol) === true;
|
|
10
10
|
}
|
|
11
11
|
/** Unlocks a kind 23195 event */
|
|
12
12
|
export async function unlockWalletResponse(response, signer, override) {
|
|
13
|
+
if (isWalletResponseUnlocked(response))
|
|
14
|
+
return response[WalletResponseSymbol];
|
|
13
15
|
const encryption = override ?? (!isNIP04Encrypted(response.content) ? "nip44" : "nip04");
|
|
14
|
-
await unlockHiddenContent(response, signer, encryption);
|
|
15
|
-
|
|
16
|
+
const content = await unlockHiddenContent(response, signer, encryption);
|
|
17
|
+
const parsed = JSON.parse(content);
|
|
18
|
+
// Save the parsed content
|
|
19
|
+
Reflect.set(response, WalletResponseSymbol, parsed);
|
|
20
|
+
notifyEventUpdate(response);
|
|
21
|
+
return parsed;
|
|
16
22
|
}
|
|
17
23
|
/** Gets the wallet response from a kind 23195 event */
|
|
18
24
|
export function getWalletResponse(response) {
|
|
19
|
-
if (
|
|
25
|
+
if (isWalletResponseUnlocked(response))
|
|
26
|
+
return response[WalletResponseSymbol];
|
|
27
|
+
else
|
|
20
28
|
return undefined;
|
|
21
|
-
return getOrComputeCachedValue(response, WalletResponseSymbol, () => {
|
|
22
|
-
const content = getHiddenContent(response);
|
|
23
|
-
if (!content)
|
|
24
|
-
return null;
|
|
25
|
-
return JSON.parse(content);
|
|
26
|
-
});
|
|
27
29
|
}
|
|
28
|
-
/** Returns the client pubkey of client this response is for */
|
|
29
30
|
export function getWalletResponseClientPubkey(response) {
|
|
30
31
|
return getTagValue(response, "p");
|
|
31
32
|
}
|
|
32
|
-
/** Returns the request id of the request this response is for */
|
|
33
33
|
export function getWalletResponseRequestId(response) {
|
|
34
34
|
return getTagValue(response, "e");
|
|
35
35
|
}
|
|
36
|
+
/** Checks if event is a valid wallet response event */
|
|
37
|
+
export function isValidWalletResponse(response) {
|
|
38
|
+
return (response.kind === WALLET_RESPONSE_KIND &&
|
|
39
|
+
getWalletResponseRequestId(response) !== undefined &&
|
|
40
|
+
getWalletResponseClientPubkey(response) !== undefined);
|
|
41
|
+
}
|
package/dist/wallet-connect.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { EncryptionMethod } from "applesauce-core/helpers";
|
|
|
2
2
|
import { EventSigner } from "applesauce-factory";
|
|
3
3
|
import { NostrEvent } from "nostr-tools";
|
|
4
4
|
import { BehaviorSubject, Observable, Subscription } from "rxjs";
|
|
5
|
-
import { GetBalanceResult, GetInfoResult, ListTransactionsResult, LookupInvoiceResult, MakeInvoiceParams, MakeInvoiceResult, NotificationType, PayInvoiceResult, PayKeysendResult, WalletAuthURI, WalletConnectEncryptionMethod, WalletConnectURI, WalletMethod, WalletNotification, WalletRequest, WalletResponse, WalletSupport } from "./helpers/index.js";
|
|
5
|
+
import { GetBalanceResult, GetInfoResult, ListTransactionsResult, LookupInvoiceResult, MakeInvoiceParams, MakeInvoiceResult, NotificationType, PayInvoiceResult, PayKeysendResult, WalletAuthURI, WalletConnectEncryptionMethod, WalletConnectURI, WalletMethod, WalletNotification, WalletNotificationEvent, WalletRequest, WalletResponse, WalletResponseEvent, WalletSupport } from "./helpers/index.js";
|
|
6
6
|
import { NostrConnectionMethodsOptions, NostrPool, NostrPublishMethod, NostrSubscriptionMethod } from "./interop.js";
|
|
7
7
|
export type SerializedWalletConnect = WalletConnectURI;
|
|
8
8
|
export type WalletConnectOptions = NostrConnectionMethodsOptions & {
|
|
@@ -48,9 +48,9 @@ export declare class WalletConnect {
|
|
|
48
48
|
protected waitForService$: Observable<string>;
|
|
49
49
|
constructor(options: WalletConnectOptions);
|
|
50
50
|
/** Process response events and return WalletResponse or throw error */
|
|
51
|
-
protected handleResponseEvent(event:
|
|
51
|
+
protected handleResponseEvent(event: WalletResponseEvent, encryption?: EncryptionMethod): Promise<WalletResponse>;
|
|
52
52
|
/** Handle notification events */
|
|
53
|
-
protected handleNotificationEvent(event:
|
|
53
|
+
protected handleNotificationEvent(event: WalletNotificationEvent): Promise<WalletNotification>;
|
|
54
54
|
/** Core RPC method that makes a request and returns the response */
|
|
55
55
|
request(request: WalletRequest, options?: {
|
|
56
56
|
timeout?: number;
|
package/dist/wallet-connect.js
CHANGED
|
@@ -2,10 +2,10 @@ 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, 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
|
-
import { createWalletAuthURI, getPreferredEncryption,
|
|
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";
|
|
9
9
|
import { getConnectionMethods, } from "./interop.js";
|
|
10
10
|
export class WalletConnect {
|
|
11
11
|
/** A fallback method to use for subscriptionMethod if none is passed in when creating the client */
|
|
@@ -103,19 +103,24 @@ export class WalletConnect {
|
|
|
103
103
|
resetOnRefCountZero: () => timer(60000), // Keep info observable around for 1 minute after last unsubscribe
|
|
104
104
|
}));
|
|
105
105
|
this.encryption$ = this.support$.pipe(map((info) => (info ? getPreferredEncryption(info) : "nip04")));
|
|
106
|
-
this.notifications$ = this.events$.pipe(filter((event) => event
|
|
107
|
-
this.waitForService$ =
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
106
|
+
this.notifications$ = this.events$.pipe(filter((event) => isValidWalletNotification(event)), mergeMap((event) => this.handleNotificationEvent(event)));
|
|
107
|
+
this.waitForService$ = defer(() =>
|
|
108
|
+
// If service is already set, return it
|
|
109
|
+
this.service$.value
|
|
110
|
+
? of(this.service$.value)
|
|
111
|
+
: // Otherwise listen for new wallet info events
|
|
112
|
+
this.events$.pipe(
|
|
113
|
+
// Only listen for wallet info events
|
|
114
|
+
filter((event) => event.kind === WALLET_INFO_KIND),
|
|
115
|
+
// Set the service to the pubkey of the wallet info event
|
|
116
|
+
tap((event) => {
|
|
117
|
+
// Set the service to the pubkey of the wallet info event
|
|
118
|
+
this.service$.next(event.pubkey);
|
|
119
|
+
}),
|
|
120
|
+
// Get the service pubkey from the event
|
|
121
|
+
map((event) => event.pubkey),
|
|
122
|
+
// Complete after the first value
|
|
123
|
+
take(1))).pipe(
|
|
119
124
|
// Only create a single subscription to avoid multiple side effects
|
|
120
125
|
share());
|
|
121
126
|
}
|
|
@@ -126,11 +131,7 @@ export class WalletConnect {
|
|
|
126
131
|
const requestId = getWalletResponseRequestId(event);
|
|
127
132
|
if (!requestId)
|
|
128
133
|
throw new Error("Response missing request ID");
|
|
129
|
-
|
|
130
|
-
if (isWalletResponseLocked(event))
|
|
131
|
-
response = await unlockWalletResponse(event, this.signer, encryption);
|
|
132
|
-
else
|
|
133
|
-
response = getWalletResponse(event);
|
|
134
|
+
const response = await unlockWalletResponse(event, this.signer, encryption);
|
|
134
135
|
if (!response)
|
|
135
136
|
throw new Error("Failed to decrypt or parse response");
|
|
136
137
|
return response;
|
|
@@ -139,11 +140,7 @@ export class WalletConnect {
|
|
|
139
140
|
async handleNotificationEvent(event) {
|
|
140
141
|
if (!verifyEvent(event))
|
|
141
142
|
throw new Error("Invalid notification event signature");
|
|
142
|
-
|
|
143
|
-
if (isWalletNotificationLocked(event))
|
|
144
|
-
notification = await unlockWalletNotification(event, this.signer);
|
|
145
|
-
else
|
|
146
|
-
notification = getWalletNotification(event);
|
|
143
|
+
const notification = await unlockWalletNotification(event, this.signer);
|
|
147
144
|
if (!notification)
|
|
148
145
|
throw new Error("Failed to decrypt or parse notification");
|
|
149
146
|
return notification;
|
|
@@ -167,7 +164,7 @@ export class WalletConnect {
|
|
|
167
164
|
// Create an observable that publishes the request event when subscribed to
|
|
168
165
|
const request$ = defer(() => from(this.publishMethod(this.relays, requestEvent))).pipe(ignoreElements());
|
|
169
166
|
// Create an observable that listens for response events
|
|
170
|
-
const responses$ = this.events$.pipe(filter((response) =>
|
|
167
|
+
const responses$ = this.events$.pipe(filter(isValidWalletResponse), filter((response) => getWalletResponseRequestId(response) === requestEvent.id), mergeMap((response) => this.handleResponseEvent(response, encryption)),
|
|
171
168
|
// Set timeout for response events
|
|
172
169
|
simpleTimeout(options.timeout || this.defaultTimeout));
|
|
173
170
|
return merge(request$, responses$);
|
package/dist/wallet-service.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { EventSigner } from "applesauce-factory";
|
|
2
|
-
import { NostrEvent } from "nostr-tools";
|
|
3
2
|
import { Observable, Subscription } from "rxjs";
|
|
4
3
|
import { WalletAuthURI } from "./helpers/auth-uri.js";
|
|
5
4
|
import { WalletErrorCode } from "./helpers/error.js";
|
|
6
5
|
import { NotificationType, WalletNotification } from "./helpers/notification.js";
|
|
7
|
-
import { GetBalanceParams, GetInfoParams, ListTransactionsParams, LookupInvoiceParams, MakeInvoiceParams, MultiPayInvoiceParams, MultiPayKeysendParams, PayInvoiceParams, PayKeysendParams, WalletRequest } from "./helpers/request.js";
|
|
6
|
+
import { GetBalanceParams, GetInfoParams, ListTransactionsParams, LookupInvoiceParams, MakeInvoiceParams, MultiPayInvoiceParams, MultiPayKeysendParams, PayInvoiceParams, PayKeysendParams, WalletRequest, WalletRequestEvent } from "./helpers/request.js";
|
|
8
7
|
import { GetBalanceResult, GetInfoResult, ListTransactionsResult, LookupInvoiceResult, MakeInvoiceResult, MultiPayInvoiceResult, MultiPayKeysendResult, PayInvoiceResult, PayKeysendResult, WalletResponse } from "./helpers/response.js";
|
|
9
8
|
import { WalletSupport } from "./helpers/support.js";
|
|
10
9
|
import { NostrConnectionMethodsOptions, NostrPool, NostrPublishMethod, NostrSubscriptionMethod } from "./interop.js";
|
|
@@ -83,11 +82,11 @@ export declare class WalletService {
|
|
|
83
82
|
/** The service's public key */
|
|
84
83
|
pubkey: string | null;
|
|
85
84
|
/** The client's secret key */
|
|
86
|
-
protected secret
|
|
85
|
+
protected secret?: Uint8Array;
|
|
87
86
|
/** The client's public key */
|
|
88
87
|
client: string;
|
|
89
88
|
/** Shared observable for all wallet request events */
|
|
90
|
-
protected events$: Observable<
|
|
89
|
+
protected events$: Observable<WalletRequestEvent> | null;
|
|
91
90
|
/** Subscription to the events observable */
|
|
92
91
|
protected subscription: Subscription | null;
|
|
93
92
|
/** Whether the service is currently running */
|
|
@@ -106,15 +105,15 @@ export declare class WalletService {
|
|
|
106
105
|
/** Publish the wallet support event */
|
|
107
106
|
protected publishSupportEvent(): Promise<void>;
|
|
108
107
|
/** Handle a wallet request event */
|
|
109
|
-
protected handleRequestEvent(requestEvent:
|
|
108
|
+
protected handleRequestEvent(requestEvent: WalletRequestEvent): Promise<void>;
|
|
110
109
|
/** Process a decrypted wallet request */
|
|
111
|
-
protected processRequest(requestEvent:
|
|
110
|
+
protected processRequest(requestEvent: WalletRequestEvent, request: WalletRequest): Promise<void>;
|
|
112
111
|
/** Send a success response */
|
|
113
|
-
protected sendSuccessResponse<T extends WalletResponse>(requestEvent:
|
|
112
|
+
protected sendSuccessResponse<T extends WalletResponse>(requestEvent: WalletRequestEvent, method: T["result_type"], result: T["result"]): Promise<void>;
|
|
114
113
|
/** Send an error response */
|
|
115
|
-
protected sendErrorResponse(requestEvent:
|
|
114
|
+
protected sendErrorResponse(requestEvent: WalletRequestEvent, errorType: WalletErrorCode, errorMessage: string): Promise<void>;
|
|
116
115
|
/** Send a response event */
|
|
117
|
-
protected sendResponse(requestEvent:
|
|
116
|
+
protected sendResponse(requestEvent: WalletRequestEvent, response: WalletResponse): Promise<void>;
|
|
118
117
|
/** Creates a service for a nostr+walletauth URI */
|
|
119
118
|
static fromAuthURI(uri: string | WalletAuthURI, options: Omit<WalletServiceOptions, "relays">): WalletService;
|
|
120
119
|
}
|
package/dist/wallet-service.js
CHANGED
|
@@ -8,7 +8,7 @@ import { WalletResponseBlueprint } from "./blueprints/response.js";
|
|
|
8
8
|
import { WalletSupportBlueprint } from "./blueprints/support.js";
|
|
9
9
|
import { parseWalletAuthURI } from "./helpers/auth-uri.js";
|
|
10
10
|
import { WalletBaseError } from "./helpers/error.js";
|
|
11
|
-
import { getWalletRequest,
|
|
11
|
+
import { getWalletRequest, isValidWalletRequest, isWalletRequestExpired, unlockWalletRequest, WALLET_REQUEST_KIND, } from "./helpers/request.js";
|
|
12
12
|
import { getConnectionMethods, } from "./interop.js";
|
|
13
13
|
/** NIP-47 Wallet Service implementation */
|
|
14
14
|
export class WalletService {
|
|
@@ -49,10 +49,16 @@ export class WalletService {
|
|
|
49
49
|
this.handlers = options.handlers;
|
|
50
50
|
// Set the client's secret and public key
|
|
51
51
|
if (options.secret) {
|
|
52
|
+
// Service was created with a custom secret
|
|
52
53
|
this.secret = options.secret;
|
|
53
54
|
this.client = getPublicKey(this.secret);
|
|
54
55
|
}
|
|
56
|
+
else if (options.client) {
|
|
57
|
+
// Service was restored with only the clients pubkey
|
|
58
|
+
this.client = options.client;
|
|
59
|
+
}
|
|
55
60
|
else {
|
|
61
|
+
// Generate secret and client pubkey
|
|
56
62
|
this.secret = generateSecretKey();
|
|
57
63
|
this.client = getPublicKey(this.secret);
|
|
58
64
|
}
|
|
@@ -98,7 +104,9 @@ export class WalletService {
|
|
|
98
104
|
// Ignore strings (support for applesauce-relay)
|
|
99
105
|
filter((event) => typeof event !== "string"),
|
|
100
106
|
// Only include valid wallet request events
|
|
101
|
-
filter(
|
|
107
|
+
filter(isValidWalletRequest),
|
|
108
|
+
// Ensure they are to our pubkey
|
|
109
|
+
filter((event) => event.pubkey === this.client),
|
|
102
110
|
// Verify event signature
|
|
103
111
|
filter((event) => verifyEvent(event)),
|
|
104
112
|
// Only create a single subscription to the relays
|
|
@@ -129,6 +137,8 @@ export class WalletService {
|
|
|
129
137
|
}
|
|
130
138
|
/** Get the connection URI for the service */
|
|
131
139
|
getConnectURI() {
|
|
140
|
+
if (!this.secret)
|
|
141
|
+
throw new Error("Service was not created with a secret");
|
|
132
142
|
if (!this.pubkey)
|
|
133
143
|
throw new Error("Service is not running");
|
|
134
144
|
if (!this.relays.length)
|
|
@@ -168,13 +178,7 @@ export class WalletService {
|
|
|
168
178
|
if (isWalletRequestExpired(requestEvent))
|
|
169
179
|
return await this.sendErrorResponse(requestEvent, "OTHER", "Request has expired");
|
|
170
180
|
// Unlock the request if needed
|
|
171
|
-
|
|
172
|
-
if (isWalletRequestLocked(requestEvent)) {
|
|
173
|
-
request = await unlockWalletRequest(requestEvent, this.signer);
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
request = getWalletRequest(requestEvent);
|
|
177
|
-
}
|
|
181
|
+
const request = await unlockWalletRequest(requestEvent, this.signer);
|
|
178
182
|
if (!request)
|
|
179
183
|
return await this.sendErrorResponse(requestEvent, "OTHER", "Failed to decrypt or parse request");
|
|
180
184
|
// Handle the request based on its method
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "applesauce-wallet-connect",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -58,23 +58,25 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"applesauce-core": "^3.1.0",
|
|
62
|
-
"applesauce-factory": "^3.1.0",
|
|
63
|
-
"nostr-tools": "~2.15",
|
|
64
61
|
"@noble/hashes": "^1.7.1",
|
|
62
|
+
"applesauce-core": "^4.0.0",
|
|
63
|
+
"applesauce-factory": "^4.0.0",
|
|
64
|
+
"nostr-tools": "~2.17",
|
|
65
65
|
"rxjs": "^7.8.1"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@hirez_io/observer-spy": "^2.2.0",
|
|
69
69
|
"@types/debug": "^4.1.12",
|
|
70
|
+
"rimraf": "^6.0.1",
|
|
70
71
|
"typescript": "^5.8.3",
|
|
71
|
-
"vitest": "^3.2.
|
|
72
|
+
"vitest": "^3.2.4"
|
|
72
73
|
},
|
|
73
74
|
"funding": {
|
|
74
75
|
"type": "lightning",
|
|
75
76
|
"url": "lightning:nostrudel@geyser.fund"
|
|
76
77
|
},
|
|
77
78
|
"scripts": {
|
|
79
|
+
"prebuild": "rimraf dist",
|
|
78
80
|
"build": "tsc",
|
|
79
81
|
"watch:build": "tsc --watch > /dev/null",
|
|
80
82
|
"test": "vitest run --passWithNoTests",
|