applesauce-wallet 0.0.0-next-20250311170821 → 0.0.0-next-20250311175838

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.
@@ -1,3 +1,8 @@
1
1
  import { Action } from "applesauce-actions";
2
2
  /** An action that creates a new 17375 wallet event and 375 wallet backup */
3
3
  export declare function CreateWallet(mints: string[], privateKey?: Uint8Array): Action;
4
+ /** Unlocks the wallet event and optionally the tokens and history events */
5
+ export declare function UnlockWallet(unlock?: {
6
+ history?: boolean;
7
+ tokens?: boolean;
8
+ }): Action;
@@ -1,6 +1,8 @@
1
1
  import { generateSecretKey } from "nostr-tools";
2
- import { WALLET_KIND } from "../helpers/wallet.js";
2
+ import { isWalletLocked, unlockWallet, WALLET_KIND } from "../helpers/wallet.js";
3
3
  import { WalletBackupBlueprint, WalletBlueprint } from "../blueprints/wallet.js";
4
+ import { unlockTokenContent, WALLET_TOKEN_KIND } from "../helpers/tokens.js";
5
+ import { unlockHistoryContent, WALLET_HISTORY_KIND } from "../helpers/history.js";
4
6
  /** An action that creates a new 17375 wallet event and 375 wallet backup */
