applesauce-wallet 0.0.0-next-20251220152312 → 0.0.0-next-20251231055351
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/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/actions/mint-recomendation.d.ts +30 -0
- package/dist/actions/mint-recomendation.js +96 -0
- package/dist/blueprints/index.d.ts +1 -0
- package/dist/blueprints/index.js +1 -0
- package/dist/blueprints/mint-recommendation.d.ts +16 -0
- package/dist/blueprints/mint-recommendation.js +11 -0
- package/dist/casts/__register__.d.ts +2 -0
- package/dist/casts/__register__.js +11 -0
- package/dist/casts/index.d.ts +2 -0
- package/dist/casts/index.js +2 -0
- package/dist/casts/mint-info.d.ts +18 -0
- package/dist/casts/mint-info.js +42 -0
- package/dist/casts/mint-recommendation.d.ts +16 -0
- package/dist/casts/mint-recommendation.js +29 -0
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.js +2 -0
- package/dist/helpers/mint-info.d.ts +40 -0
- package/dist/helpers/mint-info.js +80 -0
- package/dist/helpers/mint-recommendation.d.ts +41 -0
- package/dist/helpers/mint-recommendation.js +54 -0
- package/dist/operations/index.d.ts +1 -0
- package/dist/operations/index.js +1 -0
- package/dist/operations/mint-recommendation.d.ts +13 -0
- package/dist/operations/mint-recommendation.js +26 -0
- package/package.json +31 -31
package/dist/actions/index.d.ts
CHANGED
package/dist/actions/index.js
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Wallet } from "@cashu/cashu-ts";
|
|
2
|
+
import { Action } from "applesauce-actions";
|
|
3
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
4
|
+
import "../casts/__register__.js";
|
|
5
|
+
/**
|
|
6
|
+
* Options for reviewing a mint
|
|
7
|
+
*/
|
|
8
|
+
export type ReviewMintOptions = {
|
|
9
|
+
/** Optional review/comment content */
|
|
10
|
+
comment?: string;
|
|
11
|
+
/** Optional relays to publish to */
|
|
12
|
+
relays?: string[];
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* An action that creates and publishes a mint recommendation event.
|
|
16
|
+
* Can accept a mint URL, Wallet instance, or MintInfo event.
|
|
17
|
+
*/
|
|
18
|
+
export declare function RecommendMint(input: string | Wallet | NostrEvent, options?: ReviewMintOptions): Action;
|
|
19
|
+
/**
|
|
20
|
+
* Options for updating a mint recommendation
|
|
21
|
+
*/
|
|
22
|
+
export type UpdateMintRecommendationOptions = {
|
|
23
|
+
/** Optional relays to publish to */
|
|
24
|
+
relays?: string[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* An action that updates the comment on an existing mint recommendation event.
|
|
28
|
+
* Can accept a mint pubkey (to find the recommendation) or the recommendation event directly.
|
|
29
|
+
*/
|
|
30
|
+
export declare function UpdateMintRecommendation(input: string | NostrEvent, comment: string, options?: UpdateMintRecommendationOptions): Action;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Wallet } from "@cashu/cashu-ts";
|
|
2
|
+
import { MintRecommendationBlueprint } from "../blueprints/mint-recommendation.js";
|
|
3
|
+
import { getCashuMintPubkey, getCashuMintURL, isValidCashuMintInfo } from "../helpers/mint-info.js";
|
|
4
|
+
import { MINT_RECOMMENDATION_KIND, getRecommendationMintPubkey, isValidMintRecommendation, } from "../helpers/mint-recommendation.js";
|
|
5
|
+
import { setComment } from "../operations/mint-recommendation.js";
|
|
6
|
+
// Helper function to fetch mint pubkey from URL
|
|
7
|
+
async function fetchMintPubkey(mintUrl) {
|
|
8
|
+
// Fetch mint info directly from the /v1/info endpoint
|
|
9
|
+
const infoUrl = new URL("/v1/info", mintUrl).toString();
|
|
10
|
+
const response = await fetch(infoUrl);
|
|
11
|
+
if (!response.ok) {
|
|
12
|
+
throw new Error(`Failed to fetch mint info from ${mintUrl}: ${response.statusText}`);
|
|
13
|
+
}
|
|
14
|
+
const mintInfo = (await response.json());
|
|
15
|
+
return mintInfo.pubkey;
|
|
16
|
+
}
|
|
17
|
+
// Make sure the mint recommendation cast is registered
|
|
18
|
+
import "../casts/__register__.js";
|
|
19
|
+
/**
|
|
20
|
+
* An action that creates and publishes a mint recommendation event.
|
|
21
|
+
* Can accept a mint URL, Wallet instance, or MintInfo event.
|
|
22
|
+
*/
|
|
23
|
+
export function RecommendMint(input, options) {
|
|
24
|
+
return async ({ factory, sign, publish }) => {
|
|
25
|
+
let mintPubkey;
|
|
26
|
+
let url;
|
|
27
|
+
let addressPointer = undefined;
|
|
28
|
+
// Handle different input types
|
|
29
|
+
if (typeof input === "string") {
|
|
30
|
+
if (!URL.canParse(input))
|
|
31
|
+
throw new Error("Invalid mint URL");
|
|
32
|
+
// Input is a mint URL - fetch info directly
|
|
33
|
+
url = input;
|
|
34
|
+
mintPubkey = await fetchMintPubkey(url);
|
|
35
|
+
}
|
|
36
|
+
else if (input instanceof Wallet) {
|
|
37
|
+
const info = input.getMintInfo();
|
|
38
|
+
mintPubkey = info.pubkey;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Input is a MintInfo event (kind:38172)
|
|
42
|
+
if (!isValidCashuMintInfo(input))
|
|
43
|
+
throw new Error("Invalid mint info event. Expected kind:38172 with required `d` and `u` tags.");
|
|
44
|
+
mintPubkey = getCashuMintPubkey(input);
|
|
45
|
+
url = getCashuMintURL(input);
|
|
46
|
+
// Use the event itself as address pointer (blueprint will convert it)
|
|
47
|
+
addressPointer = input;
|
|
48
|
+
}
|
|
49
|
+
// Create the mint recommendation event
|
|
50
|
+
const recommendation = await factory
|
|
51
|
+
.create(MintRecommendationBlueprint, {
|
|
52
|
+
mintPubkey,
|
|
53
|
+
url,
|
|
54
|
+
addressPointer,
|
|
55
|
+
comment: options?.comment,
|
|
56
|
+
})
|
|
57
|
+
.then(sign);
|
|
58
|
+
// Publish the event
|
|
59
|
+
await publish(recommendation, options?.relays);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* An action that updates the comment on an existing mint recommendation event.
|
|
64
|
+
* Can accept a mint pubkey (to find the recommendation) or the recommendation event directly.
|
|
65
|
+
*/
|
|
66
|
+
export function UpdateMintRecommendation(input, comment, options) {
|
|
67
|
+
return async ({ events, factory, self, sign, publish }) => {
|
|
68
|
+
let recommendation;
|
|
69
|
+
// Handle different input types
|
|
70
|
+
if (typeof input === "string") {
|
|
71
|
+
// Input is a mint pubkey - find the recommendation event
|
|
72
|
+
const recommendations = events.getTimeline({ kinds: [MINT_RECOMMENDATION_KIND], authors: [self] });
|
|
73
|
+
recommendation = recommendations.find((rec) => {
|
|
74
|
+
if (!isValidMintRecommendation(rec))
|
|
75
|
+
return false;
|
|
76
|
+
const recMintPubkey = getRecommendationMintPubkey(rec);
|
|
77
|
+
return recMintPubkey === input;
|
|
78
|
+
});
|
|
79
|
+
if (!recommendation)
|
|
80
|
+
throw new Error(`No mint recommendation found for mint pubkey: ${input}`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// Input is a recommendation event
|
|
84
|
+
if (!isValidMintRecommendation(input))
|
|
85
|
+
throw new Error("Invalid mint recommendation event");
|
|
86
|
+
// Verify the event belongs to the current user
|
|
87
|
+
if (input.pubkey !== self)
|
|
88
|
+
throw new Error("Cannot update a mint recommendation that belongs to another user");
|
|
89
|
+
recommendation = input;
|
|
90
|
+
}
|
|
91
|
+
// Update the comment
|
|
92
|
+
const updated = await factory.modify(recommendation, setComment(comment)).then(sign);
|
|
93
|
+
// Publish the updated event
|
|
94
|
+
await publish(updated, options?.relays);
|
|
95
|
+
};
|
|
96
|
+
}
|
package/dist/blueprints/index.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EventBlueprint } from "applesauce-core/event-factory";
|
|
2
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
3
|
+
import { AddressPointer } from "applesauce-core/helpers/pointers";
|
|
4
|
+
/** Options for creating a mint recommendation */
|
|
5
|
+
export type MintRecommendationOptions = {
|
|
6
|
+
/** The mint's pubkey (from the kind:38172 event's `d` tag) - required */
|
|
7
|
+
mintPubkey: string;
|
|
8
|
+
/** Optional URL to connect to the cashu mint */
|
|
9
|
+
url?: string;
|
|
10
|
+
/** Optional address pointer to the kind:38172 event */
|
|
11
|
+
addressPointer?: AddressPointer | NostrEvent | string;
|
|
12
|
+
/** Optional review/comment content */
|
|
13
|
+
comment?: string;
|
|
14
|
+
};
|
|
15
|
+
/** A blueprint to create a kind:38000 mint recommendation event */
|
|
16
|
+
export declare function MintRecommendationBlueprint(options: MintRecommendationOptions): EventBlueprint;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { blueprint } from "applesauce-core/event-factory";
|
|
2
|
+
import { skip } from "applesauce-core/helpers";
|
|
3
|
+
import { MINT_RECOMMENDATION_KIND } from "../helpers/mint-recommendation.js";
|
|
4
|
+
import { CASHU_MINT_INFO_KIND } from "../helpers/mint-info.js";
|
|
5
|
+
import { setAddressPointer, setComment, setKind, setMintPubkey, setURL } from "../operations/mint-recommendation.js";
|
|
6
|
+
/** A blueprint to create a kind:38000 mint recommendation event */
|
|
7
|
+
export function MintRecommendationBlueprint(options) {
|
|
8
|
+
const { mintPubkey, url, addressPointer, comment } = options;
|
|
9
|
+
return blueprint(MINT_RECOMMENDATION_KIND, setKind(CASHU_MINT_INFO_KIND), // Always 38172 for cashu mints
|
|
10
|
+
setMintPubkey(mintPubkey), url ? setURL(url) : skip(), addressPointer ? setAddressPointer(addressPointer) : skip(), comment ? setComment(comment) : skip());
|
|
11
|
+
}
|
|
@@ -2,10 +2,12 @@ import { ChainableObservable } from "applesauce-common/observable";
|
|
|
2
2
|
import { NutzapInfo } from "./nutzap-info.js";
|
|
3
3
|
import { Nutzap } from "./nutzap.js";
|
|
4
4
|
import { Wallet } from "./wallet.js";
|
|
5
|
+
import { MintRecommendation } from "./mint-recommendation.js";
|
|
5
6
|
declare module "applesauce-common/casts/user" {
|
|
6
7
|
interface User {
|
|
7
8
|
readonly wallet$: ChainableObservable<Wallet | undefined>;
|
|
8
9
|
readonly nutzap$: ChainableObservable<NutzapInfo | undefined>;
|
|
10
|
+
readonly mintRecommendation$: ChainableObservable<MintRecommendation | undefined>;
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
13
|
declare module "applesauce-common/casts/stream" {
|
|
@@ -9,6 +9,8 @@ import { NUTZAP_INFO_KIND } from "../helpers/nutzap-info.js";
|
|
|
9
9
|
import { NutzapInfo } from "./nutzap-info.js";
|
|
10
10
|
import { Nutzap } from "./nutzap.js";
|
|
11
11
|
import { Wallet } from "./wallet.js";
|
|
12
|
+
import { MintRecommendation } from "./mint-recommendation.js";
|
|
13
|
+
import { MINT_RECOMMENDATION_KIND } from "../helpers/mint-recommendation.js";
|
|
12
14
|
Object.defineProperty(User.prototype, "wallet$", {
|
|
13
15
|
get: function () {
|
|
14
16
|
return this.$$ref("wallet$", (store) => this.outboxes$.pipe(switchMap((outboxes) => store
|
|
@@ -25,6 +27,15 @@ Object.defineProperty(User.prototype, "nutzap$", {
|
|
|
25
27
|
enumerable: true,
|
|
26
28
|
configurable: false,
|
|
27
29
|
});
|
|
30
|
+
Object.defineProperty(User.prototype, "mintRecommendation$", {
|
|
31
|
+
get: function () {
|
|
32
|
+
return this.$$ref("mintRecommendation$", (store) => store
|
|
33
|
+
.timeline({ kinds: [MINT_RECOMMENDATION_KIND], authors: [this.pubkey] })
|
|
34
|
+
.pipe(castTimelineStream(MintRecommendation, store)));
|
|
35
|
+
},
|
|
36
|
+
enumerable: true,
|
|
37
|
+
configurable: false,
|
|
38
|
+
});
|
|
28
39
|
Note.prototype.nutzaps$ = function () {
|
|
29
40
|
return this.$$ref("nutzaps$", (store) => store
|
|
30
41
|
.timeline(buildCommonEventRelationFilters({ kinds: [NUTZAP_KIND] }, this.event))
|
package/dist/casts/index.d.ts
CHANGED
package/dist/casts/index.js
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CastRefEventStore, EventCast } from "applesauce-common/casts";
|
|
2
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
3
|
+
import { CashuMintInfoEvent } from "../helpers/mint-info.js";
|
|
4
|
+
import { MintRecommendation } from "./mint-recommendation.js";
|
|
5
|
+
export declare class MintInfo extends EventCast<CashuMintInfoEvent> {
|
|
6
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
7
|
+
/** The mint's pubkey (from the `d` tag) */
|
|
8
|
+
get mintPubkey(): string | undefined;
|
|
9
|
+
/** The URL to the cashu mint (from the `u` tag) */
|
|
10
|
+
get url(): string;
|
|
11
|
+
/** The supported nuts (comma-separated list of nut numbers) */
|
|
12
|
+
get nuts(): number[];
|
|
13
|
+
/** The network type (mainnet, testnet, signet, or regtest) */
|
|
14
|
+
get network(): import("../helpers/mint-info.js").NetworkType | undefined;
|
|
15
|
+
/** Optional metadata content (kind:0-style JSON object) */
|
|
16
|
+
get metadata(): Record<string, any> | undefined;
|
|
17
|
+
get recomendations$(): import("applesauce-common/observable").ChainableObservable<MintRecommendation[]>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EventCast } from "applesauce-common/casts";
|
|
2
|
+
import { castTimelineStream } from "applesauce-common/observable";
|
|
3
|
+
import { getCashuMintMetadata, getCashuMintNetwork, getCashuMintNuts, getCashuMintPubkey, getCashuMintURL, isValidCashuMintInfo, } from "../helpers/mint-info.js";
|
|
4
|
+
import { MINT_RECOMMENDATION_KIND } from "../helpers/mint-recommendation.js";
|
|
5
|
+
import { MintRecommendation } from "./mint-recommendation.js";
|
|
6
|
+
export class MintInfo extends EventCast {
|
|
7
|
+
constructor(event, store) {
|
|
8
|
+
if (!isValidCashuMintInfo(event))
|
|
9
|
+
throw new Error("Invalid cashu mint info event");
|
|
10
|
+
super(event, store);
|
|
11
|
+
}
|
|
12
|
+
/** The mint's pubkey (from the `d` tag) */
|
|
13
|
+
get mintPubkey() {
|
|
14
|
+
return getCashuMintPubkey(this.event);
|
|
15
|
+
}
|
|
16
|
+
/** The URL to the cashu mint (from the `u` tag) */
|
|
17
|
+
get url() {
|
|
18
|
+
return getCashuMintURL(this.event);
|
|
19
|
+
}
|
|
20
|
+
/** The supported nuts (comma-separated list of nut numbers) */
|
|
21
|
+
get nuts() {
|
|
22
|
+
return getCashuMintNuts(this.event);
|
|
23
|
+
}
|
|
24
|
+
/** The network type (mainnet, testnet, signet, or regtest) */
|
|
25
|
+
get network() {
|
|
26
|
+
return getCashuMintNetwork(this.event);
|
|
27
|
+
}
|
|
28
|
+
/** Optional metadata content (kind:0-style JSON object) */
|
|
29
|
+
get metadata() {
|
|
30
|
+
return getCashuMintMetadata(this.event);
|
|
31
|
+
}
|
|
32
|
+
get recomendations$() {
|
|
33
|
+
return this.$$ref("recomendations$", (store) => store
|
|
34
|
+
.timeline([
|
|
35
|
+
// Based on the mint URL
|
|
36
|
+
{ kinds: [MINT_RECOMMENDATION_KIND], "#u": [this.url] },
|
|
37
|
+
// Based on the mint pubkey
|
|
38
|
+
this.mintPubkey ? { kinds: [MINT_RECOMMENDATION_KIND], "#d": [this.mintPubkey] } : undefined,
|
|
39
|
+
].filter((f) => !!f))
|
|
40
|
+
.pipe(castTimelineStream(MintRecommendation, store)));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CastRefEventStore, EventCast } from "applesauce-common/casts";
|
|
2
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
3
|
+
import { MintRecommendationEvent } from "../helpers/mint-recommendation.js";
|
|
4
|
+
export declare class MintRecommendation extends EventCast<MintRecommendationEvent> {
|
|
5
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
6
|
+
/** The recommended event kind (should be 38172 for cashu mints) */
|
|
7
|
+
get kind(): number;
|
|
8
|
+
/** The mint's pubkey (from the `d` tag) */
|
|
9
|
+
get mintPubkey(): string | undefined;
|
|
10
|
+
/** Optional URL to connect to the cashu mint (from the `u` tag) */
|
|
11
|
+
get url(): string | undefined;
|
|
12
|
+
/** Optional address pointer to the kind:38172 event (from the `a` tag) */
|
|
13
|
+
get addressPointer(): import("nostr-tools/nip19").AddressPointer | undefined;
|
|
14
|
+
/** Optional review content */
|
|
15
|
+
get comment(): string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EventCast } from "applesauce-common/casts";
|
|
2
|
+
import { getRecommendationAddressPointer, getRecommendationMintPubkey, getRecommendationKind, getRecommendationURL, isValidMintRecommendation, } from "../helpers/mint-recommendation.js";
|
|
3
|
+
export class MintRecommendation extends EventCast {
|
|
4
|
+
constructor(event, store) {
|
|
5
|
+
if (!isValidMintRecommendation(event))
|
|
6
|
+
throw new Error("Invalid mint recommendation event");
|
|
7
|
+
super(event, store);
|
|
8
|
+
}
|
|
9
|
+
/** The recommended event kind (should be 38172 for cashu mints) */
|
|
10
|
+
get kind() {
|
|
11
|
+
return getRecommendationKind(this.event);
|
|
12
|
+
}
|
|
13
|
+
/** The mint's pubkey (from the `d` tag) */
|
|
14
|
+
get mintPubkey() {
|
|
15
|
+
return getRecommendationMintPubkey(this.event);
|
|
16
|
+
}
|
|
17
|
+
/** Optional URL to connect to the cashu mint (from the `u` tag) */
|
|
18
|
+
get url() {
|
|
19
|
+
return getRecommendationURL(this.event);
|
|
20
|
+
}
|
|
21
|
+
/** Optional address pointer to the kind:38172 event (from the `a` tag) */
|
|
22
|
+
get addressPointer() {
|
|
23
|
+
return getRecommendationAddressPointer(this.event);
|
|
24
|
+
}
|
|
25
|
+
/** Optional review content */
|
|
26
|
+
get comment() {
|
|
27
|
+
return this.event.content;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/dist/helpers/index.d.ts
CHANGED
package/dist/helpers/index.js
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { KnownEvent } from "applesauce-core/helpers";
|
|
2
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
3
|
+
export declare const CASHU_MINT_INFO_KIND = 38172;
|
|
4
|
+
export type CashuMintInfoEvent = KnownEvent<typeof CASHU_MINT_INFO_KIND>;
|
|
5
|
+
export type NetworkType = "mainnet" | "testnet" | "signet" | "regtest";
|
|
6
|
+
export declare const CashuMintPubkeySymbol: unique symbol;
|
|
7
|
+
export declare const CashuMintURLSymbol: unique symbol;
|
|
8
|
+
export declare const CashuMintNutsSymbol: unique symbol;
|
|
9
|
+
export declare const CashuMintNetworkSymbol: unique symbol;
|
|
10
|
+
/**
|
|
11
|
+
* Returns the mint's pubkey from a kind:38172 cashu mint info event
|
|
12
|
+
* This is found in the `d` tag and is the pubkey from the mint's `/v1/info` endpoint
|
|
13
|
+
*/
|
|
14
|
+
export declare function getCashuMintPubkey(event: NostrEvent): string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the mint URL from a kind:38172 cashu mint info event
|
|
17
|
+
* This is the URL to the cashu mint (from the `u` tag)
|
|
18
|
+
*/
|
|
19
|
+
export declare function getCashuMintURL(event: CashuMintInfoEvent): string;
|
|
20
|
+
export declare function getCashuMintURL(event: NostrEvent): string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Returns the supported nuts from a kind:38172 cashu mint info event
|
|
23
|
+
* This is a comma-separated list of nut numbers (e.g., "1,2,3,4,5,6,7")
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCashuMintNuts(event: NostrEvent): number[];
|
|
26
|
+
/**
|
|
27
|
+
* Returns the network type from a kind:38172 cashu mint info event
|
|
28
|
+
* Should be one of: mainnet, testnet, signet, or regtest
|
|
29
|
+
*/
|
|
30
|
+
export declare function getCashuMintNetwork(event: NostrEvent): NetworkType | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the optional metadata content from a kind:38172 cashu mint info event
|
|
33
|
+
* This is a kind:0-style metadata JSON object, useful when the pubkey is not a normal user
|
|
34
|
+
*/
|
|
35
|
+
export declare function getCashuMintMetadata(event: NostrEvent): Record<string, any> | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Validates that an event is a proper kind:38172 cashu mint info event
|
|
38
|
+
* Checks that the event is kind 38172 and has the required `d` and `u` tags
|
|
39
|
+
*/
|
|
40
|
+
export declare function isValidCashuMintInfo(event?: NostrEvent): event is CashuMintInfoEvent;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { getOrComputeCachedValue, getTagValue, isHex, safeParse } from "applesauce-core/helpers";
|
|
2
|
+
import { getReplaceableIdentifier } from "applesauce-core/helpers/event";
|
|
3
|
+
// NIP-87 Cashu Mint Information Event Kind
|
|
4
|
+
export const CASHU_MINT_INFO_KIND = 38172;
|
|
5
|
+
// Symbols for caching computed values
|
|
6
|
+
export const CashuMintPubkeySymbol = Symbol.for("cashu-mint-pubkey");
|
|
7
|
+
export const CashuMintURLSymbol = Symbol.for("cashu-mint-url");
|
|
8
|
+
export const CashuMintNutsSymbol = Symbol.for("cashu-mint-nuts");
|
|
9
|
+
export const CashuMintNetworkSymbol = Symbol.for("cashu-mint-network");
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Cashu Mint Information Event (kind:38172) Helpers
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Returns the mint's pubkey from a kind:38172 cashu mint info event
|
|
15
|
+
* This is found in the `d` tag and is the pubkey from the mint's `/v1/info` endpoint
|
|
16
|
+
*/
|
|
17
|
+
export function getCashuMintPubkey(event) {
|
|
18
|
+
return getOrComputeCachedValue(event, CashuMintPubkeySymbol, () => {
|
|
19
|
+
const identifier = getReplaceableIdentifier(event);
|
|
20
|
+
// Only return hex pubkeys
|
|
21
|
+
if (!isHex(identifier))
|
|
22
|
+
return undefined;
|
|
23
|
+
return identifier || undefined;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export function getCashuMintURL(event) {
|
|
27
|
+
return getOrComputeCachedValue(event, CashuMintURLSymbol, () => {
|
|
28
|
+
const url = getTagValue(event, "u");
|
|
29
|
+
return url && URL.canParse(url) ? url : undefined;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Returns the supported nuts from a kind:38172 cashu mint info event
|
|
34
|
+
* This is a comma-separated list of nut numbers (e.g., "1,2,3,4,5,6,7")
|
|
35
|
+
*/
|
|
36
|
+
export function getCashuMintNuts(event) {
|
|
37
|
+
return getOrComputeCachedValue(event, CashuMintNutsSymbol, () => {
|
|
38
|
+
const nutsStr = getTagValue(event, "nuts");
|
|
39
|
+
if (!nutsStr)
|
|
40
|
+
return [];
|
|
41
|
+
return nutsStr
|
|
42
|
+
.split(",")
|
|
43
|
+
.map((n) => parseInt(n.trim(), 10))
|
|
44
|
+
.filter((n) => !isNaN(n));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns the network type from a kind:38172 cashu mint info event
|
|
49
|
+
* Should be one of: mainnet, testnet, signet, or regtest
|
|
50
|
+
*/
|
|
51
|
+
export function getCashuMintNetwork(event) {
|
|
52
|
+
return getOrComputeCachedValue(event, CashuMintNetworkSymbol, () => {
|
|
53
|
+
const network = getTagValue(event, "n");
|
|
54
|
+
if (!network)
|
|
55
|
+
return undefined;
|
|
56
|
+
const validNetworks = ["mainnet", "testnet", "signet", "regtest"];
|
|
57
|
+
return validNetworks.includes(network) ? network : undefined;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns the optional metadata content from a kind:38172 cashu mint info event
|
|
62
|
+
* This is a kind:0-style metadata JSON object, useful when the pubkey is not a normal user
|
|
63
|
+
*/
|
|
64
|
+
export function getCashuMintMetadata(event) {
|
|
65
|
+
if (!event.content)
|
|
66
|
+
return undefined;
|
|
67
|
+
return safeParse(event.content);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validates that an event is a proper kind:38172 cashu mint info event
|
|
71
|
+
* Checks that the event is kind 38172 and has the required `d` and `u` tags
|
|
72
|
+
*/
|
|
73
|
+
export function isValidCashuMintInfo(event) {
|
|
74
|
+
if (!event)
|
|
75
|
+
return false;
|
|
76
|
+
if (event.kind !== CASHU_MINT_INFO_KIND)
|
|
77
|
+
return false;
|
|
78
|
+
const url = getCashuMintURL(event);
|
|
79
|
+
return url !== undefined;
|
|
80
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { KnownEvent } from "applesauce-core/helpers";
|
|
2
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
3
|
+
import { AddressPointer } from "applesauce-core/helpers/pointers";
|
|
4
|
+
export declare const MINT_RECOMMENDATION_KIND = 38000;
|
|
5
|
+
export type MintRecommendationEvent = KnownEvent<typeof MINT_RECOMMENDATION_KIND>;
|
|
6
|
+
export declare const RecommendationKindSymbol: unique symbol;
|
|
7
|
+
export declare const RecommendationURLSymbol: unique symbol;
|
|
8
|
+
export declare const RecommendationAddressPointerSymbol: unique symbol;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the recommended event kind from a kind:38000 recommendation event
|
|
11
|
+
* This should be 38172 for cashu mints
|
|
12
|
+
*/
|
|
13
|
+
export declare function getRecommendationKind(event: MintRecommendationEvent): number;
|
|
14
|
+
export declare function getRecommendationKind(event: NostrEvent): number | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the d-identifier from a kind:38000 recommendation event
|
|
17
|
+
* This is the kind:38172 event identifier this event is recommending
|
|
18
|
+
*/
|
|
19
|
+
export declare function getRecommendationMintPubkey(event: NostrEvent): string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Returns the URL from a kind:38000 recommendation event
|
|
22
|
+
* This is an optional `u` tag that provides a recommended way to connect to the cashu mint
|
|
23
|
+
* Each recommendation event recommends a single mint, so there is at most one `u` tag
|
|
24
|
+
*/
|
|
25
|
+
export declare function getRecommendationURL(event: MintRecommendationEvent): string | undefined;
|
|
26
|
+
export declare function getRecommendationURL(event: NostrEvent): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Returns the address pointer from a kind:38000 recommendation event
|
|
29
|
+
* This `a` tag points to the kind:38172 event of the cashu mint
|
|
30
|
+
* The first value is the event identifier, the second value is a relay hint
|
|
31
|
+
* Each recommendation event recommends a single mint, so there is at most one `a` tag
|
|
32
|
+
*/
|
|
33
|
+
export declare function getRecommendationAddressPointer(event: MintRecommendationEvent): AddressPointer | undefined;
|
|
34
|
+
export declare function getRecommendationAddressPointer(event: NostrEvent): AddressPointer | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Validates that an event is a proper kind:38000 recommendation event
|
|
37
|
+
* Checks that the event is kind 38000, has the required `k` and `d` tags,
|
|
38
|
+
* and that the `k` tag is 38172 (cashu mint kind)
|
|
39
|
+
* Each recommendation event recommends a single cashu mint
|
|
40
|
+
*/
|
|
41
|
+
export declare function isValidMintRecommendation(event?: NostrEvent): event is MintRecommendationEvent;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { getAddressPointerFromATag, getOrComputeCachedValue, getTagValue, isATag, isHex, } from "applesauce-core/helpers";
|
|
2
|
+
import { getReplaceableIdentifier } from "applesauce-core/helpers/event";
|
|
3
|
+
import { CASHU_MINT_INFO_KIND } from "./mint-info.js";
|
|
4
|
+
// NIP-87 Recommendation Event Kind
|
|
5
|
+
export const MINT_RECOMMENDATION_KIND = 38000;
|
|
6
|
+
// Symbols for caching computed values
|
|
7
|
+
export const RecommendationKindSymbol = Symbol.for("mint-recommendation-kind");
|
|
8
|
+
export const RecommendationURLSymbol = Symbol.for("mint-recommendation-url");
|
|
9
|
+
export const RecommendationAddressPointerSymbol = Symbol.for("mint-recommendation-address-pointer");
|
|
10
|
+
export function getRecommendationKind(event) {
|
|
11
|
+
return getOrComputeCachedValue(event, RecommendationKindSymbol, () => {
|
|
12
|
+
const kindStr = getTagValue(event, "k");
|
|
13
|
+
if (!kindStr)
|
|
14
|
+
return undefined;
|
|
15
|
+
const kind = parseInt(kindStr, 10);
|
|
16
|
+
return isNaN(kind) ? undefined : kind;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns the d-identifier from a kind:38000 recommendation event
|
|
21
|
+
* This is the kind:38172 event identifier this event is recommending
|
|
22
|
+
*/
|
|
23
|
+
export function getRecommendationMintPubkey(event) {
|
|
24
|
+
const identifier = getReplaceableIdentifier(event);
|
|
25
|
+
if (!isHex(identifier))
|
|
26
|
+
return undefined;
|
|
27
|
+
return identifier || undefined;
|
|
28
|
+
}
|
|
29
|
+
export function getRecommendationURL(event) {
|
|
30
|
+
return getOrComputeCachedValue(event, RecommendationURLSymbol, () => {
|
|
31
|
+
return getTagValue(event, "u");
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function getRecommendationAddressPointer(event) {
|
|
35
|
+
return getOrComputeCachedValue(event, RecommendationAddressPointerSymbol, () => {
|
|
36
|
+
const tag = event.tags.find(isATag);
|
|
37
|
+
return tag ? (getAddressPointerFromATag(tag) ?? undefined) : undefined;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validates that an event is a proper kind:38000 recommendation event
|
|
42
|
+
* Checks that the event is kind 38000, has the required `k` and `d` tags,
|
|
43
|
+
* and that the `k` tag is 38172 (cashu mint kind)
|
|
44
|
+
* Each recommendation event recommends a single cashu mint
|
|
45
|
+
*/
|
|
46
|
+
export function isValidMintRecommendation(event) {
|
|
47
|
+
if (!event)
|
|
48
|
+
return false;
|
|
49
|
+
if (event.kind !== MINT_RECOMMENDATION_KIND)
|
|
50
|
+
return false;
|
|
51
|
+
const kind = getRecommendationKind(event);
|
|
52
|
+
// Only cashu mints (kind 38172) are supported
|
|
53
|
+
return kind === CASHU_MINT_INFO_KIND;
|
|
54
|
+
}
|
package/dist/operations/index.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EventOperation } from "applesauce-core";
|
|
2
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
3
|
+
import { AddressPointer } from "applesauce-core/helpers/pointers";
|
|
4
|
+
/** Sets the recommended event kind (should be 38172 for cashu mints) */
|
|
5
|
+
export declare function setKind(kind: number): EventOperation;
|
|
6
|
+
/** Sets the mint's pubkey (the `d` tag, which is the replaceable identifier) */
|
|
7
|
+
export declare function setMintPubkey(pubkey: string): EventOperation;
|
|
8
|
+
/** Sets the optional URL to connect to the cashu mint (the `u` tag) */
|
|
9
|
+
export declare function setURL(url: string): EventOperation;
|
|
10
|
+
/** Sets the optional address pointer to the kind:38172 event (the `a` tag) */
|
|
11
|
+
export declare function setAddressPointer(pointer: AddressPointer | NostrEvent | string): EventOperation;
|
|
12
|
+
/** Sets the optional review/comment content */
|
|
13
|
+
export declare function setComment(comment: string): EventOperation;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { modifyPublicTags } from "applesauce-core/operations";
|
|
2
|
+
import { setContent } from "applesauce-core/operations/content";
|
|
3
|
+
import { addAddressPointerTag, setSingletonTag } from "applesauce-core/operations/tag/common";
|
|
4
|
+
/** Sets the recommended event kind (should be 38172 for cashu mints) */
|
|
5
|
+
export function setKind(kind) {
|
|
6
|
+
return modifyPublicTags(setSingletonTag(["k", kind.toString()]));
|
|
7
|
+
}
|
|
8
|
+
/** Sets the mint's pubkey (the `d` tag, which is the replaceable identifier) */
|
|
9
|
+
export function setMintPubkey(pubkey) {
|
|
10
|
+
return modifyPublicTags(setSingletonTag(["d", pubkey]));
|
|
11
|
+
}
|
|
12
|
+
/** Sets the optional URL to connect to the cashu mint (the `u` tag) */
|
|
13
|
+
export function setURL(url) {
|
|
14
|
+
// Enforce valid URL for cashu mints
|
|
15
|
+
if (url && !URL.canParse(url))
|
|
16
|
+
throw new Error("Invalid URL");
|
|
17
|
+
return modifyPublicTags(setSingletonTag(["u", url]));
|
|
18
|
+
}
|
|
19
|
+
/** Sets the optional address pointer to the kind:38172 event (the `a` tag) */
|
|
20
|
+
export function setAddressPointer(pointer) {
|
|
21
|
+
return modifyPublicTags(addAddressPointerTag(pointer, true));
|
|
22
|
+
}
|
|
23
|
+
/** Sets the optional review/comment content */
|
|
24
|
+
export function setComment(comment) {
|
|
25
|
+
return setContent(comment);
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "applesauce-wallet",
|
|
3
|
-
"version": "0.0.0-next-
|
|
3
|
+
"version": "0.0.0-next-20251231055351",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,83 +16,83 @@
|
|
|
16
16
|
],
|
|
17
17
|
"exports": {
|
|
18
18
|
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
19
20
|
"import": "./dist/index.js",
|
|
20
|
-
"require": "./dist/index.js"
|
|
21
|
-
"types": "./dist/index.d.ts"
|
|
21
|
+
"require": "./dist/index.js"
|
|
22
22
|
},
|
|
23
23
|
"./helpers": {
|
|
24
|
+
"types": "./dist/helpers/index.d.ts",
|
|
24
25
|
"import": "./dist/helpers/index.js",
|
|
25
|
-
"require": "./dist/helpers/index.js"
|
|
26
|
-
"types": "./dist/helpers/index.d.ts"
|
|
26
|
+
"require": "./dist/helpers/index.js"
|
|
27
27
|
},
|
|
28
28
|
"./helpers/*": {
|
|
29
|
+
"types": "./dist/helpers/*.d.ts",
|
|
29
30
|
"import": "./dist/helpers/*.js",
|
|
30
|
-
"require": "./dist/helpers/*.js"
|
|
31
|
-
"types": "./dist/helpers/*.d.ts"
|
|
31
|
+
"require": "./dist/helpers/*.js"
|
|
32
32
|
},
|
|
33
33
|
"./models": {
|
|
34
|
+
"types": "./dist/models/index.d.ts",
|
|
34
35
|
"import": "./dist/models/index.js",
|
|
35
|
-
"require": "./dist/models/index.js"
|
|
36
|
-
"types": "./dist/models/index.d.ts"
|
|
36
|
+
"require": "./dist/models/index.js"
|
|
37
37
|
},
|
|
38
38
|
"./models/*": {
|
|
39
|
+
"types": "./dist/models/*.d.ts",
|
|
39
40
|
"import": "./dist/models/*.js",
|
|
40
|
-
"require": "./dist/models/*.js"
|
|
41
|
-
"types": "./dist/models/*.d.ts"
|
|
41
|
+
"require": "./dist/models/*.js"
|
|
42
42
|
},
|
|
43
43
|
"./casts": {
|
|
44
|
+
"types": "./dist/casts/index.d.ts",
|
|
44
45
|
"import": "./dist/casts/index.js",
|
|
45
|
-
"require": "./dist/casts/index.js"
|
|
46
|
-
"types": "./dist/casts/index.d.ts"
|
|
46
|
+
"require": "./dist/casts/index.js"
|
|
47
47
|
},
|
|
48
48
|
"./casts/*": {
|
|
49
|
+
"types": "./dist/casts/*.d.ts",
|
|
49
50
|
"import": "./dist/casts/*.js",
|
|
50
|
-
"require": "./dist/casts/*.js"
|
|
51
|
-
"types": "./dist/casts/*.d.ts"
|
|
51
|
+
"require": "./dist/casts/*.js"
|
|
52
52
|
},
|
|
53
53
|
"./blueprints": {
|
|
54
|
+
"types": "./dist/blueprints/index.d.ts",
|
|
54
55
|
"import": "./dist/blueprints/index.js",
|
|
55
|
-
"require": "./dist/blueprints/index.js"
|
|
56
|
-
"types": "./dist/blueprints/index.d.ts"
|
|
56
|
+
"require": "./dist/blueprints/index.js"
|
|
57
57
|
},
|
|
58
58
|
"./blueprints/*": {
|
|
59
|
+
"types": "./dist/blueprints/*.d.ts",
|
|
59
60
|
"import": "./dist/blueprints/*.js",
|
|
60
|
-
"require": "./dist/blueprints/*.js"
|
|
61
|
-
"types": "./dist/blueprints/*.d.ts"
|
|
61
|
+
"require": "./dist/blueprints/*.js"
|
|
62
62
|
},
|
|
63
63
|
"./operations": {
|
|
64
|
+
"types": "./dist/operations/index.d.ts",
|
|
64
65
|
"import": "./dist/operations/index.js",
|
|
65
|
-
"require": "./dist/operations/index.js"
|
|
66
|
-
"types": "./dist/operations/index.d.ts"
|
|
66
|
+
"require": "./dist/operations/index.js"
|
|
67
67
|
},
|
|
68
68
|
"./operations/*": {
|
|
69
|
+
"types": "./dist/operations/*.d.ts",
|
|
69
70
|
"import": "./dist/operations/*.js",
|
|
70
|
-
"require": "./dist/operations/*.js"
|
|
71
|
-
"types": "./dist/operations/*.d.ts"
|
|
71
|
+
"require": "./dist/operations/*.js"
|
|
72
72
|
},
|
|
73
73
|
"./actions": {
|
|
74
|
+
"types": "./dist/actions/index.d.ts",
|
|
74
75
|
"import": "./dist/actions/index.js",
|
|
75
|
-
"require": "./dist/actions/index.js"
|
|
76
|
-
"types": "./dist/actions/index.d.ts"
|
|
76
|
+
"require": "./dist/actions/index.js"
|
|
77
77
|
},
|
|
78
78
|
"./actions/*": {
|
|
79
|
+
"types": "./dist/actions/*.d.ts",
|
|
79
80
|
"import": "./dist/actions/*.js",
|
|
80
|
-
"require": "./dist/actions/*.js"
|
|
81
|
-
"types": "./dist/actions/*.d.ts"
|
|
81
|
+
"require": "./dist/actions/*.js"
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@cashu/cashu-ts": "^3.1.1",
|
|
86
86
|
"@gandlaf21/bc-ur": "^1.1.12",
|
|
87
|
-
"applesauce-actions": "0.0.0-next-
|
|
88
|
-
"applesauce-common": "0.0.0-next-
|
|
89
|
-
"applesauce-core": "0.0.0-next-
|
|
87
|
+
"applesauce-actions": "0.0.0-next-20251231055351",
|
|
88
|
+
"applesauce-common": "0.0.0-next-20251231055351",
|
|
89
|
+
"applesauce-core": "0.0.0-next-20251231055351",
|
|
90
90
|
"rxjs": "^7.8.1"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"@hirez_io/observer-spy": "^2.2.0",
|
|
94
94
|
"@types/debug": "^4.1.12",
|
|
95
|
-
"applesauce-signers": "0.0.0-next-
|
|
95
|
+
"applesauce-signers": "0.0.0-next-20251231055351",
|
|
96
96
|
"rimraf": "^6.0.1",
|
|
97
97
|
"typescript": "^5.8.3",
|
|
98
98
|
"vitest": "^4.0.15"
|