applesauce-wallet-connect 0.0.0-next-20250808173123 → 0.0.0-next-20250828144630
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 +3 -3
- package/dist/blueprints/support.d.ts +1 -1
- package/dist/blueprints/support.js +4 -2
- package/dist/helpers/auth-uri.d.ts +44 -0
- package/dist/helpers/auth-uri.js +113 -0
- package/dist/helpers/connect-uri.d.ts +5 -0
- package/dist/helpers/connect-uri.js +6 -2
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interop.d.ts +35 -0
- package/dist/interop.js +19 -0
- package/dist/types.d.ts +5 -0
- package/dist/wallet-connect.d.ts +25 -14
- package/dist/wallet-connect.js +95 -34
- package/dist/wallet-service.d.ts +19 -10
- package/dist/wallet-service.js +40 -20
- package/package.json +4 -4
- package/dist/actions/index.d.ts +0 -1
- package/dist/actions/index.js +0 -1
- package/dist/actions/tokens.d.ts +0 -17
- package/dist/actions/tokens.js +0 -110
- package/dist/actions/wallet.d.ts +0 -13
- package/dist/actions/wallet.js +0 -64
- package/dist/actions/zap-info.d.ts +0 -22
- package/dist/actions/zap-info.js +0 -83
- package/dist/actions/zaps.d.ts +0 -8
- package/dist/actions/zaps.js +0 -30
- package/dist/blueprints/history.d.ts +0 -4
- package/dist/blueprints/history.js +0 -11
- package/dist/blueprints/info.d.ts +0 -4
- package/dist/blueprints/info.js +0 -8
- package/dist/blueprints/tokens.d.ts +0 -7
- package/dist/blueprints/tokens.js +0 -11
- package/dist/blueprints/wallet.d.ts +0 -5
- package/dist/blueprints/wallet.js +0 -11
- package/dist/blueprints/zaps.d.ts +0 -8
- package/dist/blueprints/zaps.js +0 -12
- package/dist/helpers/animated-qr.d.ts +0 -30
- package/dist/helpers/animated-qr.js +0 -71
- package/dist/helpers/history.d.ts +0 -26
- package/dist/helpers/history.js +0 -47
- package/dist/helpers/info.d.ts +0 -34
- package/dist/helpers/info.js +0 -97
- package/dist/helpers/methods.d.ts +0 -1
- package/dist/helpers/methods.js +0 -1
- package/dist/helpers/nutzap.d.ts +0 -27
- package/dist/helpers/nutzap.js +0 -66
- package/dist/helpers/tokens.d.ts +0 -58
- package/dist/helpers/tokens.js +0 -162
- package/dist/helpers/wallet.d.ts +0 -15
- package/dist/helpers/wallet.js +0 -41
- package/dist/helpers/zap-info.d.ts +0 -19
- package/dist/helpers/zap-info.js +0 -42
- package/dist/interface.d.ts +0 -6
- package/dist/interface.js +0 -1
- package/dist/models/history.d.ts +0 -6
- package/dist/models/history.js +0 -21
- package/dist/models/index.d.ts +0 -4
- package/dist/models/index.js +0 -4
- package/dist/models/nutzap.d.ts +0 -6
- package/dist/models/nutzap.js +0 -16
- package/dist/models/tokens.d.ts +0 -6
- package/dist/models/tokens.js +0 -58
- package/dist/models/wallet.d.ts +0 -13
- package/dist/models/wallet.js +0 -18
- package/dist/operations/history.d.ts +0 -7
- package/dist/operations/history.js +0 -34
- package/dist/operations/index.d.ts +0 -5
- package/dist/operations/index.js +0 -5
- package/dist/operations/nutzap.d.ts +0 -14
- package/dist/operations/nutzap.js +0 -33
- package/dist/operations/tokens.d.ts +0 -4
- package/dist/operations/tokens.js +0 -24
- package/dist/operations/wallet.d.ts +0 -8
- package/dist/operations/wallet.js +0 -30
- package/dist/operations/zap-info.d.ts +0 -10
- package/dist/operations/zap-info.js +0 -17
package/dist/wallet-service.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { EventSigner } from "applesauce-factory";
|
|
2
2
|
import { NostrEvent } from "nostr-tools";
|
|
3
3
|
import { Observable, Subscription } from "rxjs";
|
|
4
|
+
import { WalletAuthURI } from "./helpers/auth-uri.js";
|
|
4
5
|
import { WalletErrorCode } from "./helpers/error.js";
|
|
5
6
|
import { NotificationType, WalletNotification } from "./helpers/notification.js";
|
|
6
7
|
import { GetBalanceParams, GetInfoParams, ListTransactionsParams, LookupInvoiceParams, MakeInvoiceParams, MultiPayInvoiceParams, MultiPayKeysendParams, PayInvoiceParams, PayKeysendParams, WalletRequest } from "./helpers/request.js";
|
|
7
8
|
import { GetBalanceResult, GetInfoResult, ListTransactionsResult, LookupInvoiceResult, MakeInvoiceResult, MultiPayInvoiceResult, MultiPayKeysendResult, PayInvoiceResult, PayKeysendResult, WalletResponse } from "./helpers/response.js";
|
|
8
9
|
import { WalletSupport } from "./helpers/support.js";
|
|
9
|
-
import { NostrPublishMethod, NostrSubscriptionMethod } from "./
|
|
10
|
+
import { NostrConnectionMethodsOptions, NostrPool, NostrPublishMethod, NostrSubscriptionMethod } from "./interop.js";
|
|
10
11
|
/** Handler function for pay_invoice method */
|
|
11
12
|
export type PayInvoiceHandler = (params: PayInvoiceParams) => Promise<PayInvoiceResult>;
|
|
12
13
|
/** Handler function for multi_pay_invoice method */
|
|
@@ -37,22 +38,26 @@ export interface WalletServiceHandlers {
|
|
|
37
38
|
get_balance?: GetBalanceHandler;
|
|
38
39
|
get_info?: GetInfoHandler;
|
|
39
40
|
}
|
|
41
|
+
export type SerializedWalletService = {
|
|
42
|
+
/** The client's public key */
|
|
43
|
+
client: string;
|
|
44
|
+
/** The relays to use for the service */
|
|
45
|
+
relays: string[];
|
|
46
|
+
};
|
|
40
47
|
/** Options for creating a WalletService */
|
|
41
|
-
export interface WalletServiceOptions {
|
|
48
|
+
export interface WalletServiceOptions extends NostrConnectionMethodsOptions {
|
|
42
49
|
/** The relays to use for the service */
|
|
43
50
|
relays: string[];
|
|
44
51
|
/** The signer to use for creating and unlocking events */
|
|
45
52
|
signer: EventSigner;
|
|
46
53
|
/** The client's secret key */
|
|
47
54
|
secret?: Uint8Array;
|
|
55
|
+
/** The client's public key (used for restoring the service) */
|
|
56
|
+
client?: string;
|
|
48
57
|
/** Map of method handlers */
|
|
49
58
|
handlers: WalletServiceHandlers;
|
|
50
59
|
/** An array of notifications this wallet supports */
|
|
51
60
|
notifications?: NotificationType[];
|
|
52
|
-
/** An optional method for subscribing to relays */
|
|
53
|
-
subscriptionMethod?: NostrSubscriptionMethod;
|
|
54
|
-
/** An optional method for publishing events */
|
|
55
|
-
publishMethod?: NostrPublishMethod;
|
|
56
61
|
}
|
|
57
62
|
/** NIP-47 Wallet Service implementation */
|
|
58
63
|
export declare class WalletService {
|
|
@@ -60,6 +65,8 @@ export declare class WalletService {
|
|
|
60
65
|
static subscriptionMethod: NostrSubscriptionMethod | undefined;
|
|
61
66
|
/** A fallback method to use for publishMethod if none is passed in when creating the client */
|
|
62
67
|
static publishMethod: NostrPublishMethod | undefined;
|
|
68
|
+
/** A fallback pool to use if none is pass in when creating the signer */
|
|
69
|
+
static pool: NostrPool | undefined;
|
|
63
70
|
/** A method for subscribing to relays */
|
|
64
71
|
protected readonly subscriptionMethod: NostrSubscriptionMethod;
|
|
65
72
|
/** A method for publishing events */
|
|
@@ -77,14 +84,14 @@ export declare class WalletService {
|
|
|
77
84
|
pubkey: string | null;
|
|
78
85
|
/** The client's secret key */
|
|
79
86
|
protected secret: Uint8Array;
|
|
87
|
+
/** The client's public key */
|
|
88
|
+
client: string;
|
|
80
89
|
/** Shared observable for all wallet request events */
|
|
81
90
|
protected events$: Observable<NostrEvent> | null;
|
|
82
91
|
/** Subscription to the events observable */
|
|
83
92
|
protected subscription: Subscription | null;
|
|
84
93
|
/** Whether the service is currently running */
|
|
85
94
|
running: boolean;
|
|
86
|
-
/** Get the clients public key */
|
|
87
|
-
get client(): string;
|
|
88
95
|
constructor(options: WalletServiceOptions);
|
|
89
96
|
/** Start the wallet service */
|
|
90
97
|
start(): Promise<void>;
|
|
@@ -92,8 +99,8 @@ export declare class WalletService {
|
|
|
92
99
|
stop(): void;
|
|
93
100
|
/** Check if the service is running */
|
|
94
101
|
isRunning(): boolean;
|
|
95
|
-
/** Get the connection
|
|
96
|
-
|
|
102
|
+
/** Get the connection URI for the service */
|
|
103
|
+
getConnectURI(): string;
|
|
97
104
|
/** Send a notification to the client */
|
|
98
105
|
notify<T extends WalletNotification>(type: T["notification_type"], notification: T["notification"], legacy?: boolean): Promise<void>;
|
|
99
106
|
/** Publish the wallet support event */
|
|
@@ -108,4 +115,6 @@ export declare class WalletService {
|
|
|
108
115
|
protected sendErrorResponse(requestEvent: NostrEvent, errorType: WalletErrorCode, errorMessage: string): Promise<void>;
|
|
109
116
|
/** Send a response event */
|
|
110
117
|
protected sendResponse(requestEvent: NostrEvent, response: WalletResponse): Promise<void>;
|
|
118
|
+
/** Creates a service for a nostr+walletauth URI */
|
|
119
|
+
static fromAuthURI(uri: string | WalletAuthURI, options: Omit<WalletServiceOptions, "relays">): WalletService;
|
|
111
120
|
}
|
package/dist/wallet-service.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { logger } from "applesauce-core";
|
|
2
2
|
import { create } from "applesauce-factory";
|
|
3
3
|
import { generateSecretKey, getPublicKey, verifyEvent } from "nostr-tools";
|
|
4
|
-
import { filter, mergeMap, share } from "rxjs";
|
|
4
|
+
import { filter, from, mergeMap, repeat, retry, share } from "rxjs";
|
|
5
|
+
import { bytesToHex } from "@noble/hashes/utils";
|
|
5
6
|
import { WalletLegacyNotificationBlueprint, WalletNotificationBlueprint } from "./blueprints/notification.js";
|
|
6
7
|
import { WalletResponseBlueprint } from "./blueprints/response.js";
|
|
7
8
|
import { WalletSupportBlueprint } from "./blueprints/support.js";
|
|
9
|
+
import { parseWalletAuthURI } from "./helpers/auth-uri.js";
|
|
8
10
|
import { WalletBaseError } from "./helpers/error.js";
|
|
9
11
|
import { getWalletRequest, isWalletRequestExpired, isWalletRequestLocked, unlockWalletRequest, WALLET_REQUEST_KIND, } from "./helpers/request.js";
|
|
10
|
-
import {
|
|
12
|
+
import { getConnectionMethods, } from "./interop.js";
|
|
11
13
|
/** NIP-47 Wallet Service implementation */
|
|
12
14
|
export class WalletService {
|
|
13
15
|
/** A fallback method to use for subscriptionMethod if none is passed in when creating the client */
|
|
14
16
|
static subscriptionMethod = undefined;
|
|
15
17
|
/** A fallback method to use for publishMethod if none is passed in when creating the client */
|
|
16
18
|
static publishMethod = undefined;
|
|
19
|
+
/** A fallback pool to use if none is pass in when creating the signer */
|
|
20
|
+
static pool = undefined;
|
|
17
21
|
/** A method for subscribing to relays */
|
|
18
22
|
subscriptionMethod;
|
|
19
23
|
/** A method for publishing events */
|
|
@@ -31,29 +35,32 @@ export class WalletService {
|
|
|
31
35
|
pubkey = null;
|
|
32
36
|
/** The client's secret key */
|
|
33
37
|
secret;
|
|
38
|
+
/** The client's public key */
|
|
39
|
+
client;
|
|
34
40
|
/** Shared observable for all wallet request events */
|
|
35
41
|
events$ = null;
|
|
36
42
|
/** Subscription to the events observable */
|
|
37
43
|
subscription = null;
|
|
38
44
|
/** Whether the service is currently running */
|
|
39
45
|
running = false;
|
|
40
|
-
/** Get the clients public key */
|
|
41
|
-
get client() {
|
|
42
|
-
return getPublicKey(this.secret);
|
|
43
|
-
}
|
|
44
46
|
constructor(options) {
|
|
45
47
|
this.relays = options.relays;
|
|
46
48
|
this.signer = options.signer;
|
|
47
49
|
this.handlers = options.handlers;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
// Set the client's secret and public key
|
|
51
|
+
if (options.secret) {
|
|
52
|
+
this.secret = options.secret;
|
|
53
|
+
this.client = getPublicKey(this.secret);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.secret = generateSecretKey();
|
|
57
|
+
this.client = getPublicKey(this.secret);
|
|
58
|
+
}
|
|
59
|
+
// Get the subscription and publish methods
|
|
60
|
+
const { subscriptionMethod, publishMethod } = getConnectionMethods(options, WalletService);
|
|
61
|
+
// Use arrow functions so "this" isn't bound to the signer
|
|
62
|
+
this.subscriptionMethod = (relays, filters) => subscriptionMethod(relays, filters);
|
|
63
|
+
this.publishMethod = (relays, event) => publishMethod(relays, event);
|
|
57
64
|
const encryption = [];
|
|
58
65
|
if (options.signer.nip04)
|
|
59
66
|
encryption.push("nip04");
|
|
@@ -77,13 +84,17 @@ export class WalletService {
|
|
|
77
84
|
// Get our public key
|
|
78
85
|
this.pubkey = await this.signer.getPublicKey();
|
|
79
86
|
// Create shared request observable with ref counting and timer
|
|
80
|
-
this.events$ = this.subscriptionMethod(this.relays, [
|
|
87
|
+
this.events$ = from(this.subscriptionMethod(this.relays, [
|
|
81
88
|
{
|
|
82
89
|
kinds: [WALLET_REQUEST_KIND],
|
|
83
90
|
"#p": [this.pubkey], // Only requests directed to us
|
|
84
91
|
authors: [this.client], // Only requests from the client
|
|
85
92
|
},
|
|
86
|
-
]).pipe(
|
|
93
|
+
])).pipe(
|
|
94
|
+
// Keep the connection open indefinitely
|
|
95
|
+
repeat(),
|
|
96
|
+
// Retry on connection failure
|
|
97
|
+
retry(),
|
|
87
98
|
// Ignore strings (support for applesauce-relay)
|
|
88
99
|
filter((event) => typeof event !== "string"),
|
|
89
100
|
// Only include valid wallet request events
|
|
@@ -116,8 +127,8 @@ export class WalletService {
|
|
|
116
127
|
isRunning() {
|
|
117
128
|
return this.running;
|
|
118
129
|
}
|
|
119
|
-
/** Get the connection
|
|
120
|
-
|
|
130
|
+
/** Get the connection URI for the service */
|
|
131
|
+
getConnectURI() {
|
|
121
132
|
if (!this.pubkey)
|
|
122
133
|
throw new Error("Service is not running");
|
|
123
134
|
if (!this.relays.length)
|
|
@@ -141,7 +152,7 @@ export class WalletService {
|
|
|
141
152
|
/** Publish the wallet support event */
|
|
142
153
|
async publishSupportEvent() {
|
|
143
154
|
try {
|
|
144
|
-
const draft = await create({ signer: this.signer }, WalletSupportBlueprint, this.support);
|
|
155
|
+
const draft = await create({ signer: this.signer }, WalletSupportBlueprint, this.support, this.client);
|
|
145
156
|
const event = await this.signer.signEvent(draft);
|
|
146
157
|
await this.publishMethod(this.relays, event);
|
|
147
158
|
}
|
|
@@ -267,4 +278,13 @@ export class WalletService {
|
|
|
267
278
|
throw error;
|
|
268
279
|
}
|
|
269
280
|
}
|
|
281
|
+
/** Creates a service for a nostr+walletauth URI */
|
|
282
|
+
static fromAuthURI(uri, options) {
|
|
283
|
+
const { client, relays } = typeof uri === "string" ? parseWalletAuthURI(uri) : uri;
|
|
284
|
+
return new WalletService({
|
|
285
|
+
...options,
|
|
286
|
+
client,
|
|
287
|
+
relays,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
270
290
|
}
|
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-20250828144630",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"applesauce-core": "0.0.0-next-
|
|
62
|
-
"applesauce-factory": "0.0.0-next-
|
|
63
|
-
"nostr-tools": "
|
|
61
|
+
"applesauce-core": "0.0.0-next-20250828144630",
|
|
62
|
+
"applesauce-factory": "0.0.0-next-20250828144630",
|
|
63
|
+
"nostr-tools": "~2.15",
|
|
64
64
|
"@noble/hashes": "^1.7.1",
|
|
65
65
|
"rxjs": "^7.8.1"
|
|
66
66
|
},
|
package/dist/actions/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/actions/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/actions/tokens.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Token } from "@cashu/cashu-ts";
|
|
2
|
-
import { Action } from "applesauce-actions";
|
|
3
|
-
import { NostrEvent } from "nostr-tools";
|
|
4
|
-
/**
|
|
5
|
-
* Adds a cashu token to the wallet and marks a list of nutzaps as redeemed
|
|
6
|
-
* @param token the cashu token to add
|
|
7
|
-
* @param redeemed an array of nutzap event ids to mark as redeemed
|
|
8
|
-
*/
|
|
9
|
-
export declare function ReceiveToken(token: Token, redeemed?: string[], fee?: number): Action;
|
|
10
|
-
/** An action that deletes old tokens and creates a new one but does not add a history event */
|
|
11
|
-
export declare function RolloverTokens(tokens: NostrEvent[], token: Token): Action;
|
|
12
|
-
/** An action that deletes old token events and adds a spend history item */
|
|
13
|
-
export declare function CompleteSpend(spent: NostrEvent[], change: Token): Action;
|
|
14
|
-
/** Combines all unlocked token events into a single event per mint */
|
|
15
|
-
export declare function ConsolidateTokens(opts?: {
|
|
16
|
-
ignoreLocked?: boolean;
|
|
17
|
-
}): Action;
|
package/dist/actions/tokens.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { CashuMint, CashuWallet, CheckStateEnum } from "@cashu/cashu-ts";
|
|
2
|
-
import { DeleteBlueprint } from "applesauce-factory/blueprints";
|
|
3
|
-
import { getTokenContent, ignoreDuplicateProofs, isTokenContentLocked, WALLET_TOKEN_KIND } from "../helpers/tokens.js";
|
|
4
|
-
import { WalletTokenBlueprint } from "../blueprints/tokens.js";
|
|
5
|
-
import { WalletHistoryBlueprint } from "../blueprints/history.js";
|
|
6
|
-
/**
|
|
7
|
-
* Adds a cashu token to the wallet and marks a list of nutzaps as redeemed
|
|
8
|
-
* @param token the cashu token to add
|
|
9
|
-
* @param redeemed an array of nutzap event ids to mark as redeemed
|
|
10
|
-
*/
|
|
11
|
-
export function ReceiveToken(token, redeemed, fee) {
|
|
12
|
-
return async function* ({ factory }) {
|
|
13
|
-
const amount = token.proofs.reduce((t, p) => t + p.amount, 0);
|
|
14
|
-
const tokenEvent = await factory.sign(await factory.create(WalletTokenBlueprint, token, []));
|
|
15
|
-
const history = await factory.sign(await factory.create(WalletHistoryBlueprint, { direction: "in", amount, mint: token.mint, created: [tokenEvent.id], fee }, redeemed ?? []));
|
|
16
|
-
yield tokenEvent;
|
|
17
|
-
yield history;
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
/** An action that deletes old tokens and creates a new one but does not add a history event */
|
|
21
|
-
export function RolloverTokens(tokens, token) {
|
|
22
|
-
return async function* ({ factory }) {
|
|
23
|
-
// create a delete event for old tokens
|
|
24
|
-
const deleteDraft = await factory.create(DeleteBlueprint, tokens);
|
|
25
|
-
// create a new token event
|
|
26
|
-
const tokenDraft = await factory.create(WalletTokenBlueprint, token, tokens.map((e) => e.id));
|
|
27
|
-
// sign events
|
|
28
|
-
const signedDelete = await factory.sign(deleteDraft);
|
|
29
|
-
const signedToken = await factory.sign(tokenDraft);
|
|
30
|
-
// publish events
|
|
31
|
-
yield signedDelete;
|
|
32
|
-
yield signedToken;
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/** An action that deletes old token events and adds a spend history item */
|
|
36
|
-
export function CompleteSpend(spent, change) {
|
|
37
|
-
return async function* ({ factory }) {
|
|
38
|
-
if (spent.length === 0)
|
|
39
|
-
throw new Error("Cant complete spent with no token events");
|
|
40
|
-
if (spent.some((s) => isTokenContentLocked(s)))
|
|
41
|
-
throw new Error("Cant complete spend with locked tokens");
|
|
42
|
-
// create the nip-09 delete event for previous events
|
|
43
|
-
const deleteDraft = await factory.create(DeleteBlueprint, spent);
|
|
44
|
-
const changeAmount = change.proofs.reduce((t, p) => t + p.amount, 0);
|
|
45
|
-
// create a new token event if needed
|
|
46
|
-
const changeDraft = changeAmount > 0
|
|
47
|
-
? await factory.create(WalletTokenBlueprint, change, spent.map((e) => e.id))
|
|
48
|
-
: undefined;
|
|
49
|
-
const total = spent.reduce((total, token) => total + getTokenContent(token).proofs.reduce((t, p) => t + p.amount, 0), 0);
|
|
50
|
-
// calculate the amount that was spent
|
|
51
|
-
const diff = total - changeAmount;
|
|
52
|
-
// sign delete and token
|
|
53
|
-
const signedDelete = await factory.sign(deleteDraft);
|
|
54
|
-
const signedToken = changeDraft && (await factory.sign(changeDraft));
|
|
55
|
-
// create a history entry
|
|
56
|
-
const history = await factory.create(WalletHistoryBlueprint, { direction: "out", mint: change.mint, amount: diff, created: signedToken ? [signedToken.id] : [] }, []);
|
|
57
|
-
// sign history
|
|
58
|
-
const signedHistory = await factory.sign(history);
|
|
59
|
-
// publish events
|
|
60
|
-
yield signedDelete;
|
|
61
|
-
if (signedToken)
|
|
62
|
-
yield signedToken;
|
|
63
|
-
yield signedHistory;
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
/** Combines all unlocked token events into a single event per mint */
|
|
67
|
-
export function ConsolidateTokens(opts) {
|
|
68
|
-
return async function* ({ events, factory, self }) {
|
|
69
|
-
const tokens = Array.from(events.getByFilters({ kinds: [WALLET_TOKEN_KIND], authors: [self] })).filter((token) => {
|
|
70
|
-
if (isTokenContentLocked(token)) {
|
|
71
|
-
if (opts?.ignoreLocked)
|
|
72
|
-
return false;
|
|
73
|
-
else
|
|
74
|
-
throw new Error("Token is locked");
|
|
75
|
-
}
|
|
76
|
-
else
|
|
77
|
-
return true;
|
|
78
|
-
});
|
|
79
|
-
const byMint = tokens.reduce((map, token) => {
|
|
80
|
-
const mint = getTokenContent(token).mint;
|
|
81
|
-
if (!map.has(mint))
|
|
82
|
-
map.set(mint, []);
|
|
83
|
-
map.get(mint).push(token);
|
|
84
|
-
return map;
|
|
85
|
-
}, new Map());
|
|
86
|
-
// loop over each mint and consolidate proofs
|
|
87
|
-
for (const [mint, tokens] of byMint) {
|
|
88
|
-
const cashuMint = new CashuMint(mint);
|
|
89
|
-
const cashuWallet = new CashuWallet(cashuMint);
|
|
90
|
-
// get all tokens proofs
|
|
91
|
-
const proofs = tokens
|
|
92
|
-
.map((t) => getTokenContent(t).proofs)
|
|
93
|
-
.flat()
|
|
94
|
-
// filter out duplicate proofs
|
|
95
|
-
.filter(ignoreDuplicateProofs());
|
|
96
|
-
// NOTE: this assumes that the states array is the same length and order as the proofs array
|
|
97
|
-
const states = await cashuWallet.checkProofsStates(proofs);
|
|
98
|
-
const notSpent = proofs.filter((_, i) => states[i].state !== CheckStateEnum.SPENT);
|
|
99
|
-
// create delete and token event
|
|
100
|
-
const deleteDraft = await factory.create(DeleteBlueprint, tokens);
|
|
101
|
-
const tokenDraft = await factory.create(WalletTokenBlueprint, { mint, proofs: notSpent }, tokens.map((t) => t.id));
|
|
102
|
-
// sign events
|
|
103
|
-
const signedToken = await factory.sign(tokenDraft);
|
|
104
|
-
const signedDelete = await factory.sign(deleteDraft);
|
|
105
|
-
// publish events for mint
|
|
106
|
-
yield signedToken;
|
|
107
|
-
yield signedDelete;
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
}
|
package/dist/actions/wallet.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Action } from "applesauce-actions";
|
|
2
|
-
/** An action that creates a new 17375 wallet event and 375 wallet backup */
|
|
3
|
-
export declare function CreateWallet(mints: string[], privateKey?: Uint8Array): Action;
|
|
4
|
-
/**
|
|
5
|
-
* Adds a private key to a wallet event
|
|
6
|
-
* @throws if the wallet does not exist or is locked
|
|
7
|
-
*/
|
|
8
|
-
export declare function WalletAddPrivateKey(privateKey: Uint8Array): Action;
|
|
9
|
-
/** Unlocks the wallet event and optionally the tokens and history events */
|
|
10
|
-
export declare function UnlockWallet(unlock?: {
|
|
11
|
-
history?: boolean;
|
|
12
|
-
tokens?: boolean;
|
|
13
|
-
}): Action;
|
package/dist/actions/wallet.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { getWalletMints, getWalletPrivateKey, isWalletLocked, unlockWallet, WALLET_KIND } from "../helpers/wallet.js";
|
|
2
|
-
import { WalletBackupBlueprint, WalletBlueprint } from "../blueprints/wallet.js";
|
|
3
|
-
import { isTokenContentLocked, unlockTokenContent, WALLET_TOKEN_KIND } from "../helpers/tokens.js";
|
|
4
|
-
import { isHistoryContentLocked, unlockHistoryContent, WALLET_HISTORY_KIND } from "../helpers/history.js";
|
|
5
|
-
/** An action that creates a new 17375 wallet event and 375 wallet backup */
|
|
6
|
-
export function CreateWallet(mints, privateKey) {
|
|
7
|
-
return async function* ({ events, factory, self }) {
|
|
8
|
-
const existing = events.getReplaceable(WALLET_KIND, self);
|
|
9
|
-
if (existing)
|
|
10
|
-
throw new Error("Wallet already exists");
|
|
11
|
-
const wallet = await factory.sign(await factory.create(WalletBlueprint, mints, privateKey));
|
|
12
|
-
const backup = await factory.sign(await factory.create(WalletBackupBlueprint, wallet));
|
|
13
|
-
// publish the backup first
|
|
14
|
-
yield backup;
|
|
15
|
-
yield wallet;
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Adds a private key to a wallet event
|
|
20
|
-
* @throws if the wallet does not exist or is locked
|
|
21
|
-
*/
|
|
22
|
-
export function WalletAddPrivateKey(privateKey) {
|
|
23
|
-
return async function* ({ events, self, factory }) {
|
|
24
|
-
const wallet = events.getReplaceable(WALLET_KIND, self);
|
|
25
|
-
if (!wallet)
|
|
26
|
-
throw new Error("Wallet does not exist");
|
|
27
|
-
if (isWalletLocked(wallet))
|
|
28
|
-
throw new Error("Wallet is locked");
|
|
29
|
-
if (getWalletPrivateKey(wallet))
|
|
30
|
-
throw new Error("Wallet already has a private key");
|
|
31
|
-
const draft = await factory.create(WalletBlueprint, getWalletMints(wallet), privateKey);
|
|
32
|
-
const signed = await factory.sign(draft);
|
|
33
|
-
// create backup event for wallet
|
|
34
|
-
const backup = await factory.sign(await factory.create(WalletBackupBlueprint, signed));
|
|
35
|
-
// publish events
|
|
36
|
-
yield backup;
|
|
37
|
-
yield signed;
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
/** Unlocks the wallet event and optionally the tokens and history events */
|
|
41
|
-
export function UnlockWallet(unlock) {
|
|
42
|
-
return async function* ({ events, self, factory }) {
|
|
43
|
-
const signer = factory.context.signer;
|
|
44
|
-
if (!signer)
|
|
45
|
-
throw new Error("Missing signer");
|
|
46
|
-
const wallet = events.getReplaceable(WALLET_KIND, self);
|
|
47
|
-
if (!wallet)
|
|
48
|
-
throw new Error("Wallet does not exist");
|
|
49
|
-
if (isWalletLocked(wallet))
|
|
50
|
-
await unlockWallet(wallet, signer);
|
|
51
|
-
if (unlock?.tokens) {
|
|
52
|
-
const tokens = events.getTimeline({ kinds: [WALLET_TOKEN_KIND], authors: [self] });
|
|
53
|
-
for (const token of tokens)
|
|
54
|
-
if (isTokenContentLocked(token))
|
|
55
|
-
await unlockTokenContent(token, signer);
|
|
56
|
-
}
|
|
57
|
-
if (unlock?.history) {
|
|
58
|
-
const history = events.getTimeline({ kinds: [WALLET_HISTORY_KIND], authors: [self] });
|
|
59
|
-
for (const entry of history)
|
|
60
|
-
if (isHistoryContentLocked(entry))
|
|
61
|
-
await unlockHistoryContent(entry, signer);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Action } from "applesauce-actions";
|
|
2
|
-
/** An action to add a relay to the kind 10019 nutzap info event */
|
|
3
|
-
export declare function AddNutzapInfoRelay(relay: string | string[]): Action;
|
|
4
|
-
/** An action to remove a relay from the kind 10019 nutzap info event */
|
|
5
|
-
export declare function RemoveNutzapInfoRelay(relay: string | string[]): Action;
|
|
6
|
-
/** An action to add a mint to the kind 10019 nutzap info event */
|
|
7
|
-
export declare function AddNutzapInfoMint(mint: {
|
|
8
|
-
url: string;
|
|
9
|
-
units?: string[];
|
|
10
|
-
} | Array<{
|
|
11
|
-
url: string;
|
|
12
|
-
units?: string[];
|
|
13
|
-
}>): Action;
|
|
14
|
-
/** An action to remove a mint from the kind 10019 nutzap info event */
|
|
15
|
-
export declare function RemoveNutzapInfoMint(mint: string | string[]): Action;
|
|
16
|
-
/** An action to set the pubkey for the kind 10019 nutzap info event */
|
|
17
|
-
export declare function SetNutzapInfoPubkey(pubkey: string): Action;
|
|
18
|
-
/** An action to update the entire nutzap info event */
|
|
19
|
-
export declare function UpdateNutzapInfo(relays: string[], mints: Array<{
|
|
20
|
-
url: string;
|
|
21
|
-
units?: string[];
|
|
22
|
-
}>, pubkey: string): Action;
|
package/dist/actions/zap-info.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { modifyPublicTags } from "applesauce-factory/operations";
|
|
2
|
-
import { addNameValueTag, removeNameValueTag, setSingletonTag } from "applesauce-factory/operations/tag";
|
|
3
|
-
import { NUTZAP_INFO_KIND } from "../helpers/zap-info.js";
|
|
4
|
-
import { setNutzapInfoMints, setNutzapInfoPubkey, setNutzapInfoRelays } from "../operations/zap-info.js";
|
|
5
|
-
/** An action to add a relay to the kind 10019 nutzap info event */
|
|
6
|
-
export function AddNutzapInfoRelay(relay) {
|
|
7
|
-
return async function* ({ events, factory, self }) {
|
|
8
|
-
if (typeof relay === "string")
|
|
9
|
-
relay = [relay];
|
|
10
|
-
const operations = relay.map((r) => addNameValueTag(["relay", r], false));
|
|
11
|
-
const nutzapInfo = events.getReplaceable(NUTZAP_INFO_KIND, self);
|
|
12
|
-
const draft = nutzapInfo
|
|
13
|
-
? await factory.modifyTags(nutzapInfo, ...operations)
|
|
14
|
-
: await factory.build({ kind: NUTZAP_INFO_KIND }, modifyPublicTags(...operations));
|
|
15
|
-
const signed = await factory.sign(draft);
|
|
16
|
-
yield signed;
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
/** An action to remove a relay from the kind 10019 nutzap info event */
|
|
20
|
-
export function RemoveNutzapInfoRelay(relay) {
|
|
21
|
-
return async function* ({ events, factory, self }) {
|
|
22
|
-
if (typeof relay === "string")
|
|
23
|
-
relay = [relay];
|
|
24
|
-
const nutzapInfo = events.getReplaceable(NUTZAP_INFO_KIND, self);
|
|
25
|
-
if (!nutzapInfo)
|
|
26
|
-
return;
|
|
27
|
-
const draft = await factory.modifyTags(nutzapInfo, ...relay.map((r) => removeNameValueTag(["relay", r])));
|
|
28
|
-
const signed = await factory.sign(draft);
|
|
29
|
-
yield signed;
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
/** An action to add a mint to the kind 10019 nutzap info event */
|
|
33
|
-
export function AddNutzapInfoMint(mint) {
|
|
34
|
-
return async function* ({ events, factory, self }) {
|
|
35
|
-
const mints = Array.isArray(mint) ? mint : [mint];
|
|
36
|
-
const operations = mints.map((m) => {
|
|
37
|
-
const tag = m.units ? ["mint", m.url, ...m.units] : ["mint", m.url];
|
|
38
|
-
return addNameValueTag(tag, false);
|
|
39
|
-
});
|
|
40
|
-
const nutzapInfo = events.getReplaceable(NUTZAP_INFO_KIND, self);
|
|
41
|
-
const draft = nutzapInfo
|
|
42
|
-
? await factory.modifyTags(nutzapInfo, ...operations)
|
|
43
|
-
: await factory.build({ kind: NUTZAP_INFO_KIND }, modifyPublicTags(...operations));
|
|
44
|
-
const signed = await factory.sign(draft);
|
|
45
|
-
yield signed;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
/** An action to remove a mint from the kind 10019 nutzap info event */
|
|
49
|
-
export function RemoveNutzapInfoMint(mint) {
|
|
50
|
-
return async function* ({ events, factory, self }) {
|
|
51
|
-
if (typeof mint === "string")
|
|
52
|
-
mint = [mint];
|
|
53
|
-
const nutzapInfo = events.getReplaceable(NUTZAP_INFO_KIND, self);
|
|
54
|
-
if (!nutzapInfo)
|
|
55
|
-
return;
|
|
56
|
-
const draft = await factory.modifyTags(nutzapInfo, ...mint.map((m) => removeNameValueTag(["mint", m])));
|
|
57
|
-
const signed = await factory.sign(draft);
|
|
58
|
-
yield signed;
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
/** An action to set the pubkey for the kind 10019 nutzap info event */
|
|
62
|
-
export function SetNutzapInfoPubkey(pubkey) {
|
|
63
|
-
return async function* ({ events, factory, self }) {
|
|
64
|
-
const nutzapInfo = events.getReplaceable(NUTZAP_INFO_KIND, self);
|
|
65
|
-
const draft = nutzapInfo
|
|
66
|
-
? await factory.modifyTags(nutzapInfo, setSingletonTag(["pubkey", pubkey], true))
|
|
67
|
-
: await factory.build({ kind: NUTZAP_INFO_KIND }, modifyPublicTags(setSingletonTag(["pubkey", pubkey], true)));
|
|
68
|
-
const signed = await factory.sign(draft);
|
|
69
|
-
yield signed;
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
/** An action to update the entire nutzap info event */
|
|
73
|
-
export function UpdateNutzapInfo(relays, mints, pubkey) {
|
|
74
|
-
return async function* ({ events, factory, self }) {
|
|
75
|
-
const operations = [setNutzapInfoRelays(relays), setNutzapInfoMints(mints), setNutzapInfoPubkey(pubkey)];
|
|
76
|
-
const nutzapInfo = events.getReplaceable(NUTZAP_INFO_KIND, self);
|
|
77
|
-
const draft = nutzapInfo
|
|
78
|
-
? await factory.modify(nutzapInfo, ...operations)
|
|
79
|
-
: await factory.build({ kind: NUTZAP_INFO_KIND }, ...operations);
|
|
80
|
-
const signed = await factory.sign(draft);
|
|
81
|
-
yield signed;
|
|
82
|
-
};
|
|
83
|
-
}
|
package/dist/actions/zaps.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Token } from "@cashu/cashu-ts";
|
|
2
|
-
import { Action } from "applesauce-actions";
|
|
3
|
-
import { NostrEvent } from "nostr-tools";
|
|
4
|
-
import { ProfilePointer } from "nostr-tools/nip19";
|
|
5
|
-
/** Creates a NIP-61 nutzap event for an event with a token */
|
|
6
|
-
export declare function NutzapEvent(event: NostrEvent, token: Token, comment?: string): Action;
|
|
7
|
-
/** Creates a NIP-61 nutzap event to a users profile */
|
|
8
|
-
export declare function NutzapProfile(user: string | ProfilePointer, token: Token, comment?: string): Action;
|
package/dist/actions/zaps.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { NutzapBlueprint, ProfileNutzapBlueprint } from "../blueprints/zaps.js";
|
|
2
|
-
import { NUTZAP_INFO_KIND, verifyProofsLocked } from "../helpers/zap-info.js";
|
|
3
|
-
/** Creates a NIP-61 nutzap event for an event with a token */
|
|
4
|
-
export function NutzapEvent(event, token, comment) {
|
|
5
|
-
return async function* ({ events, factory }) {
|
|
6
|
-
const recipient = event.pubkey;
|
|
7
|
-
const info = events.getReplaceable(NUTZAP_INFO_KIND, recipient);
|
|
8
|
-
if (!info)
|
|
9
|
-
throw new Error("Nutzap info not found");
|
|
10
|
-
// Verify all tokens are p2pk locked
|
|
11
|
-
verifyProofsLocked(token.proofs, info);
|
|
12
|
-
// NOTE: Disabled because mints and units should be checked by the app before
|
|
13
|
-
// const mints = getNutzapInfoMints(info);
|
|
14
|
-
// if (!mints.some((m) => m.mint === token.mint)) throw new Error("Token mint not found in nutzap info");
|
|
15
|
-
const nutzap = await factory.sign(await factory.create(NutzapBlueprint, event, token, comment || token.memo));
|
|
16
|
-
yield nutzap;
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
/** Creates a NIP-61 nutzap event to a users profile */
|
|
20
|
-
export function NutzapProfile(user, token, comment) {
|
|
21
|
-
return async function* ({ events, factory }) {
|
|
22
|
-
const info = events.getReplaceable(NUTZAP_INFO_KIND, typeof user === "string" ? user : user.pubkey);
|
|
23
|
-
if (!info)
|
|
24
|
-
throw new Error("Nutzap info not found");
|
|
25
|
-
// Verify all tokens are p2pk locked
|
|
26
|
-
verifyProofsLocked(token.proofs, info);
|
|
27
|
-
const nutzap = await factory.sign(await factory.create(ProfileNutzapBlueprint, user, token, comment || token.memo));
|
|
28
|
-
yield nutzap;
|
|
29
|
-
};
|
|
30
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { EventPointer } from "nostr-tools/nip19";
|
|
2
|
-
import { HistoryContent } from "../helpers/history.js";
|
|
3
|
-
/** A blueprint that creates a wallet history event */
|
|
4
|
-
export declare function WalletHistoryBlueprint(content: HistoryContent, redeemed: (string | EventPointer)[]): import("applesauce-factory").EventBlueprint;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { blueprint } from "applesauce-factory";
|
|
2
|
-
import { WALLET_HISTORY_KIND } from "../helpers/history.js";
|
|
3
|
-
import { setHistoryContent, setHistoryRedeemed } from "../operations/history.js";
|
|
4
|
-
/** A blueprint that creates a wallet history event */
|
|
5
|
-
export function WalletHistoryBlueprint(content, redeemed) {
|
|
6
|
-
return blueprint(WALLET_HISTORY_KIND,
|
|
7
|
-
// set the encrypted tags on the event
|
|
8
|
-
setHistoryContent(content),
|
|
9
|
-
// set the public redeemed tags
|
|
10
|
-
setHistoryRedeemed(redeemed));
|
|
11
|
-
}
|
package/dist/blueprints/info.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { blueprint } from "applesauce-factory";
|
|
2
|
-
import { setContent } from "applesauce-factory/operations/content";
|
|
3
|
-
import { includeSingletonTag } from "applesauce-factory/operations";
|
|
4
|
-
import { WALLET_INFO_KIND } from "../helpers/support.js";
|
|
5
|
-
/** Creates a wallet info event */
|
|
6
|
-
export function WalletInfoBlueprint(info) {
|
|
7
|
-
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
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Token } from "@cashu/cashu-ts";
|
|
2
|
-
/**
|
|
3
|
-
* A blueprint for a wallet token event, takes a cashu token and previous deleted token event ids
|
|
4
|
-
* @param token the cashu token to store
|
|
5
|
-
* @param [del=[]] an array of previous token event ids that are deleted
|
|
6
|
-
*/
|
|
7
|
-
export declare function WalletTokenBlueprint(token: Token, del?: string[]): import("applesauce-factory").EventBlueprint;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { blueprint } from "applesauce-factory";
|
|
2
|
-
import { WALLET_TOKEN_KIND } from "../helpers/tokens.js";
|
|
3
|
-
import { setToken } from "../operations/tokens.js";
|
|
4
|
-
/**
|
|
5
|
-
* A blueprint for a wallet token event, takes a cashu token and previous deleted token event ids
|
|
6
|
-
* @param token the cashu token to store
|
|
7
|
-
* @param [del=[]] an array of previous token event ids that are deleted
|
|
8
|
-
*/
|
|
9
|
-
export function WalletTokenBlueprint(token, del = []) {
|
|
10
|
-
return blueprint(WALLET_TOKEN_KIND, setToken(token, del));
|
|
11
|
-
}
|