mirror of
https://github.com/dergigi/boris.git
synced 2026-02-16 20:45:01 +01:00
Compare commits
268 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
560a4a6785 | ||
|
|
320e7f000a | ||
|
|
832740fb59 | ||
|
|
4aea7b899b | ||
|
|
43492a4488 | ||
|
|
1552dd85d9 | ||
|
|
0bc89889e0 | ||
|
|
7a3dd421fb | ||
|
|
4d95657bca | ||
|
|
6f28c3906c | ||
|
|
fafe378585 | ||
|
|
70b85b0cf0 | ||
|
|
2297d8ae96 | ||
|
|
343f176f06 | ||
|
|
ee788cffb0 | ||
|
|
ca46feb80f | ||
|
|
82ab07e606 | ||
|
|
1f5e3f82b0 | ||
|
|
6265af74f2 | ||
|
|
e8f44986da | ||
|
|
3d304dab15 | ||
|
|
0f7a4d7877 | ||
|
|
d5e847e515 | ||
|
|
edd4e20e22 | ||
|
|
9b0c59b1ae | ||
|
|
8faa2e2de0 | ||
|
|
07a5826774 | ||
|
|
21d6916ae3 | ||
|
|
482ba9b2df | ||
|
|
e4b6d1a122 | ||
|
|
b59a295ad3 | ||
|
|
e771b9778f | ||
|
|
a95c0ed3ff | ||
|
|
4b9a4fb286 | ||
|
|
0c9f68c5cd | ||
|
|
850a4bede5 | ||
|
|
89c00035a8 | ||
|
|
61307fc22d | ||
|
|
31610af706 | ||
|
|
e9cbe56bc0 | ||
|
|
09bbe10aa6 | ||
|
|
188147d057 | ||
|
|
91fe1711cd | ||
|
|
cc0b27f7cd | ||
|
|
0a3bb72d89 | ||
|
|
2719ad3602 | ||
|
|
02798e99e8 | ||
|
|
aba91f7a52 | ||
|
|
dea647f36a | ||
|
|
8be57dea2c | ||
|
|
14a429ca61 | ||
|
|
caf73b7c9f | ||
|
|
915829e82c | ||
|
|
dd3203f34f | ||
|
|
183af3a80c | ||
|
|
3e441925e5 | ||
|
|
9a1efd5b18 | ||
|
|
af6538d577 | ||
|
|
0a78d19195 | ||
|
|
25a1adaeaa | ||
|
|
5c2c8f618c | ||
|
|
726b8a9c10 | ||
|
|
b6edf8de73 | ||
|
|
e10ae00a1a | ||
|
|
bb351ae35f | ||
|
|
ad1e06c867 | ||
|
|
bf8dfe79dd | ||
|
|
0ccad88dfd | ||
|
|
20e9ba1675 | ||
|
|
85d3508190 | ||
|
|
4cf0138706 | ||
|
|
d6e093b3bb | ||
|
|
6489714f33 | ||
|
|
e2749b6a3c | ||
|
|
89e089ad25 | ||
|
|
7e5196d73d | ||
|
|
1b8c276529 | ||
|
|
1b381a0f8c | ||
|
|
35aa9d6cce | ||
|
|
f8c8ab5402 | ||
|
|
67f0a0b3b6 | ||
|
|
4ab9d238d5 | ||
|
|
e0ddd43fe4 | ||
|
|
5f8d4b2c47 | ||
|
|
a4c15ecc0e | ||
|
|
967aac49ef | ||
|
|
d9b50f80d0 | ||
|
|
6ae101c9c6 | ||
|
|
a62e493590 | ||
|
|
9f251d43ad | ||
|
|
b326a9d5b3 | ||
|
|
749270b698 | ||
|
|
b34d8172e0 | ||
|
|
2b9b7d0ebf | ||
|
|
2ca23d67de | ||
|
|
a941449ba4 | ||
|
|
05636046a8 | ||
|
|
1bcaa1998d | ||
|
|
e98dc1c5da | ||
|
|
aa8d3c285d | ||
|
|
9ac8e8f69c | ||
|
|
842bfa5491 | ||
|
|
e2e5d59197 | ||
|
|
0255ff5d03 | ||
|
|
930cd272cb | ||
|
|
2dea3c2a5c | ||
|
|
38b80bc85b | ||
|
|
c0de624fe6 | ||
|
|
1d7ab59272 | ||
|
|
0803417755 | ||
|
|
a602f163fb | ||
|
|
4aa496ec3f | ||
|
|
296600bb0d | ||
|
|
7390104414 | ||
|
|
f4fbc34bc1 | ||
|
|
e83976e5e0 | ||
|
|
0cf7f93482 | ||
|
|
796380ea0d | ||
|
|
3d6403f139 | ||
|
|
57c5be9907 | ||
|
|
bd3193957c | ||
|
|
64efb103a4 | ||
|
|
4afd9ed6d1 | ||
|
|
7e9cdfb0e1 | ||
|
|
bdfb7ca9a6 | ||
|
|
288b96d614 | ||
|
|
99c6a4c23b | ||
|
|
5727a38a7e | ||
|
|
9046150d1f | ||
|
|
53b54c77e7 | ||
|
|
d6756dc5a1 | ||
|
|
5ea81bda8e | ||
|
|
6ad273b5f9 | ||
|
|
32bbda0364 | ||
|
|
857337c748 | ||
|
|
c21c29d5ee | ||
|
|
0d956ed692 | ||
|
|
8fe01d5337 | ||
|
|
55c4fe9d4e | ||
|
|
8014ee4ddd | ||
|
|
365b84ba9d | ||
|
|
c419679099 | ||
|
|
e644f07828 | ||
|
|
448c4dac1c | ||
|
|
85695b5934 | ||
|
|
ef3ce445f5 | ||
|
|
436bbf2b43 | ||
|
|
0c2f528a23 | ||
|
|
d2cf27db42 | ||
|
|
53a6c86d8a | ||
|
|
0b058440bc | ||
|
|
0964156bcc | ||
|
|
86de9c9f1f | ||
|
|
974cecb85f | ||
|
|
9b245b3d29 | ||
|
|
4fe9fd5470 | ||
|
|
18af2d02ea | ||
|
|
a80352d8d3 | ||
|
|
6652694304 | ||
|
|
728c269a29 | ||
|
|
91c68a9d48 | ||
|
|
f9d381e451 | ||
|
|
81a48bd0f6 | ||
|
|
386a821c6b | ||
|
|
d10e12b8df | ||
|
|
c3eb29445e | ||
|
|
e0450385ed | ||
|
|
a2620caa29 | ||
|
|
609e15a738 | ||
|
|
fdb8511c87 | ||
|
|
acce3ad4e2 | ||
|
|
bdecb1409e | ||
|
|
2ca350ee5f | ||
|
|
20f37b94e1 | ||
|
|
21890f002d | ||
|
|
7a5dd2f444 | ||
|
|
5495890204 | ||
|
|
6d585dcef6 | ||
|
|
0bae6674ce | ||
|
|
096509baf6 | ||
|
|
4c2626f3c4 | ||
|
|
70fa3bb6a8 | ||
|
|
719ddf3f0b | ||
|
|
80408148fb | ||
|
|
4163ffa4ba | ||
|
|
cf230623a4 | ||
|
|
9cd4b72f98 | ||
|
|
eb57330915 | ||
|
|
96d93d0e17 | ||
|
|
1d10c10a44 | ||
|
|
dab35820b7 | ||
|
|
9d5e8c194b | ||
|
|
de32807995 | ||
|
|
b671e0e259 | ||
|
|
e5d6fe99f3 | ||
|
|
9400faa00f | ||
|
|
5173a37b69 | ||
|
|
50b32a66de | ||
|
|
1b41b6e823 | ||
|
|
2696bdb57a | ||
|
|
e0b042b6c0 | ||
|
|
1226124566 | ||
|
|
8967963535 | ||
|
|
b64fd6cedb | ||
|
|
c748f173b3 | ||
|
|
51f009a489 | ||
|
|
18d936e222 | ||
|
|
ce7fbdbdf3 | ||
|
|
6e6d43cb25 | ||
|
|
0ed7c1497f | ||
|
|
a2c31b32de | ||
|
|
cdce972e72 | ||
|
|
00638410c0 | ||
|
|
2e5d0e3725 | ||
|
|
a66c051444 | ||
|
|
eb282fcbb0 | ||
|
|
d54313b015 | ||
|
|
03c6a0c9c7 | ||
|
|
dc36992199 | ||
|
|
08fc541eaa | ||
|
|
3eca2879ef | ||
|
|
de428b8719 | ||
|
|
ac7f1007a7 | ||
|
|
4db147ddf3 | ||
|
|
2eda8f3227 | ||
|
|
64825175a7 | ||
|
|
5ee0f49b69 | ||
|
|
7d26372878 | ||
|
|
ab00bd84e6 | ||
|
|
ec4473fc51 | ||
|
|
0f57338866 | ||
|
|
a8cdeeaef2 | ||
|
|
92d49468cd | ||
|
|
a625203fe4 | ||
|
|
e3efcd4a7c | ||
|
|
ba76a6a9ef | ||
|
|
c5a32b911d | ||
|
|
610de95481 | ||
|
|
82c63e5d18 | ||
|
|
b112520056 | ||
|
|
06b15f3fe2 | ||
|
|
4be8eff80a | ||
|
|
559e7ee944 | ||
|
|
7fd8e5341e | ||
|
|
211a89afbb | ||
|
|
695d3509ac | ||
|
|
7bb037f12a | ||
|
|
a7cfc802d1 | ||
|
|
465278742e | ||
|
|
79f83b214f | ||
|
|
170feb1bd7 | ||
|
|
f37deefa36 | ||
|
|
ebdfa47bd8 | ||
|
|
6e57c6227c | ||
|
|
e0acd2f7e7 | ||
|
|
2253172e04 | ||
|
|
15d155c565 | ||
|
|
9c34e8d806 | ||
|
|
934043f858 | ||
|
|
774ce0f1bf | ||
|
|
6481dd1bed | ||
|
|
d7b5b4f9b4 | ||
|
|
bed0f3d508 | ||
|
|
44954a6c15 | ||
|
|
a43e742183 | ||
|
|
a97808b23e | ||
|
|
bf79bbceb8 | ||
|
|
e2690e7177 |
@@ -1,12 +1,10 @@
|
||||
---
|
||||
description: applesauce reference documentation and examples
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
If you can use an applesauce-module for something, use applesauce. https://hzrd149.github.io/applesauce/typedoc/modules.html
|
||||
If you can use an applesauce-module for something, use applesauce.
|
||||
|
||||
Code snippets & examples:
|
||||
- https://hzrd149.github.io/applesauce/snippets/?q=applesauce#nevent1qgszv6q4uryjzr06xfxxew34wwc5hmjfmfpqn229d72gfegsdn2q3fgppemhxue69uhkummn9ekx7mp0qqs8c7umrjum47vjp9jxyyedhyq4v6kvahs6s8tu0r87dvv4cx2ekdq2nepz3
|
||||
- https://hzrd149.github.io/applesauce/snippets/?q=applesauce#nevent1qgszv6q4uryjzr06xfxxew34wwc5hmjfmfpqn229d72gfegsdn2q3fgpz9mhxue69uhkummnw3ezumrpdejz7qpq860x9snxtqxg2jyn8dpmq8we8j6avnw5dhkpgl2s66fzy3rumatqm36qyh
|
||||
- https://hzrd149.github.io/applesauce/snippets/?q=applesauce#nevent1qgsrkwjz6dx0pg2q95vd2dkf62kzavwxqxdfz5a72uyyeqt96xfwxfgppemhxue69uhkummn9ekx7mp0qqsgpexqt77wq4hl3j8l4gvza9cq0hedtlcp6veg04ghg5kl322t7tgqk205c
|
||||
- https://hzrd149.github.io/applesauce/snippets/?q=applesauce#nevent1qgszv6q4uryjzr06xfxxew34wwc5hmjfmfpqn229d72gfegsdn2q3fgpz9mhxue69uhkummnw3ezumrpdejz7qpqqjfzehsxvdq4r2eqc9c5hd80nkznj8sspcs6f77l3498qwz5ne2sst2t48
|
||||
- https://hzrd149.github.io/applesauce/snippets/?q=applesauce#nevent1qgszv6q4uryjzr06xfxxew34wwc5hmjfmfpqn229d72gfegsdn2q3fgpz9mhxue69uhkummnw3ezumrpdejz7qpqsjgpalr742kqcke5av2ey8pnfz7j837u78l30wuzktw3v8j6vufqufzyte
|
||||
Documentation: https://hzrd149.github.io/applesauce/typedoc/modules.html
|
||||
|
||||
When unsure how to use applesauce correctly, look at the examples in the `applesauce/packages/examples` directory.
|
||||
16
.cursor/rules/bookmarks.mdc
Normal file
16
.cursor/rules/bookmarks.mdc
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
description: documentation that's useful when dealing with bookmark events (kind:10003 or kind:30003) or anything related to NIP-51
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
Read the nostrbook to understand how bookmarks work:
|
||||
- https://nostrbook.dev/kinds/10003
|
||||
- https://nostrbook.dev/kinds/30003
|
||||
|
||||
They are defined in NIP-51:
|
||||
- https://github.com/nostr-protocol/nips/blob/master/51.md
|
||||
|
||||
Also refer to the applesauce bookmark helpers:
|
||||
- https://github.com/hzrd149/applesauce/blob/17c9dbb0f2c263e2ebd01729ea2fa138eca12bd1/packages/core/src/helpers/bookmarks.ts
|
||||
|
||||
Make sure to always use applesauce, and use it properly.
|
||||
6
.cursor/rules/fontawesome.mdc
Normal file
6
.cursor/rules/fontawesome.mdc
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
description: when creating or modifying UI elements, especially related to icons and buttons
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
We use FontAwesome. If you can use a fa-icon (instead of text) use a fa-icon. Always strive to keep the UI modern, beautiful, and minimalistic. Shy away from using too many colors, borders, glow, and animations.
|
||||
9
.cursor/rules/highlights-nip-and-docs.mdc
Normal file
9
.cursor/rules/highlights-nip-and-docs.mdc
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
description: nostr highlights spec and docs
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
Here's the spec for nostr-native highlights:
|
||||
|
||||
- https://github.com/nostr-protocol/nips/blob/master/84.md
|
||||
- https://nostrbook.dev/kinds/9802
|
||||
11
.cursor/rules/nostr-native-blog-post-aka-long-form-kind.mdc
Normal file
11
.cursor/rules/nostr-native-blog-post-aka-long-form-kind.mdc
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
description: anything that has to do with kind:30023 aka nostr blog posts aka nostr-native long-form content
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
Always stick to NIPs. Do everything with applesauce (getArticleTitle, getArticleSummary, getHashtags, getMentions).
|
||||
|
||||
- https://github.com/hzrd149/applesauce/blob/17c9dbb0f2c263e2ebd01729ea2fa138eca12bd1/packages/docs/tutorial/02-helpers.md
|
||||
- https://github.com/nostr-protocol/nips/blob/master/19.md
|
||||
- https://github.com/nostr-protocol/nips/blob/master/23.md
|
||||
- https://nostrbook.dev/kinds/30023
|
||||
3
.env.example
Normal file
3
.env.example
Normal file
@@ -0,0 +1,3 @@
|
||||
# Default article to display on app load
|
||||
# This should be a valid naddr1... string (NIP-19 encoded address pointer to a kind:30023 long-form article)
|
||||
VITE_DEFAULT_ARTICLE_NADDR=naddr1qvzqqqr4gupzqmjxss3dld622uu8q25gywum9qtg4w4cv4064jmg20xsac2aam5nqqxnzd3cxqmrzv3exgmr2wfesgsmew
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -116,3 +116,6 @@ temp/
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# applesauce examples
|
||||
applesauce/
|
||||
|
||||
125
README.md
125
README.md
@@ -1,12 +1,21 @@
|
||||
# Markr
|
||||
# Boris
|
||||
|
||||
A minimal nostr client for bookmark management, built with [applesauce](https://github.com/hzrd149/applesauce).
|
||||
|
||||
## Features
|
||||
|
||||
- **Nostr Authentication**: Connect using your nostr account
|
||||
- **Nostr Authentication**: Connect using your nostr account via browser extension
|
||||
- **Bookmark Display**: View your nostr bookmarks as per [NIP-51](https://github.com/nostr-protocol/nips/blob/master/51.md)
|
||||
- **Minimal UI**: Clean, simple interface focused on bookmark management
|
||||
- **Content Classification**: Automatically detect and classify URLs (articles, videos, YouTube, images)
|
||||
- **Reader Mode**: View article content inline with readable formatting
|
||||
- **Collapsible Sidebar**: Expand/collapse bookmark list for focused reading
|
||||
- **Profile Integration**: Display user profile images using applesauce ProfileModel
|
||||
- **Relative Timestamps**: Human-friendly time display (e.g., "2 hours ago")
|
||||
- **Event Links**: Quick access to view bookmarks on search.dergigi.com
|
||||
- **Private Bookmarks**: Support for Amethyst-style hidden/encrypted bookmarks
|
||||
- **Highlights Panel**: View and manage your NIP-84 highlights in a dedicated collapsible panel
|
||||
- **Three-Pane Layout**: Bookmarks sidebar, content viewer, and highlights panel working together
|
||||
- **Minimal UI**: Clean, modern interface focused on bookmark management
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -20,7 +29,7 @@ A minimal nostr client for bookmark management, built with [applesauce](https://
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone <your-repo-url>
|
||||
cd markr
|
||||
cd boris
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
@@ -46,8 +55,10 @@ yarn dev
|
||||
## Usage
|
||||
|
||||
1. **Connect**: Click "Connect with Nostr" to authenticate using your nostr account
|
||||
2. **View Bookmarks**: Once connected, you'll see all your nostr bookmarks
|
||||
3. **Navigate**: Click on bookmark URLs to open them in a new tab
|
||||
2. **View Bookmarks**: Once connected, you'll see all your nostr bookmarks in the left sidebar
|
||||
3. **View Highlights**: Your NIP-84 highlights appear in the right panel
|
||||
4. **Navigate**: Click on bookmark URLs to view content in the center panel
|
||||
5. **Collapse Panels**: Use the collapse buttons to hide/show sidebars for focused viewing
|
||||
|
||||
## Technical Details
|
||||
|
||||
@@ -63,13 +74,66 @@ yarn dev
|
||||
```
|
||||
src/
|
||||
├── components/
|
||||
│ ├── Login.tsx # Authentication component
|
||||
│ └── Bookmarks.tsx # Bookmark display component
|
||||
├── App.tsx # Main application component
|
||||
├── main.tsx # Application entry point
|
||||
└── index.css # Global styles
|
||||
│ ├── Login.tsx # Authentication component
|
||||
│ ├── Bookmarks.tsx # Main bookmarks view with layout
|
||||
│ ├── BookmarkList.tsx # Bookmark list sidebar
|
||||
│ ├── BookmarkItem.tsx # Individual bookmark card
|
||||
│ ├── SidebarHeader.tsx # Header bar with collapse, profile, logout
|
||||
│ ├── ContentPanel.tsx # Content viewer panel
|
||||
│ ├── HighlightsPanel.tsx # Highlights sidebar panel (NIP-84)
|
||||
│ ├── HighlightItem.tsx # Individual highlight display
|
||||
│ ├── IconButton.tsx # Reusable icon button component
|
||||
│ ├── ContentWithResolvedProfiles.tsx # Profile mention resolver
|
||||
│ ├── ResolvedMention.tsx # Nostr mention component
|
||||
│ └── kindIcon.ts # Kind-specific icon mapping
|
||||
├── services/
|
||||
│ ├── bookmarkService.ts # Main bookmark fetching orchestration
|
||||
│ ├── bookmarkProcessing.ts # Decryption and processing pipeline
|
||||
│ ├── bookmarkHelpers.ts # Shared types, guards, and utilities
|
||||
│ ├── bookmarkEvents.ts # Event type handling and deduplication
|
||||
│ ├── highlightService.ts # Highlight fetching (NIP-84)
|
||||
│ └── readerService.ts # Content extraction via reader API
|
||||
├── types/
|
||||
│ ├── bookmarks.ts # Bookmark type definitions
|
||||
│ ├── highlights.ts # Highlight type definitions (NIP-84)
|
||||
│ ├── nostr.d.ts # Nostr type augmentations
|
||||
│ └── relative-time.d.ts # relative-time package types
|
||||
├── utils/
|
||||
│ ├── bookmarkUtils.tsx # Bookmark rendering utilities
|
||||
│ └── helpers.ts # General helper functions
|
||||
├── App.tsx # Main application component
|
||||
├── main.tsx # Application entry point
|
||||
└── index.css # Global styles
|
||||
```
|
||||
|
||||
### Private (hidden) bookmarks (Amethyst-style)
|
||||
|
||||
We support Amethyst-style private (hidden) bookmark lists alongside public ones (NIP‑51):
|
||||
|
||||
- **Detection and unlock**
|
||||
- Use `Helpers.hasHiddenTags(evt)` and `Helpers.isHiddenTagsLocked(evt)` to detect hidden tags.
|
||||
- First try `Helpers.unlockHiddenTags(evt, signer)`; if that fails, try with `'nip44'`.
|
||||
- For events with encrypted `content` that aren’t recognized as supporting hidden tags (e.g. kind 30001), manually decrypt:
|
||||
- Prefer `signer.nip44.decrypt(evt.pubkey, evt.content)`, fallback to `signer.nip04.decrypt(evt.pubkey, evt.content)`.
|
||||
|
||||
- **Parsing and rendering**
|
||||
- Decrypted `content` is JSON `string[][]` (tags). Convert with `Helpers.parseBookmarkTags(hiddenTags)`.
|
||||
- Map to `IndividualBookmark[]` via our `processApplesauceBookmarks(..., isPrivate=true)` and append to the private list so they render immediately alongside public items.
|
||||
|
||||
- **Caching for downstream helpers**
|
||||
- Cache manual results on the event with `BookmarkHiddenSymbol` and also store the decrypted blob under `EncryptedContentSymbol` to aid debugging and hydration.
|
||||
|
||||
- **Structure**
|
||||
- `src/services/bookmarkService.ts`: orchestrates fetching, hydration, and assembling the final bookmark payload.
|
||||
- `src/services/bookmarkProcessing.ts`: decryption/collection pipeline (unlock, manual decrypt, parse, merge).
|
||||
- `src/services/bookmarkHelpers.ts`: shared types, guards, mapping, hydration, and symbols.
|
||||
- `src/services/bookmarkEvents.ts`: event type and de‑duplication for NIP‑51 lists/sets.
|
||||
|
||||
- **Notes**
|
||||
- We avoid `any` via narrow type guards for `nip44`/`nip04` decrypt functions.
|
||||
- Files are kept small and DRY per project rules.
|
||||
- Built on applesauce helpers (`Helpers.getPublicBookmarks`, `Helpers.getHiddenBookmarks`, etc.). See applesauce docs: https://hzrd149.github.io/applesauce/typedoc/modules.html
|
||||
|
||||
### Building for Production
|
||||
|
||||
```bash
|
||||
@@ -80,15 +144,42 @@ pnpm build
|
||||
yarn build
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
### High Priority
|
||||
- [ ] **Mobile Responsive Design**: Optimize sidebar and content panel for mobile devices
|
||||
- [ ] **Keyboard Shortcuts**: Add keyboard navigation (collapse sidebar, navigate bookmarks)
|
||||
- [ ] **Search & Filter**: Add ability to search bookmarks by title, URL, or content
|
||||
- [ ] **Error Handling**: Improve error states and retry logic for failed fetches
|
||||
- [ ] **Loading States**: Better skeleton screens and loading indicators
|
||||
|
||||
### Medium Priority
|
||||
- [ ] **Bookmark Creation**: Add ability to create new bookmarks
|
||||
- [ ] **Bookmark Editing**: Edit existing bookmark metadata and tags
|
||||
- [ ] **Bookmark Deletion**: Remove bookmarks from lists
|
||||
- [ ] **Sorting Options**: Sort by date, title, kind, or custom order
|
||||
- [ ] **Bulk Actions**: Select and perform actions on multiple bookmarks
|
||||
- [ ] **Video Embeds**: Inline YouTube and video playback for video bookmarks
|
||||
|
||||
### Nice to Have
|
||||
- [ ] **Dark/Light Mode Toggle**: User preference for color scheme
|
||||
- [ ] **Export Functionality**: Export bookmarks as JSON, CSV, or HTML
|
||||
- [ ] **Import Bookmarks**: Import from browser bookmarks or other formats
|
||||
- [ ] **Tags & Categories**: Better organization with custom tags
|
||||
- [ ] **Bookmark Collections**: Create and manage custom bookmark collections
|
||||
- [ ] **Offline Support**: Cache bookmarks for offline viewing
|
||||
- [ ] **Share Bookmarks**: Generate shareable links to bookmark lists
|
||||
- [ ] **Performance Optimization**: Virtual scrolling for large bookmark lists
|
||||
- [ ] **Browser Extension**: Quick bookmark saving from any page
|
||||
|
||||
## Contributing
|
||||
|
||||
This is a minimal MVP. Future enhancements could include:
|
||||
Contributions are welcome! Please feel free to submit a Pull Request. Make sure to:
|
||||
|
||||
- Bookmark creation and editing
|
||||
- Bookmark organization and tagging
|
||||
- Search functionality
|
||||
- Export capabilities
|
||||
- Mobile-responsive design improvements
|
||||
- Follow the existing code style
|
||||
- Keep files under 210 lines
|
||||
- Use conventional commits
|
||||
- Run linter and type checks before submitting
|
||||
|
||||
## License
|
||||
|
||||
|
||||
1
applesauce
Symbolic link
1
applesauce
Symbolic link
@@ -0,0 +1 @@
|
||||
../applesauce
|
||||
6
dist/index.html
vendored
6
dist/index.html
vendored
@@ -4,9 +4,9 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Markr - Nostr Bookmarks</title>
|
||||
<script type="module" crossorigin src="/assets/index-ez6f4baA.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DCTVEVF8.css">
|
||||
<title>Boris - Nostr Bookmarks</title>
|
||||
<script type="module" crossorigin src="/assets/index-8PiwZoBK.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Dljx1pJR.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Markr - Nostr Bookmarks</title>
|
||||
<title>Boris - Nostr Bookmarks</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
19
kind-icons.txt
Normal file
19
kind-icons.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
kind:0 = fa-circle-user
|
||||
kind:1 = fa-feather
|
||||
kind:6 = fa-retweet
|
||||
kind:7 = fa-heart
|
||||
kind:20 = fa-image
|
||||
kind:21 = fa-video
|
||||
kind:22 = fa-video
|
||||
kind:1063 = fa-file
|
||||
kind:1337 = fa-laptop-code
|
||||
kind:1617 = fa-code-pull-request
|
||||
kind:1621 = fa-bug
|
||||
kind:1984 = fa-exclamation-triangle
|
||||
kind:9735 = fa-bolt
|
||||
kind:9321 = fa-cloud-bolt
|
||||
kind:9802 = fa-highlighter
|
||||
kind:30023 = fa-newspaper
|
||||
kind:10000 = fa-eye-slash
|
||||
kind:10001 = fa-thumbtack
|
||||
kind:10003 = fa-bookmark
|
||||
1291
node_modules/.package-lock.json
generated
vendored
1291
node_modules/.package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
21
node_modules/@cashu/crypto/LICENSE
generated
vendored
21
node_modules/@cashu/crypto/LICENSE
generated
vendored
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 bitcoinjs contributors, gandlaf21
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
12
node_modules/@cashu/crypto/README.md
generated
vendored
12
node_modules/@cashu/crypto/README.md
generated
vendored
@@ -1,12 +0,0 @@
|
||||
# Cashu Crypto
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
[code coverage](https://gandlafbtc.github.io/cashu-crypto-ts/coverage)
|
||||
|
||||
|
||||
Basic crypto operations for cashu wallets and mints written in TypeScript
|
||||
5
node_modules/@cashu/crypto/modules/client/NUT09.d.ts
generated
vendored
5
node_modules/@cashu/crypto/modules/client/NUT09.d.ts
generated
vendored
@@ -1,5 +0,0 @@
|
||||
export declare const deriveSecret: (seed: Uint8Array, keysetId: string, counter: number) => Uint8Array;
|
||||
export declare const deriveBlindingFactor: (seed: Uint8Array, keysetId: string, counter: number) => Uint8Array;
|
||||
export declare const generateNewMnemonic: () => string;
|
||||
export declare const deriveSeedFromMnemonic: (mnemonic: string) => Uint8Array;
|
||||
//# sourceMappingURL=NUT09.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/client/NUT09.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/client/NUT09.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT09.d.ts","sourceRoot":"","sources":["../../src/client/NUT09.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,YAAY,SAAU,UAAU,YAAY,MAAM,WAAW,MAAM,KAAG,UAElF,CAAC;AAEF,eAAO,MAAM,oBAAoB,SAC1B,UAAU,YACN,MAAM,WACP,MAAM,KACb,UAEF,CAAC;AAkBF,eAAO,MAAM,mBAAmB,QAAO,MAGtC,CAAC;AAEF,eAAO,MAAM,sBAAsB,aAAc,MAAM,KAAG,UAGzD,CAAC"}
|
||||
42
node_modules/@cashu/crypto/modules/client/NUT09.js
generated
vendored
42
node_modules/@cashu/crypto/modules/client/NUT09.js
generated
vendored
@@ -1,42 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.deriveSeedFromMnemonic = exports.generateNewMnemonic = exports.deriveBlindingFactor = exports.deriveSecret = void 0;
|
||||
const bip32_1 = require("@scure/bip32");
|
||||
const index_js_1 = require("../common/index.js");
|
||||
const bip39_1 = require("@scure/bip39");
|
||||
const english_1 = require("@scure/bip39/wordlists/english");
|
||||
const STANDARD_DERIVATION_PATH = `m/129372'/0'`;
|
||||
var DerivationType;
|
||||
(function (DerivationType) {
|
||||
DerivationType[DerivationType["SECRET"] = 0] = "SECRET";
|
||||
DerivationType[DerivationType["BLINDING_FACTOR"] = 1] = "BLINDING_FACTOR";
|
||||
})(DerivationType || (DerivationType = {}));
|
||||
const deriveSecret = (seed, keysetId, counter) => {
|
||||
return derive(seed, keysetId, counter, DerivationType.SECRET);
|
||||
};
|
||||
exports.deriveSecret = deriveSecret;
|
||||
const deriveBlindingFactor = (seed, keysetId, counter) => {
|
||||
return derive(seed, keysetId, counter, DerivationType.BLINDING_FACTOR);
|
||||
};
|
||||
exports.deriveBlindingFactor = deriveBlindingFactor;
|
||||
const derive = (seed, keysetId, counter, secretOrBlinding) => {
|
||||
const hdkey = bip32_1.HDKey.fromMasterSeed(seed);
|
||||
const keysetIdInt = (0, index_js_1.getKeysetIdInt)(keysetId);
|
||||
const derivationPath = `${STANDARD_DERIVATION_PATH}/${keysetIdInt}'/${counter}'/${secretOrBlinding}`;
|
||||
const derived = hdkey.derive(derivationPath);
|
||||
if (derived.privateKey === null) {
|
||||
throw new Error('Could not derive private key');
|
||||
}
|
||||
return derived.privateKey;
|
||||
};
|
||||
const generateNewMnemonic = () => {
|
||||
const mnemonic = (0, bip39_1.generateMnemonic)(english_1.wordlist, 128);
|
||||
return mnemonic;
|
||||
};
|
||||
exports.generateNewMnemonic = generateNewMnemonic;
|
||||
const deriveSeedFromMnemonic = (mnemonic) => {
|
||||
const seed = (0, bip39_1.mnemonicToSeedSync)(mnemonic);
|
||||
return seed;
|
||||
};
|
||||
exports.deriveSeedFromMnemonic = deriveSeedFromMnemonic;
|
||||
//# sourceMappingURL=NUT09.js.map
|
||||
1
node_modules/@cashu/crypto/modules/client/NUT09.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/client/NUT09.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT09.js","sourceRoot":"","sources":["../../src/client/NUT09.ts"],"names":[],"mappings":";;;AAAA,wCAAqC;AACrC,iDAAoD;AACpD,wCAAoE;AACpE,4DAA0D;AAE1D,MAAM,wBAAwB,GAAG,cAAc,CAAC;AAEhD,IAAK,cAGJ;AAHD,WAAK,cAAc;IAClB,uDAAU,CAAA;IACV,yEAAmB,CAAA;AACpB,CAAC,EAHI,cAAc,KAAd,cAAc,QAGlB;AAEM,MAAM,YAAY,GAAG,CAAC,IAAgB,EAAE,QAAgB,EAAE,OAAe,EAAc,EAAE;IAC/F,OAAO,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;AAC/D,CAAC,CAAC;AAFW,QAAA,YAAY,gBAEvB;AAEK,MAAM,oBAAoB,GAAG,CACnC,IAAgB,EAChB,QAAgB,EAChB,OAAe,EACF,EAAE;IACf,OAAO,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,CAAC,eAAe,CAAC,CAAC;AACxE,CAAC,CAAC;AANW,QAAA,oBAAoB,wBAM/B;AAEF,MAAM,MAAM,GAAG,CACd,IAAgB,EAChB,QAAgB,EAChB,OAAe,EACf,gBAAgC,EACnB,EAAE;IACf,MAAM,KAAK,GAAG,aAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,IAAA,yBAAc,EAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,GAAG,wBAAwB,IAAI,WAAW,KAAK,OAAO,KAAK,gBAAgB,EAAE,CAAC;IACrG,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,OAAO,CAAC,UAAU,CAAC;AAC3B,CAAC,CAAC;AAEK,MAAM,mBAAmB,GAAG,GAAW,EAAE;IAC/C,MAAM,QAAQ,GAAG,IAAA,wBAAgB,EAAC,kBAAQ,EAAE,GAAG,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAHW,QAAA,mBAAmB,uBAG9B;AAEK,MAAM,sBAAsB,GAAG,CAAC,QAAgB,EAAc,EAAE;IACtE,MAAM,IAAI,GAAG,IAAA,0BAAkB,EAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AAHW,QAAA,sBAAsB,0BAGjC"}
|
||||
7
node_modules/@cashu/crypto/modules/client/NUT11.d.ts
generated
vendored
7
node_modules/@cashu/crypto/modules/client/NUT11.d.ts
generated
vendored
@@ -1,7 +0,0 @@
|
||||
import { PrivKey } from '@noble/curves/abstract/utils';
|
||||
import { Proof } from '../common/index.js';
|
||||
export declare const createP2PKsecret: (pubkey: string) => Uint8Array;
|
||||
export declare const signP2PKsecret: (secret: Uint8Array, privateKey: PrivKey) => Uint8Array;
|
||||
export declare const getSignedProofs: (proofs: Array<Proof>, privateKey: string) => Array<Proof>;
|
||||
export declare const getSignedProof: (proof: Proof, privateKey: PrivKey) => Proof;
|
||||
//# sourceMappingURL=NUT11.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/client/NUT11.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/client/NUT11.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.d.ts","sourceRoot":"","sources":["../../src/client/NUT11.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAA0B,MAAM,8BAA8B,CAAC;AAK/E,OAAO,EAAE,KAAK,EAAU,MAAM,oBAAoB,CAAC;AAEnD,eAAO,MAAM,gBAAgB,WAAY,MAAM,KAAG,UAUjD,CAAC;AAEF,eAAO,MAAM,cAAc,WAAY,UAAU,cAAc,OAAO,eAIrE,CAAC;AAEF,eAAO,MAAM,eAAe,WAAY,MAAM,KAAK,CAAC,cAAc,MAAM,KAAG,MAAM,KAAK,CAYrF,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,KAAK,cAAc,OAAO,KAAG,KAOlE,CAAC"}
|
||||
51
node_modules/@cashu/crypto/modules/client/NUT11.js
generated
vendored
51
node_modules/@cashu/crypto/modules/client/NUT11.js
generated
vendored
@@ -1,51 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getSignedProof = exports.getSignedProofs = exports.signP2PKsecret = exports.createP2PKsecret = void 0;
|
||||
const utils_1 = require("@noble/curves/abstract/utils");
|
||||
const sha256_1 = require("@noble/hashes/sha256");
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const utils_2 = require("@noble/hashes/utils");
|
||||
const NUT11_js_1 = require("../common/NUT11.js");
|
||||
const createP2PKsecret = (pubkey) => {
|
||||
const newSecret = [
|
||||
'P2PK',
|
||||
{
|
||||
nonce: (0, utils_1.bytesToHex)((0, utils_2.randomBytes)(32)),
|
||||
data: pubkey
|
||||
}
|
||||
];
|
||||
const parsed = JSON.stringify(newSecret);
|
||||
return new TextEncoder().encode(parsed);
|
||||
};
|
||||
exports.createP2PKsecret = createP2PKsecret;
|
||||
const signP2PKsecret = (secret, privateKey) => {
|
||||
const msghash = (0, sha256_1.sha256)(new TextDecoder().decode(secret));
|
||||
const sig = secp256k1_1.schnorr.sign(msghash, privateKey);
|
||||
return sig;
|
||||
};
|
||||
exports.signP2PKsecret = signP2PKsecret;
|
||||
const getSignedProofs = (proofs, privateKey) => {
|
||||
return proofs.map((p) => {
|
||||
try {
|
||||
const parsed = (0, NUT11_js_1.parseSecret)(p.secret);
|
||||
if (parsed[0] !== 'P2PK') {
|
||||
throw new Error('unknown secret type');
|
||||
}
|
||||
return (0, exports.getSignedProof)(p, (0, utils_1.hexToBytes)(privateKey));
|
||||
}
|
||||
catch (error) {
|
||||
return p;
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.getSignedProofs = getSignedProofs;
|
||||
const getSignedProof = (proof, privateKey) => {
|
||||
if (!proof.witness) {
|
||||
proof.witness = {
|
||||
signatures: [(0, utils_1.bytesToHex)((0, exports.signP2PKsecret)(proof.secret, privateKey))]
|
||||
};
|
||||
}
|
||||
return proof;
|
||||
};
|
||||
exports.getSignedProof = getSignedProof;
|
||||
//# sourceMappingURL=NUT11.js.map
|
||||
1
node_modules/@cashu/crypto/modules/client/NUT11.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/client/NUT11.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.js","sourceRoot":"","sources":["../../src/client/NUT11.ts"],"names":[],"mappings":";;;AAAA,wDAA+E;AAC/E,iDAA8C;AAC9C,uDAAkD;AAClD,+CAAkD;AAClD,iDAAiD;AAG1C,MAAM,gBAAgB,GAAG,CAAC,MAAc,EAAc,EAAE;IAC9D,MAAM,SAAS,GAAW;QACzB,MAAM;QACN;YACC,KAAK,EAAE,IAAA,kBAAU,EAAC,IAAA,mBAAW,EAAC,EAAE,CAAC,CAAC;YAClC,IAAI,EAAE,MAAM;SACZ;KACD,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACzC,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC,CAAC;AAVW,QAAA,gBAAgB,oBAU3B;AAEK,MAAM,cAAc,GAAG,CAAC,MAAkB,EAAE,UAAmB,EAAE,EAAE;IACzE,MAAM,OAAO,GAAG,IAAA,eAAM,EAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,mBAAO,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC;AAJW,QAAA,cAAc,kBAIzB;AAEK,MAAM,eAAe,GAAG,CAAC,MAAoB,EAAE,UAAkB,EAAgB,EAAE;IACzF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACvB,IAAI,CAAC;YACJ,MAAM,MAAM,GAAW,IAAA,sBAAW,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,IAAA,sBAAc,EAAC,CAAC,EAAE,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,CAAC;QACV,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAZW,QAAA,eAAe,mBAY1B;AAEK,MAAM,cAAc,GAAG,CAAC,KAAY,EAAE,UAAmB,EAAS,EAAE;IAC1E,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,CAAC,OAAO,GAAG;YACf,UAAU,EAAE,CAAC,IAAA,kBAAU,EAAC,IAAA,sBAAc,EAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;SAClE,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AAPW,QAAA,cAAc,kBAOzB"}
|
||||
15
node_modules/@cashu/crypto/modules/client/index.d.ts
generated
vendored
15
node_modules/@cashu/crypto/modules/client/index.d.ts
generated
vendored
@@ -1,15 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
import type { BlindSignature, Proof, SerializedBlindedMessage, SerializedProof } from '../common/index.js';
|
||||
export type BlindedMessage = {
|
||||
B_: ProjPointType<bigint>;
|
||||
r: bigint;
|
||||
secret: Uint8Array;
|
||||
};
|
||||
export declare function createRandomBlindedMessage(): BlindedMessage;
|
||||
export declare function blindMessage(secret: Uint8Array, r?: bigint): BlindedMessage;
|
||||
export declare function unblindSignature(C_: ProjPointType<bigint>, r: bigint, A: ProjPointType<bigint>): ProjPointType<bigint>;
|
||||
export declare function constructProofFromPromise(promise: BlindSignature, r: bigint, secret: Uint8Array, key: ProjPointType<bigint>): Proof;
|
||||
export declare const serializeProof: (proof: Proof) => SerializedProof;
|
||||
export declare const deserializeProof: (proof: SerializedProof) => Proof;
|
||||
export declare const serializeBlindedMessage: (bm: BlindedMessage, amount: number) => SerializedBlindedMessage;
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/client/index.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/client/index.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAInE,OAAO,KAAK,EACX,cAAc,EACd,KAAK,EACL,wBAAwB,EACxB,eAAe,EACf,MAAM,oBAAoB,CAAC;AAI5B,MAAM,MAAM,cAAc,GAAG;IAC5B,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,UAAU,CAAC;CACnB,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,cAAc,CAE3D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,cAAc,CAQ3E;AAED,wBAAgB,gBAAgB,CAC/B,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,EACzB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GACtB,aAAa,CAAC,MAAM,CAAC,CAGvB;AAED,wBAAgB,yBAAyB,CACxC,OAAO,EAAE,cAAc,EACvB,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,GACxB,KAAK,CAUP;AAED,eAAO,MAAM,cAAc,UAAW,KAAK,KAAG,eAQ7C,CAAC;AAEF,eAAO,MAAM,gBAAgB,UAAW,eAAe,KAAG,KAQzD,CAAC;AACF,eAAO,MAAM,uBAAuB,OAC/B,cAAc,UACV,MAAM,KACZ,wBAKF,CAAC"}
|
||||
66
node_modules/@cashu/crypto/modules/client/index.js
generated
vendored
66
node_modules/@cashu/crypto/modules/client/index.js
generated
vendored
@@ -1,66 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.serializeBlindedMessage = exports.deserializeProof = exports.serializeProof = exports.constructProofFromPromise = exports.unblindSignature = exports.blindMessage = exports.createRandomBlindedMessage = void 0;
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const utils_1 = require("@noble/hashes/utils");
|
||||
const utils_js_1 = require("../util/utils.js");
|
||||
const index_js_1 = require("../common/index.js");
|
||||
function createRandomBlindedMessage() {
|
||||
return blindMessage((0, utils_1.randomBytes)(32));
|
||||
}
|
||||
exports.createRandomBlindedMessage = createRandomBlindedMessage;
|
||||
function blindMessage(secret, r) {
|
||||
const Y = (0, index_js_1.hashToCurve)(secret);
|
||||
if (!r) {
|
||||
r = (0, utils_js_1.bytesToNumber)(secp256k1_1.secp256k1.utils.randomPrivateKey());
|
||||
}
|
||||
const rG = secp256k1_1.secp256k1.ProjectivePoint.BASE.multiply(r);
|
||||
const B_ = Y.add(rG);
|
||||
return { B_, r, secret };
|
||||
}
|
||||
exports.blindMessage = blindMessage;
|
||||
function unblindSignature(C_, r, A) {
|
||||
const C = C_.subtract(A.multiply(r));
|
||||
return C;
|
||||
}
|
||||
exports.unblindSignature = unblindSignature;
|
||||
function constructProofFromPromise(promise, r, secret, key) {
|
||||
const A = key;
|
||||
const C = unblindSignature(promise.C_, r, A);
|
||||
const proof = {
|
||||
id: promise.id,
|
||||
amount: promise.amount,
|
||||
secret,
|
||||
C
|
||||
};
|
||||
return proof;
|
||||
}
|
||||
exports.constructProofFromPromise = constructProofFromPromise;
|
||||
const serializeProof = (proof) => {
|
||||
return {
|
||||
amount: proof.amount,
|
||||
C: proof.C.toHex(true),
|
||||
id: proof.id,
|
||||
secret: new TextDecoder().decode(proof.secret),
|
||||
witness: JSON.stringify(proof.witness)
|
||||
};
|
||||
};
|
||||
exports.serializeProof = serializeProof;
|
||||
const deserializeProof = (proof) => {
|
||||
return {
|
||||
amount: proof.amount,
|
||||
C: (0, index_js_1.pointFromHex)(proof.C),
|
||||
id: proof.id,
|
||||
secret: new TextEncoder().encode(proof.secret),
|
||||
witness: proof.witness ? JSON.parse(proof.witness) : undefined
|
||||
};
|
||||
};
|
||||
exports.deserializeProof = deserializeProof;
|
||||
const serializeBlindedMessage = (bm, amount) => {
|
||||
return {
|
||||
B_: bm.B_.toHex(true),
|
||||
amount: amount
|
||||
};
|
||||
};
|
||||
exports.serializeBlindedMessage = serializeBlindedMessage;
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@cashu/crypto/modules/client/index.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/client/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AACA,uDAAoD;AACpD,+CAA0E;AAC1E,+CAAiD;AAOjD,iDAA+D;AAS/D,SAAgB,0BAA0B;IACzC,OAAO,YAAY,CAAC,IAAA,mBAAW,EAAC,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC;AAFD,gEAEC;AAED,SAAgB,YAAY,CAAC,MAAkB,EAAE,CAAU;IAC1D,MAAM,CAAC,GAAG,IAAA,sBAAW,EAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;QACR,CAAC,GAAG,IAAA,wBAAa,EAAC,qBAAS,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,EAAE,GAAG,qBAAS,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AARD,oCAQC;AAED,SAAgB,gBAAgB,CAC/B,EAAyB,EACzB,CAAS,EACT,CAAwB;IAExB,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,CAAC;AACV,CAAC;AAPD,4CAOC;AAED,SAAgB,yBAAyB,CACxC,OAAuB,EACvB,CAAS,EACT,MAAkB,EAClB,GAA0B;IAE1B,MAAM,CAAC,GAAG,GAAG,CAAC;IACd,MAAM,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG;QACb,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM;QACN,CAAC;KACD,CAAC;IACF,OAAO,KAAK,CAAC;AACd,CAAC;AAfD,8DAeC;AAEM,MAAM,cAAc,GAAG,CAAC,KAAY,EAAmB,EAAE;IAC/D,OAAO;QACN,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QACtB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;KACtC,CAAC;AACH,CAAC,CAAC;AARW,QAAA,cAAc,kBAQzB;AAEK,MAAM,gBAAgB,GAAG,CAAC,KAAsB,EAAS,EAAE;IACjE,OAAO;QACN,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,CAAC,EAAE,IAAA,uBAAY,EAAC,KAAK,CAAC,CAAC,CAAC;QACxB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9C,OAAO,EAAE,KAAK,CAAC,OAAO,CAAA,CAAC,CAAA,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA,CAAC,CAAA,SAAS;KAC1D,CAAC;AACH,CAAC,CAAC;AARW,QAAA,gBAAgB,oBAQ3B;AACK,MAAM,uBAAuB,GAAG,CACtC,EAAkB,EAClB,MAAc,EACa,EAAE;IAC7B,OAAO;QACN,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;QACrB,MAAM,EAAE,MAAM;KACd,CAAC;AACH,CAAC,CAAC;AARW,QAAA,uBAAuB,2BAQlC"}
|
||||
3
node_modules/@cashu/crypto/modules/common/NUT11.d.ts
generated
vendored
3
node_modules/@cashu/crypto/modules/common/NUT11.d.ts
generated
vendored
@@ -1,3 +0,0 @@
|
||||
import { Secret } from "./index.js";
|
||||
export declare const parseSecret: (secret: string | Uint8Array) => Secret;
|
||||
//# sourceMappingURL=NUT11.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/common/NUT11.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/common/NUT11.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.d.ts","sourceRoot":"","sources":["../../src/common/NUT11.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,eAAO,MAAM,WAAW,WAAY,MAAM,GAAG,UAAU,WAStD,CAAC"}
|
||||
16
node_modules/@cashu/crypto/modules/common/NUT11.js
generated
vendored
16
node_modules/@cashu/crypto/modules/common/NUT11.js
generated
vendored
@@ -1,16 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseSecret = void 0;
|
||||
const parseSecret = (secret) => {
|
||||
try {
|
||||
if (secret instanceof Uint8Array) {
|
||||
secret = new TextDecoder().decode(secret);
|
||||
}
|
||||
return JSON.parse(secret);
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error("can't parse secret");
|
||||
}
|
||||
};
|
||||
exports.parseSecret = parseSecret;
|
||||
//# sourceMappingURL=NUT11.js.map
|
||||
1
node_modules/@cashu/crypto/modules/common/NUT11.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/common/NUT11.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.js","sourceRoot":"","sources":["../../src/common/NUT11.ts"],"names":[],"mappings":";;;AAEO,MAAM,WAAW,GAAG,CAAC,MAA2B,EAAU,EAAE;IAClE,IAAI,CAAC;QACJ,IAAI,MAAM,YAAY,UAAU,EAAE,CAAC;YAClC,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC;AATW,QAAA,WAAW,eAStB"}
|
||||
65
node_modules/@cashu/crypto/modules/common/index.d.ts
generated
vendored
65
node_modules/@cashu/crypto/modules/common/index.d.ts
generated
vendored
@@ -1,65 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
export type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N ? Acc[number] : Enumerate<N, [...Acc, Acc['length']]>;
|
||||
export type IntRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>;
|
||||
export type MintKeys = {
|
||||
[k: string]: Uint8Array;
|
||||
};
|
||||
export type SerializedMintKeys = {
|
||||
[k: string]: string;
|
||||
};
|
||||
export type Keyset = {
|
||||
id: string;
|
||||
unit: string;
|
||||
active: boolean;
|
||||
};
|
||||
export type BlindSignature = {
|
||||
C_: ProjPointType<bigint>;
|
||||
amount: number;
|
||||
id: string;
|
||||
};
|
||||
export type SerializedBlindSignature = {
|
||||
C_: string;
|
||||
amount: number;
|
||||
id: string;
|
||||
};
|
||||
export type Proof = {
|
||||
C: ProjPointType<bigint>;
|
||||
secret: Uint8Array;
|
||||
amount: number;
|
||||
id: string;
|
||||
witness?: Witness;
|
||||
};
|
||||
export type SerializedProof = {
|
||||
C: string;
|
||||
secret: string;
|
||||
amount: number;
|
||||
id: string;
|
||||
witness?: string;
|
||||
};
|
||||
export type SerializedBlindedMessage = {
|
||||
B_: string;
|
||||
amount: number;
|
||||
witness?: string;
|
||||
};
|
||||
export type Secret = [WellKnownSecret, SecretData];
|
||||
export type WellKnownSecret = 'P2PK';
|
||||
export type SecretData = {
|
||||
nonce: string;
|
||||
data: string;
|
||||
tags?: Array<Array<string>>;
|
||||
};
|
||||
export type Witness = {
|
||||
signatures: Array<string>;
|
||||
};
|
||||
export type Tags = {
|
||||
[k: string]: string;
|
||||
};
|
||||
export type SigFlag = 'SIG_INPUTS' | 'SIG_ALL';
|
||||
export declare function hashToCurve(secret: Uint8Array): ProjPointType<bigint>;
|
||||
export declare function pointFromHex(hex: string): ProjPointType<bigint>;
|
||||
export declare const getKeysetIdInt: (keysetId: string) => bigint;
|
||||
export declare function createRandomPrivateKey(): Uint8Array;
|
||||
export declare function serializeMintKeys(mintKeys: MintKeys): SerializedMintKeys;
|
||||
export declare function deserializeMintKeys(serializedMintKeys: SerializedMintKeys): MintKeys;
|
||||
export declare function deriveKeysetId(keys: MintKeys): string;
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/common/index.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/common/index.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"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"}
|
||||
85
node_modules/@cashu/crypto/modules/common/index.js
generated
vendored
85
node_modules/@cashu/crypto/modules/common/index.js
generated
vendored
@@ -1,85 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.deriveKeysetId = exports.deserializeMintKeys = exports.serializeMintKeys = exports.createRandomPrivateKey = exports.getKeysetIdInt = exports.pointFromHex = exports.hashToCurve = void 0;
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const sha256_1 = require("@noble/hashes/sha256");
|
||||
const utils_1 = require("@noble/curves/abstract/utils");
|
||||
const utils_js_1 = require("../util/utils.js");
|
||||
const buffer_1 = require("buffer/");
|
||||
const DOMAIN_SEPARATOR = (0, utils_1.hexToBytes)('536563703235366b315f48617368546f43757276655f43617368755f');
|
||||
function hashToCurve(secret) {
|
||||
const msgToHash = (0, sha256_1.sha256)(buffer_1.Buffer.concat([DOMAIN_SEPARATOR, secret]));
|
||||
const counter = new Uint32Array(1);
|
||||
const maxIterations = 2 ** 16;
|
||||
for (let i = 0; i < maxIterations; i++) {
|
||||
const counterBytes = new Uint8Array(counter.buffer);
|
||||
const hash = (0, sha256_1.sha256)(buffer_1.Buffer.concat([msgToHash, counterBytes]));
|
||||
try {
|
||||
return pointFromHex((0, utils_1.bytesToHex)(buffer_1.Buffer.concat([new Uint8Array([0x02]), hash])));
|
||||
}
|
||||
catch (error) {
|
||||
counter[0]++;
|
||||
}
|
||||
}
|
||||
throw new Error('No valid point found');
|
||||
}
|
||||
exports.hashToCurve = hashToCurve;
|
||||
function pointFromHex(hex) {
|
||||
return secp256k1_1.secp256k1.ProjectivePoint.fromHex(hex);
|
||||
}
|
||||
exports.pointFromHex = pointFromHex;
|
||||
const getKeysetIdInt = (keysetId) => {
|
||||
let keysetIdInt;
|
||||
if (/^[a-fA-F0-9]+$/.test(keysetId)) {
|
||||
keysetIdInt = (0, utils_js_1.hexToNumber)(keysetId) % BigInt(2 ** 31 - 1);
|
||||
}
|
||||
else {
|
||||
//legacy keyset compatibility
|
||||
keysetIdInt = (0, utils_js_1.bytesToNumber)((0, utils_js_1.encodeBase64toUint8)(keysetId)) % BigInt(2 ** 31 - 1);
|
||||
}
|
||||
return keysetIdInt;
|
||||
};
|
||||
exports.getKeysetIdInt = getKeysetIdInt;
|
||||
function createRandomPrivateKey() {
|
||||
return secp256k1_1.secp256k1.utils.randomPrivateKey();
|
||||
}
|
||||
exports.createRandomPrivateKey = createRandomPrivateKey;
|
||||
function serializeMintKeys(mintKeys) {
|
||||
const serializedMintKeys = {};
|
||||
Object.keys(mintKeys).forEach((p) => {
|
||||
serializedMintKeys[p] = (0, utils_1.bytesToHex)(mintKeys[p]);
|
||||
});
|
||||
return serializedMintKeys;
|
||||
}
|
||||
exports.serializeMintKeys = serializeMintKeys;
|
||||
function deserializeMintKeys(serializedMintKeys) {
|
||||
const mintKeys = {};
|
||||
Object.keys(serializedMintKeys).forEach((p) => {
|
||||
mintKeys[p] = (0, utils_1.hexToBytes)(serializedMintKeys[p]);
|
||||
});
|
||||
return mintKeys;
|
||||
}
|
||||
exports.deserializeMintKeys = deserializeMintKeys;
|
||||
function deriveKeysetId(keys) {
|
||||
const KEYSET_VERSION = '00';
|
||||
const mapBigInt = (k) => {
|
||||
return [BigInt(k[0]), k[1]];
|
||||
};
|
||||
const pubkeysConcat = Object.entries(serializeMintKeys(keys))
|
||||
.map(mapBigInt)
|
||||
.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0))
|
||||
.map(([, pubKey]) => (0, utils_1.hexToBytes)(pubKey))
|
||||
.reduce((prev, curr) => mergeUInt8Arrays(prev, curr), new Uint8Array());
|
||||
const hash = (0, sha256_1.sha256)(pubkeysConcat);
|
||||
const hashHex = buffer_1.Buffer.from(hash).toString('hex').slice(0, 14);
|
||||
return '00' + hashHex;
|
||||
}
|
||||
exports.deriveKeysetId = deriveKeysetId;
|
||||
function mergeUInt8Arrays(a1, a2) {
|
||||
// sum of individual array lengths
|
||||
const mergedArray = new Uint8Array(a1.length + a2.length);
|
||||
mergedArray.set(a1);
|
||||
mergedArray.set(a2, a1.length);
|
||||
return mergedArray;
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@cashu/crypto/modules/common/index.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/common/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"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"}
|
||||
4
node_modules/@cashu/crypto/modules/esm/client/NUT09.d.ts
generated
vendored
4
node_modules/@cashu/crypto/modules/esm/client/NUT09.d.ts
generated
vendored
@@ -1,4 +0,0 @@
|
||||
export declare const deriveSecret: (seed: Uint8Array, keysetId: string, counter: number) => Uint8Array;
|
||||
export declare const deriveBlindingFactor: (seed: Uint8Array, keysetId: string, counter: number) => Uint8Array;
|
||||
export declare const generateNewMnemonic: () => string;
|
||||
export declare const deriveSeedFromMnemonic: (mnemonic: string) => Uint8Array;
|
||||
42
node_modules/@cashu/crypto/modules/esm/client/NUT09.js
generated
vendored
42
node_modules/@cashu/crypto/modules/esm/client/NUT09.js
generated
vendored
@@ -1,42 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.deriveSeedFromMnemonic = exports.generateNewMnemonic = exports.deriveBlindingFactor = exports.deriveSecret = void 0;
|
||||
const bip32_1 = require("@scure/bip32");
|
||||
const index_js_1 = require("../common/index.js");
|
||||
const bip39_1 = require("@scure/bip39");
|
||||
const english_1 = require("@scure/bip39/wordlists/english");
|
||||
const STANDARD_DERIVATION_PATH = `m/129372'/0'`;
|
||||
var DerivationType;
|
||||
(function (DerivationType) {
|
||||
DerivationType[DerivationType["SECRET"] = 0] = "SECRET";
|
||||
DerivationType[DerivationType["BLINDING_FACTOR"] = 1] = "BLINDING_FACTOR";
|
||||
})(DerivationType || (DerivationType = {}));
|
||||
const deriveSecret = (seed, keysetId, counter) => {
|
||||
return derive(seed, keysetId, counter, DerivationType.SECRET);
|
||||
};
|
||||
exports.deriveSecret = deriveSecret;
|
||||
const deriveBlindingFactor = (seed, keysetId, counter) => {
|
||||
return derive(seed, keysetId, counter, DerivationType.BLINDING_FACTOR);
|
||||
};
|
||||
exports.deriveBlindingFactor = deriveBlindingFactor;
|
||||
const derive = (seed, keysetId, counter, secretOrBlinding) => {
|
||||
const hdkey = bip32_1.HDKey.fromMasterSeed(seed);
|
||||
const keysetIdInt = (0, index_js_1.getKeysetIdInt)(keysetId);
|
||||
const derivationPath = `${STANDARD_DERIVATION_PATH}/${keysetIdInt}'/${counter}'/${secretOrBlinding}`;
|
||||
const derived = hdkey.derive(derivationPath);
|
||||
if (derived.privateKey === null) {
|
||||
throw new Error('Could not derive private key');
|
||||
}
|
||||
return derived.privateKey;
|
||||
};
|
||||
const generateNewMnemonic = () => {
|
||||
const mnemonic = (0, bip39_1.generateMnemonic)(english_1.wordlist, 128);
|
||||
return mnemonic;
|
||||
};
|
||||
exports.generateNewMnemonic = generateNewMnemonic;
|
||||
const deriveSeedFromMnemonic = (mnemonic) => {
|
||||
const seed = (0, bip39_1.mnemonicToSeedSync)(mnemonic);
|
||||
return seed;
|
||||
};
|
||||
exports.deriveSeedFromMnemonic = deriveSeedFromMnemonic;
|
||||
//# sourceMappingURL=NUT09.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/client/NUT09.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/client/NUT09.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT09.js","sourceRoot":"","sources":["../../../src/client/NUT09.ts"],"names":[],"mappings":";;;AAAA,wCAAqC;AACrC,iDAAoD;AACpD,wCAAoE;AACpE,4DAA0D;AAE1D,MAAM,wBAAwB,GAAG,cAAc,CAAC;AAEhD,IAAK,cAGJ;AAHD,WAAK,cAAc;IAClB,uDAAU,CAAA;IACV,yEAAmB,CAAA;AACpB,CAAC,EAHI,cAAc,KAAd,cAAc,QAGlB;AAEM,MAAM,YAAY,GAAG,CAAC,IAAgB,EAAE,QAAgB,EAAE,OAAe,EAAc,EAAE;IAC/F,OAAO,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;AAC/D,CAAC,CAAC;AAFW,QAAA,YAAY,gBAEvB;AAEK,MAAM,oBAAoB,GAAG,CACnC,IAAgB,EAChB,QAAgB,EAChB,OAAe,EACF,EAAE;IACf,OAAO,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,CAAC,eAAe,CAAC,CAAC;AACxE,CAAC,CAAC;AANW,QAAA,oBAAoB,wBAM/B;AAEF,MAAM,MAAM,GAAG,CACd,IAAgB,EAChB,QAAgB,EAChB,OAAe,EACf,gBAAgC,EACnB,EAAE;IACf,MAAM,KAAK,GAAG,aAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,IAAA,yBAAc,EAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,GAAG,wBAAwB,IAAI,WAAW,KAAK,OAAO,KAAK,gBAAgB,EAAE,CAAC;IACrG,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,OAAO,CAAC,UAAU,CAAC;AAC3B,CAAC,CAAC;AAEK,MAAM,mBAAmB,GAAG,GAAW,EAAE;IAC/C,MAAM,QAAQ,GAAG,IAAA,wBAAgB,EAAC,kBAAQ,EAAE,GAAG,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAHW,QAAA,mBAAmB,uBAG9B;AAEK,MAAM,sBAAsB,GAAG,CAAC,QAAgB,EAAc,EAAE;IACtE,MAAM,IAAI,GAAG,IAAA,0BAAkB,EAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AAHW,QAAA,sBAAsB,0BAGjC"}
|
||||
6
node_modules/@cashu/crypto/modules/esm/client/NUT11.d.ts
generated
vendored
6
node_modules/@cashu/crypto/modules/esm/client/NUT11.d.ts
generated
vendored
@@ -1,6 +0,0 @@
|
||||
import { PrivKey } from '@noble/curves/abstract/utils';
|
||||
import { Proof } from '../common/index.js';
|
||||
export declare const createP2PKsecret: (pubkey: string) => Uint8Array;
|
||||
export declare const signP2PKsecret: (secret: Uint8Array, privateKey: PrivKey) => Uint8Array;
|
||||
export declare const getSignedProofs: (proofs: Array<Proof>, privateKey: string) => Array<Proof>;
|
||||
export declare const getSignedProof: (proof: Proof, privateKey: PrivKey) => Proof;
|
||||
51
node_modules/@cashu/crypto/modules/esm/client/NUT11.js
generated
vendored
51
node_modules/@cashu/crypto/modules/esm/client/NUT11.js
generated
vendored
@@ -1,51 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getSignedProof = exports.getSignedProofs = exports.signP2PKsecret = exports.createP2PKsecret = void 0;
|
||||
const utils_1 = require("@noble/curves/abstract/utils");
|
||||
const sha256_1 = require("@noble/hashes/sha256");
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const utils_2 = require("@noble/hashes/utils");
|
||||
const NUT11_js_1 = require("../common/NUT11.js");
|
||||
const createP2PKsecret = (pubkey) => {
|
||||
const newSecret = [
|
||||
'P2PK',
|
||||
{
|
||||
nonce: (0, utils_1.bytesToHex)((0, utils_2.randomBytes)(32)),
|
||||
data: pubkey
|
||||
}
|
||||
];
|
||||
const parsed = JSON.stringify(newSecret);
|
||||
return new TextEncoder().encode(parsed);
|
||||
};
|
||||
exports.createP2PKsecret = createP2PKsecret;
|
||||
const signP2PKsecret = (secret, privateKey) => {
|
||||
const msghash = (0, sha256_1.sha256)(new TextDecoder().decode(secret));
|
||||
const sig = secp256k1_1.schnorr.sign(msghash, privateKey);
|
||||
return sig;
|
||||
};
|
||||
exports.signP2PKsecret = signP2PKsecret;
|
||||
const getSignedProofs = (proofs, privateKey) => {
|
||||
return proofs.map((p) => {
|
||||
try {
|
||||
const parsed = (0, NUT11_js_1.parseSecret)(p.secret);
|
||||
if (parsed[0] !== 'P2PK') {
|
||||
throw new Error('unknown secret type');
|
||||
}
|
||||
return (0, exports.getSignedProof)(p, (0, utils_1.hexToBytes)(privateKey));
|
||||
}
|
||||
catch (error) {
|
||||
return p;
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.getSignedProofs = getSignedProofs;
|
||||
const getSignedProof = (proof, privateKey) => {
|
||||
if (!proof.witness) {
|
||||
proof.witness = {
|
||||
signatures: [(0, utils_1.bytesToHex)((0, exports.signP2PKsecret)(proof.secret, privateKey))]
|
||||
};
|
||||
}
|
||||
return proof;
|
||||
};
|
||||
exports.getSignedProof = getSignedProof;
|
||||
//# sourceMappingURL=NUT11.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/client/NUT11.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/client/NUT11.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.js","sourceRoot":"","sources":["../../../src/client/NUT11.ts"],"names":[],"mappings":";;;AAAA,wDAA+E;AAC/E,iDAA8C;AAC9C,uDAAkD;AAClD,+CAAkD;AAClD,iDAAiD;AAG1C,MAAM,gBAAgB,GAAG,CAAC,MAAc,EAAc,EAAE;IAC9D,MAAM,SAAS,GAAW;QACzB,MAAM;QACN;YACC,KAAK,EAAE,IAAA,kBAAU,EAAC,IAAA,mBAAW,EAAC,EAAE,CAAC,CAAC;YAClC,IAAI,EAAE,MAAM;SACZ;KACD,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACzC,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC,CAAC;AAVW,QAAA,gBAAgB,oBAU3B;AAEK,MAAM,cAAc,GAAG,CAAC,MAAkB,EAAE,UAAmB,EAAE,EAAE;IACzE,MAAM,OAAO,GAAG,IAAA,eAAM,EAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,mBAAO,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC;AAJW,QAAA,cAAc,kBAIzB;AAEK,MAAM,eAAe,GAAG,CAAC,MAAoB,EAAE,UAAkB,EAAgB,EAAE;IACzF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACvB,IAAI,CAAC;YACJ,MAAM,MAAM,GAAW,IAAA,sBAAW,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,IAAA,sBAAc,EAAC,CAAC,EAAE,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,CAAC;QACV,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAZW,QAAA,eAAe,mBAY1B;AAEK,MAAM,cAAc,GAAG,CAAC,KAAY,EAAE,UAAmB,EAAS,EAAE;IAC1E,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,CAAC,OAAO,GAAG;YACf,UAAU,EAAE,CAAC,IAAA,kBAAU,EAAC,IAAA,sBAAc,EAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;SAClE,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AAPW,QAAA,cAAc,kBAOzB"}
|
||||
14
node_modules/@cashu/crypto/modules/esm/client/index.d.ts
generated
vendored
14
node_modules/@cashu/crypto/modules/esm/client/index.d.ts
generated
vendored
@@ -1,14 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
import type { BlindSignature, Proof, SerializedBlindedMessage, SerializedProof } from '../common/index.js';
|
||||
export type BlindedMessage = {
|
||||
B_: ProjPointType<bigint>;
|
||||
r: bigint;
|
||||
secret: Uint8Array;
|
||||
};
|
||||
export declare function createRandomBlindedMessage(): BlindedMessage;
|
||||
export declare function blindMessage(secret: Uint8Array, r?: bigint): BlindedMessage;
|
||||
export declare function unblindSignature(C_: ProjPointType<bigint>, r: bigint, A: ProjPointType<bigint>): ProjPointType<bigint>;
|
||||
export declare function constructProofFromPromise(promise: BlindSignature, r: bigint, secret: Uint8Array, key: ProjPointType<bigint>): Proof;
|
||||
export declare const serializeProof: (proof: Proof) => SerializedProof;
|
||||
export declare const deserializeProof: (proof: SerializedProof) => Proof;
|
||||
export declare const serializeBlindedMessage: (bm: BlindedMessage, amount: number) => SerializedBlindedMessage;
|
||||
66
node_modules/@cashu/crypto/modules/esm/client/index.js
generated
vendored
66
node_modules/@cashu/crypto/modules/esm/client/index.js
generated
vendored
@@ -1,66 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.serializeBlindedMessage = exports.deserializeProof = exports.serializeProof = exports.constructProofFromPromise = exports.unblindSignature = exports.blindMessage = exports.createRandomBlindedMessage = void 0;
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const utils_1 = require("@noble/hashes/utils");
|
||||
const utils_js_1 = require("../util/utils.js");
|
||||
const index_js_1 = require("../common/index.js");
|
||||
function createRandomBlindedMessage() {
|
||||
return blindMessage((0, utils_1.randomBytes)(32));
|
||||
}
|
||||
exports.createRandomBlindedMessage = createRandomBlindedMessage;
|
||||
function blindMessage(secret, r) {
|
||||
const Y = (0, index_js_1.hashToCurve)(secret);
|
||||
if (!r) {
|
||||
r = (0, utils_js_1.bytesToNumber)(secp256k1_1.secp256k1.utils.randomPrivateKey());
|
||||
}
|
||||
const rG = secp256k1_1.secp256k1.ProjectivePoint.BASE.multiply(r);
|
||||
const B_ = Y.add(rG);
|
||||
return { B_, r, secret };
|
||||
}
|
||||
exports.blindMessage = blindMessage;
|
||||
function unblindSignature(C_, r, A) {
|
||||
const C = C_.subtract(A.multiply(r));
|
||||
return C;
|
||||
}
|
||||
exports.unblindSignature = unblindSignature;
|
||||
function constructProofFromPromise(promise, r, secret, key) {
|
||||
const A = key;
|
||||
const C = unblindSignature(promise.C_, r, A);
|
||||
const proof = {
|
||||
id: promise.id,
|
||||
amount: promise.amount,
|
||||
secret,
|
||||
C
|
||||
};
|
||||
return proof;
|
||||
}
|
||||
exports.constructProofFromPromise = constructProofFromPromise;
|
||||
const serializeProof = (proof) => {
|
||||
return {
|
||||
amount: proof.amount,
|
||||
C: proof.C.toHex(true),
|
||||
id: proof.id,
|
||||
secret: new TextDecoder().decode(proof.secret),
|
||||
witness: JSON.stringify(proof.witness)
|
||||
};
|
||||
};
|
||||
exports.serializeProof = serializeProof;
|
||||
const deserializeProof = (proof) => {
|
||||
return {
|
||||
amount: proof.amount,
|
||||
C: (0, index_js_1.pointFromHex)(proof.C),
|
||||
id: proof.id,
|
||||
secret: new TextEncoder().encode(proof.secret),
|
||||
witness: proof.witness ? JSON.parse(proof.witness) : undefined
|
||||
};
|
||||
};
|
||||
exports.deserializeProof = deserializeProof;
|
||||
const serializeBlindedMessage = (bm, amount) => {
|
||||
return {
|
||||
B_: bm.B_.toHex(true),
|
||||
amount: amount
|
||||
};
|
||||
};
|
||||
exports.serializeBlindedMessage = serializeBlindedMessage;
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/client/index.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/client/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":";;;AACA,uDAAoD;AACpD,+CAA0E;AAC1E,+CAAiD;AAOjD,iDAA+D;AAS/D,SAAgB,0BAA0B;IACzC,OAAO,YAAY,CAAC,IAAA,mBAAW,EAAC,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC;AAFD,gEAEC;AAED,SAAgB,YAAY,CAAC,MAAkB,EAAE,CAAU;IAC1D,MAAM,CAAC,GAAG,IAAA,sBAAW,EAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;QACR,CAAC,GAAG,IAAA,wBAAa,EAAC,qBAAS,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,EAAE,GAAG,qBAAS,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AARD,oCAQC;AAED,SAAgB,gBAAgB,CAC/B,EAAyB,EACzB,CAAS,EACT,CAAwB;IAExB,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,CAAC;AACV,CAAC;AAPD,4CAOC;AAED,SAAgB,yBAAyB,CACxC,OAAuB,EACvB,CAAS,EACT,MAAkB,EAClB,GAA0B;IAE1B,MAAM,CAAC,GAAG,GAAG,CAAC;IACd,MAAM,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG;QACb,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM;QACN,CAAC;KACD,CAAC;IACF,OAAO,KAAK,CAAC;AACd,CAAC;AAfD,8DAeC;AAEM,MAAM,cAAc,GAAG,CAAC,KAAY,EAAmB,EAAE;IAC/D,OAAO;QACN,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QACtB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;KACtC,CAAC;AACH,CAAC,CAAC;AARW,QAAA,cAAc,kBAQzB;AAEK,MAAM,gBAAgB,GAAG,CAAC,KAAsB,EAAS,EAAE;IACjE,OAAO;QACN,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,CAAC,EAAE,IAAA,uBAAY,EAAC,KAAK,CAAC,CAAC,CAAC;QACxB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9C,OAAO,EAAE,KAAK,CAAC,OAAO,CAAA,CAAC,CAAA,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA,CAAC,CAAA,SAAS;KAC1D,CAAC;AACH,CAAC,CAAC;AARW,QAAA,gBAAgB,oBAQ3B;AACK,MAAM,uBAAuB,GAAG,CACtC,EAAkB,EAClB,MAAc,EACa,EAAE;IAC7B,OAAO;QACN,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;QACrB,MAAM,EAAE,MAAM;KACd,CAAC;AACH,CAAC,CAAC;AARW,QAAA,uBAAuB,2BAQlC"}
|
||||
2
node_modules/@cashu/crypto/modules/esm/common/NUT11.d.ts
generated
vendored
2
node_modules/@cashu/crypto/modules/esm/common/NUT11.d.ts
generated
vendored
@@ -1,2 +0,0 @@
|
||||
import { Secret } from "./index.js";
|
||||
export declare const parseSecret: (secret: string | Uint8Array) => Secret;
|
||||
16
node_modules/@cashu/crypto/modules/esm/common/NUT11.js
generated
vendored
16
node_modules/@cashu/crypto/modules/esm/common/NUT11.js
generated
vendored
@@ -1,16 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseSecret = void 0;
|
||||
const parseSecret = (secret) => {
|
||||
try {
|
||||
if (secret instanceof Uint8Array) {
|
||||
secret = new TextDecoder().decode(secret);
|
||||
}
|
||||
return JSON.parse(secret);
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error("can't parse secret");
|
||||
}
|
||||
};
|
||||
exports.parseSecret = parseSecret;
|
||||
//# sourceMappingURL=NUT11.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/common/NUT11.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/common/NUT11.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.js","sourceRoot":"","sources":["../../../src/common/NUT11.ts"],"names":[],"mappings":";;;AAEO,MAAM,WAAW,GAAG,CAAC,MAA2B,EAAU,EAAE;IAClE,IAAI,CAAC;QACJ,IAAI,MAAM,YAAY,UAAU,EAAE,CAAC;YAClC,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC;AATW,QAAA,WAAW,eAStB"}
|
||||
64
node_modules/@cashu/crypto/modules/esm/common/index.d.ts
generated
vendored
64
node_modules/@cashu/crypto/modules/esm/common/index.d.ts
generated
vendored
@@ -1,64 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
export type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N ? Acc[number] : Enumerate<N, [...Acc, Acc['length']]>;
|
||||
export type IntRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>;
|
||||
export type MintKeys = {
|
||||
[k: string]: Uint8Array;
|
||||
};
|
||||
export type SerializedMintKeys = {
|
||||
[k: string]: string;
|
||||
};
|
||||
export type Keyset = {
|
||||
id: string;
|
||||
unit: string;
|
||||
active: boolean;
|
||||
};
|
||||
export type BlindSignature = {
|
||||
C_: ProjPointType<bigint>;
|
||||
amount: number;
|
||||
id: string;
|
||||
};
|
||||
export type SerializedBlindSignature = {
|
||||
C_: string;
|
||||
amount: number;
|
||||
id: string;
|
||||
};
|
||||
export type Proof = {
|
||||
C: ProjPointType<bigint>;
|
||||
secret: Uint8Array;
|
||||
amount: number;
|
||||
id: string;
|
||||
witness?: Witness;
|
||||
};
|
||||
export type SerializedProof = {
|
||||
C: string;
|
||||
secret: string;
|
||||
amount: number;
|
||||
id: string;
|
||||
witness?: string;
|
||||
};
|
||||
export type SerializedBlindedMessage = {
|
||||
B_: string;
|
||||
amount: number;
|
||||
witness?: string;
|
||||
};
|
||||
export type Secret = [WellKnownSecret, SecretData];
|
||||
export type WellKnownSecret = 'P2PK';
|
||||
export type SecretData = {
|
||||
nonce: string;
|
||||
data: string;
|
||||
tags?: Array<Array<string>>;
|
||||
};
|
||||
export type Witness = {
|
||||
signatures: Array<string>;
|
||||
};
|
||||
export type Tags = {
|
||||
[k: string]: string;
|
||||
};
|
||||
export type SigFlag = 'SIG_INPUTS' | 'SIG_ALL';
|
||||
export declare function hashToCurve(secret: Uint8Array): ProjPointType<bigint>;
|
||||
export declare function pointFromHex(hex: string): ProjPointType<bigint>;
|
||||
export declare const getKeysetIdInt: (keysetId: string) => bigint;
|
||||
export declare function createRandomPrivateKey(): Uint8Array;
|
||||
export declare function serializeMintKeys(mintKeys: MintKeys): SerializedMintKeys;
|
||||
export declare function deserializeMintKeys(serializedMintKeys: SerializedMintKeys): MintKeys;
|
||||
export declare function deriveKeysetId(keys: MintKeys): string;
|
||||
85
node_modules/@cashu/crypto/modules/esm/common/index.js
generated
vendored
85
node_modules/@cashu/crypto/modules/esm/common/index.js
generated
vendored
@@ -1,85 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.deriveKeysetId = exports.deserializeMintKeys = exports.serializeMintKeys = exports.createRandomPrivateKey = exports.getKeysetIdInt = exports.pointFromHex = exports.hashToCurve = void 0;
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const sha256_1 = require("@noble/hashes/sha256");
|
||||
const utils_1 = require("@noble/curves/abstract/utils");
|
||||
const utils_js_1 = require("../util/utils.js");
|
||||
const buffer_1 = require("buffer/");
|
||||
const DOMAIN_SEPARATOR = (0, utils_1.hexToBytes)('536563703235366b315f48617368546f43757276655f43617368755f');
|
||||
function hashToCurve(secret) {
|
||||
const msgToHash = (0, sha256_1.sha256)(buffer_1.Buffer.concat([DOMAIN_SEPARATOR, secret]));
|
||||
const counter = new Uint32Array(1);
|
||||
const maxIterations = 2 ** 16;
|
||||
for (let i = 0; i < maxIterations; i++) {
|
||||
const counterBytes = new Uint8Array(counter.buffer);
|
||||
const hash = (0, sha256_1.sha256)(buffer_1.Buffer.concat([msgToHash, counterBytes]));
|
||||
try {
|
||||
return pointFromHex((0, utils_1.bytesToHex)(buffer_1.Buffer.concat([new Uint8Array([0x02]), hash])));
|
||||
}
|
||||
catch (error) {
|
||||
counter[0]++;
|
||||
}
|
||||
}
|
||||
throw new Error('No valid point found');
|
||||
}
|
||||
exports.hashToCurve = hashToCurve;
|
||||
function pointFromHex(hex) {
|
||||
return secp256k1_1.secp256k1.ProjectivePoint.fromHex(hex);
|
||||
}
|
||||
exports.pointFromHex = pointFromHex;
|
||||
const getKeysetIdInt = (keysetId) => {
|
||||
let keysetIdInt;
|
||||
if (/^[a-fA-F0-9]+$/.test(keysetId)) {
|
||||
keysetIdInt = (0, utils_js_1.hexToNumber)(keysetId) % BigInt(2 ** 31 - 1);
|
||||
}
|
||||
else {
|
||||
//legacy keyset compatibility
|
||||
keysetIdInt = (0, utils_js_1.bytesToNumber)((0, utils_js_1.encodeBase64toUint8)(keysetId)) % BigInt(2 ** 31 - 1);
|
||||
}
|
||||
return keysetIdInt;
|
||||
};
|
||||
exports.getKeysetIdInt = getKeysetIdInt;
|
||||
function createRandomPrivateKey() {
|
||||
return secp256k1_1.secp256k1.utils.randomPrivateKey();
|
||||
}
|
||||
exports.createRandomPrivateKey = createRandomPrivateKey;
|
||||
function serializeMintKeys(mintKeys) {
|
||||
const serializedMintKeys = {};
|
||||
Object.keys(mintKeys).forEach((p) => {
|
||||
serializedMintKeys[p] = (0, utils_1.bytesToHex)(mintKeys[p]);
|
||||
});
|
||||
return serializedMintKeys;
|
||||
}
|
||||
exports.serializeMintKeys = serializeMintKeys;
|
||||
function deserializeMintKeys(serializedMintKeys) {
|
||||
const mintKeys = {};
|
||||
Object.keys(serializedMintKeys).forEach((p) => {
|
||||
mintKeys[p] = (0, utils_1.hexToBytes)(serializedMintKeys[p]);
|
||||
});
|
||||
return mintKeys;
|
||||
}
|
||||
exports.deserializeMintKeys = deserializeMintKeys;
|
||||
function deriveKeysetId(keys) {
|
||||
const KEYSET_VERSION = '00';
|
||||
const mapBigInt = (k) => {
|
||||
return [BigInt(k[0]), k[1]];
|
||||
};
|
||||
const pubkeysConcat = Object.entries(serializeMintKeys(keys))
|
||||
.map(mapBigInt)
|
||||
.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0))
|
||||
.map(([, pubKey]) => (0, utils_1.hexToBytes)(pubKey))
|
||||
.reduce((prev, curr) => mergeUInt8Arrays(prev, curr), new Uint8Array());
|
||||
const hash = (0, sha256_1.sha256)(pubkeysConcat);
|
||||
const hashHex = buffer_1.Buffer.from(hash).toString('hex').slice(0, 14);
|
||||
return '00' + hashHex;
|
||||
}
|
||||
exports.deriveKeysetId = deriveKeysetId;
|
||||
function mergeUInt8Arrays(a1, a2) {
|
||||
// sum of individual array lengths
|
||||
const mergedArray = new Uint8Array(a1.length + a2.length);
|
||||
mergedArray.set(a1);
|
||||
mergedArray.set(a2, a1.length);
|
||||
return mergedArray;
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/common/index.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/common/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/common/index.ts"],"names":[],"mappings":"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"}
|
||||
1
node_modules/@cashu/crypto/modules/esm/index.d.ts
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/index.d.ts
generated
vendored
@@ -1 +0,0 @@
|
||||
export {};
|
||||
4
node_modules/@cashu/crypto/modules/esm/index.js
generated
vendored
4
node_modules/@cashu/crypto/modules/esm/index.js
generated
vendored
@@ -1,4 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
throw new Error('Incorrect usage. Import submodules instead');
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/index.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;AAAA,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC"}
|
||||
2
node_modules/@cashu/crypto/modules/esm/mint/NUT11.d.ts
generated
vendored
2
node_modules/@cashu/crypto/modules/esm/mint/NUT11.d.ts
generated
vendored
@@ -1,2 +0,0 @@
|
||||
import { Proof } from '../common/index.js';
|
||||
export declare const verifyP2PKSig: (proof: Proof) => boolean;
|
||||
37
node_modules/@cashu/crypto/modules/esm/mint/NUT11.js
generated
vendored
37
node_modules/@cashu/crypto/modules/esm/mint/NUT11.js
generated
vendored
@@ -1,37 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.verifyP2PKSig = void 0;
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const sha256_1 = require("@noble/hashes/sha256");
|
||||
const NUT11_js_1 = require("../common/NUT11.js");
|
||||
const verifyP2PKSig = (proof) => {
|
||||
if (!proof.witness) {
|
||||
throw new Error('could not verify signature, no witness provided');
|
||||
}
|
||||
const parsedSecret = (0, NUT11_js_1.parseSecret)(proof.secret);
|
||||
// const tags = {} as Tags
|
||||
// parsedSecret[1].tags.forEach((e: string[]) => {tags[e[0]]=e.shift()})
|
||||
// if (tags.locktime) {
|
||||
// const locktime = parseInt(tags.locktime[1])
|
||||
// let isUnlocked = false
|
||||
// if (Math.floor(Date.now() / 1000)>=locktime) {
|
||||
// isUnlocked = true
|
||||
// }
|
||||
// }
|
||||
// if (tags.sigflag as SigFlag) {
|
||||
// if (tags.sigflag[0]==='SIG_INPUT') {
|
||||
// }
|
||||
// else if(tags.sigflag[0]==='SIG_ALL') {
|
||||
// }
|
||||
// else {
|
||||
// throw new Error("Unknown sigflag");
|
||||
// }
|
||||
// }
|
||||
// if (tags.n_sigs) {
|
||||
// if (tags.pubkeys) {
|
||||
// }
|
||||
// }
|
||||
return secp256k1_1.schnorr.verify(proof.witness.signatures[0], (0, sha256_1.sha256)(new TextDecoder().decode(proof.secret)), parsedSecret[1].data);
|
||||
};
|
||||
exports.verifyP2PKSig = verifyP2PKSig;
|
||||
//# sourceMappingURL=NUT11.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/mint/NUT11.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/mint/NUT11.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.js","sourceRoot":"","sources":["../../../src/mint/NUT11.ts"],"names":[],"mappings":";;;AAAA,uDAAkD;AAClD,iDAA8C;AAC9C,iDAAiD;AAG1C,MAAM,aAAa,GAAG,CAAC,KAAY,EAAE,EAAE;IAC7C,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,YAAY,GAAG,IAAA,sBAAW,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE/C,0BAA0B;IAC1B,wEAAwE;IACxE,uBAAuB;IACvB,kDAAkD;IAElD,6BAA6B;IAC7B,qDAAqD;IACrD,4BAA4B;IAC5B,QAAQ;IACR,IAAI;IACJ,iCAAiC;IACjC,2CAA2C;IAE3C,QAAQ;IACR,6CAA6C;IAE7C,QAAQ;IACR,aAAa;IACb,8CAA8C;IAC9C,QAAQ;IACR,IAAI;IACJ,qBAAqB;IACrB,0BAA0B;IAE1B,QAAQ;IACR,IAAI;IAEJ,OAAO,mBAAO,CAAC,MAAM,CACpB,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAC3B,IAAA,eAAM,EAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAC9C,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CACpB,CAAC;AACH,CAAC,CAAC;AAtCW,QAAA,aAAa,iBAsCxB"}
|
||||
14
node_modules/@cashu/crypto/modules/esm/mint/index.d.ts
generated
vendored
14
node_modules/@cashu/crypto/modules/esm/mint/index.d.ts
generated
vendored
@@ -1,14 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
import { BlindSignature, IntRange, Keyset, MintKeys, Proof } from '../common/index.js';
|
||||
export type KeysetPair = {
|
||||
keysetId: string;
|
||||
pubKeys: MintKeys;
|
||||
privKeys: MintKeys;
|
||||
};
|
||||
export type KeysetWithKeys = Keyset & {
|
||||
pubKeys: MintKeys;
|
||||
};
|
||||
export declare function createBlindSignature(B_: ProjPointType<bigint>, privateKey: Uint8Array, amount: number, id: string): BlindSignature;
|
||||
export declare function getPubKeyFromPrivKey(privKey: Uint8Array): Uint8Array;
|
||||
export declare function createNewMintKeys(pow2height: IntRange<0, 65>, seed?: Uint8Array): KeysetPair;
|
||||
export declare function verifyProof(proof: Proof, privKey: Uint8Array): boolean;
|
||||
53
node_modules/@cashu/crypto/modules/esm/mint/index.js
generated
vendored
53
node_modules/@cashu/crypto/modules/esm/mint/index.js
generated
vendored
@@ -1,53 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.verifyProof = exports.createNewMintKeys = exports.getPubKeyFromPrivKey = exports.createBlindSignature = void 0;
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const utils_js_1 = require("../util/utils.js");
|
||||
const index_js_1 = require("../common/index.js");
|
||||
const bip32_1 = require("@scure/bip32");
|
||||
const DERIVATION_PATH = "m/0'/0'/0'";
|
||||
function createBlindSignature(B_, privateKey, amount, id) {
|
||||
const C_ = B_.multiply((0, utils_js_1.bytesToNumber)(privateKey));
|
||||
return { C_, amount, id };
|
||||
}
|
||||
exports.createBlindSignature = createBlindSignature;
|
||||
function getPubKeyFromPrivKey(privKey) {
|
||||
return secp256k1_1.secp256k1.getPublicKey(privKey, true);
|
||||
}
|
||||
exports.getPubKeyFromPrivKey = getPubKeyFromPrivKey;
|
||||
function createNewMintKeys(pow2height, seed) {
|
||||
let counter = 0n;
|
||||
const pubKeys = {};
|
||||
const privKeys = {};
|
||||
let masterKey;
|
||||
if (seed) {
|
||||
masterKey = bip32_1.HDKey.fromMasterSeed(seed);
|
||||
}
|
||||
while (counter < pow2height) {
|
||||
const index = (2n ** counter).toString();
|
||||
if (masterKey) {
|
||||
const k = masterKey.derive(`${DERIVATION_PATH}/${counter}`).privateKey;
|
||||
if (k) {
|
||||
privKeys[index] = k;
|
||||
}
|
||||
else {
|
||||
throw new Error(`Could not derive Private key from: ${DERIVATION_PATH}/${counter}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
privKeys[index] = (0, index_js_1.createRandomPrivateKey)();
|
||||
}
|
||||
pubKeys[index] = getPubKeyFromPrivKey(privKeys[index]);
|
||||
counter++;
|
||||
}
|
||||
const keysetId = (0, index_js_1.deriveKeysetId)(pubKeys);
|
||||
return { pubKeys, privKeys, keysetId };
|
||||
}
|
||||
exports.createNewMintKeys = createNewMintKeys;
|
||||
function verifyProof(proof, privKey) {
|
||||
const Y = (0, index_js_1.hashToCurve)(proof.secret);
|
||||
const aY = Y.multiply((0, utils_js_1.bytesToNumber)(privKey));
|
||||
return aY.equals(proof.C);
|
||||
}
|
||||
exports.verifyProof = verifyProof;
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/mint/index.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/mint/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mint/index.ts"],"names":[],"mappings":";;;AACA,uDAAoD;AACpD,+CAAiD;AAEjD,iDAAyF;AACzF,wCAAqC;AAErC,MAAM,eAAe,GAAG,YAAY,CAAC;AAYrC,SAAgB,oBAAoB,CACnC,EAAyB,EACzB,UAAsB,EACtB,MAAc,EACd,EAAU;IAEV,MAAM,EAAE,GAA0B,EAAE,CAAC,QAAQ,CAAC,IAAA,wBAAa,EAAC,UAAU,CAAC,CAAC,CAAC;IACzE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAC3B,CAAC;AARD,oDAQC;AAED,SAAgB,oBAAoB,CAAC,OAAmB;IACvD,OAAO,qBAAS,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC;AAFD,oDAEC;AAED,SAAgB,iBAAiB,CAAC,UAA2B,EAAE,IAAiB;IAC/E,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,SAAS,CAAC;IACd,IAAI,IAAI,EAAE,CAAC;QACV,SAAS,GAAG,aAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAW,CAAC,EAAE,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACjD,IAAI,SAAS,EAAE,CAAC;YACf,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,eAAe,IAAI,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC;YACvE,IAAI,CAAC,EAAE,CAAC;gBACP,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,sCAAsC,eAAe,IAAI,OAAO,EAAE,CAAC,CAAC;YACrF,CAAC;QACF,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAA,iCAAsB,GAAE,CAAC;QAC5C,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACvD,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,QAAQ,GAAG,IAAA,yBAAc,EAAC,OAAO,CAAC,CAAC;IACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AACxC,CAAC;AA1BD,8CA0BC;AAED,SAAgB,WAAW,CAAC,KAAY,EAAE,OAAmB;IAC5D,MAAM,CAAC,GAA0B,IAAA,sBAAW,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,EAAE,GAA0B,CAAC,CAAC,QAAQ,CAAC,IAAA,wBAAa,EAAC,OAAO,CAAC,CAAC,CAAC;IACrE,OAAO,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAJD,kCAIC"}
|
||||
3
node_modules/@cashu/crypto/modules/esm/util/utils.d.ts
generated
vendored
3
node_modules/@cashu/crypto/modules/esm/util/utils.d.ts
generated
vendored
@@ -1,3 +0,0 @@
|
||||
export declare function bytesToNumber(bytes: Uint8Array): bigint;
|
||||
export declare function hexToNumber(hex: string): bigint;
|
||||
export declare function encodeBase64toUint8(base64String: string): Uint8Array;
|
||||
18
node_modules/@cashu/crypto/modules/esm/util/utils.js
generated
vendored
18
node_modules/@cashu/crypto/modules/esm/util/utils.js
generated
vendored
@@ -1,18 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.encodeBase64toUint8 = exports.hexToNumber = exports.bytesToNumber = void 0;
|
||||
const utils_1 = require("@noble/curves/abstract/utils");
|
||||
const buffer_1 = require("buffer/");
|
||||
function bytesToNumber(bytes) {
|
||||
return hexToNumber((0, utils_1.bytesToHex)(bytes));
|
||||
}
|
||||
exports.bytesToNumber = bytesToNumber;
|
||||
function hexToNumber(hex) {
|
||||
return BigInt(`0x${hex}`);
|
||||
}
|
||||
exports.hexToNumber = hexToNumber;
|
||||
function encodeBase64toUint8(base64String) {
|
||||
return buffer_1.Buffer.from(base64String, 'base64');
|
||||
}
|
||||
exports.encodeBase64toUint8 = encodeBase64toUint8;
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
node_modules/@cashu/crypto/modules/esm/util/utils.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/esm/util/utils.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/util/utils.ts"],"names":[],"mappings":";;;AAAA,wDAA0D;AAC1D,oCAAiC;AAEjC,SAAgB,aAAa,CAAC,KAAiB;IAC9C,OAAO,WAAW,CAAC,IAAA,kBAAU,EAAC,KAAK,CAAC,CAAC,CAAC;AACvC,CAAC;AAFD,sCAEC;AAED,SAAgB,WAAW,CAAC,GAAW;IACtC,OAAO,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;AAC3B,CAAC;AAFD,kCAEC;AAED,SAAgB,mBAAmB,CAAC,YAAoB;IACvD,OAAO,eAAM,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAFD,kDAEC"}
|
||||
1
node_modules/@cashu/crypto/modules/index.d.ts
generated
vendored
1
node_modules/@cashu/crypto/modules/index.d.ts
generated
vendored
@@ -1 +0,0 @@
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/index.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/index.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
||||
3
node_modules/@cashu/crypto/modules/index.js
generated
vendored
3
node_modules/@cashu/crypto/modules/index.js
generated
vendored
@@ -1,3 +0,0 @@
|
||||
"use strict";
|
||||
throw new Error('Incorrect usage. Import submodules instead');
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@cashu/crypto/modules/index.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC"}
|
||||
3
node_modules/@cashu/crypto/modules/mint/NUT11.d.ts
generated
vendored
3
node_modules/@cashu/crypto/modules/mint/NUT11.d.ts
generated
vendored
@@ -1,3 +0,0 @@
|
||||
import { Proof } from '../common/index.js';
|
||||
export declare const verifyP2PKSig: (proof: Proof) => boolean;
|
||||
//# sourceMappingURL=NUT11.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/mint/NUT11.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/mint/NUT11.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.d.ts","sourceRoot":"","sources":["../../src/mint/NUT11.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,eAAO,MAAM,aAAa,UAAW,KAAK,YAsCzC,CAAC"}
|
||||
37
node_modules/@cashu/crypto/modules/mint/NUT11.js
generated
vendored
37
node_modules/@cashu/crypto/modules/mint/NUT11.js
generated
vendored
@@ -1,37 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.verifyP2PKSig = void 0;
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const sha256_1 = require("@noble/hashes/sha256");
|
||||
const NUT11_js_1 = require("../common/NUT11.js");
|
||||
const verifyP2PKSig = (proof) => {
|
||||
if (!proof.witness) {
|
||||
throw new Error('could not verify signature, no witness provided');
|
||||
}
|
||||
const parsedSecret = (0, NUT11_js_1.parseSecret)(proof.secret);
|
||||
// const tags = {} as Tags
|
||||
// parsedSecret[1].tags.forEach((e: string[]) => {tags[e[0]]=e.shift()})
|
||||
// if (tags.locktime) {
|
||||
// const locktime = parseInt(tags.locktime[1])
|
||||
// let isUnlocked = false
|
||||
// if (Math.floor(Date.now() / 1000)>=locktime) {
|
||||
// isUnlocked = true
|
||||
// }
|
||||
// }
|
||||
// if (tags.sigflag as SigFlag) {
|
||||
// if (tags.sigflag[0]==='SIG_INPUT') {
|
||||
// }
|
||||
// else if(tags.sigflag[0]==='SIG_ALL') {
|
||||
// }
|
||||
// else {
|
||||
// throw new Error("Unknown sigflag");
|
||||
// }
|
||||
// }
|
||||
// if (tags.n_sigs) {
|
||||
// if (tags.pubkeys) {
|
||||
// }
|
||||
// }
|
||||
return secp256k1_1.schnorr.verify(proof.witness.signatures[0], (0, sha256_1.sha256)(new TextDecoder().decode(proof.secret)), parsedSecret[1].data);
|
||||
};
|
||||
exports.verifyP2PKSig = verifyP2PKSig;
|
||||
//# sourceMappingURL=NUT11.js.map
|
||||
1
node_modules/@cashu/crypto/modules/mint/NUT11.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/mint/NUT11.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"NUT11.js","sourceRoot":"","sources":["../../src/mint/NUT11.ts"],"names":[],"mappings":";;;AAAA,uDAAkD;AAClD,iDAA8C;AAC9C,iDAAiD;AAG1C,MAAM,aAAa,GAAG,CAAC,KAAY,EAAE,EAAE;IAC7C,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,YAAY,GAAG,IAAA,sBAAW,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE/C,0BAA0B;IAC1B,wEAAwE;IACxE,uBAAuB;IACvB,kDAAkD;IAElD,6BAA6B;IAC7B,qDAAqD;IACrD,4BAA4B;IAC5B,QAAQ;IACR,IAAI;IACJ,iCAAiC;IACjC,2CAA2C;IAE3C,QAAQ;IACR,6CAA6C;IAE7C,QAAQ;IACR,aAAa;IACb,8CAA8C;IAC9C,QAAQ;IACR,IAAI;IACJ,qBAAqB;IACrB,0BAA0B;IAE1B,QAAQ;IACR,IAAI;IAEJ,OAAO,mBAAO,CAAC,MAAM,CACpB,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAC3B,IAAA,eAAM,EAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAC9C,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CACpB,CAAC;AACH,CAAC,CAAC;AAtCW,QAAA,aAAa,iBAsCxB"}
|
||||
15
node_modules/@cashu/crypto/modules/mint/index.d.ts
generated
vendored
15
node_modules/@cashu/crypto/modules/mint/index.d.ts
generated
vendored
@@ -1,15 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
import { BlindSignature, IntRange, Keyset, MintKeys, Proof } from '../common/index.js';
|
||||
export type KeysetPair = {
|
||||
keysetId: string;
|
||||
pubKeys: MintKeys;
|
||||
privKeys: MintKeys;
|
||||
};
|
||||
export type KeysetWithKeys = Keyset & {
|
||||
pubKeys: MintKeys;
|
||||
};
|
||||
export declare function createBlindSignature(B_: ProjPointType<bigint>, privateKey: Uint8Array, amount: number, id: string): BlindSignature;
|
||||
export declare function getPubKeyFromPrivKey(privKey: Uint8Array): Uint8Array;
|
||||
export declare function createNewMintKeys(pow2height: IntRange<0, 65>, seed?: Uint8Array): KeysetPair;
|
||||
export declare function verifyProof(proof: Proof, privKey: Uint8Array): boolean;
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/mint/index.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/mint/index.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mint/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAGnE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAMvF,MAAM,MAAM,UAAU,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,QAAQ,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IACrC,OAAO,EAAE,QAAQ,CAAC;CAClB,CAAC;AAEF,wBAAgB,oBAAoB,CACnC,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,EACzB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,GACR,cAAc,CAGhB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,cAEvD;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CA0B5F;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAItE"}
|
||||
53
node_modules/@cashu/crypto/modules/mint/index.js
generated
vendored
53
node_modules/@cashu/crypto/modules/mint/index.js
generated
vendored
@@ -1,53 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.verifyProof = exports.createNewMintKeys = exports.getPubKeyFromPrivKey = exports.createBlindSignature = void 0;
|
||||
const secp256k1_1 = require("@noble/curves/secp256k1");
|
||||
const utils_js_1 = require("../util/utils.js");
|
||||
const index_js_1 = require("../common/index.js");
|
||||
const bip32_1 = require("@scure/bip32");
|
||||
const DERIVATION_PATH = "m/0'/0'/0'";
|
||||
function createBlindSignature(B_, privateKey, amount, id) {
|
||||
const C_ = B_.multiply((0, utils_js_1.bytesToNumber)(privateKey));
|
||||
return { C_, amount, id };
|
||||
}
|
||||
exports.createBlindSignature = createBlindSignature;
|
||||
function getPubKeyFromPrivKey(privKey) {
|
||||
return secp256k1_1.secp256k1.getPublicKey(privKey, true);
|
||||
}
|
||||
exports.getPubKeyFromPrivKey = getPubKeyFromPrivKey;
|
||||
function createNewMintKeys(pow2height, seed) {
|
||||
let counter = 0n;
|
||||
const pubKeys = {};
|
||||
const privKeys = {};
|
||||
let masterKey;
|
||||
if (seed) {
|
||||
masterKey = bip32_1.HDKey.fromMasterSeed(seed);
|
||||
}
|
||||
while (counter < pow2height) {
|
||||
const index = (2n ** counter).toString();
|
||||
if (masterKey) {
|
||||
const k = masterKey.derive(`${DERIVATION_PATH}/${counter}`).privateKey;
|
||||
if (k) {
|
||||
privKeys[index] = k;
|
||||
}
|
||||
else {
|
||||
throw new Error(`Could not derive Private key from: ${DERIVATION_PATH}/${counter}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
privKeys[index] = (0, index_js_1.createRandomPrivateKey)();
|
||||
}
|
||||
pubKeys[index] = getPubKeyFromPrivKey(privKeys[index]);
|
||||
counter++;
|
||||
}
|
||||
const keysetId = (0, index_js_1.deriveKeysetId)(pubKeys);
|
||||
return { pubKeys, privKeys, keysetId };
|
||||
}
|
||||
exports.createNewMintKeys = createNewMintKeys;
|
||||
function verifyProof(proof, privKey) {
|
||||
const Y = (0, index_js_1.hashToCurve)(proof.secret);
|
||||
const aY = Y.multiply((0, utils_js_1.bytesToNumber)(privKey));
|
||||
return aY.equals(proof.C);
|
||||
}
|
||||
exports.verifyProof = verifyProof;
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@cashu/crypto/modules/mint/index.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/mint/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mint/index.ts"],"names":[],"mappings":";;;AACA,uDAAoD;AACpD,+CAAiD;AAEjD,iDAAyF;AACzF,wCAAqC;AAErC,MAAM,eAAe,GAAG,YAAY,CAAC;AAYrC,SAAgB,oBAAoB,CACnC,EAAyB,EACzB,UAAsB,EACtB,MAAc,EACd,EAAU;IAEV,MAAM,EAAE,GAA0B,EAAE,CAAC,QAAQ,CAAC,IAAA,wBAAa,EAAC,UAAU,CAAC,CAAC,CAAC;IACzE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAC3B,CAAC;AARD,oDAQC;AAED,SAAgB,oBAAoB,CAAC,OAAmB;IACvD,OAAO,qBAAS,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC;AAFD,oDAEC;AAED,SAAgB,iBAAiB,CAAC,UAA2B,EAAE,IAAiB;IAC/E,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,SAAS,CAAC;IACd,IAAI,IAAI,EAAE,CAAC;QACV,SAAS,GAAG,aAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAW,CAAC,EAAE,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACjD,IAAI,SAAS,EAAE,CAAC;YACf,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,eAAe,IAAI,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC;YACvE,IAAI,CAAC,EAAE,CAAC;gBACP,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,sCAAsC,eAAe,IAAI,OAAO,EAAE,CAAC,CAAC;YACrF,CAAC;QACF,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAA,iCAAsB,GAAE,CAAC;QAC5C,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACvD,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,QAAQ,GAAG,IAAA,yBAAc,EAAC,OAAO,CAAC,CAAC;IACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AACxC,CAAC;AA1BD,8CA0BC;AAED,SAAgB,WAAW,CAAC,KAAY,EAAE,OAAmB;IAC5D,MAAM,CAAC,GAA0B,IAAA,sBAAW,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,EAAE,GAA0B,CAAC,CAAC,QAAQ,CAAC,IAAA,wBAAa,EAAC,OAAO,CAAC,CAAC,CAAC;IACrE,OAAO,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAJD,kCAIC"}
|
||||
4
node_modules/@cashu/crypto/modules/util/utils.d.ts
generated
vendored
4
node_modules/@cashu/crypto/modules/util/utils.d.ts
generated
vendored
@@ -1,4 +0,0 @@
|
||||
export declare function bytesToNumber(bytes: Uint8Array): bigint;
|
||||
export declare function hexToNumber(hex: string): bigint;
|
||||
export declare function encodeBase64toUint8(base64String: string): Uint8Array;
|
||||
//# sourceMappingURL=utils.d.ts.map
|
||||
1
node_modules/@cashu/crypto/modules/util/utils.d.ts.map
generated
vendored
1
node_modules/@cashu/crypto/modules/util/utils.d.ts.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEvD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,CAEpE"}
|
||||
18
node_modules/@cashu/crypto/modules/util/utils.js
generated
vendored
18
node_modules/@cashu/crypto/modules/util/utils.js
generated
vendored
@@ -1,18 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.encodeBase64toUint8 = exports.hexToNumber = exports.bytesToNumber = void 0;
|
||||
const utils_1 = require("@noble/curves/abstract/utils");
|
||||
const buffer_1 = require("buffer/");
|
||||
function bytesToNumber(bytes) {
|
||||
return hexToNumber((0, utils_1.bytesToHex)(bytes));
|
||||
}
|
||||
exports.bytesToNumber = bytesToNumber;
|
||||
function hexToNumber(hex) {
|
||||
return BigInt(`0x${hex}`);
|
||||
}
|
||||
exports.hexToNumber = hexToNumber;
|
||||
function encodeBase64toUint8(base64String) {
|
||||
return buffer_1.Buffer.from(base64String, 'base64');
|
||||
}
|
||||
exports.encodeBase64toUint8 = encodeBase64toUint8;
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
node_modules/@cashu/crypto/modules/util/utils.js.map
generated
vendored
1
node_modules/@cashu/crypto/modules/util/utils.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":";;;AAAA,wDAA0D;AAC1D,oCAAiC;AAEjC,SAAgB,aAAa,CAAC,KAAiB;IAC9C,OAAO,WAAW,CAAC,IAAA,kBAAU,EAAC,KAAK,CAAC,CAAC,CAAC;AACvC,CAAC;AAFD,sCAEC;AAED,SAAgB,WAAW,CAAC,GAAW;IACtC,OAAO,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;AAC3B,CAAC;AAFD,kCAEC;AAED,SAAgB,mBAAmB,CAAC,YAAoB;IACvD,OAAO,eAAM,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAFD,kDAEC"}
|
||||
100
node_modules/@cashu/crypto/package.json
generated
vendored
100
node_modules/@cashu/crypto/package.json
generated
vendored
@@ -1,100 +0,0 @@
|
||||
{
|
||||
"name": "@cashu/crypto",
|
||||
"version": "0.2.7",
|
||||
"description": "Basic cashu crypto functions",
|
||||
"main": "./modules/index.js",
|
||||
"files": [
|
||||
"src",
|
||||
"modules"
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "rm -rf modules && tsc && tsc -p tsconfig.esm.json",
|
||||
"test": "jest --coverage --maxWorkers=1",
|
||||
"dev": "tsc --watch",
|
||||
"lint": "eslint --ext .js,.ts .",
|
||||
"format": "prettier --write .",
|
||||
"typedoc": "typedoc --entryPointStrategy expand ./src"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/cashubtc/cashu-crypto-ts.git"
|
||||
},
|
||||
"keywords": [
|
||||
"blindsignature",
|
||||
"ecash",
|
||||
"chaumium",
|
||||
"mint",
|
||||
"cashu"
|
||||
],
|
||||
"author": "gandlaf21",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/curves": "^1.3.0",
|
||||
"@noble/hashes": "^1.3.3",
|
||||
"@scure/bip32": "^1.3.3",
|
||||
"@scure/bip39": "^1.2.2",
|
||||
"buffer": "^6.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.12",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-n": "^16.6.2",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-jest-resolver": "^2.0.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typedoc": "^0.25.8",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"exports": {
|
||||
"./modules": {
|
||||
"types": "./modules/index.d.ts",
|
||||
"import": "./modules/esm/index.js",
|
||||
"default": "./modules/index.js"
|
||||
},
|
||||
"./modules/util": {
|
||||
"types": "./modules/util/index.d.ts",
|
||||
"import": "./modules/esm/util/index.js",
|
||||
"default": "./modules/util/index.js"
|
||||
},
|
||||
"./modules/common": {
|
||||
"types": "./modules/common/index.d.ts",
|
||||
"import": "./modules/esm/common/index.js",
|
||||
"default": "./modules/common/index.js"
|
||||
},
|
||||
"./modules/mint": {
|
||||
"types": "./modules/mint/index.d.ts",
|
||||
"import": "./modules/esm/mint/index.js",
|
||||
"default": "./modules/mint/index.js"
|
||||
},
|
||||
"./modules/client": {
|
||||
"types": "./modules/client/index.d.ts",
|
||||
"import": "./modules/esm/client/index.js",
|
||||
"default": "./modules/client/index.js"
|
||||
},
|
||||
"./modules/client/NUT09": {
|
||||
"types": "./modules/client/NUT09.d.ts",
|
||||
"import": "./modules/esm/client/NUT09.js",
|
||||
"default": "./modules/client/NUT09.js"
|
||||
},
|
||||
"./modules/common/NUT11": {
|
||||
"types": "./modules/common/NUT11.d.ts",
|
||||
"import": "./modules/esm/common/NUT11.js",
|
||||
"default": "./modules/common/NUT11.js"
|
||||
},
|
||||
"./modules/client/NUT11": {
|
||||
"types": "./modules/client/NUT11.d.ts",
|
||||
"import": "./modules/esm/client/NUT11.js",
|
||||
"default": "./modules/client/NUT11.js"
|
||||
},
|
||||
"./modules/mint/NUT11": {
|
||||
"types": "./modules/mint/NUT11.d.ts",
|
||||
"import": "./modules/esm/mint/NUT11.js",
|
||||
"default": "./modules/mint/NUT11.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
49
node_modules/@cashu/crypto/src/client/NUT09.ts
generated
vendored
49
node_modules/@cashu/crypto/src/client/NUT09.ts
generated
vendored
@@ -1,49 +0,0 @@
|
||||
import { HDKey } from '@scure/bip32';
|
||||
import { getKeysetIdInt } from '../common/index.js';
|
||||
import { generateMnemonic, mnemonicToSeedSync } from '@scure/bip39';
|
||||
import { wordlist } from '@scure/bip39/wordlists/english';
|
||||
|
||||
const STANDARD_DERIVATION_PATH = `m/129372'/0'`;
|
||||
|
||||
enum DerivationType {
|
||||
SECRET = 0,
|
||||
BLINDING_FACTOR = 1
|
||||
}
|
||||
|
||||
export const deriveSecret = (seed: Uint8Array, keysetId: string, counter: number): Uint8Array => {
|
||||
return derive(seed, keysetId, counter, DerivationType.SECRET);
|
||||
};
|
||||
|
||||
export const deriveBlindingFactor = (
|
||||
seed: Uint8Array,
|
||||
keysetId: string,
|
||||
counter: number
|
||||
): Uint8Array => {
|
||||
return derive(seed, keysetId, counter, DerivationType.BLINDING_FACTOR);
|
||||
};
|
||||
|
||||
const derive = (
|
||||
seed: Uint8Array,
|
||||
keysetId: string,
|
||||
counter: number,
|
||||
secretOrBlinding: DerivationType
|
||||
): Uint8Array => {
|
||||
const hdkey = HDKey.fromMasterSeed(seed);
|
||||
const keysetIdInt = getKeysetIdInt(keysetId);
|
||||
const derivationPath = `${STANDARD_DERIVATION_PATH}/${keysetIdInt}'/${counter}'/${secretOrBlinding}`;
|
||||
const derived = hdkey.derive(derivationPath);
|
||||
if (derived.privateKey === null) {
|
||||
throw new Error('Could not derive private key');
|
||||
}
|
||||
return derived.privateKey;
|
||||
};
|
||||
|
||||
export const generateNewMnemonic = (): string => {
|
||||
const mnemonic = generateMnemonic(wordlist, 128);
|
||||
return mnemonic;
|
||||
};
|
||||
|
||||
export const deriveSeedFromMnemonic = (mnemonic: string): Uint8Array => {
|
||||
const seed = mnemonicToSeedSync(mnemonic);
|
||||
return seed;
|
||||
};
|
||||
47
node_modules/@cashu/crypto/src/client/NUT11.ts
generated
vendored
47
node_modules/@cashu/crypto/src/client/NUT11.ts
generated
vendored
@@ -1,47 +0,0 @@
|
||||
import { PrivKey, bytesToHex, hexToBytes } from '@noble/curves/abstract/utils';
|
||||
import { sha256 } from '@noble/hashes/sha256';
|
||||
import { schnorr } from '@noble/curves/secp256k1';
|
||||
import { randomBytes } from '@noble/hashes/utils';
|
||||
import { parseSecret } from '../common/NUT11.js';
|
||||
import { Proof, Secret } from '../common/index.js';
|
||||
|
||||
export const createP2PKsecret = (pubkey: string): Uint8Array => {
|
||||
const newSecret: Secret = [
|
||||
'P2PK',
|
||||
{
|
||||
nonce: bytesToHex(randomBytes(32)),
|
||||
data: pubkey
|
||||
}
|
||||
];
|
||||
const parsed = JSON.stringify(newSecret);
|
||||
return new TextEncoder().encode(parsed);
|
||||
};
|
||||
|
||||
export const signP2PKsecret = (secret: Uint8Array, privateKey: PrivKey) => {
|
||||
const msghash = sha256(new TextDecoder().decode(secret));
|
||||
const sig = schnorr.sign(msghash, privateKey);
|
||||
return sig;
|
||||
};
|
||||
|
||||
export const getSignedProofs = (proofs: Array<Proof>, privateKey: string): Array<Proof> => {
|
||||
return proofs.map((p) => {
|
||||
try {
|
||||
const parsed: Secret = parseSecret(p.secret);
|
||||
if (parsed[0] !== 'P2PK') {
|
||||
throw new Error('unknown secret type');
|
||||
}
|
||||
return getSignedProof(p, hexToBytes(privateKey));
|
||||
} catch (error) {
|
||||
return p;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getSignedProof = (proof: Proof, privateKey: PrivKey): Proof => {
|
||||
if (!proof.witness) {
|
||||
proof.witness = {
|
||||
signatures: [bytesToHex(signP2PKsecret(proof.secret, privateKey))]
|
||||
};
|
||||
}
|
||||
return proof;
|
||||
};
|
||||
87
node_modules/@cashu/crypto/src/client/index.ts
generated
vendored
87
node_modules/@cashu/crypto/src/client/index.ts
generated
vendored
@@ -1,87 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
import { secp256k1 } from '@noble/curves/secp256k1';
|
||||
import { bytesToHex, hexToBytes, randomBytes } from '@noble/hashes/utils';
|
||||
import { bytesToNumber } from '../util/utils.js';
|
||||
import type {
|
||||
BlindSignature,
|
||||
Proof,
|
||||
SerializedBlindedMessage,
|
||||
SerializedProof
|
||||
} from '../common/index.js';
|
||||
import { hashToCurve, pointFromHex } from '../common/index.js';
|
||||
import { Witness } from '../common/index';
|
||||
|
||||
export type BlindedMessage = {
|
||||
B_: ProjPointType<bigint>;
|
||||
r: bigint;
|
||||
secret: Uint8Array;
|
||||
};
|
||||
|
||||
export function createRandomBlindedMessage(): BlindedMessage {
|
||||
return blindMessage(randomBytes(32));
|
||||
}
|
||||
|
||||
export function blindMessage(secret: Uint8Array, r?: bigint): BlindedMessage {
|
||||
const Y = hashToCurve(secret);
|
||||
if (!r) {
|
||||
r = bytesToNumber(secp256k1.utils.randomPrivateKey());
|
||||
}
|
||||
const rG = secp256k1.ProjectivePoint.BASE.multiply(r);
|
||||
const B_ = Y.add(rG);
|
||||
return { B_, r, secret };
|
||||
}
|
||||
|
||||
export function unblindSignature(
|
||||
C_: ProjPointType<bigint>,
|
||||
r: bigint,
|
||||
A: ProjPointType<bigint>
|
||||
): ProjPointType<bigint> {
|
||||
const C = C_.subtract(A.multiply(r));
|
||||
return C;
|
||||
}
|
||||
|
||||
export function constructProofFromPromise(
|
||||
promise: BlindSignature,
|
||||
r: bigint,
|
||||
secret: Uint8Array,
|
||||
key: ProjPointType<bigint>
|
||||
): Proof {
|
||||
const A = key;
|
||||
const C = unblindSignature(promise.C_, r, A);
|
||||
const proof = {
|
||||
id: promise.id,
|
||||
amount: promise.amount,
|
||||
secret,
|
||||
C
|
||||
};
|
||||
return proof;
|
||||
}
|
||||
|
||||
export const serializeProof = (proof: Proof): SerializedProof => {
|
||||
return {
|
||||
amount: proof.amount,
|
||||
C: proof.C.toHex(true),
|
||||
id: proof.id,
|
||||
secret: new TextDecoder().decode(proof.secret),
|
||||
witness: JSON.stringify(proof.witness)
|
||||
};
|
||||
};
|
||||
|
||||
export const deserializeProof = (proof: SerializedProof): Proof => {
|
||||
return {
|
||||
amount: proof.amount,
|
||||
C: pointFromHex(proof.C),
|
||||
id: proof.id,
|
||||
secret: new TextEncoder().encode(proof.secret),
|
||||
witness: proof.witness?JSON.parse(proof.witness):undefined
|
||||
};
|
||||
};
|
||||
export const serializeBlindedMessage = (
|
||||
bm: BlindedMessage,
|
||||
amount: number
|
||||
): SerializedBlindedMessage => {
|
||||
return {
|
||||
B_: bm.B_.toHex(true),
|
||||
amount: amount
|
||||
};
|
||||
};
|
||||
12
node_modules/@cashu/crypto/src/common/NUT11.ts
generated
vendored
12
node_modules/@cashu/crypto/src/common/NUT11.ts
generated
vendored
@@ -1,12 +0,0 @@
|
||||
import { Secret } from "./index.js";
|
||||
|
||||
export const parseSecret = (secret: string | Uint8Array): Secret => {
|
||||
try {
|
||||
if (secret instanceof Uint8Array) {
|
||||
secret = new TextDecoder().decode(secret);
|
||||
}
|
||||
return JSON.parse(secret);
|
||||
} catch (e) {
|
||||
throw new Error("can't parse secret");
|
||||
}
|
||||
};
|
||||
154
node_modules/@cashu/crypto/src/common/index.ts
generated
vendored
154
node_modules/@cashu/crypto/src/common/index.ts
generated
vendored
@@ -1,154 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
import { secp256k1 } from '@noble/curves/secp256k1';
|
||||
import { sha256 } from '@noble/hashes/sha256';
|
||||
import { bytesToHex, hexToBytes } from '@noble/curves/abstract/utils';
|
||||
import { bytesToNumber, encodeBase64toUint8, hexToNumber } from '../util/utils.js';
|
||||
import { Buffer } from 'buffer/';
|
||||
|
||||
export type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N
|
||||
? Acc[number]
|
||||
: Enumerate<N, [...Acc, Acc['length']]>;
|
||||
|
||||
export type IntRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>;
|
||||
|
||||
export type MintKeys = { [k: string]: Uint8Array };
|
||||
|
||||
export type SerializedMintKeys = {
|
||||
[k: string]: string;
|
||||
};
|
||||
|
||||
export type Keyset = {
|
||||
id: string;
|
||||
unit: string;
|
||||
active: boolean;
|
||||
};
|
||||
|
||||
export type BlindSignature = {
|
||||
C_: ProjPointType<bigint>;
|
||||
amount: number;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type SerializedBlindSignature = {
|
||||
C_: string;
|
||||
amount: number;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type Proof = {
|
||||
C: ProjPointType<bigint>;
|
||||
secret: Uint8Array;
|
||||
amount: number;
|
||||
id: string;
|
||||
witness?: Witness;
|
||||
};
|
||||
|
||||
export type SerializedProof = {
|
||||
C: string;
|
||||
secret: string;
|
||||
amount: number;
|
||||
id: string;
|
||||
witness?: string;
|
||||
};
|
||||
|
||||
export type SerializedBlindedMessage = {
|
||||
B_: string;
|
||||
amount: number;
|
||||
witness?: string;
|
||||
};
|
||||
|
||||
export type Secret = [WellKnownSecret, SecretData];
|
||||
|
||||
export type WellKnownSecret = 'P2PK';
|
||||
|
||||
export type SecretData = {
|
||||
nonce: string;
|
||||
data: string;
|
||||
tags?: Array<Array<string>>;
|
||||
};
|
||||
|
||||
export type Witness = {
|
||||
signatures: Array<string>;
|
||||
};
|
||||
|
||||
export type Tags = {
|
||||
[k: string]: string;
|
||||
};
|
||||
|
||||
export type SigFlag = 'SIG_INPUTS' | 'SIG_ALL';
|
||||
|
||||
const DOMAIN_SEPARATOR = hexToBytes('536563703235366b315f48617368546f43757276655f43617368755f');
|
||||
|
||||
export function hashToCurve(secret: Uint8Array): ProjPointType<bigint> {
|
||||
const msgToHash = sha256(Buffer.concat([DOMAIN_SEPARATOR, secret]));
|
||||
const counter = new Uint32Array(1);
|
||||
const maxIterations = 2 ** 16;
|
||||
for (let i = 0; i < maxIterations; i++) {
|
||||
const counterBytes = new Uint8Array(counter.buffer);
|
||||
const hash = sha256(Buffer.concat([msgToHash, counterBytes]));
|
||||
try {
|
||||
return pointFromHex(bytesToHex(Buffer.concat([new Uint8Array([0x02]), hash])));
|
||||
} catch (error) {
|
||||
counter[0]++;
|
||||
}
|
||||
}
|
||||
throw new Error('No valid point found');
|
||||
}
|
||||
|
||||
export function pointFromHex(hex: string) {
|
||||
return secp256k1.ProjectivePoint.fromHex(hex);
|
||||
}
|
||||
|
||||
export const getKeysetIdInt = (keysetId: string): bigint => {
|
||||
let keysetIdInt: bigint;
|
||||
if (/^[a-fA-F0-9]+$/.test(keysetId)) {
|
||||
keysetIdInt = hexToNumber(keysetId) % BigInt(2 ** 31 - 1);
|
||||
} else {
|
||||
//legacy keyset compatibility
|
||||
keysetIdInt = bytesToNumber(encodeBase64toUint8(keysetId)) % BigInt(2 ** 31 - 1);
|
||||
}
|
||||
return keysetIdInt;
|
||||
};
|
||||
|
||||
export function createRandomPrivateKey() {
|
||||
return secp256k1.utils.randomPrivateKey();
|
||||
}
|
||||
|
||||
export function serializeMintKeys(mintKeys: MintKeys): SerializedMintKeys {
|
||||
const serializedMintKeys: SerializedMintKeys = {};
|
||||
Object.keys(mintKeys).forEach((p) => {
|
||||
serializedMintKeys[p] = bytesToHex(mintKeys[p]);
|
||||
});
|
||||
return serializedMintKeys;
|
||||
}
|
||||
|
||||
export function deserializeMintKeys(serializedMintKeys: SerializedMintKeys): MintKeys {
|
||||
const mintKeys: MintKeys = {};
|
||||
Object.keys(serializedMintKeys).forEach((p) => {
|
||||
mintKeys[p] = hexToBytes(serializedMintKeys[p]);
|
||||
});
|
||||
return mintKeys;
|
||||
}
|
||||
|
||||
export function deriveKeysetId(keys: MintKeys): string {
|
||||
const KEYSET_VERSION = '00';
|
||||
const mapBigInt = (k: [string, string]): [bigint, string] => {
|
||||
return [BigInt(k[0]), k[1]];
|
||||
};
|
||||
const pubkeysConcat = Object.entries(serializeMintKeys(keys))
|
||||
.map(mapBigInt)
|
||||
.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0))
|
||||
.map(([, pubKey]) => hexToBytes(pubKey))
|
||||
.reduce((prev, curr) => mergeUInt8Arrays(prev, curr), new Uint8Array());
|
||||
const hash = sha256(pubkeysConcat);
|
||||
const hashHex = Buffer.from(hash).toString('hex').slice(0, 14);
|
||||
return '00' + hashHex;
|
||||
}
|
||||
|
||||
function mergeUInt8Arrays(a1: Uint8Array, a2: Uint8Array): Uint8Array {
|
||||
// sum of individual array lengths
|
||||
const mergedArray = new Uint8Array(a1.length + a2.length);
|
||||
mergedArray.set(a1);
|
||||
mergedArray.set(a2, a1.length);
|
||||
return mergedArray;
|
||||
}
|
||||
1
node_modules/@cashu/crypto/src/index.ts
generated
vendored
1
node_modules/@cashu/crypto/src/index.ts
generated
vendored
@@ -1 +0,0 @@
|
||||
throw new Error('Incorrect usage. Import submodules instead');
|
||||
44
node_modules/@cashu/crypto/src/mint/NUT11.ts
generated
vendored
44
node_modules/@cashu/crypto/src/mint/NUT11.ts
generated
vendored
@@ -1,44 +0,0 @@
|
||||
import { schnorr } from '@noble/curves/secp256k1';
|
||||
import { sha256 } from '@noble/hashes/sha256';
|
||||
import { parseSecret } from '../common/NUT11.js';
|
||||
import { Proof } from '../common/index.js';
|
||||
|
||||
export const verifyP2PKSig = (proof: Proof) => {
|
||||
if (!proof.witness) {
|
||||
throw new Error('could not verify signature, no witness provided');
|
||||
}
|
||||
const parsedSecret = parseSecret(proof.secret);
|
||||
|
||||
// const tags = {} as Tags
|
||||
// parsedSecret[1].tags.forEach((e: string[]) => {tags[e[0]]=e.shift()})
|
||||
// if (tags.locktime) {
|
||||
// const locktime = parseInt(tags.locktime[1])
|
||||
|
||||
// let isUnlocked = false
|
||||
// if (Math.floor(Date.now() / 1000)>=locktime) {
|
||||
// isUnlocked = true
|
||||
// }
|
||||
// }
|
||||
// if (tags.sigflag as SigFlag) {
|
||||
// if (tags.sigflag[0]==='SIG_INPUT') {
|
||||
|
||||
// }
|
||||
// else if(tags.sigflag[0]==='SIG_ALL') {
|
||||
|
||||
// }
|
||||
// else {
|
||||
// throw new Error("Unknown sigflag");
|
||||
// }
|
||||
// }
|
||||
// if (tags.n_sigs) {
|
||||
// if (tags.pubkeys) {
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
return schnorr.verify(
|
||||
proof.witness.signatures[0],
|
||||
sha256(new TextDecoder().decode(proof.secret)),
|
||||
parsedSecret[1].data
|
||||
);
|
||||
};
|
||||
66
node_modules/@cashu/crypto/src/mint/index.ts
generated
vendored
66
node_modules/@cashu/crypto/src/mint/index.ts
generated
vendored
@@ -1,66 +0,0 @@
|
||||
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
||||
import { secp256k1 } from '@noble/curves/secp256k1';
|
||||
import { bytesToNumber } from '../util/utils.js';
|
||||
import { BlindSignature, IntRange, Keyset, MintKeys, Proof } from '../common/index.js';
|
||||
import { createRandomPrivateKey, deriveKeysetId, hashToCurve } from '../common/index.js';
|
||||
import { HDKey } from '@scure/bip32';
|
||||
|
||||
const DERIVATION_PATH = "m/0'/0'/0'";
|
||||
|
||||
export type KeysetPair = {
|
||||
keysetId: string;
|
||||
pubKeys: MintKeys;
|
||||
privKeys: MintKeys;
|
||||
};
|
||||
|
||||
export type KeysetWithKeys = Keyset & {
|
||||
pubKeys: MintKeys;
|
||||
};
|
||||
|
||||
export function createBlindSignature(
|
||||
B_: ProjPointType<bigint>,
|
||||
privateKey: Uint8Array,
|
||||
amount: number,
|
||||
id: string
|
||||
): BlindSignature {
|
||||
const C_: ProjPointType<bigint> = B_.multiply(bytesToNumber(privateKey));
|
||||
return { C_, amount, id };
|
||||
}
|
||||
|
||||
export function getPubKeyFromPrivKey(privKey: Uint8Array) {
|
||||
return secp256k1.getPublicKey(privKey, true);
|
||||
}
|
||||
|
||||
export function createNewMintKeys(pow2height: IntRange<0, 65>, seed?: Uint8Array): KeysetPair {
|
||||
let counter = 0n;
|
||||
const pubKeys: MintKeys = {};
|
||||
const privKeys: MintKeys = {};
|
||||
let masterKey;
|
||||
if (seed) {
|
||||
masterKey = HDKey.fromMasterSeed(seed);
|
||||
}
|
||||
while (counter < pow2height) {
|
||||
const index: string = (2n ** counter).toString();
|
||||
if (masterKey) {
|
||||
const k = masterKey.derive(`${DERIVATION_PATH}/${counter}`).privateKey;
|
||||
if (k) {
|
||||
privKeys[index] = k;
|
||||
} else {
|
||||
throw new Error(`Could not derive Private key from: ${DERIVATION_PATH}/${counter}`);
|
||||
}
|
||||
} else {
|
||||
privKeys[index] = createRandomPrivateKey();
|
||||
}
|
||||
|
||||
pubKeys[index] = getPubKeyFromPrivKey(privKeys[index]);
|
||||
counter++;
|
||||
}
|
||||
const keysetId = deriveKeysetId(pubKeys);
|
||||
return { pubKeys, privKeys, keysetId };
|
||||
}
|
||||
|
||||
export function verifyProof(proof: Proof, privKey: Uint8Array): boolean {
|
||||
const Y: ProjPointType<bigint> = hashToCurve(proof.secret);
|
||||
const aY: ProjPointType<bigint> = Y.multiply(bytesToNumber(privKey));
|
||||
return aY.equals(proof.C);
|
||||
}
|
||||
14
node_modules/@cashu/crypto/src/util/utils.ts
generated
vendored
14
node_modules/@cashu/crypto/src/util/utils.ts
generated
vendored
@@ -1,14 +0,0 @@
|
||||
import { bytesToHex } from '@noble/curves/abstract/utils';
|
||||
import { Buffer } from 'buffer/';
|
||||
|
||||
export function bytesToNumber(bytes: Uint8Array): bigint {
|
||||
return hexToNumber(bytesToHex(bytes));
|
||||
}
|
||||
|
||||
export function hexToNumber(hex: string): bigint {
|
||||
return BigInt(`0x${hex}`);
|
||||
}
|
||||
|
||||
export function encodeBase64toUint8(base64String: string): Uint8Array {
|
||||
return Buffer.from(base64String, 'base64');
|
||||
}
|
||||
12
node_modules/applesauce-accounts/package.json
generated
vendored
12
node_modules/applesauce-accounts/package.json
generated
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "applesauce-accounts",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0",
|
||||
"description": "A simple nostr account management system",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
@@ -33,21 +33,23 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.7.1",
|
||||
"applesauce-signers": "^3.1.0",
|
||||
"applesauce-core": "^3.1.0",
|
||||
"applesauce-core": "^4.0.0",
|
||||
"applesauce-signers": "^4.0.0",
|
||||
"nanoid": "^5.1.5",
|
||||
"nostr-tools": "~2.15",
|
||||
"nostr-tools": "~2.17",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^3.2.3"
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"funding": {
|
||||
"type": "lightning",
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "tsc",
|
||||
"watch:build": "tsc --watch > /dev/null",
|
||||
"test": "vitest run --passWithNoTests",
|
||||
|
||||
1
node_modules/applesauce-actions/dist/actions/index.d.ts
generated
vendored
1
node_modules/applesauce-actions/dist/actions/index.d.ts
generated
vendored
@@ -1,3 +1,4 @@
|
||||
export * from "./app-data.js";
|
||||
export * from "./blocked-relays.js";
|
||||
export * from "./blossom.js";
|
||||
export * from "./bookmarks.js";
|
||||
|
||||
1
node_modules/applesauce-actions/dist/actions/index.js
generated
vendored
1
node_modules/applesauce-actions/dist/actions/index.js
generated
vendored
@@ -1,3 +1,4 @@
|
||||
export * from "./app-data.js";
|
||||
export * from "./blocked-relays.js";
|
||||
export * from "./blossom.js";
|
||||
export * from "./bookmarks.js";
|
||||
|
||||
14
node_modules/applesauce-actions/package.json
generated
vendored
14
node_modules/applesauce-actions/package.json
generated
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "applesauce-actions",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0",
|
||||
"description": "A package for performing common nostr actions",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
@@ -32,24 +32,26 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"applesauce-core": "^3.1.0",
|
||||
"applesauce-factory": "^3.1.0",
|
||||
"nostr-tools": "~2.15",
|
||||
"applesauce-core": "^4.0.0",
|
||||
"applesauce-factory": "^4.0.0",
|
||||
"nostr-tools": "~2.17",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hirez_io/observer-spy": "^2.2.0",
|
||||
"@types/debug": "^4.1.12",
|
||||
"applesauce-signers": "^3.1.0",
|
||||
"applesauce-signers": "^4.0.0",
|
||||
"nanoid": "^5.1.5",
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^3.2.3"
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"funding": {
|
||||
"type": "lightning",
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "tsc",
|
||||
"watch:build": "tsc --watch > /dev/null",
|
||||
"test": "vitest run --passWithNoTests",
|
||||
|
||||
84
node_modules/applesauce-core/dist/event-store/event-set.d.ts
generated
vendored
84
node_modules/applesauce-core/dist/event-store/event-set.d.ts
generated
vendored
@@ -1,84 +0,0 @@
|
||||
import { Filter, NostrEvent } from "nostr-tools";
|
||||
import { Subject } from "rxjs";
|
||||
import { LRU } from "../helpers/lru.js";
|
||||
import { IEventSet } from "./interface.js";
|
||||
/**
|
||||
* A set of nostr events that can be queried and subscribed to
|
||||
* NOTE: does not handle replaceable events or any deletion logic
|
||||
*/
|
||||
export declare class EventSet implements IEventSet {
|
||||
protected log: import("debug").Debugger;
|
||||
/** Indexes */
|
||||
protected kinds: Map<number, Set<import("nostr-tools").Event>>;
|
||||
protected authors: Map<string, Set<import("nostr-tools").Event>>;
|
||||
protected tags: LRU<Set<import("nostr-tools").Event>>;
|
||||
protected created_at: NostrEvent[];
|
||||
/** LRU cache of last events touched */
|
||||
events: LRU<import("nostr-tools").Event>;
|
||||
/** A sorted array of replaceable events by address */
|
||||
protected replaceable: Map<string, import("nostr-tools").Event[]>;
|
||||
/** A stream of events inserted into the database */
|
||||
insert$: Subject<import("nostr-tools").Event>;
|
||||
/** A stream of events that have been updated */
|
||||
update$: Subject<import("nostr-tools").Event>;
|
||||
/** A stream of events removed from the database */
|
||||
remove$: Subject<import("nostr-tools").Event>;
|
||||
/** A method thats called before a new event is inserted */
|
||||
onBeforeInsert?: (event: NostrEvent) => boolean;
|
||||
/** The number of events in the event set */
|
||||
get size(): number;
|
||||
/** Moves an event to the top of the LRU cache */
|
||||
touch(event: NostrEvent): void;
|
||||
/** Checks if the database contains an event without touching it */
|
||||
hasEvent(id: string): boolean;
|
||||
/** Gets a single event based on id */
|
||||
getEvent(id: string): NostrEvent | undefined;
|
||||
/** Checks if the event set has a replaceable event */
|
||||
hasReplaceable(kind: number, pubkey: string, identifier?: string): boolean;
|
||||
/** Gets the latest replaceable event */
|
||||
getReplaceable(kind: number, pubkey: string, identifier?: string): NostrEvent | undefined;
|
||||
/** Gets the history of a replaceable event */
|
||||
getReplaceableHistory(kind: number, pubkey: string, identifier?: string): NostrEvent[] | undefined;
|
||||
/** Gets all events that match the filters */
|
||||
getByFilters(filters: Filter | Filter[]): Set<NostrEvent>;
|
||||
/** Gets a timeline of events that match the filters */
|
||||
getTimeline(filters: Filter | Filter[]): NostrEvent[];
|
||||
/** Inserts an event into the database and notifies all subscriptions */
|
||||
add(event: NostrEvent): NostrEvent | null;
|
||||
/** Inserts and event into the database and notifies all subscriptions that the event has updated */
|
||||
update(event: NostrEvent): boolean;
|
||||
/** Removes an event from the database and notifies all subscriptions */
|
||||
remove(eventOrId: string | NostrEvent): boolean;
|
||||
/** A weak map of events that are claimed by other things */
|
||||
protected claims: WeakMap<import("nostr-tools").Event, any>;
|
||||
/** Sets the claim on the event and touches it */
|
||||
claim(event: NostrEvent, claim: any): void;
|
||||
/** Checks if an event is claimed by anything */
|
||||
isClaimed(event: NostrEvent): boolean;
|
||||
/** Removes a claim from an event */
|
||||
removeClaim(event: NostrEvent, claim: any): void;
|
||||
/** Removes all claims on an event */
|
||||
clearClaim(event: NostrEvent): void;
|
||||
/** Index helper methods */
|
||||
protected getKindIndex(kind: number): Set<import("nostr-tools").Event>;
|
||||
protected getAuthorsIndex(author: string): Set<import("nostr-tools").Event>;
|
||||
protected getTagIndex(tagAndValue: string): Set<import("nostr-tools").Event>;
|
||||
/** Iterates over all events by author */
|
||||
iterateAuthors(authors: Iterable<string>): Generator<NostrEvent>;
|
||||
/** Iterates over all events by indexable tag and value */
|
||||
iterateTag(tag: string, values: Iterable<string>): Generator<NostrEvent>;
|
||||
/** Iterates over all events by kind */
|
||||
iterateKinds(kinds: Iterable<number>): Generator<NostrEvent>;
|
||||
/** Iterates over all events by time */
|
||||
iterateTime(since: number | undefined, until: number | undefined): Generator<NostrEvent>;
|
||||
/** Iterates over all events by id */
|
||||
iterateIds(ids: Iterable<string>): Generator<NostrEvent>;
|
||||
/** Returns all events that match the filter */
|
||||
getEventsForFilter(filter: Filter): Set<NostrEvent>;
|
||||
/** Returns all events that match the filters */
|
||||
getEventsForFilters(filters: Filter[]): Set<NostrEvent>;
|
||||
/** Remove the oldest events that are not claimed */
|
||||
prune(limit?: number): number;
|
||||
/** Resets the event set */
|
||||
reset(): void;
|
||||
}
|
||||
359
node_modules/applesauce-core/dist/event-store/event-set.js
generated
vendored
359
node_modules/applesauce-core/dist/event-store/event-set.js
generated
vendored
@@ -1,359 +0,0 @@
|
||||
import { binarySearch, insertEventIntoDescendingList } from "nostr-tools/utils";
|
||||
import { Subject } from "rxjs";
|
||||
import { getIndexableTags, INDEXABLE_TAGS } from "../helpers/event-tags.js";
|
||||
import { createReplaceableAddress, isReplaceable } from "../helpers/event.js";
|
||||
import { LRU } from "../helpers/lru.js";
|
||||
import { logger } from "../logger.js";
|
||||
/**
|
||||
* A set of nostr events that can be queried and subscribed to
|
||||
* NOTE: does not handle replaceable events or any deletion logic
|
||||
*/
|
||||
export class EventSet {
|
||||
log = logger.extend("EventSet");
|
||||
/** Indexes */
|
||||
kinds = new Map();
|
||||
authors = new Map();
|
||||
tags = new LRU();
|
||||
created_at = [];
|
||||
/** LRU cache of last events touched */
|
||||
events = new LRU();
|
||||
/** A sorted array of replaceable events by address */
|
||||
replaceable = new Map();
|
||||
/** A stream of events inserted into the database */
|
||||
insert$ = new Subject();
|
||||
/** A stream of events that have been updated */
|
||||
update$ = new Subject();
|
||||
/** A stream of events removed from the database */
|
||||
remove$ = new Subject();
|
||||
/** A method thats called before a new event is inserted */
|
||||
onBeforeInsert;
|
||||
/** The number of events in the event set */
|
||||
get size() {
|
||||
return this.events.size;
|
||||
}
|
||||
/** Moves an event to the top of the LRU cache */
|
||||
touch(event) {
|
||||
this.events.set(event.id, event);
|
||||
}
|
||||
/** Checks if the database contains an event without touching it */
|
||||
hasEvent(id) {
|
||||
return this.events.has(id);
|
||||
}
|
||||
/** Gets a single event based on id */
|
||||
getEvent(id) {
|
||||
return this.events.get(id);
|
||||
}
|
||||
/** Checks if the event set has a replaceable event */
|
||||
hasReplaceable(kind, pubkey, identifier) {
|
||||
const events = this.replaceable.get(createReplaceableAddress(kind, pubkey, identifier));
|
||||
return !!events && events.length > 0;
|
||||
}
|
||||
/** Gets the latest replaceable event */
|
||||
getReplaceable(kind, pubkey, identifier) {
|
||||
const address = createReplaceableAddress(kind, pubkey, identifier);
|
||||
const events = this.replaceable.get(address);
|
||||
return events?.[0];
|
||||
}
|
||||
/** Gets the history of a replaceable event */
|
||||
getReplaceableHistory(kind, pubkey, identifier) {
|
||||
const address = createReplaceableAddress(kind, pubkey, identifier);
|
||||
return this.replaceable.get(address);
|
||||
}
|
||||
/** Gets all events that match the filters */
|
||||
getByFilters(filters) {
|
||||
return this.getEventsForFilters(Array.isArray(filters) ? filters : [filters]);
|
||||
}
|
||||
/** Gets a timeline of events that match the filters */
|
||||
getTimeline(filters) {
|
||||
const timeline = [];
|
||||
const events = this.getEventsForFilters(Array.isArray(filters) ? filters : [filters]);
|
||||
for (const event of events)
|
||||
insertEventIntoDescendingList(timeline, event);
|
||||
return timeline;
|
||||
}
|
||||
/** Inserts an event into the database and notifies all subscriptions */
|
||||
add(event) {
|
||||
const id = event.id;
|
||||
const current = this.events.get(id);
|
||||
if (current)
|
||||
return current;
|
||||
// Ignore events if before insert returns false
|
||||
if (this.onBeforeInsert?.(event) === false)
|
||||
return null;
|
||||
this.events.set(id, event);
|
||||
this.getKindIndex(event.kind).add(event);
|
||||
this.getAuthorsIndex(event.pubkey).add(event);
|
||||
// Add the event to the tag indexes if they exist
|
||||
for (const tag of getIndexableTags(event)) {
|
||||
if (this.tags.has(tag))
|
||||
this.getTagIndex(tag).add(event);
|
||||
}
|
||||
// Insert into time index
|
||||
insertEventIntoDescendingList(this.created_at, event);
|
||||
// Insert into replaceable index
|
||||
if (isReplaceable(event.kind)) {
|
||||
const identifier = event.tags.find((t) => t[0] === "d")?.[1];
|
||||
const address = createReplaceableAddress(event.kind, event.pubkey, identifier);
|
||||
let array = this.replaceable.get(address);
|
||||
if (!this.replaceable.has(address)) {
|
||||
// add an empty array if there is no array
|
||||
array = [];
|
||||
this.replaceable.set(address, array);
|
||||
}
|
||||
// insert the event into the sorted array
|
||||
insertEventIntoDescendingList(array, event);
|
||||
}
|
||||
// Notify subscribers that the event was inserted
|
||||
this.insert$.next(event);
|
||||
return event;
|
||||
}
|
||||
/** Inserts and event into the database and notifies all subscriptions that the event has updated */
|
||||
update(event) {
|
||||
const inserted = this.add(event);
|
||||
if (inserted)
|
||||
this.update$.next(inserted);
|
||||
return inserted !== null;
|
||||
}
|
||||
/** Removes an event from the database and notifies all subscriptions */
|
||||
remove(eventOrId) {
|
||||
let event = typeof eventOrId === "string" ? this.events.get(eventOrId) : eventOrId;
|
||||
if (!event)
|
||||
throw new Error("Missing event");
|
||||
const id = event.id;
|
||||
// only remove events that are known
|
||||
if (!this.events.has(id))
|
||||
return false;
|
||||
this.getAuthorsIndex(event.pubkey).delete(event);
|
||||
this.getKindIndex(event.kind).delete(event);
|
||||
for (const tag of getIndexableTags(event)) {
|
||||
if (this.tags.has(tag)) {
|
||||
this.getTagIndex(tag).delete(event);
|
||||
}
|
||||
}
|
||||
// remove from created_at index
|
||||
const i = this.created_at.indexOf(event);
|
||||
this.created_at.splice(i, 1);
|
||||
this.events.delete(id);
|
||||
// remove from replaceable index
|
||||
if (isReplaceable(event.kind)) {
|
||||
const identifier = event.tags.find((t) => t[0] === "d")?.[1];
|
||||
const address = createReplaceableAddress(event.kind, event.pubkey, identifier);
|
||||
const array = this.replaceable.get(address);
|
||||
if (array && array.includes(event)) {
|
||||
const idx = array.indexOf(event);
|
||||
array.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
// remove any claims this event has
|
||||
this.claims.delete(event);
|
||||
// notify subscribers this event was removed
|
||||
this.remove$.next(event);
|
||||
return true;
|
||||
}
|
||||
/** A weak map of events that are claimed by other things */
|
||||
claims = new WeakMap();
|
||||
/** Sets the claim on the event and touches it */
|
||||
claim(event, claim) {
|
||||
if (!this.claims.has(event)) {
|
||||
this.claims.set(event, claim);
|
||||
}
|
||||
// always touch event
|
||||
this.touch(event);
|
||||
}
|
||||
/** Checks if an event is claimed by anything */
|
||||
isClaimed(event) {
|
||||
return this.claims.has(event);
|
||||
}
|
||||
/** Removes a claim from an event */
|
||||
removeClaim(event, claim) {
|
||||
const current = this.claims.get(event);
|
||||
if (current === claim)
|
||||
this.claims.delete(event);
|
||||
}
|
||||
/** Removes all claims on an event */
|
||||
clearClaim(event) {
|
||||
this.claims.delete(event);
|
||||
}
|
||||
/** Index helper methods */
|
||||
getKindIndex(kind) {
|
||||
if (!this.kinds.has(kind))
|
||||
this.kinds.set(kind, new Set());
|
||||
return this.kinds.get(kind);
|
||||
}
|
||||
getAuthorsIndex(author) {
|
||||
if (!this.authors.has(author))
|
||||
this.authors.set(author, new Set());
|
||||
return this.authors.get(author);
|
||||
}
|
||||
getTagIndex(tagAndValue) {
|
||||
if (!this.tags.has(tagAndValue)) {
|
||||
// build new tag index from existing events
|
||||
const events = new Set();
|
||||
const ts = Date.now();
|
||||
for (const event of this.events.values()) {
|
||||
if (getIndexableTags(event).has(tagAndValue)) {
|
||||
events.add(event);
|
||||
}
|
||||
}
|
||||
const took = Date.now() - ts;
|
||||
if (took > 100)
|
||||
this.log(`Built index ${tagAndValue} took ${took}ms`);
|
||||
this.tags.set(tagAndValue, events);
|
||||
}
|
||||
return this.tags.get(tagAndValue);
|
||||
}
|
||||
/** Iterates over all events by author */
|
||||
*iterateAuthors(authors) {
|
||||
for (const author of authors) {
|
||||
const events = this.authors.get(author);
|
||||
if (events) {
|
||||
for (const event of events)
|
||||
yield event;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Iterates over all events by indexable tag and value */
|
||||
*iterateTag(tag, values) {
|
||||
for (const value of values) {
|
||||
const events = this.getTagIndex(tag + ":" + value);
|
||||
if (events) {
|
||||
for (const event of events)
|
||||
yield event;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Iterates over all events by kind */
|
||||
*iterateKinds(kinds) {
|
||||
for (const kind of kinds) {
|
||||
const events = this.kinds.get(kind);
|
||||
if (events) {
|
||||
for (const event of events)
|
||||
yield event;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Iterates over all events by time */
|
||||
*iterateTime(since, until) {
|
||||
let untilIndex = 0;
|
||||
let sinceIndex = this.created_at.length - 1;
|
||||
let start = until
|
||||
? binarySearch(this.created_at, (mid) => {
|
||||
return mid.created_at - until;
|
||||
})
|
||||
: undefined;
|
||||
if (start)
|
||||
untilIndex = start[0];
|
||||
const end = since
|
||||
? binarySearch(this.created_at, (mid) => {
|
||||
return mid.created_at - since;
|
||||
})
|
||||
: undefined;
|
||||
if (end)
|
||||
sinceIndex = end[0];
|
||||
for (let i = untilIndex; i < sinceIndex; i++) {
|
||||
yield this.created_at[i];
|
||||
}
|
||||
}
|
||||
/** Iterates over all events by id */
|
||||
*iterateIds(ids) {
|
||||
for (const id of ids) {
|
||||
if (this.events.has(id))
|
||||
yield this.events.get(id);
|
||||
}
|
||||
}
|
||||
/** Returns all events that match the filter */
|
||||
getEventsForFilter(filter) {
|
||||
// search is not supported, return an empty set
|
||||
if (filter.search)
|
||||
return new Set();
|
||||
let first = true;
|
||||
let events = new Set();
|
||||
const and = (iterable) => {
|
||||
const set = iterable instanceof Set ? iterable : new Set(iterable);
|
||||
if (first) {
|
||||
events = set;
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
for (const event of events) {
|
||||
if (!set.has(event))
|
||||
events.delete(event);
|
||||
}
|
||||
}
|
||||
return events;
|
||||
};
|
||||
if (filter.ids)
|
||||
and(this.iterateIds(filter.ids));
|
||||
let time = null;
|
||||
// query for time first if since is set
|
||||
if (filter.since !== undefined) {
|
||||
time = Array.from(this.iterateTime(filter.since, filter.until));
|
||||
and(time);
|
||||
}
|
||||
for (const t of INDEXABLE_TAGS) {
|
||||
const key = `#${t}`;
|
||||
const values = filter[key];
|
||||
if (values?.length)
|
||||
and(this.iterateTag(t, values));
|
||||
}
|
||||
if (filter.authors)
|
||||
and(this.iterateAuthors(filter.authors));
|
||||
if (filter.kinds)
|
||||
and(this.iterateKinds(filter.kinds));
|
||||
// query for time last if only until is set
|
||||
if (filter.since === undefined && filter.until !== undefined) {
|
||||
time = Array.from(this.iterateTime(filter.since, filter.until));
|
||||
and(time);
|
||||
}
|
||||
// if the filter queried on time and has a limit. truncate the events now
|
||||
if (filter.limit && time) {
|
||||
const limited = new Set();
|
||||
for (const event of time) {
|
||||
if (limited.size >= filter.limit)
|
||||
break;
|
||||
if (events.has(event))
|
||||
limited.add(event);
|
||||
}
|
||||
return limited;
|
||||
}
|
||||
return events;
|
||||
}
|
||||
/** Returns all events that match the filters */
|
||||
getEventsForFilters(filters) {
|
||||
if (filters.length === 0)
|
||||
throw new Error("No Filters");
|
||||
let events = new Set();
|
||||
for (const filter of filters) {
|
||||
const filtered = this.getEventsForFilter(filter);
|
||||
for (const event of filtered)
|
||||
events.add(event);
|
||||
}
|
||||
return events;
|
||||
}
|
||||
/** Remove the oldest events that are not claimed */
|
||||
prune(limit = 1000) {
|
||||
let removed = 0;
|
||||
let cursor = this.events.first;
|
||||
while (cursor) {
|
||||
const event = cursor.value;
|
||||
if (!this.isClaimed(event)) {
|
||||
this.remove(event);
|
||||
removed++;
|
||||
if (removed >= limit)
|
||||
break;
|
||||
}
|
||||
cursor = cursor.next;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
/** Resets the event set */
|
||||
reset() {
|
||||
this.events.clear();
|
||||
this.kinds.clear();
|
||||
this.authors.clear();
|
||||
this.tags.clear();
|
||||
this.created_at = [];
|
||||
this.replaceable.clear();
|
||||
this.claims = new WeakMap();
|
||||
}
|
||||
}
|
||||
120
node_modules/applesauce-core/dist/event-store/event-store.d.ts
generated
vendored
120
node_modules/applesauce-core/dist/event-store/event-store.d.ts
generated
vendored
@@ -1,12 +1,47 @@
|
||||
import { Filter, NostrEvent } from "nostr-tools";
|
||||
import { Observable } from "rxjs";
|
||||
import { AddressPointer, EventPointer, ProfilePointer } from "nostr-tools/nip19";
|
||||
import { AddressPointer, EventPointer } from "nostr-tools/nip19";
|
||||
import { Observable, Subject } from "rxjs";
|
||||
import { AddressPointerWithoutD } from "../helpers/pointers.js";
|
||||
import { EventSet } from "./event-set.js";
|
||||
import { IEventStore, ModelConstructor } from "./interface.js";
|
||||
/** An extended {@link EventSet} that handles replaceable events, delets, and models */
|
||||
export declare class EventStore implements IEventStore {
|
||||
database: EventSet;
|
||||
import { EventMemory } from "./event-memory.js";
|
||||
import { IEventDatabase, IEventStore } from "./interface.js";
|
||||
declare const EventStore_base: {
|
||||
new (...args: any[]): {
|
||||
[x: string]: any;
|
||||
models: Map<import("./interface.js").ModelConstructor<any, any[], IEventStore | import("./interface.js").IAsyncEventStore>, Map<string, Observable<any>>>;
|
||||
modelKeepWarm: number;
|
||||
model<T extends unknown, Args extends Array<any>>(constructor: import("./interface.js").ModelConstructor<T, Args, IEventStore | import("./interface.js").IAsyncEventStore>, ...args: Args): Observable<T>;
|
||||
filters(filters: Filter | Filter[], onlyNew?: boolean): Observable<NostrEvent>;
|
||||
event(pointer: string | EventPointer): Observable<NostrEvent | undefined>;
|
||||
replaceable(pointer: AddressPointer | AddressPointerWithoutD): Observable<NostrEvent | undefined>;
|
||||
replaceable(kind: number, pubkey: string, identifier?: string): Observable<NostrEvent | undefined>;
|
||||
addressable(pointer: AddressPointer): Observable<NostrEvent | undefined>;
|
||||
timeline(filters: Filter | Filter[], includeOldVersion?: boolean): Observable<NostrEvent[]>;
|
||||
profile(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<import("../helpers/profile.js").ProfileContent | undefined>;
|
||||
contacts(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<import("nostr-tools/nip19").ProfilePointer[]>;
|
||||
mutes(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<import("../helpers/mutes.js").Mutes | undefined>;
|
||||
mailboxes(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<{
|
||||
inboxes: string[];
|
||||
outboxes: string[];
|
||||
} | undefined>;
|
||||
blossomServers(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<URL[]>;
|
||||
reactions(event: NostrEvent): Observable<import("nostr-tools").Event[]>;
|
||||
thread(root: string | EventPointer | AddressPointer): Observable<import("../models/thread.js").Thread>;
|
||||
comments(event: NostrEvent): Observable<import("nostr-tools").Event[]>;
|
||||
events(ids: string[]): Observable<Record<string, NostrEvent | undefined>>;
|
||||
replaceableSet(pointers: {
|
||||
kind: number;
|
||||
pubkey: string;
|
||||
identifier?: string;
|
||||
}[]): Observable<Record<string, NostrEvent | undefined>>;
|
||||
};
|
||||
} & {
|
||||
new (): {};
|
||||
};
|
||||
/** A wrapper around an event database that handles replaceable events, deletes, and models */
|
||||
export declare class EventStore extends EventStore_base implements IEventStore {
|
||||
database: IEventDatabase;
|
||||
/** Optional memory database for ensuring single event instances */
|
||||
memory?: EventMemory;
|
||||
/** Enable this to keep old versions of replaceable events */
|
||||
keepOldVersions: boolean;
|
||||
/** Enable this to keep expired events */
|
||||
@@ -17,11 +52,11 @@ export declare class EventStore implements IEventStore {
|
||||
*/
|
||||
verifyEvent?: (event: NostrEvent) => boolean;
|
||||
/** A stream of new events added to the store */
|
||||
insert$: Observable<NostrEvent>;
|
||||
insert$: Subject<import("nostr-tools").Event>;
|
||||
/** A stream of events that have been updated */
|
||||
update$: Observable<NostrEvent>;
|
||||
update$: Subject<import("nostr-tools").Event>;
|
||||
/** A stream of events that have been removed */
|
||||
remove$: Observable<NostrEvent>;
|
||||
remove$: Subject<import("nostr-tools").Event>;
|
||||
/**
|
||||
* A method that will be called when an event isn't found in the store
|
||||
* @experimental
|
||||
@@ -37,7 +72,9 @@ export declare class EventStore implements IEventStore {
|
||||
* @experimental
|
||||
*/
|
||||
addressableLoader?: (pointer: AddressPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
||||
constructor();
|
||||
constructor(database?: IEventDatabase);
|
||||
/** A method to add all events to memory to ensure there is only ever a single instance of an event */
|
||||
private mapToMemory;
|
||||
protected deletedIds: Set<string>;
|
||||
protected deletedCoords: Map<string, number>;
|
||||
protected checkDeleted(event: string | NostrEvent): boolean;
|
||||
@@ -57,12 +94,10 @@ export declare class EventStore implements IEventStore {
|
||||
* @returns The existing event or the event that was added, if it was ignored returns null
|
||||
*/
|
||||
add(event: NostrEvent, fromRelay?: string): NostrEvent | null;
|
||||
/** Removes an event from the database and updates subscriptions */
|
||||
/** Removes an event from the store and updates subscriptions */
|
||||
remove(event: string | NostrEvent): boolean;
|
||||
/** Add an event to the store and notifies all subscribes it has updated */
|
||||
update(event: NostrEvent): boolean;
|
||||
/** Removes any event that is not being used by a subscription */
|
||||
prune(max?: number): number;
|
||||
/** Check if the store has an event by id */
|
||||
hasEvent(id: string): boolean;
|
||||
/** Get an event by id from the store */
|
||||
@@ -74,9 +109,11 @@ export declare class EventStore implements IEventStore {
|
||||
/** Returns all versions of a replaceable event */
|
||||
getReplaceableHistory(kind: number, pubkey: string, identifier?: string): NostrEvent[] | undefined;
|
||||
/** Get all events matching a filter */
|
||||
getByFilters(filters: Filter | Filter[]): Set<NostrEvent>;
|
||||
getByFilters(filters: Filter | Filter[]): NostrEvent[];
|
||||
/** Returns a timeline of events that match filters */
|
||||
getTimeline(filters: Filter | Filter[]): NostrEvent[];
|
||||
/** Passthrough method for the database.touch */
|
||||
touch(event: NostrEvent): void | undefined;
|
||||
/** Sets the claim on the event and touches it */
|
||||
claim(event: NostrEvent, claim: any): void;
|
||||
/** Checks if an event is claimed by anything */
|
||||
@@ -85,56 +122,13 @@ export declare class EventStore implements IEventStore {
|
||||
removeClaim(event: NostrEvent, claim: any): void;
|
||||
/** Removes all claims on an event */
|
||||
clearClaim(event: NostrEvent): void;
|
||||
/** A directory of all active models */
|
||||
protected models: Map<ModelConstructor<any, any[]>, Map<string, Observable<any>>>;
|
||||
/** How long a model should be kept "warm" while nothing is subscribed to it */
|
||||
modelKeepWarm: number;
|
||||
/** Get or create a model on the event store */
|
||||
model<T extends unknown, Args extends Array<any>>(constructor: ModelConstructor<T, Args>, ...args: Args): Observable<T>;
|
||||
/**
|
||||
* Creates an observable that streams all events that match the filter
|
||||
* @param filters
|
||||
* @param [onlyNew=false] Only subscribe to new events
|
||||
*/
|
||||
filters(filters: Filter | Filter[], onlyNew?: boolean): Observable<NostrEvent>;
|
||||
/** Pass through method for the database.unclaimed */
|
||||
unclaimed(): Generator<NostrEvent>;
|
||||
/** Removes any event that is not being used by a subscription */
|
||||
prune(limit?: number): number;
|
||||
/** Returns an observable that completes when an event is removed */
|
||||
removed(id: string): Observable<never>;
|
||||
/** Creates an observable that emits when event is updated */
|
||||
updated(event: string | NostrEvent): Observable<NostrEvent>;
|
||||
/** Creates a {@link EventModel} */
|
||||
event(pointer: string | EventPointer): Observable<NostrEvent | undefined>;
|
||||
/** Creates a {@link ReplaceableModel} */
|
||||
replaceable(pointer: AddressPointer | AddressPointerWithoutD): Observable<NostrEvent | undefined>;
|
||||
replaceable(kind: number, pubkey: string, identifier?: string): Observable<NostrEvent | undefined>;
|
||||
/** Subscribe to an addressable event by pointer */
|
||||
addressable(pointer: AddressPointer): Observable<NostrEvent | undefined>;
|
||||
/** Creates a {@link TimelineModel} */
|
||||
timeline(filters: Filter | Filter[], includeOldVersion?: boolean): Observable<NostrEvent[]>;
|
||||
/** Subscribe to a users profile */
|
||||
profile(user: string | ProfilePointer): Observable<import("../helpers/profile.js").ProfileContent | undefined>;
|
||||
/** Subscribe to a users contacts */
|
||||
contacts(user: string | ProfilePointer): Observable<ProfilePointer[]>;
|
||||
/** Subscribe to a users mutes */
|
||||
mutes(user: string | ProfilePointer): Observable<import("../helpers/mutes.js").Mutes | undefined>;
|
||||
/** Subscribe to a users NIP-65 mailboxes */
|
||||
mailboxes(user: string | ProfilePointer): Observable<{
|
||||
inboxes: string[];
|
||||
outboxes: string[];
|
||||
} | undefined>;
|
||||
/** Subscribe to a users blossom servers */
|
||||
blossomServers(user: string | ProfilePointer): Observable<URL[]>;
|
||||
/** Subscribe to an event's reactions */
|
||||
reactions(event: NostrEvent): Observable<import("nostr-tools").Event[]>;
|
||||
/** Subscribe to a thread */
|
||||
thread(root: string | EventPointer | AddressPointer): Observable<import("../models/thread.js").Thread>;
|
||||
/** Subscribe to a event's comments */
|
||||
comments(event: NostrEvent): Observable<import("nostr-tools").Event[]>;
|
||||
/** @deprecated use multiple {@link EventModel} instead */
|
||||
events(ids: string[]): Observable<Record<string, NostrEvent | undefined>>;
|
||||
/** @deprecated use multiple {@link ReplaceableModel} instead */
|
||||
replaceableSet(pointers: {
|
||||
kind: number;
|
||||
pubkey: string;
|
||||
identifier?: string;
|
||||
}[]): Observable<Record<string, NostrEvent | undefined>>;
|
||||
}
|
||||
export {};
|
||||
|
||||
301
node_modules/applesauce-core/dist/event-store/event-store.js
generated
vendored
301
node_modules/applesauce-core/dist/event-store/event-store.js
generated
vendored
@@ -1,26 +1,20 @@
|
||||
import { kinds } from "nostr-tools";
|
||||
import { isAddressableKind } from "nostr-tools/kinds";
|
||||
import { EMPTY, filter, finalize, from, merge, mergeMap, ReplaySubject, share, take, timer } from "rxjs";
|
||||
import hash_sum from "hash-sum";
|
||||
import { EMPTY, filter, mergeMap, Subject, take } from "rxjs";
|
||||
import { getDeleteCoordinates, getDeleteIds } from "../helpers/delete.js";
|
||||
import { createReplaceableAddress, EventStoreSymbol, FromCacheSymbol, isReplaceable } from "../helpers/event.js";
|
||||
import { getExpirationTimestamp } from "../helpers/expiration.js";
|
||||
import { matchFilters } from "../helpers/filter.js";
|
||||
import { parseCoordinate } from "../helpers/pointers.js";
|
||||
import { addSeenRelay, getSeenRelays } from "../helpers/relays.js";
|
||||
import { unixNow } from "../helpers/time.js";
|
||||
import { UserBlossomServersModel } from "../models/blossom.js";
|
||||
import { EventModel, EventsModel, ReplaceableModel, ReplaceableSetModel, TimelineModel } from "../models/common.js";
|
||||
import { ContactsModel } from "../models/contacts.js";
|
||||
import { CommentsModel, ThreadModel } from "../models/index.js";
|
||||
import { MailboxesModel } from "../models/mailboxes.js";
|
||||
import { MuteModel } from "../models/mutes.js";
|
||||
import { ProfileModel } from "../models/profile.js";
|
||||
import { ReactionsModel } from "../models/reactions.js";
|
||||
import { EventSet } from "./event-set.js";
|
||||
/** An extended {@link EventSet} that handles replaceable events, delets, and models */
|
||||
export class EventStore {
|
||||
import { EventMemory } from "./event-memory.js";
|
||||
import { EventStoreModelMixin } from "./model-mixin.js";
|
||||
/** A wrapper around an event database that handles replaceable events, deletes, and models */
|
||||
export class EventStore extends EventStoreModelMixin(class {
|
||||
}) {
|
||||
database;
|
||||
/** Optional memory database for ensuring single event instances */
|
||||
memory;
|
||||
/** Enable this to keep old versions of replaceable events */
|
||||
keepOldVersions = false;
|
||||
/** Enable this to keep expired events */
|
||||
@@ -31,11 +25,11 @@ export class EventStore {
|
||||
*/
|
||||
verifyEvent;
|
||||
/** A stream of new events added to the store */
|
||||
insert$;
|
||||
insert$ = new Subject();
|
||||
/** A stream of events that have been updated */
|
||||
update$;
|
||||
update$ = new Subject();
|
||||
/** A stream of events that have been removed */
|
||||
remove$;
|
||||
remove$ = new Subject();
|
||||
/**
|
||||
* A method that will be called when an event isn't found in the store
|
||||
* @experimental
|
||||
@@ -51,27 +45,31 @@ export class EventStore {
|
||||
* @experimental
|
||||
*/
|
||||
addressableLoader;
|
||||
constructor() {
|
||||
this.database = new EventSet();
|
||||
// verify events before they are added to the database
|
||||
this.database.onBeforeInsert = (event) => {
|
||||
// Ignore events that are invalid
|
||||
if (this.verifyEvent && this.verifyEvent(event) === false)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
};
|
||||
constructor(database = new EventMemory()) {
|
||||
super();
|
||||
if (database) {
|
||||
this.database = database;
|
||||
this.memory = new EventMemory();
|
||||
}
|
||||
else {
|
||||
// If no database is provided, its the same as having a memory database
|
||||
this.database = this.memory = new EventMemory();
|
||||
}
|
||||
// when events are added to the database, add the symbol
|
||||
this.database.insert$.subscribe((event) => {
|
||||
this.insert$.subscribe((event) => {
|
||||
Reflect.set(event, EventStoreSymbol, this);
|
||||
});
|
||||
// when events are removed from the database, remove the symbol
|
||||
this.database.remove$.subscribe((event) => {
|
||||
this.remove$.subscribe((event) => {
|
||||
Reflect.deleteProperty(event, EventStoreSymbol);
|
||||
});
|
||||
this.insert$ = this.database.insert$;
|
||||
this.update$ = this.database.update$;
|
||||
this.remove$ = this.database.remove$;
|
||||
}
|
||||
mapToMemory(event) {
|
||||
if (event === undefined)
|
||||
return undefined;
|
||||
if (!this.memory)
|
||||
return event;
|
||||
return this.memory.add(event);
|
||||
}
|
||||
// delete state
|
||||
deletedIds = new Set();
|
||||
@@ -137,9 +135,7 @@ export class EventStore {
|
||||
for (const id of ids) {
|
||||
this.deletedIds.add(id);
|
||||
// remove deleted events in the database
|
||||
const event = this.database.getEvent(id);
|
||||
if (event)
|
||||
this.database.remove(event);
|
||||
this.remove(id);
|
||||
}
|
||||
const coords = getDeleteCoordinates(deleteEvent);
|
||||
for (const coord of coords) {
|
||||
@@ -152,7 +148,7 @@ export class EventStore {
|
||||
const events = this.database.getReplaceableHistory(parsed.kind, parsed.pubkey, parsed.identifier) ?? [];
|
||||
for (const event of events) {
|
||||
if (event.created_at < deleteEvent.created_at)
|
||||
this.database.remove(event);
|
||||
this.remove(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,6 +169,7 @@ export class EventStore {
|
||||
* @returns The existing event or the event that was added, if it was ignored returns null
|
||||
*/
|
||||
add(event, fromRelay) {
|
||||
// Handle delete events differently
|
||||
if (event.kind === kinds.EventDeletion)
|
||||
this.handleDeleteEvent(event);
|
||||
// Ignore if the event was deleted
|
||||
@@ -193,32 +190,38 @@ export class EventStore {
|
||||
return existing[0];
|
||||
}
|
||||
}
|
||||
else if (this.database.hasEvent(event.id)) {
|
||||
// Duplicate event, copy symbols and return existing event
|
||||
const existing = this.database.getEvent(event.id);
|
||||
if (existing) {
|
||||
EventStore.mergeDuplicateEvent(event, existing);
|
||||
return existing;
|
||||
}
|
||||
// Verify event before inserting into the database
|
||||
if (this.verifyEvent && this.verifyEvent(event) === false)
|
||||
return null;
|
||||
// Always add event to memory
|
||||
const existing = this.memory?.add(event);
|
||||
// If the memory returned a different instance, this is a duplicate event
|
||||
if (existing && existing !== event) {
|
||||
// Copy cached symbols and return existing event
|
||||
EventStore.mergeDuplicateEvent(event, existing);
|
||||
// attach relay this event was from
|
||||
if (fromRelay)
|
||||
addSeenRelay(existing, fromRelay);
|
||||
return existing;
|
||||
}
|
||||
// Insert event into database
|
||||
const inserted = this.database.add(event);
|
||||
// If the event was ignored, return null
|
||||
if (inserted === null)
|
||||
return null;
|
||||
const inserted = this.mapToMemory(this.database.add(event));
|
||||
// Copy cached data if its a duplicate event
|
||||
if (event !== inserted)
|
||||
EventStore.mergeDuplicateEvent(event, inserted);
|
||||
// attach relay this event was from
|
||||
if (fromRelay)
|
||||
addSeenRelay(inserted, fromRelay);
|
||||
// Emit insert$ signal
|
||||
if (inserted === event)
|
||||
this.insert$.next(inserted);
|
||||
// remove all old version of the replaceable event
|
||||
if (!this.keepOldVersions && isReplaceable(event.kind)) {
|
||||
const existing = this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
|
||||
if (existing) {
|
||||
if (existing && existing.length > 0) {
|
||||
const older = Array.from(existing).filter((e) => e.created_at < event.created_at);
|
||||
for (const old of older)
|
||||
this.database.remove(old);
|
||||
this.remove(old);
|
||||
// return the newest version of the replaceable event
|
||||
// most of the time this will be === event, but not always
|
||||
if (existing.length !== older.length)
|
||||
@@ -230,108 +233,103 @@ export class EventStore {
|
||||
this.handleExpiringEvent(inserted);
|
||||
return inserted;
|
||||
}
|
||||
/** Removes an event from the database and updates subscriptions */
|
||||
/** Removes an event from the store and updates subscriptions */
|
||||
remove(event) {
|
||||
return this.database.remove(event);
|
||||
let instance = this.memory?.getEvent(typeof event === "string" ? event : event.id);
|
||||
// Remove from memory if available
|
||||
if (this.memory)
|
||||
this.memory.remove(event);
|
||||
// Remove the event from the database
|
||||
const removed = this.database.remove(event);
|
||||
// If the event was removed, notify the subscriptions
|
||||
if (removed && instance) {
|
||||
this.remove$.next(instance);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
/** Add an event to the store and notifies all subscribes it has updated */
|
||||
update(event) {
|
||||
return this.database.update(event);
|
||||
}
|
||||
/** Removes any event that is not being used by a subscription */
|
||||
prune(max) {
|
||||
return this.database.prune(max);
|
||||
// Map the event to the current instance in the database
|
||||
const e = this.database.add(event);
|
||||
if (!e)
|
||||
return false;
|
||||
// Notify the database that the event has updated
|
||||
this.database.update?.(event);
|
||||
this.update$.next(event);
|
||||
return true;
|
||||
}
|
||||
/** Check if the store has an event by id */
|
||||
hasEvent(id) {
|
||||
return this.database.hasEvent(id);
|
||||
// Check if the event exists in memory first, then in the database
|
||||
return this.memory?.hasEvent(id) || this.database.hasEvent(id);
|
||||
}
|
||||
/** Get an event by id from the store */
|
||||
getEvent(id) {
|
||||
return this.database.getEvent(id);
|
||||
// Get the event from memory first, then from the database
|
||||
return this.memory?.getEvent(id) ?? this.mapToMemory(this.database.getEvent(id));
|
||||
}
|
||||
/** Check if the store has a replaceable event */
|
||||
hasReplaceable(kind, pubkey, d) {
|
||||
return this.database.hasReplaceable(kind, pubkey, d);
|
||||
// Check if the event exists in memory first, then in the database
|
||||
return this.memory?.hasReplaceable(kind, pubkey, d) || this.database.hasReplaceable(kind, pubkey, d);
|
||||
}
|
||||
/** Gets the latest version of a replaceable event */
|
||||
getReplaceable(kind, pubkey, identifier) {
|
||||
return this.database.getReplaceable(kind, pubkey, identifier);
|
||||
// Get the event from memory first, then from the database
|
||||
return (this.memory?.getReplaceable(kind, pubkey, identifier) ??
|
||||
this.mapToMemory(this.database.getReplaceable(kind, pubkey, identifier)));
|
||||
}
|
||||
/** Returns all versions of a replaceable event */
|
||||
getReplaceableHistory(kind, pubkey, identifier) {
|
||||
return this.database.getReplaceableHistory(kind, pubkey, identifier);
|
||||
// Get the events from memory first, then from the database
|
||||
return (this.memory?.getReplaceableHistory(kind, pubkey, identifier) ??
|
||||
this.database.getReplaceableHistory(kind, pubkey, identifier)?.map((e) => this.mapToMemory(e) ?? e));
|
||||
}
|
||||
/** Get all events matching a filter */
|
||||
getByFilters(filters) {
|
||||
return this.database.getByFilters(filters);
|
||||
// NOTE: no way to read from memory since memory won't have the full set of events
|
||||
const events = this.database.getByFilters(filters);
|
||||
// Map events to memory if available for better performance
|
||||
if (this.memory)
|
||||
return events.map((e) => this.mapToMemory(e));
|
||||
else
|
||||
return events;
|
||||
}
|
||||
/** Returns a timeline of events that match filters */
|
||||
getTimeline(filters) {
|
||||
return this.database.getTimeline(filters);
|
||||
const events = this.database.getTimeline(filters);
|
||||
if (this.memory)
|
||||
return events.map((e) => this.mapToMemory(e));
|
||||
else
|
||||
return events;
|
||||
}
|
||||
/** Passthrough method for the database.touch */
|
||||
touch(event) {
|
||||
return this.memory?.touch(event);
|
||||
}
|
||||
/** Sets the claim on the event and touches it */
|
||||
claim(event, claim) {
|
||||
this.database.claim(event, claim);
|
||||
return this.memory?.claim(event, claim);
|
||||
}
|
||||
/** Checks if an event is claimed by anything */
|
||||
isClaimed(event) {
|
||||
return this.database.isClaimed(event);
|
||||
return this.memory?.isClaimed(event) ?? false;
|
||||
}
|
||||
/** Removes a claim from an event */
|
||||
removeClaim(event, claim) {
|
||||
this.database.removeClaim(event, claim);
|
||||
return this.memory?.removeClaim(event, claim);
|
||||
}
|
||||
/** Removes all claims on an event */
|
||||
clearClaim(event) {
|
||||
this.database.clearClaim(event);
|
||||
return this.memory?.clearClaim(event);
|
||||
}
|
||||
/** A directory of all active models */
|
||||
models = new Map();
|
||||
/** How long a model should be kept "warm" while nothing is subscribed to it */
|
||||
modelKeepWarm = 60_000;
|
||||
/** Get or create a model on the event store */
|
||||
model(constructor, ...args) {
|
||||
let models = this.models.get(constructor);
|
||||
if (!models) {
|
||||
models = new Map();
|
||||
this.models.set(constructor, models);
|
||||
}
|
||||
const key = constructor.getKey ? constructor.getKey(...args) : hash_sum(args);
|
||||
let model = models.get(key);
|
||||
// Create the model if it does not exist
|
||||
if (!model) {
|
||||
const cleanup = () => {
|
||||
// Remove the model from the cache if its the same one
|
||||
if (models.get(key) === model)
|
||||
models.delete(key);
|
||||
};
|
||||
model = constructor(...args)(this).pipe(
|
||||
// remove the model when its unsubscribed
|
||||
finalize(cleanup),
|
||||
// only subscribe to models once for all subscriptions
|
||||
share({
|
||||
connector: () => new ReplaySubject(1),
|
||||
resetOnComplete: () => timer(this.modelKeepWarm),
|
||||
resetOnRefCountZero: () => timer(this.modelKeepWarm),
|
||||
}));
|
||||
// Add the model to the cache
|
||||
models.set(key, model);
|
||||
}
|
||||
return model;
|
||||
/** Pass through method for the database.unclaimed */
|
||||
unclaimed() {
|
||||
return this.memory?.unclaimed() || (function* () { })();
|
||||
}
|
||||
/**
|
||||
* Creates an observable that streams all events that match the filter
|
||||
* @param filters
|
||||
* @param [onlyNew=false] Only subscribe to new events
|
||||
*/
|
||||
filters(filters, onlyNew = false) {
|
||||
filters = Array.isArray(filters) ? filters : [filters];
|
||||
return merge(
|
||||
// merge existing events
|
||||
onlyNew ? EMPTY : from(this.getByFilters(filters)),
|
||||
// subscribe to future events
|
||||
this.insert$.pipe(filter((e) => matchFilters(filters, e))));
|
||||
/** Removes any event that is not being used by a subscription */
|
||||
prune(limit) {
|
||||
return this.memory?.prune(limit) ?? 0;
|
||||
}
|
||||
/** Returns an observable that completes when an event is removed */
|
||||
removed(id) {
|
||||
@@ -348,83 +346,6 @@ export class EventStore {
|
||||
}
|
||||
/** Creates an observable that emits when event is updated */
|
||||
updated(event) {
|
||||
return this.database.update$.pipe(filter((e) => e.id === event || e === event));
|
||||
}
|
||||
// Helper methods for creating models
|
||||
/** Creates a {@link EventModel} */
|
||||
event(pointer) {
|
||||
if (typeof pointer === "string")
|
||||
pointer = { id: pointer };
|
||||
return this.model(EventModel, pointer);
|
||||
}
|
||||
replaceable(...args) {
|
||||
let pointer;
|
||||
// Parse arguments
|
||||
if (args.length === 1) {
|
||||
pointer = args[0];
|
||||
}
|
||||
else if (args.length === 3 || args.length === 2) {
|
||||
let [kind, pubkey, identifier] = args;
|
||||
pointer = { kind, pubkey, identifier };
|
||||
}
|
||||
if (!pointer)
|
||||
throw new Error("Invalid arguments, expected address pointer or kind, pubkey, identifier");
|
||||
return this.model(ReplaceableModel, pointer);
|
||||
}
|
||||
/** Subscribe to an addressable event by pointer */
|
||||
addressable(pointer) {
|
||||
return this.model(ReplaceableModel, pointer);
|
||||
}
|
||||
/** Creates a {@link TimelineModel} */
|
||||
timeline(filters, includeOldVersion = false) {
|
||||
return this.model(TimelineModel, filters, includeOldVersion);
|
||||
}
|
||||
/** Subscribe to a users profile */
|
||||
profile(user) {
|
||||
return this.model(ProfileModel, user);
|
||||
}
|
||||
/** Subscribe to a users contacts */
|
||||
contacts(user) {
|
||||
if (typeof user === "string")
|
||||
user = { pubkey: user };
|
||||
return this.model(ContactsModel, user);
|
||||
}
|
||||
/** Subscribe to a users mutes */
|
||||
mutes(user) {
|
||||
if (typeof user === "string")
|
||||
user = { pubkey: user };
|
||||
return this.model(MuteModel, user);
|
||||
}
|
||||
/** Subscribe to a users NIP-65 mailboxes */
|
||||
mailboxes(user) {
|
||||
if (typeof user === "string")
|
||||
user = { pubkey: user };
|
||||
return this.model(MailboxesModel, user);
|
||||
}
|
||||
/** Subscribe to a users blossom servers */
|
||||
blossomServers(user) {
|
||||
if (typeof user === "string")
|
||||
user = { pubkey: user };
|
||||
return this.model(UserBlossomServersModel, user);
|
||||
}
|
||||
/** Subscribe to an event's reactions */
|
||||
reactions(event) {
|
||||
return this.model(ReactionsModel, event);
|
||||
}
|
||||
/** Subscribe to a thread */
|
||||
thread(root) {
|
||||
return this.model(ThreadModel, root);
|
||||
}
|
||||
/** Subscribe to a event's comments */
|
||||
comments(event) {
|
||||
return this.model(CommentsModel, event);
|
||||
}
|
||||
/** @deprecated use multiple {@link EventModel} instead */
|
||||
events(ids) {
|
||||
return this.model(EventsModel, ids);
|
||||
}
|
||||
/** @deprecated use multiple {@link ReplaceableModel} instead */
|
||||
replaceableSet(pointers) {
|
||||
return this.model(ReplaceableSetModel, pointers);
|
||||
return this.update$.pipe(filter((e) => e.id === event || e === event));
|
||||
}
|
||||
}
|
||||
|
||||
3
node_modules/applesauce-core/dist/event-store/index.d.ts
generated
vendored
3
node_modules/applesauce-core/dist/event-store/index.d.ts
generated
vendored
@@ -1,3 +1,4 @@
|
||||
export * from "./async-event-store.js";
|
||||
export * from "./event-memory.js";
|
||||
export * from "./event-store.js";
|
||||
export * from "./event-set.js";
|
||||
export * from "./interface.js";
|
||||
|
||||
3
node_modules/applesauce-core/dist/event-store/index.js
generated
vendored
3
node_modules/applesauce-core/dist/event-store/index.js
generated
vendored
@@ -1,3 +1,4 @@
|
||||
export * from "./async-event-store.js";
|
||||
export * from "./event-memory.js";
|
||||
export * from "./event-store.js";
|
||||
export * from "./event-set.js";
|
||||
export * from "./interface.js";
|
||||
|
||||
151
node_modules/applesauce-core/dist/event-store/interface.d.ts
generated
vendored
151
node_modules/applesauce-core/dist/event-store/interface.d.ts
generated
vendored
@@ -1,28 +1,44 @@
|
||||
import { Filter, NostrEvent } from "nostr-tools";
|
||||
import { AddressPointer, EventPointer, ProfilePointer } from "nostr-tools/nip19";
|
||||
import { Observable } from "rxjs";
|
||||
import { LRU } from "../helpers/lru.js";
|
||||
import { Mutes } from "../helpers/mutes.js";
|
||||
import { ProfileContent } from "../helpers/profile.js";
|
||||
import { Thread } from "../models/thread.js";
|
||||
import { AddressPointerWithoutD } from "../helpers/pointers.js";
|
||||
import { ProfileContent } from "../helpers/profile.js";
|
||||
import { Mutes } from "../helpers/mutes.js";
|
||||
import { Thread } from "../models/thread.js";
|
||||
/** The read interface for an event store */
|
||||
export interface IEventStoreRead {
|
||||
/** Check if the event store has an event with id */
|
||||
hasEvent(id: string): boolean;
|
||||
/** Check if the event store has a replaceable event */
|
||||
hasReplaceable(kind: number, pubkey: string, identifier?: string): boolean;
|
||||
/** Get an event by id */
|
||||
getEvent(id: string): NostrEvent | undefined;
|
||||
/** Check if the event store has a replaceable event */
|
||||
hasReplaceable(kind: number, pubkey: string, identifier?: string): boolean;
|
||||
/** Get a replaceable event */
|
||||
getReplaceable(kind: number, pubkey: string, identifier?: string): NostrEvent | undefined;
|
||||
/** Get the history of a replaceable event */
|
||||
getReplaceableHistory(kind: number, pubkey: string, identifier?: string): NostrEvent[] | undefined;
|
||||
/** Get all events that match the filters */
|
||||
getByFilters(filters: Filter | Filter[]): Set<NostrEvent>;
|
||||
getByFilters(filters: Filter | Filter[]): NostrEvent[];
|
||||
/** Get a timeline of events that match the filters */
|
||||
getTimeline(filters: Filter | Filter[]): NostrEvent[];
|
||||
}
|
||||
/** The async read interface for an event store */
|
||||
export interface IAsyncEventStoreRead {
|
||||
/** Check if the event store has an event with id */
|
||||
hasEvent(id: string): Promise<boolean>;
|
||||
/** Get an event by id */
|
||||
getEvent(id: string): Promise<NostrEvent | undefined>;
|
||||
/** Check if the event store has a replaceable event */
|
||||
hasReplaceable(kind: number, pubkey: string, identifier?: string): Promise<boolean>;
|
||||
/** Get a replaceable event */
|
||||
getReplaceable(kind: number, pubkey: string, identifier?: string): Promise<NostrEvent | undefined>;
|
||||
/** Get the history of a replaceable event */
|
||||
getReplaceableHistory(kind: number, pubkey: string, identifier?: string): Promise<NostrEvent[] | undefined>;
|
||||
/** Get all events that match the filters */
|
||||
getByFilters(filters: Filter | Filter[]): Promise<NostrEvent[]>;
|
||||
/** Get a timeline of events that match the filters */
|
||||
getTimeline(filters: Filter | Filter[]): Promise<NostrEvent[]>;
|
||||
}
|
||||
/** The stream interface for an event store */
|
||||
export interface IEventStoreStreams {
|
||||
/** A stream of new events added to the store */
|
||||
@@ -41,8 +57,19 @@ export interface IEventStoreActions {
|
||||
/** Notify the store that an event has updated */
|
||||
update(event: NostrEvent): void;
|
||||
}
|
||||
/** The async actions for an event store */
|
||||
export interface IAsyncEventStoreActions {
|
||||
/** Add an event to the store */
|
||||
add(event: NostrEvent): Promise<NostrEvent | null>;
|
||||
/** Remove an event from the store */
|
||||
remove(event: string | NostrEvent): Promise<boolean>;
|
||||
/** Notify the store that an event has updated */
|
||||
update(event: NostrEvent): Promise<void>;
|
||||
}
|
||||
/** The claim interface for an event store */
|
||||
export interface IEventClaims {
|
||||
/** Tell the store that this event was used */
|
||||
touch(event: NostrEvent): void;
|
||||
/** Sets the claim on the event and touches it */
|
||||
claim(event: NostrEvent, claim: any): void;
|
||||
/** Checks if an event is claimed by anything */
|
||||
@@ -51,59 +78,105 @@ export interface IEventClaims {
|
||||
removeClaim(event: NostrEvent, claim: any): void;
|
||||
/** Removes all claims on an event */
|
||||
clearClaim(event: NostrEvent): void;
|
||||
/** Returns a generator of unclaimed events in order of least used */
|
||||
unclaimed(): Generator<NostrEvent>;
|
||||
}
|
||||
/** An event store that can be subscribed to */
|
||||
export interface IEventStoreSubscriptions {
|
||||
/** Susbscribe to an event by id */
|
||||
export interface IEventSubscriptions {
|
||||
/** Subscribe to an event by id */
|
||||
event(id: string | EventPointer): Observable<NostrEvent | undefined>;
|
||||
/** Subscribe to a replaceable event by pointer */
|
||||
replaceable(pointer: AddressPointerWithoutD): Observable<NostrEvent | undefined>;
|
||||
/** Subscribe to a replaceable event with legacy arguments */
|
||||
replaceable(kind: number, pubkey: string, identifier?: string): Observable<NostrEvent | undefined>;
|
||||
/** Subscribe to an addressable event by pointer */
|
||||
addressable(pointer: AddressPointer): Observable<NostrEvent | undefined>;
|
||||
/** Subscribe to a batch of events that match the filters */
|
||||
filter(filters: Filter | Filter[]): Observable<NostrEvent[]>;
|
||||
filters(filters: Filter | Filter[], onlyNew?: boolean): Observable<NostrEvent>;
|
||||
/** Subscribe to a sorted timeline of events that match the filters */
|
||||
timeline(filters: Filter | Filter[], onlyNew?: boolean): Observable<NostrEvent[]>;
|
||||
}
|
||||
/** @deprecated use {@link IEventSubscriptions} instead */
|
||||
export interface IEventStoreSubscriptions extends IEventSubscriptions {
|
||||
}
|
||||
/** Methods for creating common models */
|
||||
export interface IEventStoreModels {
|
||||
model<T extends unknown, Args extends Array<any>>(constructor: ModelConstructor<T, Args>, ...args: Args): Observable<T>;
|
||||
event(id: string): Observable<NostrEvent | undefined>;
|
||||
replaceable(pointer: AddressPointerWithoutD): Observable<NostrEvent | undefined>;
|
||||
addressable(pointer: AddressPointer): Observable<NostrEvent | undefined>;
|
||||
timeline(filters: Filter | Filter[], includeOldVersion?: boolean): Observable<NostrEvent[]>;
|
||||
export interface IEventModelMixin<TStore extends IEventStore | IAsyncEventStore> {
|
||||
model<T extends unknown, Args extends Array<any>>(constructor: ModelConstructor<T, Args, TStore>, ...args: Args): Observable<T>;
|
||||
/** @deprecated use multiple {@link EventModel} instead */
|
||||
events(ids: string[]): Observable<Record<string, NostrEvent | undefined>>;
|
||||
/** @deprecated use multiple {@link ReplaceableModel} instead */
|
||||
replaceableSet(pointers: (AddressPointer | AddressPointerWithoutD)[]): Observable<Record<string, NostrEvent | undefined>>;
|
||||
}
|
||||
/** A computed view of an event set or event store */
|
||||
export type Model<T extends unknown> = (events: IEventStore) => Observable<T>;
|
||||
/** A constructor for a {@link Model} */
|
||||
export type ModelConstructor<T extends unknown, Args extends Array<any>> = ((...args: Args) => Model<T>) & {
|
||||
getKey?: (...args: Args) => string;
|
||||
};
|
||||
/** The base interface for a set of events */
|
||||
export interface IEventSet extends IEventStoreRead, IEventStoreStreams, IEventStoreActions, IEventClaims {
|
||||
events: LRU<NostrEvent>;
|
||||
}
|
||||
export interface IEventStore extends IEventStoreRead, IEventStoreStreams, IEventStoreActions, IEventStoreModels, IEventClaims {
|
||||
/** Enable this to keep old versions of replaceable events */
|
||||
keepOldVersions: boolean;
|
||||
/** Enable this to keep expired events */
|
||||
keepExpired: boolean;
|
||||
filters(filters: Filter | Filter[]): Observable<NostrEvent>;
|
||||
updated(id: string | NostrEvent): Observable<NostrEvent>;
|
||||
removed(id: string): Observable<never>;
|
||||
replaceable(kind: number, pubkey: string, identifier?: string): Observable<NostrEvent | undefined>;
|
||||
replaceable(pointer: AddressPointerWithoutD): Observable<NostrEvent | undefined>;
|
||||
eventLoader?: (pointer: EventPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
||||
replaceableLoader?: (pointer: AddressPointerWithoutD) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
||||
addressableLoader?: (pointer: AddressPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
||||
/** Methods for creating helpful models */
|
||||
export interface IEventHelpfulSubscriptions {
|
||||
/** Subscribe to a users profile */
|
||||
profile(user: string | ProfilePointer): Observable<ProfileContent | undefined>;
|
||||
/** Subscribe to a users contacts */
|
||||
contacts(user: string | ProfilePointer): Observable<ProfilePointer[]>;
|
||||
/** Subscribe to a users mutes */
|
||||
mutes(user: string | ProfilePointer): Observable<Mutes | undefined>;
|
||||
/** Subscribe to a users NIP-65 mailboxes */
|
||||
mailboxes(user: string | ProfilePointer): Observable<{
|
||||
inboxes: string[];
|
||||
outboxes: string[];
|
||||
} | undefined>;
|
||||
/** Subscribe to a users blossom servers */
|
||||
blossomServers(user: string | ProfilePointer): Observable<URL[]>;
|
||||
/** Subscribe to an event's reactions */
|
||||
reactions(event: NostrEvent): Observable<NostrEvent[]>;
|
||||
/** Subscribe to a thread */
|
||||
thread(root: string | EventPointer | AddressPointer): Observable<Thread>;
|
||||
/** Subscribe to a event's comments */
|
||||
comments(event: NostrEvent): Observable<NostrEvent[]>;
|
||||
}
|
||||
/** @deprecated use {@link IEventModelMixin} instead */
|
||||
export interface IEventStoreModels extends IEventModelMixin<IEventStore> {
|
||||
}
|
||||
/** The interface that is passed to the model for creating subscriptions */
|
||||
export type ModelEventStore<TStore extends IEventStore | IAsyncEventStore> = IEventStoreStreams & IEventSubscriptions & IEventModelMixin<TStore> & IEventFallbackLoaders & TStore;
|
||||
/** A computed view of an event set or event store */
|
||||
export type Model<T extends unknown, TStore extends IEventStore | IAsyncEventStore = IEventStore | IAsyncEventStore> = (events: ModelEventStore<TStore>) => Observable<T>;
|
||||
/** A constructor for a {@link Model} */
|
||||
export type ModelConstructor<T extends unknown, Args extends Array<any>, TStore extends IEventStore | IAsyncEventStore = IEventStore> = ((...args: Args) => Model<T, TStore>) & {
|
||||
getKey?: (...args: Args) => string;
|
||||
};
|
||||
/** The base interface for a database of events */
|
||||
export interface IEventDatabase extends IEventStoreRead {
|
||||
/** Add an event to the database */
|
||||
add(event: NostrEvent): NostrEvent;
|
||||
/** Remove an event from the database */
|
||||
remove(event: string | NostrEvent): boolean;
|
||||
/** Notifies the database that an event has updated */
|
||||
update?: (event: NostrEvent) => void;
|
||||
}
|
||||
/** The async base interface for a set of events */
|
||||
export interface IAsyncEventDatabase extends IAsyncEventStoreRead {
|
||||
/** Add an event to the database */
|
||||
add(event: NostrEvent): Promise<NostrEvent>;
|
||||
/** Remove an event from the database */
|
||||
remove(event: string | NostrEvent): Promise<boolean>;
|
||||
/** Notifies the database that an event has updated */
|
||||
update?: (event: NostrEvent) => void;
|
||||
}
|
||||
/** The base interface for the in-memory database of events */
|
||||
export interface IEventMemory extends IEventStoreRead, IEventClaims {
|
||||
/** Add an event to the store */
|
||||
add(event: NostrEvent): NostrEvent;
|
||||
/** Remove an event from the store */
|
||||
remove(event: string | NostrEvent): boolean;
|
||||
}
|
||||
/** A set of methods that an event store will use to load single events it does not have */
|
||||
export interface IEventFallbackLoaders {
|
||||
/** A method that will be called when an event isn't found in the store */
|
||||
eventLoader?: (pointer: EventPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
||||
/** A method that will be called when a replaceable event isn't found in the store */
|
||||
replaceableLoader?: (pointer: AddressPointerWithoutD) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
||||
/** A method that will be called when an addressable event isn't found in the store */
|
||||
addressableLoader?: (pointer: AddressPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
||||
}
|
||||
/** The async event store interface */
|
||||
export interface IAsyncEventStore extends IAsyncEventStoreRead, IEventStoreStreams, IEventSubscriptions, IAsyncEventStoreActions, IEventModelMixin<IAsyncEventStore>, IEventHelpfulSubscriptions, IEventClaims, IEventFallbackLoaders {
|
||||
}
|
||||
/** The sync event store interface */
|
||||
export interface IEventStore extends IEventStoreRead, IEventStoreStreams, IEventSubscriptions, IEventStoreActions, IEventModelMixin<IEventStore>, IEventHelpfulSubscriptions, IEventClaims, IEventFallbackLoaders {
|
||||
}
|
||||
|
||||
12
node_modules/applesauce-core/dist/helpers/bookmarks.d.ts
generated
vendored
12
node_modules/applesauce-core/dist/helpers/bookmarks.d.ts
generated
vendored
@@ -1,7 +1,12 @@
|
||||
import { NostrEvent } from "nostr-tools";
|
||||
import { AddressPointer, EventPointer } from "nostr-tools/nip19";
|
||||
import { HiddenContentSigner } from "./index.js";
|
||||
export declare const BookmarkPublicSymbol: unique symbol;
|
||||
export declare const BookmarkHiddenSymbol: unique symbol;
|
||||
/** Type for unlocked bookmarks events */
|
||||
export type UnlockedBookmarks = {
|
||||
[BookmarkHiddenSymbol]: Bookmarks;
|
||||
};
|
||||
export type Bookmarks = {
|
||||
notes: EventPointer[];
|
||||
articles: AddressPointer[];
|
||||
@@ -16,5 +21,10 @@ export declare function mergeBookmarks(...bookmarks: (Bookmarks | undefined)[]):
|
||||
export declare function getBookmarks(bookmark: NostrEvent): Bookmarks;
|
||||
/** Returns the public bookmarks of the event */
|
||||
export declare function getPublicBookmarks(bookmark: NostrEvent): Bookmarks;
|
||||
/** Checks if the hidden bookmarks are unlocked */
|
||||
export declare function isHiddenBookmarksUnlocked<T extends NostrEvent>(bookmark: T): bookmark is T & UnlockedBookmarks;
|
||||
/** Returns the bookmarks of the event if its unlocked */
|
||||
export declare function getHiddenBookmarks(bookmark: NostrEvent): Bookmarks | undefined;
|
||||
export declare function getHiddenBookmarks<T extends NostrEvent & UnlockedBookmarks>(bookmark: T): Bookmarks;
|
||||
export declare function getHiddenBookmarks<T extends NostrEvent>(bookmark: T): Bookmarks | undefined;
|
||||
/** Unlocks the hidden bookmarks on a bookmarks event */
|
||||
export declare function unlockHiddenBookmarks(bookmark: NostrEvent, signer: HiddenContentSigner): Promise<Bookmarks>;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user