5
7
  export function CreateWallet(mints, privateKey = generateSecretKey()) {
6
8
  return async ({ events, factory, self, publish }) => {
@@ -13,3 +15,26 @@ export function CreateWallet(mints, privateKey = generateSecretKey()) {
13
15
  await publish("Create wallet", wallet);
14
16
  };
15
17
  }
18
+ /** Unlocks the wallet event and optionally the tokens and history events */
19
+ export function UnlockWallet(unlock) {
20
+ return async ({ events, self, factory }) => {
21
+ const signer = factory.context.signer;
22
+ if (!signer)
23
+ throw new Error("Missing signer");
24
+ const wallet = events.getReplaceable(WALLET_KIND, self);
25
+ if (!wallet)
26
+ throw new Error("Wallet does not exist");
27
+ if (!isWalletLocked(wallet))
28
+ await unlockWallet(wallet, signer);
29
+ if (unlock?.tokens) {
30
+ const tokens = events.getTimeline({ kinds: [WALLET_TOKEN_KIND], authors: [self] });
31
+ for (const token of tokens)
32
+ await unlockTokenContent(token, signer);
33
+ }
34
+ if (unlock?.history) {
35
+ const history = events.getTimeline({ kinds: [WALLET_HISTORY_KIND], authors: [self] });
36
+ for (const entry of history)
37
+ await unlockHistoryContent(entry, signer);
38
+ }
39
+ };
40
+ }
@@ -1,7 +1,7 @@
1
1
  import { HiddenContentSigner } from "applesauce-core/helpers";
2
2
  import { NostrEvent } from "nostr-tools";
3
3
  export declare const WALLET_HISTORY_KIND = 7376;
4
- export type HistoryDetails = {
4
+ export type HistoryContent = {
5
5
  /** The direction of the transaction, in = received, out = sent */
6
6
  direction: "in" | "out";
7
7
  /** The amount of the transaction */
@@ -13,12 +13,12 @@ export type HistoryDetails = {
13
13
  /** The fee paid */
14
14
  fee?: number;
15
15
  };
16
- export declare const HistoryDetailsSymbol: unique symbol;
16
+ export declare const HistoryContentSymbol: unique symbol;
17
17
  /** returns an array of redeemed event ids in a history event */
18
18
  export declare function getHistoryRedeemed(history: NostrEvent): string[];
19
- /** Checks if the history details are locked */
20
- export declare function isHistoryDetailsLocked(history: NostrEvent): boolean;
21
- /** Returns the parsed details of a 7376 history event */
22
- export declare function getHistoryDetails(history: NostrEvent): HistoryDetails;
19
+ /** Checks if the history contents are locked */
20
+ export declare function isHistoryContentLocked(history: NostrEvent): boolean;
21
+ /** Returns the parsed content of a 7376 history event */
22
+ export declare function getHistoryContent(history: NostrEvent): HistoryContent;
23
23
  /** Decrypts a wallet history event */
24
- export declare function unlockHistoryDetails(history: NostrEvent, signer: HiddenContentSigner): Promise<HistoryDetails>;
24
+ export declare function unlockHistoryContent(history: NostrEvent, signer: HiddenContentSigner): Promise<HistoryContent>;
@@ -1,17 +1,17 @@
1
1
  import { getHiddenTags, getOrComputeCachedValue, isETag, isHiddenTagsLocked, unlockHiddenTags, } from "applesauce-core/helpers";
2
2
  export const WALLET_HISTORY_KIND = 7376;
3
- export const HistoryDetailsSymbol = Symbol.for("history-details");
3
+ export const HistoryContentSymbol = Symbol.for("history-content");
4
4
  /** returns an array of redeemed event ids in a history event */
5
5
  export function getHistoryRedeemed(history) {
6
6
  return history.tags.filter((t) => isETag(t) && t[3] === "redeemed").map((t) => t[1]);
7
7
  }
8
- /** Checks if the history details are locked */
9
- export function isHistoryDetailsLocked(history) {
8
+ /** Checks if the history contents are locked */
9
+ export function isHistoryContentLocked(history) {
10
10
  return isHiddenTagsLocked(history);
11
11
  }
12
- /** Returns the parsed details of a 7376 history event */
13
- export function getHistoryDetails(history) {
14
- return getOrComputeCachedValue(history, HistoryDetailsSymbol, () => {
12
+ /** Returns the parsed content of a 7376 history event */
13
+ export function getHistoryContent(history) {
14
+ return getOrComputeCachedValue(history, HistoryContentSymbol, () => {
15
15
  const tags = getHiddenTags(history);
16
16
  if (!tags)
17
17
  throw new Error("History event is locked");
@@ -32,7 +32,7 @@ export function getHistoryDetails(history) {
32
32
  });
33
33
  }
34
34
  /** Decrypts a wallet history event */
35
- export async function unlockHistoryDetails(history, signer) {
35
+ export async function unlockHistoryContent(history, signer) {
36
36
  await unlockHiddenTags(history, signer);
37
- return getHistoryDetails(history);
37
+ return getHistoryContent(history);
38
38
  }
@@ -1,7 +1,7 @@
1
1
  import { HiddenContentSigner } from "applesauce-core/helpers";
2
2
  import { NostrEvent } from "nostr-tools";
3
3
  export declare const WALLET_TOKEN_KIND = 7375;
4
- export type TokenDetails = {
4
+ export type TokenContent = {
5
5
  /** Cashu mint for the proofs */
6
6
  mint: string;
7
7
  /** Cashu proofs */
@@ -14,10 +14,10 @@ export type TokenDetails = {
14
14
  /** tokens that were destroyed in the creation of this token (helps on wallet state transitions) */
15
15
  del: string[];
16
16
  };
17
- export declare const TokenDetailsSymbol: unique symbol;
17
+ export declare const TokenContentSymbol: unique symbol;
18
18
  /** Returns the decrypted and parsed details of a 7375 token event */
19
- export declare function getTokenDetails(token: NostrEvent): TokenDetails;
19
+ export declare function getTokenContent(token: NostrEvent): TokenContent;
20
20
  /** Returns if token details are locked */
21
- export declare function isTokenDetailsLocked(token: NostrEvent): boolean;
21
+ export declare function isTokenContentLocked(token: NostrEvent): boolean;
22
22
  /** Decrypts a k:7375 token event */
23
- export declare function unlockTokenDetails(token: NostrEvent, signer: HiddenContentSigner): Promise<TokenDetails>;
23
+ export declare function unlockTokenContent(token: NostrEvent, signer: HiddenContentSigner): Promise<TokenContent>;
@@ -1,9 +1,9 @@
1
1
  import { getHiddenContent, getOrComputeCachedValue, isHiddenContentLocked, unlockHiddenContent, } from "applesauce-core/helpers";
2
2
  export const WALLET_TOKEN_KIND = 7375;
3
- export const TokenDetailsSymbol = Symbol.for("token-details");
3
+ export const TokenContentSymbol = Symbol.for("token-content");
4
4
  /** Returns the decrypted and parsed details of a 7375 token event */
5
- export function getTokenDetails(token) {
6
- return getOrComputeCachedValue(token, TokenDetailsSymbol, () => {
5
+ export function getTokenContent(token) {
6
+ return getOrComputeCachedValue(token, TokenContentSymbol, () => {
7
7
  const plaintext = getHiddenContent(token);
8
8
  if (!plaintext)
9
9
  throw new Error("Token is locked");
@@ -18,12 +18,12 @@ export function getTokenDetails(token) {
18
18
  });
19
19
  }
20
20
  /** Returns if token details are locked */
21
- export function isTokenDetailsLocked(token) {
21
+ export function isTokenContentLocked(token) {
22
22
  return isHiddenContentLocked(token);
23
23
  }
24
24
  /** Decrypts a k:7375 token event */
25
- export async function unlockTokenDetails(token, signer) {
25
+ export async function unlockTokenContent(token, signer) {
26
26
  if (isHiddenContentLocked(token))
27
27
  await unlockHiddenContent(token, signer);
28
- return getTokenDetails(token);
28
+ return getTokenContent(token);
29
29
  }
@@ -11,4 +11,4 @@ export declare function unlockWallet(wallet: NostrEvent, signer: HiddenContentSi
11
11
  /** Returns the wallets mints */
12
12
  export declare function getWalletMints(wallet: NostrEvent): string[];
13
13
  /** Returns the wallets private key as a string */
14
- export declare function getWalletPrivateKey(wallet: NostrEvent): string;
14
+ export declare function getWalletPrivateKey(wallet: NostrEvent): Uint8Array;
@@ -1,3 +1,4 @@
1
+ import { hexToBytes } from "@noble/hashes/utils";
1
2
  import { getHiddenTags, getOrComputeCachedValue, isHiddenTagsLocked, unlockHiddenTags, } from "applesauce-core/helpers";
2
3
  export const WALLET_KIND = 17375;
3
4
  export const WALLET_BACKUP_KIND = 375;
@@ -29,6 +30,6 @@ export function getWalletPrivateKey(wallet) {
29
30
  const key = tags.find((t) => t[0] === "privkey" && t[1])?.[1];
30
31
  if (!key)
31
32
  throw new Error("Wallet missing private key");
32
- return key;
33
+ return hexToBytes(key);
33
34
  });
34
35
  }
@@ -1,4 +1,4 @@
1
- import { getHistoryRedeemed, isHistoryDetailsLocked, WALLET_HISTORY_KIND } from "../helpers/history.js";
1
+ import { getHistoryRedeemed, isHistoryContentLocked, WALLET_HISTORY_KIND } from "../helpers/history.js";
2
2
  import { combineLatest, filter, map, scan, startWith } from "rxjs";
3
3
  /** Query that returns an array of redeemed event ids for a wallet */
4
4
  export function WalletRedeemedQuery(pubkey) {
@@ -20,7 +20,7 @@ export function WalletHistoryQuery(pubkey, locked) {
20
20
  if (locked === undefined)
21
21
  return history;
22
22
  else
23
- return history.filter((entry) => isHistoryDetailsLocked(entry) === locked);
23
+ return history.filter((entry) => isHistoryContentLocked(entry) === locked);
24
24
  }));
25
25
  },
26
26
  };
@@ -1,5 +1,5 @@
1
1
  import { combineLatest, filter, map, startWith } from "rxjs";
2
- import { getTokenDetails, isTokenDetailsLocked, WALLET_TOKEN_KIND } from "../helpers/tokens.js";
2
+ import { getTokenContent, isTokenContentLocked, WALLET_TOKEN_KIND } from "../helpers/tokens.js";
3
3
  /** removes deleted events from sorted array */
4
4
  function filterDeleted(tokens) {
5
5
  const deleted = new Set();
@@ -10,11 +10,11 @@ function filterDeleted(tokens) {
10
10
  if (deleted.has(token.id))
11
11
  return false;
12
12
  // skip if token is locked
13
- if (isTokenDetailsLocked(token))
13
+ if (isTokenContentLocked(token))
14
14
  return false;
15
15
  else {
16
16
  // add ids to deleted array
17
- const details = getTokenDetails(token);
17
+ const details = getTokenContent(token);
18
18
  for (const id of details.del)
19
19
  deleted.add(id);
20
20
  }
@@ -35,7 +35,7 @@ export function WalletTokensQuery(pubkey, locked) {
35
35
  if (locked === undefined)
36
36
  return tokens;
37
37
  else
38
- return tokens.filter((t) => isTokenDetailsLocked(t) === locked);
38
+ return tokens.filter((t) => isTokenContentLocked(t) === locked);
39
39
  }),
40
40
  // remove deleted events
41
41
  map(filterDeleted));
@@ -54,7 +54,7 @@ export function WalletBalanceQuery(pubkey) {
54
54
  map(filterDeleted),
55
55
  // map tokens to totals
56
56
  map((tokens) => tokens.reduce((totals, token) => {
57
- const details = getTokenDetails(token);
57
+ const details = getTokenContent(token);
58
58
  const total = details.proofs.reduce((t, p) => t + p.amount, 0);
59
59
  return { ...totals, [details.mint]: (totals[details.mint] ?? 0) + total };
60
60
  }, {})));
@@ -1,9 +1,12 @@
1
1
  import { Query } from "applesauce-core";
2
+ import { NostrEvent } from "nostr-tools";
2
3
  export type WalletInfo = {
3
4
  locked: true;
5
+ event: NostrEvent;
4
6
  } | {
5
7
  locked: false;
6
- privateKey: string;
8
+ event: NostrEvent;
9
+ privateKey: Uint8Array;
7
10
  mints: string[];
8
11
  };
9
12
  /** A query to get the state of a NIP-60 wallet */
@@ -12,10 +12,10 @@ export function WalletQuery(pubkey) {
12
12
  if (!wallet)
13
13
  return;
14
14
  if (isWalletLocked(wallet))
15
- return { locked: true };
15
+ return { locked: true, event: wallet };
16
16
  const mints = getWalletMints(wallet);
17
17
  const privateKey = getWalletPrivateKey(wallet);
18
- return { locked: false, mints, privateKey };
18
+ return { locked: false, mints, privateKey, event: wallet };
19
19
  })),
20
20
  };
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-wallet",
3
- "version": "0.0.0-next-20250311170821",
3
+ "version": "0.0.0-next-20250311175838",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -78,16 +78,16 @@
78
78
  },
79
79
  "dependencies": {
80
80
  "@noble/hashes": "^1.7.1",
81
- "applesauce-actions": "0.0.0-next-20250311170821",
82
- "applesauce-core": "0.0.0-next-20250311170821",
83
- "applesauce-factory": "0.0.0-next-20250311170821",
81
+ "applesauce-actions": "0.0.0-next-20250311175838",
82
+ "applesauce-core": "0.0.0-next-20250311175838",
83
+ "applesauce-factory": "0.0.0-next-20250311175838",
84
84
  "nostr-tools": "^2.10.4",
85
85
  "rxjs": "^7.8.1"
86
86
  },
87
87
  "devDependencies": {
88
88
  "@hirez_io/observer-spy": "^2.2.0",
89
89
  "@types/debug": "^4.1.12",
90
- "applesauce-signers": "0.0.0-next-20250311170821",
90
+ "applesauce-signers": "0.0.0-next-20250311175838",
91
91
  "typescript": "^5.7.3",
92
92
  "vitest": "^3.0.5"
93
93
  },