applesauce-wallet 0.0.0-next-20250723224513 → 0.0.0-next-20250726160247
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/zap-info.js +2 -2
- package/dist/blueprints/history.js +1 -1
- package/dist/blueprints/tokens.js +2 -2
- package/dist/blueprints/wallet.js +3 -5
- package/dist/blueprints/zaps.js +4 -4
- package/dist/helpers/index.d.ts +1 -1
- package/dist/helpers/index.js +1 -1
- package/dist/helpers/{zaps.d.ts → nutzap.d.ts} +1 -0
- package/dist/helpers/{zaps.js → nutzap.js} +7 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.js +1 -1
- package/dist/models/{zaps.js → nutzap.js} +1 -1
- package/dist/operations/{event/history.d.ts → history.d.ts} +2 -2
- package/dist/operations/history.js +34 -0
- package/dist/operations/index.d.ts +5 -2
- package/dist/operations/index.js +5 -2
- package/dist/operations/{event/zaps.d.ts → nutzap.d.ts} +5 -5
- package/dist/operations/{event/zaps.js → nutzap.js} +8 -7
- package/dist/operations/{event/tokens.d.ts → tokens.d.ts} +1 -1
- package/dist/operations/{event/tokens.js → tokens.js} +2 -2
- package/dist/operations/wallet.d.ts +8 -0
- package/dist/operations/wallet.js +30 -0
- package/dist/operations/{event/zap-info.js → zap-info.js} +1 -1
- package/package.json +5 -5
- package/dist/__tests__/exports.test.d.ts +0 -1
- package/dist/__tests__/exports.test.js +0 -16
- package/dist/__tests__/fake-user.d.ts +0 -10
- package/dist/__tests__/fake-user.js +0 -31
- package/dist/actions/__tests__/exports.test.d.ts +0 -1
- package/dist/actions/__tests__/exports.test.js +0 -17
- package/dist/actions/__tests__/tokens.test.d.ts +0 -1
- package/dist/actions/__tests__/tokens.test.js +0 -139
- package/dist/actions/__tests__/wallet.test.d.ts +0 -1
- package/dist/actions/__tests__/wallet.test.js +0 -56
- package/dist/blueprints/__tests__/exports.test.d.ts +0 -1
- package/dist/blueprints/__tests__/exports.test.js +0 -13
- package/dist/helpers/__tests__/animated-qr.test.d.ts +0 -1
- package/dist/helpers/__tests__/animated-qr.test.js +0 -44
- package/dist/helpers/__tests__/exports.test.d.ts +0 -1
- package/dist/helpers/__tests__/exports.test.js +0 -42
- package/dist/helpers/__tests__/tokens.test.d.ts +0 -1
- package/dist/helpers/__tests__/tokens.test.js +0 -127
- package/dist/models/__tests__/exports.test.d.ts +0 -1
- package/dist/models/__tests__/exports.test.js +0 -15
- package/dist/models/__tests__/wallet.test.d.ts +0 -1
- package/dist/models/__tests__/wallet.test.js +0 -28
- package/dist/operations/__tests__/exports.test.d.ts +0 -1
- package/dist/operations/__tests__/exports.test.js +0 -12
- package/dist/operations/event/__tests__/exports.test.d.ts +0 -1
- package/dist/operations/event/__tests__/exports.test.js +0 -14
- package/dist/operations/event/__tests__/wallet.test.d.ts +0 -1
- package/dist/operations/event/__tests__/wallet.test.js +0 -25
- package/dist/operations/event/history.js +0 -19
- package/dist/operations/event/index.d.ts +0 -5
- package/dist/operations/event/index.js +0 -5
- package/dist/operations/event/wallet.d.ts +0 -4
- package/dist/operations/event/wallet.js +0 -14
- package/dist/operations/tag/__tests__/exports.test.d.ts +0 -1
- package/dist/operations/tag/__tests__/exports.test.js +0 -18
- package/dist/operations/tag/__tests__/wallet.test.d.ts +0 -1
- package/dist/operations/tag/__tests__/wallet.test.js +0 -16
- package/dist/operations/tag/history.d.ts +0 -14
- package/dist/operations/tag/history.js +0 -34
- package/dist/operations/tag/index.d.ts +0 -2
- package/dist/operations/tag/index.js +0 -2
- package/dist/operations/tag/wallet.d.ts +0 -5
- package/dist/operations/tag/wallet.js +0 -15
- package/dist/queries/__tests__/exports.test.d.ts +0 -1
- package/dist/queries/__tests__/exports.test.js +0 -15
- package/dist/queries/__tests__/wallet.test.d.ts +0 -1
- package/dist/queries/__tests__/wallet.test.js +0 -30
- package/dist/queries/history.d.ts +0 -6
- package/dist/queries/history.js +0 -21
- package/dist/queries/index.d.ts +0 -3
- package/dist/queries/index.js +0 -3
- package/dist/queries/tokens.d.ts +0 -6
- package/dist/queries/tokens.js +0 -58
- package/dist/queries/wallet.d.ts +0 -13
- package/dist/queries/wallet.js +0 -18
- /package/dist/models/{zaps.d.ts → nutzap.d.ts} +0 -0
- /package/dist/operations/{event/zap-info.d.ts → zap-info.d.ts} +0 -0
package/dist/actions/zap-info.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { modifyPublicTags } from "applesauce-factory/operations
|
|
1
|
+
import { modifyPublicTags } from "applesauce-factory/operations";
|
|
2
2
|
import { addNameValueTag, removeNameValueTag, setSingletonTag } from "applesauce-factory/operations/tag";
|
|
3
3
|
import { NUTZAP_INFO_KIND } from "../helpers/zap-info.js";
|
|
4
|
-
import { setNutzapInfoMints, setNutzapInfoPubkey, setNutzapInfoRelays } from "../operations/
|
|
4
|
+
import { setNutzapInfoMints, setNutzapInfoPubkey, setNutzapInfoRelays } from "../operations/zap-info.js";
|
|
5
5
|
/** An action to add a relay to the kind 10019 nutzap info event */
|
|
6
6
|
export function AddNutzapInfoRelay(relay) {
|
|
7
7
|
return async function* ({ events, factory, self }) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { blueprint } from "applesauce-factory";
|
|
2
2
|
import { WALLET_HISTORY_KIND } from "../helpers/history.js";
|
|
3
|
-
import { setHistoryContent, setHistoryRedeemed } from "../operations/
|
|
3
|
+
import { setHistoryContent, setHistoryRedeemed } from "../operations/history.js";
|
|
4
4
|
/** A blueprint that creates a wallet history event */
|
|
5
5
|
export function WalletHistoryBlueprint(content, redeemed) {
|
|
6
6
|
return blueprint(WALLET_HISTORY_KIND,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { blueprint } from "applesauce-factory";
|
|
2
2
|
import { WALLET_TOKEN_KIND } from "../helpers/tokens.js";
|
|
3
|
-
import {
|
|
3
|
+
import { setToken } from "../operations/tokens.js";
|
|
4
4
|
/**
|
|
5
5
|
* A blueprint for a wallet token event, takes a cashu token and previous deleted token event ids
|
|
6
6
|
* @param token the cashu token to store
|
|
7
7
|
* @param [del=[]] an array of previous token event ids that are deleted
|
|
8
8
|
*/
|
|
9
9
|
export function WalletTokenBlueprint(token, del = []) {
|
|
10
|
-
return blueprint(WALLET_TOKEN_KIND,
|
|
10
|
+
return blueprint(WALLET_TOKEN_KIND, setToken(token, del));
|
|
11
11
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { blueprint } from "applesauce-factory";
|
|
2
|
-
import { modifyHiddenTags } from "applesauce-factory/operations/event";
|
|
3
2
|
import { WALLET_BACKUP_KIND, WALLET_KIND } from "../helpers/wallet.js";
|
|
4
|
-
import {
|
|
5
|
-
import { setMintTags, setPrivateKeyTag } from "../operations/tag/wallet.js";
|
|
3
|
+
import { setBackupContent, setMints, setPrivateKey } from "../operations/wallet.js";
|
|
6
4
|
/** A blueprint to create a new 17375 wallet */
|
|
7
5
|
export function WalletBlueprint(mints, privateKey) {
|
|
8
|
-
return blueprint(WALLET_KIND,
|
|
6
|
+
return blueprint(WALLET_KIND, setMints(mints), privateKey ? setPrivateKey(privateKey) : undefined);
|
|
9
7
|
}
|
|
10
8
|
/** A blueprint that creates a new 375 wallet backup event */
|
|
11
9
|
export function WalletBackupBlueprint(wallet) {
|
|
12
|
-
return blueprint(WALLET_BACKUP_KIND,
|
|
10
|
+
return blueprint(WALLET_BACKUP_KIND, setBackupContent(wallet));
|
|
13
11
|
}
|
package/dist/blueprints/zaps.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { blueprint } from "applesauce-factory";
|
|
2
2
|
import { skip } from "applesauce-factory/helpers";
|
|
3
|
-
import { NUTZAP_KIND } from "../helpers/
|
|
4
|
-
import {
|
|
3
|
+
import { NUTZAP_KIND } from "../helpers/nutzap.js";
|
|
4
|
+
import { setComment, setEvent, setMint, setProofs, setRecipient } from "../operations/nutzap.js";
|
|
5
5
|
/** A blueprint to create a NIP-61 nutzap event for an event */
|
|
6
6
|
export function NutzapBlueprint(event, token, comment) {
|
|
7
|
-
return blueprint(NUTZAP_KIND,
|
|
7
|
+
return blueprint(NUTZAP_KIND, setProofs(token.proofs), setMint(token.mint), setEvent(event), setRecipient(event.pubkey), comment ? setComment(comment) : skip());
|
|
8
8
|
}
|
|
9
9
|
/** A blueprint to create a NIP-61 nutzap event for a user instead of an event */
|
|
10
10
|
export function ProfileNutzapBlueprint(user, token, comment) {
|
|
11
|
-
return blueprint(NUTZAP_KIND,
|
|
11
|
+
return blueprint(NUTZAP_KIND, setProofs(token.proofs), setMint(token.mint), setRecipient(user), comment ? setComment(comment) : skip());
|
|
12
12
|
}
|
package/dist/helpers/index.d.ts
CHANGED
package/dist/helpers/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { AddressPointer, EventPointer } from "nostr-tools/nip19";
|
|
|
4
4
|
export declare const NUTZAP_KIND = 9321;
|
|
5
5
|
export declare const NutzapProofsSymbol: unique symbol;
|
|
6
6
|
export declare const NutzapAmountSymbol: unique symbol;
|
|
7
|
+
export declare const NutzapMintSymbol: unique symbol;
|
|
7
8
|
/** Returns the cashu proofs from a kind:9321 nutzap event */
|
|
8
9
|
export declare function getNutzapProofs(event: NostrEvent): Proof[];
|
|
9
10
|
/** Returns the mint URL from a kind:9321 nutzap event */
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { getAddressPointerFromATag, getEventPointerFromETag, getOrComputeCachedValue, processTags, safeParse, } from "applesauce-core/helpers";
|
|
1
|
+
import { getAddressPointerFromATag, getEventPointerFromETag, getOrComputeCachedValue, getTagValue, processTags, safeParse, } from "applesauce-core/helpers";
|
|
2
2
|
import { getHistoryRedeemed } from "./history.js";
|
|
3
3
|
export const NUTZAP_KIND = 9321;
|
|
4
4
|
// Symbols for caching computed values
|
|
5
5
|
export const NutzapProofsSymbol = Symbol.for("nutzap-proofs");
|
|
6
6
|
export const NutzapAmountSymbol = Symbol.for("nutzap-amount");
|
|
7
|
+
export const NutzapMintSymbol = Symbol.for("nutzap-mint");
|
|
7
8
|
/** Returns the cashu proofs from a kind:9321 nutzap event */
|
|
8
9
|
export function getNutzapProofs(event) {
|
|
9
10
|
return getOrComputeCachedValue(event, NutzapProofsSymbol, () => {
|
|
@@ -12,11 +13,14 @@ export function getNutzapProofs(event) {
|
|
|
12
13
|
}
|
|
13
14
|
/** Returns the mint URL from a kind:9321 nutzap event */
|
|
14
15
|
export function getNutzapMint(event) {
|
|
15
|
-
return event
|
|
16
|
+
return getOrComputeCachedValue(event, NutzapMintSymbol, () => {
|
|
17
|
+
const url = getTagValue(event, "u");
|
|
18
|
+
return url && URL.canParse(url) ? url : undefined;
|
|
19
|
+
});
|
|
16
20
|
}
|
|
17
21
|
/** Returns the recipient pubkey from a kind:9321 nutzap event */
|
|
18
22
|
export function getNutzapRecipient(event) {
|
|
19
|
-
return event
|
|
23
|
+
return getTagValue(event, "p");
|
|
20
24
|
}
|
|
21
25
|
/** Returns the event ID being nutzapped from a kind:9321 nutzap event */
|
|
22
26
|
export function getNutzapEventPointer(event) {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export * as Actions from "./actions/index.js";
|
|
|
2
2
|
export * as Blueprints from "./blueprints/index.js";
|
|
3
3
|
export * as Helpers from "./helpers/index.js";
|
|
4
4
|
export * as Models from "./models/index.js";
|
|
5
|
-
export * from "./operations/index.js";
|
|
5
|
+
export * as Operations from "./operations/index.js";
|
package/dist/index.js
CHANGED
|
@@ -2,4 +2,4 @@ export * as Actions from "./actions/index.js";
|
|
|
2
2
|
export * as Blueprints from "./blueprints/index.js";
|
|
3
3
|
export * as Helpers from "./helpers/index.js";
|
|
4
4
|
export * as Models from "./models/index.js";
|
|
5
|
-
export * from "./operations/index.js";
|
|
5
|
+
export * as Operations from "./operations/index.js";
|
package/dist/models/index.d.ts
CHANGED
package/dist/models/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getReplaceableAddress, isReplaceable } from "applesauce-core/helpers";
|
|
2
2
|
import { map } from "rxjs";
|
|
3
|
-
import { getNutzapPointer, NUTZAP_KIND } from "../helpers/
|
|
3
|
+
import { getNutzapPointer, NUTZAP_KIND } from "../helpers/nutzap.js";
|
|
4
4
|
/** A model that returns all nutzap events for an event */
|
|
5
5
|
export function EventNutZapzModel(event) {
|
|
6
6
|
return (events) => isReplaceable(event.kind)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EventOperation } from "applesauce-factory";
|
|
2
|
-
import { HistoryContent } from "../../helpers/history.js";
|
|
3
2
|
import { EventPointer } from "nostr-tools/nip19";
|
|
3
|
+
import { HistoryContent } from "../helpers/history.js";
|
|
4
4
|
/** Sets the encrypted tags of a wallet history event */
|
|
5
5
|
export declare function setHistoryContent(content: HistoryContent): EventOperation;
|
|
6
|
-
/** Sets the "redeemed" tags on a wallet history event */
|
|
6
|
+
/** Sets the "e" "redeemed" tags on a wallet history event */
|
|
7
7
|
export declare function setHistoryRedeemed(redeemed: (string | EventPointer)[]): EventOperation;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ensureMarkedEventPointerTag } from "applesauce-factory/helpers";
|
|
2
|
+
import { modifyHiddenTags, modifyPublicTags } from "applesauce-factory/operations";
|
|
3
|
+
import { setSingletonTag } from "applesauce-factory/operations/tag";
|
|
4
|
+
/** Includes "e" "created" tags in wallet history tags */
|
|
5
|
+
function includeHistoryCreatedTags(created) {
|
|
6
|
+
return (tags) => {
|
|
7
|
+
for (const id of created) {
|
|
8
|
+
tags = ensureMarkedEventPointerTag(tags, typeof id === "string" ? { id } : id, "created");
|
|
9
|
+
}
|
|
10
|
+
return tags;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Sets the encrypted tags of a wallet history event */
|
|
14
|
+
export function setHistoryContent(content) {
|
|
15
|
+
const operations = [
|
|
16
|
+
setSingletonTag(["direction", content.direction], true),
|
|
17
|
+
setSingletonTag(["amount", String(content.amount)], true),
|
|
18
|
+
includeHistoryCreatedTags(content.created),
|
|
19
|
+
];
|
|
20
|
+
if (content.fee !== undefined)
|
|
21
|
+
operations.push(setSingletonTag(["fee", String(content.fee)], true));
|
|
22
|
+
if (content.mint !== undefined)
|
|
23
|
+
operations.push(setSingletonTag(["mint", content.mint], true));
|
|
24
|
+
return modifyHiddenTags(...operations);
|
|
25
|
+
}
|
|
26
|
+
/** Sets the "e" "redeemed" tags on a wallet history event */
|
|
27
|
+
export function setHistoryRedeemed(redeemed) {
|
|
28
|
+
return modifyPublicTags((tags) => {
|
|
29
|
+
for (const id of redeemed) {
|
|
30
|
+
tags = ensureMarkedEventPointerTag(tags, typeof id === "string" ? { id } : id, "redeemed");
|
|
31
|
+
}
|
|
32
|
+
return tags;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
export * as
|
|
2
|
-
export * as
|
|
1
|
+
export * as History from "./history.js";
|
|
2
|
+
export * as Tokens from "./tokens.js";
|
|
3
|
+
export * as Wallet from "./wallet.js";
|
|
4
|
+
export * as ZapInfo from "./zap-info.js";
|
|
5
|
+
export * as NutZap from "./nutzap.js";
|
package/dist/operations/index.js
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
export * as
|
|
2
|
-
export * as
|
|
1
|
+
export * as History from "./history.js";
|
|
2
|
+
export * as Tokens from "./tokens.js";
|
|
3
|
+
export * as Wallet from "./wallet.js";
|
|
4
|
+
export * as ZapInfo from "./zap-info.js";
|
|
5
|
+
export * as NutZap from "./nutzap.js";
|
|
@@ -3,12 +3,12 @@ import { EventOperation } from "applesauce-factory";
|
|
|
3
3
|
import { NostrEvent } from "nostr-tools";
|
|
4
4
|
import { AddressPointer, EventPointer, ProfilePointer } from "nostr-tools/nip19";
|
|
5
5
|
/** Sets the cashu proofs for a nutzap event */
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function setProofs(proofs: Proof[]): EventOperation;
|
|
7
7
|
/** Sets the mint URL for a nutzap event */
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function setMint(mint: string): EventOperation;
|
|
9
9
|
/** Sets the recipient of a nutzap event */
|
|
10
|
-
export declare function
|
|
10
|
+
export declare function setRecipient(recipient: string | ProfilePointer): EventOperation;
|
|
11
11
|
/** Sets the event that is being nutzapped */
|
|
12
|
-
export declare function
|
|
12
|
+
export declare function setEvent(event: EventPointer | AddressPointer | NostrEvent): EventOperation;
|
|
13
13
|
/** Sets the comment content for a nutzap event */
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function setComment(comment: string): EventOperation;
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { getReplaceableAddress, isAddressPointer, isEvent, isReplaceable } from "applesauce-core/helpers";
|
|
2
|
-
import { modifyPublicTags } from "applesauce-factory/operations
|
|
2
|
+
import { modifyPublicTags } from "applesauce-factory/operations";
|
|
3
|
+
import { setContent } from "applesauce-factory/operations/content";
|
|
3
4
|
import { addAddressTag, addEventTag, addPubkeyTag, setSingletonTag } from "applesauce-factory/operations/tag";
|
|
4
5
|
/** Sets the cashu proofs for a nutzap event */
|
|
5
|
-
export function
|
|
6
|
+
export function setProofs(proofs) {
|
|
6
7
|
// Create an operation to append proof tags
|
|
7
8
|
const operation = (tags) => [...tags, ...proofs.map((proof) => ["proof", JSON.stringify(proof)])];
|
|
8
9
|
return modifyPublicTags(operation);
|
|
9
10
|
}
|
|
10
11
|
/** Sets the mint URL for a nutzap event */
|
|
11
|
-
export function
|
|
12
|
+
export function setMint(mint) {
|
|
12
13
|
return modifyPublicTags(setSingletonTag(["u", mint]));
|
|
13
14
|
}
|
|
14
15
|
/** Sets the recipient of a nutzap event */
|
|
15
|
-
export function
|
|
16
|
+
export function setRecipient(recipient) {
|
|
16
17
|
return modifyPublicTags(addPubkeyTag(recipient, true));
|
|
17
18
|
}
|
|
18
19
|
/** Sets the event that is being nutzapped */
|
|
19
|
-
export function
|
|
20
|
+
export function setEvent(event) {
|
|
20
21
|
let operation;
|
|
21
22
|
if (isEvent(event))
|
|
22
23
|
operation = isReplaceable(event.kind) ? addEventTag(event.id) : addAddressTag(getReplaceableAddress(event));
|
|
@@ -27,6 +28,6 @@ export function setNutzapEvent(event) {
|
|
|
27
28
|
return modifyPublicTags(operation);
|
|
28
29
|
}
|
|
29
30
|
/** Sets the comment content for a nutzap event */
|
|
30
|
-
export function
|
|
31
|
-
return (
|
|
31
|
+
export function setComment(comment) {
|
|
32
|
+
return setContent(comment);
|
|
32
33
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Token } from "@cashu/cashu-ts";
|
|
2
2
|
import { EventOperation } from "applesauce-factory";
|
|
3
3
|
/** Sets the content of a 7375 token event */
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function setToken(token: Token, del?: string[]): EventOperation;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EventContentEncryptionMethod } from "applesauce-core/helpers";
|
|
2
|
-
import { setEncryptedContent } from "applesauce-factory/operations/
|
|
2
|
+
import { setEncryptedContent } from "applesauce-factory/operations/content";
|
|
3
3
|
/** Sets the content of a 7375 token event */
|
|
4
|
-
export function
|
|
4
|
+
export function setToken(token, del = []) {
|
|
5
5
|
return async (draft, ctx) => {
|
|
6
6
|
if (!ctx.signer)
|
|
7
7
|
throw new Error(`Missing signer`);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { EventOperation } from "applesauce-factory";
|
|
2
|
+
import { NostrEvent } from "nostr-tools";
|
|
3
|
+
/** Sets the content of a kind 375 wallet backup event */
|
|
4
|
+
export declare function setBackupContent(wallet: NostrEvent): EventOperation;
|
|
5
|
+
/** Sets the "mint" tags in a wallet event */
|
|
6
|
+
export declare function setMints(mints: string[]): EventOperation;
|
|
7
|
+
/** Sets the "privkey" tag on a wallet event */
|
|
8
|
+
export declare function setPrivateKey(privateKey: Uint8Array): EventOperation;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { bytesToHex } from "@noble/hashes/utils";
|
|
2
|
+
import { modifyHiddenTags } from "applesauce-factory/operations";
|
|
3
|
+
import { setSingletonTag } from "applesauce-factory/operations/tag";
|
|
4
|
+
import { WALLET_KIND } from "../helpers/wallet.js";
|
|
5
|
+
/** Sets the content of a kind 375 wallet backup event */
|
|
6
|
+
export function setBackupContent(wallet) {
|
|
7
|
+
return async (draft, ctx) => {
|
|
8
|
+
if (wallet.kind !== WALLET_KIND)
|
|
9
|
+
throw new Error(`Cant create a wallet backup from kind ${wallet.kind}`);
|
|
10
|
+
if (!wallet.content)
|
|
11
|
+
throw new Error("Wallet missing content");
|
|
12
|
+
const pubkey = await ctx.signer?.getPublicKey();
|
|
13
|
+
if (wallet.pubkey !== pubkey)
|
|
14
|
+
throw new Error("Wallet pubkey dose not match signer pubkey");
|
|
15
|
+
return { ...draft, content: wallet.content };
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Sets the "mint" tags in a wallet event */
|
|
19
|
+
export function setMints(mints) {
|
|
20
|
+
return modifyHiddenTags((tags) => [
|
|
21
|
+
// remove all existing mint tags
|
|
22
|
+
...tags.filter((t) => t[0] !== "mint"),
|
|
23
|
+
// add new mint tags
|
|
24
|
+
...mints.map((mint) => ["mint", mint]),
|
|
25
|
+
]);
|
|
26
|
+
}
|
|
27
|
+
/** Sets the "privkey" tag on a wallet event */
|
|
28
|
+
export function setPrivateKey(privateKey) {
|
|
29
|
+
return modifyHiddenTags(setSingletonTag(["privkey", bytesToHex(privateKey)], true));
|
|
30
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { modifyPublicTags } from "applesauce-factory/operations
|
|
1
|
+
import { modifyPublicTags } from "applesauce-factory/operations";
|
|
2
2
|
import { addNameValueTag, setSingletonTag } from "applesauce-factory/operations/tag";
|
|
3
3
|
/** Sets the relays for a nutzap info event */
|
|
4
4
|
export function setNutzapInfoRelays(relays) {
|
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-20250726160247",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -80,16 +80,16 @@
|
|
|
80
80
|
"@cashu/cashu-ts": "2.0.0-rc1",
|
|
81
81
|
"@gandlaf21/bc-ur": "^1.1.12",
|
|
82
82
|
"@noble/hashes": "^1.7.1",
|
|
83
|
-
"applesauce-actions": "0.0.0-next-
|
|
84
|
-
"applesauce-core": "0.0.0-next-
|
|
85
|
-
"applesauce-factory": "0.0.0-next-
|
|
83
|
+
"applesauce-actions": "0.0.0-next-20250726160247",
|
|
84
|
+
"applesauce-core": "0.0.0-next-20250726160247",
|
|
85
|
+
"applesauce-factory": "0.0.0-next-20250726160247",
|
|
86
86
|
"nostr-tools": "^2.13",
|
|
87
87
|
"rxjs": "^7.8.1"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@hirez_io/observer-spy": "^2.2.0",
|
|
91
91
|
"@types/debug": "^4.1.12",
|
|
92
|
-
"applesauce-signers": "0.0.0-next-
|
|
92
|
+
"applesauce-signers": "0.0.0-next-20250726160247",
|
|
93
93
|
"typescript": "^5.8.3",
|
|
94
94
|
"vitest": "^3.2.3"
|
|
95
95
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import * as exports from "../index.js";
|
|
3
|
-
describe("exports", () => {
|
|
4
|
-
it("should export the expected functions", () => {
|
|
5
|
-
expect(Object.keys(exports).sort()).toMatchInlineSnapshot(`
|
|
6
|
-
[
|
|
7
|
-
"Actions",
|
|
8
|
-
"Blueprints",
|
|
9
|
-
"EventOperations",
|
|
10
|
-
"Helpers",
|
|
11
|
-
"Queries",
|
|
12
|
-
"TagOperations",
|
|
13
|
-
]
|
|
14
|
-
`);
|
|
15
|
-
});
|
|
16
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { SimpleSigner } from "applesauce-signers/signers/simple-signer";
|
|
2
|
-
import type { NostrEvent } from "nostr-tools";
|
|
3
|
-
export declare class FakeUser extends SimpleSigner {
|
|
4
|
-
pubkey: string;
|
|
5
|
-
event(data?: Partial<NostrEvent>): NostrEvent;
|
|
6
|
-
note(content?: string, extra?: Partial<NostrEvent>): import("nostr-tools").Event;
|
|
7
|
-
profile(profile: any, extra?: Partial<NostrEvent>): import("nostr-tools").Event;
|
|
8
|
-
contacts(pubkeys?: string[]): import("nostr-tools").Event;
|
|
9
|
-
list(tags?: string[][], extra?: Partial<NostrEvent>): import("nostr-tools").Event;
|
|
10
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { unixNow } from "applesauce-core/helpers";
|
|
2
|
-
import { SimpleSigner } from "applesauce-signers/signers/simple-signer";
|
|
3
|
-
import { finalizeEvent, getPublicKey, kinds } from "nostr-tools";
|
|
4
|
-
export class FakeUser extends SimpleSigner {
|
|
5
|
-
pubkey = getPublicKey(this.key);
|
|
6
|
-
event(data) {
|
|
7
|
-
return finalizeEvent({
|
|
8
|
-
kind: data?.kind ?? kinds.ShortTextNote,
|
|
9
|
-
content: data?.content || "",
|
|
10
|
-
created_at: data?.created_at ?? unixNow(),
|
|
11
|
-
tags: data?.tags || [],
|
|
12
|
-
}, this.key);
|
|
13
|
-
}
|
|
14
|
-
note(content = "Hello World", extra) {
|
|
15
|
-
return this.event({ kind: kinds.ShortTextNote, content, ...extra });
|
|
16
|
-
}
|
|
17
|
-
profile(profile, extra) {
|
|
18
|
-
return this.event({ kind: kinds.Metadata, content: JSON.stringify({ ...profile }), ...extra });
|
|
19
|
-
}
|
|
20
|
-
contacts(pubkeys = []) {
|
|
21
|
-
return this.event({ kind: kinds.Contacts, tags: pubkeys.map((p) => ["p", p]) });
|
|
22
|
-
}
|
|
23
|
-
list(tags = [], extra) {
|
|
24
|
-
return this.event({
|
|
25
|
-
kind: kinds.Bookmarksets,
|
|
26
|
-
content: "",
|
|
27
|
-
tags: [["d", String(Math.round(Math.random() * 10000))], ...tags],
|
|
28
|
-
...extra,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import * as exports from "../index.js";
|
|
3
|
-
describe("exports", () => {
|
|
4
|
-
it("should export the expected functions", () => {
|
|
5
|
-
expect(Object.keys(exports).sort()).toMatchInlineSnapshot(`
|
|
6
|
-
[
|
|
7
|
-
"CompleteSpend",
|
|
8
|
-
"ConsolidateTokens",
|
|
9
|
-
"CreateWallet",
|
|
10
|
-
"ReceiveToken",
|
|
11
|
-
"RolloverTokens",
|
|
12
|
-
"UnlockWallet",
|
|
13
|
-
"WalletAddPrivateKey",
|
|
14
|
-
]
|
|
15
|
-
`);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, vitest } from "vitest";
|
|
2
|
-
import { EventStore } from "applesauce-core";
|
|
3
|
-
import { EventFactory } from "applesauce-factory";
|
|
4
|
-
import { ActionHub } from "applesauce-actions";
|
|
5
|
-
import { CheckStateEnum } from "@cashu/cashu-ts";
|
|
6
|
-
import { subscribeSpyTo } from "@hirez_io/observer-spy";
|
|
7
|
-
import { FakeUser } from "../../__tests__/fake-user.js";
|
|
8
|
-
import { ConsolidateTokens } from "../tokens.js";
|
|
9
|
-
import { WalletTokenBlueprint } from "../../blueprints/tokens.js";
|
|
10
|
-
import { unlockTokenContent, WALLET_TOKEN_KIND } from "../../helpers/tokens.js";
|
|
11
|
-
// Update the mock to allow controlling the states
|
|
12
|
-
const mockCheckProofsStates = vitest.fn();
|
|
13
|
-
vitest.mock("@cashu/cashu-ts", () => ({
|
|
14
|
-
CashuMint: vitest.fn(),
|
|
15
|
-
CashuWallet: vitest.fn().mockImplementation(() => ({
|
|
16
|
-
checkProofsStates: mockCheckProofsStates,
|
|
17
|
-
})),
|
|
18
|
-
CheckStateEnum: { UNSPENT: "UNSPENT", SPENT: "SPENT" },
|
|
19
|
-
}));
|
|
20
|
-
const user = new FakeUser();
|
|
21
|
-
const testMint = "https://mint.test.com";
|
|
22
|
-
let events;
|
|
23
|
-
let factory;
|
|
24
|
-
let hub;
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
events = new EventStore();
|
|
27
|
-
factory = new EventFactory({ signer: user });
|
|
28
|
-
hub = new ActionHub(events, factory);
|
|
29
|
-
// Reset the mock before each test
|
|
30
|
-
mockCheckProofsStates.mockReset();
|
|
31
|
-
});
|
|
32
|
-
describe("ConsolidateTokens", () => {
|
|
33
|
-
it("should combine multiple token events into a single event", async () => {
|
|
34
|
-
// Set all proofs to be unspent
|
|
35
|
-
mockCheckProofsStates.mockResolvedValue([{ state: CheckStateEnum.UNSPENT }, { state: CheckStateEnum.UNSPENT }]);
|
|
36
|
-
// Create two token events with different proofs
|
|
37
|
-
const token1 = await factory.sign(await factory.create(WalletTokenBlueprint, {
|
|
38
|
-
mint: testMint,
|
|
39
|
-
proofs: [{ amount: 10, secret: "secret1", C: "C", id: "id" }],
|
|
40
|
-
}));
|
|
41
|
-
const token2 = await factory.sign(await factory.create(WalletTokenBlueprint, {
|
|
42
|
-
mint: testMint,
|
|
43
|
-
proofs: [{ amount: 20, secret: "secret2", C: "C", id: "id" }],
|
|
44
|
-
}));
|
|
45
|
-
// Add tokens to event store
|
|
46
|
-
events.add(token1);
|
|
47
|
-
events.add(token2);
|
|
48
|
-
// Run consolidate action
|
|
49
|
-
const spy = subscribeSpyTo(hub.exec(ConsolidateTokens));
|
|
50
|
-
await spy.onComplete();
|
|
51
|
-
// First event should be the new consolidated token
|
|
52
|
-
expect(spy.getValueAt(0).kind).toBe(WALLET_TOKEN_KIND);
|
|
53
|
-
// Extract token content and verify proofs were combined
|
|
54
|
-
const content = await unlockTokenContent(spy.getValueAt(0), user);
|
|
55
|
-
expect(content.proofs).toHaveLength(2);
|
|
56
|
-
expect(content.proofs).toEqual(expect.arrayContaining([
|
|
57
|
-
expect.objectContaining({ amount: 10, secret: "secret1" }),
|
|
58
|
-
expect.objectContaining({ amount: 20, secret: "secret2" }),
|
|
59
|
-
]));
|
|
60
|
-
expect(content.mint).toBe(testMint);
|
|
61
|
-
});
|
|
62
|
-
it("should handle duplicate proofs", async () => {
|
|
63
|
-
// Set all proofs to be unspent
|
|
64
|
-
mockCheckProofsStates.mockResolvedValue([{ state: CheckStateEnum.UNSPENT }, { state: CheckStateEnum.UNSPENT }]);
|
|
65
|
-
// Create two token events with different proofs
|
|
66
|
-
const token1 = await factory.sign(await factory.create(WalletTokenBlueprint, {
|
|
67
|
-
mint: testMint,
|
|
68
|
-
proofs: [{ amount: 10, secret: "secret1", C: "C", id: "id" }],
|
|
69
|
-
}));
|
|
70
|
-
const token2 = await factory.sign(await factory.create(WalletTokenBlueprint, {
|
|
71
|
-
mint: testMint,
|
|
72
|
-
proofs: [
|
|
73
|
-
{ amount: 20, secret: "secret2", C: "C", id: "id" },
|
|
74
|
-
{ amount: 10, secret: "secret1", C: "C", id: "id" },
|
|
75
|
-
],
|
|
76
|
-
}));
|
|
77
|
-
// Add tokens to event store
|
|
78
|
-
events.add(token1);
|
|
79
|
-
events.add(token2);
|
|
80
|
-
// Run consolidate action
|
|
81
|
-
const spy = subscribeSpyTo(hub.exec(ConsolidateTokens));
|
|
82
|
-
await spy.onComplete();
|
|
83
|
-
// First event should be the new consolidated token
|
|
84
|
-
expect(spy.getValueAt(0).kind).toBe(WALLET_TOKEN_KIND);
|
|
85
|
-
// Extract token content and verify proofs were combined
|
|
86
|
-
const content = await unlockTokenContent(spy.getValueAt(0), user);
|
|
87
|
-
expect(content.proofs).toHaveLength(2);
|
|
88
|
-
expect(content.proofs).toEqual(expect.arrayContaining([
|
|
89
|
-
expect.objectContaining({ amount: 10, secret: "secret1" }),
|
|
90
|
-
expect.objectContaining({ amount: 20, secret: "secret2" }),
|
|
91
|
-
]));
|
|
92
|
-
expect(content.mint).toBe(testMint);
|
|
93
|
-
});
|
|
94
|
-
it("should filter out spent proofs", async () => {
|
|
95
|
-
// Create token events with multiple proofs
|
|
96
|
-
const token1 = await factory.sign(await factory.create(WalletTokenBlueprint, {
|
|
97
|
-
mint: testMint,
|
|
98
|
-
proofs: [
|
|
99
|
-
{ amount: 10, secret: "secret1", C: "C", id: "id" },
|
|
100
|
-
{ amount: 20, secret: "secret2", C: "C", id: "id" },
|
|
101
|
-
],
|
|
102
|
-
}, []));
|
|
103
|
-
const token2 = await factory.sign(await factory.create(WalletTokenBlueprint, {
|
|
104
|
-
mint: testMint,
|
|
105
|
-
proofs: [
|
|
106
|
-
{ amount: 30, secret: "secret3", C: "C", id: "id" },
|
|
107
|
-
{ amount: 40, secret: "secret4", C: "C", id: "id" },
|
|
108
|
-
],
|
|
109
|
-
}, []));
|
|
110
|
-
// Add tokens to event store
|
|
111
|
-
events.add(token1);
|
|
112
|
-
events.add(token2);
|
|
113
|
-
// Mock some proofs as spent
|
|
114
|
-
mockCheckProofsStates.mockResolvedValue([
|
|
115
|
-
{ state: CheckStateEnum.UNSPENT }, // secret1
|
|
116
|
-
{ state: CheckStateEnum.SPENT }, // secret2
|
|
117
|
-
{ state: CheckStateEnum.SPENT }, // secret3
|
|
118
|
-
{ state: CheckStateEnum.UNSPENT }, // secret4
|
|
119
|
-
]);
|
|
120
|
-
// Run consolidate action
|
|
121
|
-
const spy = subscribeSpyTo(hub.exec(ConsolidateTokens));
|
|
122
|
-
await spy.onComplete();
|
|
123
|
-
// Verify the consolidated token only contains unspent proofs
|
|
124
|
-
const content = await unlockTokenContent(spy.getValueAt(0), user);
|
|
125
|
-
expect(content.proofs).toHaveLength(2);
|
|
126
|
-
expect(content.proofs).toEqual(expect.arrayContaining([
|
|
127
|
-
expect.objectContaining({ amount: 10, secret: "secret1" }),
|
|
128
|
-
expect.objectContaining({ amount: 40, secret: "secret4" }),
|
|
129
|
-
]));
|
|
130
|
-
expect(content.mint).toBe(testMint);
|
|
131
|
-
// Verify checkProofsStates was called with all proofs
|
|
132
|
-
expect(mockCheckProofsStates).toHaveBeenCalledWith(expect.arrayContaining([
|
|
133
|
-
expect.objectContaining({ amount: 10, secret: "secret1" }),
|
|
134
|
-
expect.objectContaining({ amount: 20, secret: "secret2" }),
|
|
135
|
-
expect.objectContaining({ amount: 30, secret: "secret3" }),
|
|
136
|
-
expect.objectContaining({ amount: 40, secret: "secret4" }),
|
|
137
|
-
]));
|
|
138
|
-
});
|
|
139
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|