mirror of
https://github.com/dergigi/boris.git
synced 2026-02-16 04:24:25 +01:00
Compare commits
213 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7de8c49b01 | ||
|
|
c3aece1722 | ||
|
|
7a4cb77aa3 | ||
|
|
9065501043 | ||
|
|
c9ace72d4d | ||
|
|
be6ad79f60 | ||
|
|
0473ba71fb | ||
|
|
7e575ea617 | ||
|
|
c3a2dd5603 | ||
|
|
ad54f2aaa5 | ||
|
|
a6ea97b731 | ||
|
|
2f2e19fdf9 | ||
|
|
ce99600aa9 | ||
|
|
77bcc481b5 | ||
|
|
8bb97b3e4e | ||
|
|
2bbfa82eec | ||
|
|
cc68e67726 | ||
|
|
f3a8cf1c23 | ||
|
|
290d9303b5 | ||
|
|
0ca62c4797 | ||
|
|
1441d8d998 | ||
|
|
9252078fb7 | ||
|
|
d5ab88082f | ||
|
|
a8e48ba280 | ||
|
|
dbccb28113 | ||
|
|
b1f6ac88a6 | ||
|
|
c07797ff7c | ||
|
|
41fb51c357 | ||
|
|
5e2abfa8c7 | ||
|
|
7cf2b7d35d | ||
|
|
66f0b2bc3f | ||
|
|
647cf1caf7 | ||
|
|
d4e8e465b4 | ||
|
|
fa52d61c20 | ||
|
|
c407663c2b | ||
|
|
e931f36dee | ||
|
|
ba34e51803 | ||
|
|
c67d831efd | ||
|
|
c1dedb248d | ||
|
|
b177907eb9 | ||
|
|
518c6d9714 | ||
|
|
89b14ce5b7 | ||
|
|
5f7aab90a7 | ||
|
|
6d41d95627 | ||
|
|
9aea1f9a70 | ||
|
|
8594b733ef | ||
|
|
be42203944 | ||
|
|
c51c1810c4 | ||
|
|
6bbc5eb1fc | ||
|
|
ff5c974557 | ||
|
|
61bc64ea26 | ||
|
|
73da428cd7 | ||
|
|
ce2ccd54b3 | ||
|
|
4f8bc0c641 | ||
|
|
d6edddc572 | ||
|
|
d275cb37ab | ||
|
|
959e83699a | ||
|
|
6e0a88fbd9 | ||
|
|
ba682dde1d | ||
|
|
5e788b0026 | ||
|
|
256540bf60 | ||
|
|
e710391962 | ||
|
|
29906397db | ||
|
|
aac4adeda6 | ||
|
|
008c14c14a | ||
|
|
0798267084 | ||
|
|
6088dcc395 | ||
|
|
7425121746 | ||
|
|
7735508c77 | ||
|
|
f2422e9601 | ||
|
|
336f2b62ab | ||
|
|
d3ad08dd61 | ||
|
|
d148433fcc | ||
|
|
9638ab0b84 | ||
|
|
8d7b853e75 | ||
|
|
cdbb920a5f | ||
|
|
cc311c7dc4 | ||
|
|
d4d54b1a7c | ||
|
|
235d6e33a9 | ||
|
|
0fe1085457 | ||
|
|
65e7709c63 | ||
|
|
17b5ffd96e | ||
|
|
7f95eae405 | ||
|
|
8f1e5e1082 | ||
|
|
c536de0144 | ||
|
|
8e0970b717 | ||
|
|
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 |
9
.cursor/rules/app-settings-and-nostr.mdc
Normal file
9
.cursor/rules/app-settings-and-nostr.mdc
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
description: when dealing with user and app settings
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
We use nostr to load/save/sync our settings.
|
||||
|
||||
- https://nostrbook.dev/kinds/30078
|
||||
- https://github.com/nostr-protocol/nips/blob/master/78.md
|
||||
@@ -3,4 +3,6 @@ description: when creating or modifying UI elements, especially related to icons
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
We use FontAwesome. If you can use a fa-icon (instead of text) use a fa-icon.
|
||||
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.
|
||||
|
||||
Never write "Loading" - always show a spinner, and just a spinner.
|
||||
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
|
||||
206
README.md
206
README.md
@@ -1,179 +1,77 @@
|
||||
# Markr
|
||||
# Boris
|
||||
|
||||
A minimal nostr client for bookmark management, built with [applesauce](https://github.com/hzrd149/applesauce).
|
||||
Your reading list for the Nostr world.
|
||||
|
||||
## Features
|
||||
Boris turns your Nostr bookmarks into a calm, fast, and focused reading experience. Connect your Nostr account and you'll get a clean three‑pane reader: bookmarks on the left, the article in the middle, and highlights on the right.
|
||||
|
||||
- **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)
|
||||
- **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
|
||||
- **Minimal UI**: Clean, modern interface focused on bookmark management
|
||||
## The Vision
|
||||
|
||||
## Getting Started
|
||||
When I wrote "Purple Text, Orange Highlights" 2.5 years ago, I had a certain interface in mind that would allow the reader to curate, discover, highlight, and provide value to writers and other readers alike. Boris is my attempt to build this interface.
|
||||
|
||||
### Prerequisites
|
||||
Boris has three "levels" of highlights for each article:
|
||||
- user = yellow
|
||||
- friends = orange
|
||||
- nostrverse = purple
|
||||
|
||||
- Node.js 18+
|
||||
- npm, pnpm, or yarn
|
||||
In case it's not self-explanatory:
|
||||
- **your highlights** = highlights that the logged-in npub made
|
||||
- **friends** = highlights that your friends made, i.e. highlights of the npubs that the logged-in user follows
|
||||
- **nostrverse** = all the highlights we can find on all the relays we're connected to
|
||||
|
||||
### Installation
|
||||
The user can toggle hide/show any of these "levels".
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone <your-repo-url>
|
||||
cd markr
|
||||
```
|
||||
In addition to rendering articles from nostr and the legacy web, Boris can act as a "read it later" app, thanks to the power of nostr bookmarks.
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
npm install
|
||||
# or
|
||||
pnpm install
|
||||
# or
|
||||
yarn install
|
||||
```
|
||||
If you bookmark something on nostr, Boris will show it in the bookmarks bar. If said something contains a URL, Boris will extract and render it in a distraction-free and reader-friendly way.
|
||||
|
||||
3. Start the development server:
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
yarn dev
|
||||
```
|
||||
## What Boris does
|
||||
|
||||
4. Open your browser and navigate to `http://localhost:3000`
|
||||
- Collects your saved links from Nostr and shows them as a tidy reading list
|
||||
- Opens articles in a distraction‑free reader with clear typography
|
||||
- Shows community highlights layered on the article (yours, friends, everyone)
|
||||
- Lets you collapse sidebars anytime for full‑focus reading
|
||||
- Remembers simple preferences like view mode, fonts, and highlight style
|
||||
|
||||
## Usage
|
||||
## How it works
|
||||
|
||||
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
|
||||
1. Connect your Nostr account.
|
||||
- Click “Connect” and approve with your usual Nostr signer.
|
||||
2. Browse your bookmarks.
|
||||
- Your lists and items appear on the left. Pick anything to read.
|
||||
3. Read in comfort.
|
||||
- The center panel renders a readable article view with images and headings.
|
||||
4. See what people highlighted.
|
||||
- The right panel shows highlights by level:
|
||||
- Mine (your highlights)
|
||||
- Friends (people you follow)
|
||||
- Nostrverse (everyone else)
|
||||
- Each level has its own color. Click any highlight to jump to that spot.
|
||||
5. Focus when you want.
|
||||
- Collapse one or both side panels. The layout adapts without wasting space.
|
||||
|
||||
## Technical Details
|
||||
## Why people like Boris
|
||||
|
||||
- Built with React and TypeScript
|
||||
- Uses [applesauce-core](https://github.com/hzrd149/applesauce) for nostr functionality
|
||||
- Implements [NIP-51](https://github.com/nostr-protocol/nips/blob/master/51.md) for bookmark management
|
||||
- Supports both individual bookmarks and bookmark lists
|
||||
- No noise: Just your saved links and the best excerpts others found
|
||||
- Fast by default: Opens instantly in your browser
|
||||
- Portable: Works with any Nostr account; your data travels with you
|
||||
- Designed for reading: Smooth navigation and instant scroll‑to‑highlight
|
||||
|
||||
## Development
|
||||
## Tips
|
||||
|
||||
### Project Structure
|
||||
- Hover icons and counters to see what they do — most controls are discoverable.
|
||||
- Lots of highlights? Scan the right panel and click to jump between them.
|
||||
- Open Settings to switch fonts, tweak highlight styles, and change the list view.
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/
|
||||
│ ├── 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
|
||||
│ ├── 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
|
||||
│ └── readerService.ts # Content extraction via reader API
|
||||
├── types/
|
||||
│ ├── bookmarks.ts # Bookmark type definitions
|
||||
│ ├── 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
|
||||
```
|
||||
## Privacy and data
|
||||
|
||||
### Private (hidden) bookmarks (Amethyst-style)
|
||||
- Boris doesn’t ask for an email or create a new account — it connects to your existing Nostr identity.
|
||||
- Your bookmarks and highlights live on Nostr. Boris reads from the network and renders everything locally in your browser.
|
||||
|
||||
We support Amethyst-style private (hidden) bookmark lists alongside public ones (NIP‑51):
|
||||
## Troubleshooting
|
||||
|
||||
- **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
|
||||
npm run build
|
||||
# or
|
||||
pnpm build
|
||||
# or
|
||||
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
|
||||
|
||||
Contributions are welcome! Please feel free to submit a Pull Request. Make sure to:
|
||||
|
||||
- Follow the existing code style
|
||||
- Keep files under 210 lines
|
||||
- Use conventional commits
|
||||
- Run linter and type checks before submitting
|
||||
- If something looks empty, try opening another article and coming back — network data can arrive in bursts.
|
||||
- Not every article has highlights yet; they grow as the community reads.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
|
||||
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--wClm1wz.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Bj-Uhit8.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>
|
||||
|
||||
586
node_modules/.package-lock.json
generated
vendored
586
node_modules/.package-lock.json
generated
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "markr",
|
||||
"version": "0.1.1",
|
||||
"name": "boris",
|
||||
"version": "0.1.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
@@ -320,32 +320,6 @@
|
||||
"node": ">=22.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cashu/crypto": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@cashu/crypto/-/crypto-0.2.7.tgz",
|
||||
"integrity": "sha512-1aaDfUjiHNXoJqg8nW+341TLWV9W28DsVNXJUKcHL0yAmwLs5+56SSnb8LLDJzPamLVoYL0U0bda91klAzptig==",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"node_modules/@cashu/crypto/node_modules/@scure/bip39": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz",
|
||||
"integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "~1.8.0",
|
||||
"@scure/base": "~1.2.5"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||
@@ -1914,16 +1888,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-accounts": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-accounts/-/applesauce-accounts-3.1.0.tgz",
|
||||
"integrity": "sha512-F0xFi4CU5Ak917VcUap+6YIxyvbjP2BJejWBjVurFMY6tCK3kWWPQnoPc+GjU6LkMsL8BfQcOQ6wKIX4MvTB7Q==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-accounts/-/applesauce-accounts-4.0.0.tgz",
|
||||
"integrity": "sha512-JHv63cRSSWXqbId6anNfOlPCE+sr3zJeHT6Jt9p+3X+hZkHrlNy5sLBK+fBHvKc5w/eQFsmnIWYfuLxPdqZcrA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.7.1",
|
||||
"applesauce-core": "^3.1.0",
|
||||
"applesauce-signers": "^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"
|
||||
},
|
||||
"funding": {
|
||||
@@ -1932,14 +1906,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-actions": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-actions/-/applesauce-actions-3.1.0.tgz",
|
||||
"integrity": "sha512-wNZQr1qAmlQCjOQQXK0sHyNtcEbYbcUmA97bYg4KctSwlEQAI14fUTltYHdLZ3Zw4xJ9F0Xq4O2YCUJA4UOYlA==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-actions/-/applesauce-actions-4.0.0.tgz",
|
||||
"integrity": "sha512-oYAjrazKGDINeVwypNDnV9eNSv7ZDTjNeV3azo5jeUU1haEQ0t+zwVWzGxk9/VutT1yWQHFsCZBInYZIegfLhQ==",
|
||||
"license": "MIT",
|
||||
"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"
|
||||
},
|
||||
"funding": {
|
||||
@@ -1970,90 +1944,7 @@
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/@noble/curves": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.3.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/@noble/curves/node_modules/@noble/hashes": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/@scure/bip32": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
|
||||
"integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/curves": "~1.1.0",
|
||||
"@noble/hashes": "~1.3.1",
|
||||
"@scure/base": "~1.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/@scure/bip32/node_modules/@noble/curves": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
|
||||
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.3.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
||||
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/@scure/bip32/node_modules/@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/@scure/bip32/node_modules/@scure/base": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz",
|
||||
"integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/applesauce-core": {
|
||||
"node_modules/applesauce-core": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-core/-/applesauce-core-4.0.0.tgz",
|
||||
"integrity": "sha512-cXg9lDU0PKpAeVw7FGN3jzKB/k9kX5YOI7uwzrZhibYB5PfpHAYRiVexxBuFdT2RNaDgQogXl75gV2hag5uLuw==",
|
||||
@@ -2074,82 +1965,14 @@
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/nostr-tools": {
|
||||
"version": "2.17.0",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.17.0.tgz",
|
||||
"integrity": "sha512-lrvHM7cSaGhz7F0YuBvgHMoU2s8/KuThihDoOYk8w5gpVHTy0DeUCAgCN8uLGeuSl5MAWekJr9Dkfo5HClqO9w==",
|
||||
"license": "Unlicense",
|
||||
"dependencies": {
|
||||
"@noble/ciphers": "^0.5.1",
|
||||
"@noble/curves": "1.2.0",
|
||||
"@noble/hashes": "1.3.1",
|
||||
"@scure/base": "1.1.1",
|
||||
"@scure/bip32": "1.3.1",
|
||||
"@scure/bip39": "1.2.1",
|
||||
"nostr-wasm": "0.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/nostr-tools/node_modules/@noble/hashes": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
||||
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-content/node_modules/nostr-tools/node_modules/@scure/base": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
|
||||
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/applesauce-core": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-core/-/applesauce-core-3.1.0.tgz",
|
||||
"integrity": "sha512-rIvtAYm8jJiLkv251yT12olmlmlkeT5x9kptWlAz0wMiAhymGG/RoWtMN80mbOAebjwcLCRLRfrAO6YYal1XpQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.7.1",
|
||||
"@scure/base": "^1.2.4",
|
||||
"debug": "^4.4.0",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"hash-sum": "^2.0.0",
|
||||
"light-bolt11-decoder": "^3.2.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"nostr-tools": "~2.15",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "lightning",
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-factory": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-factory/-/applesauce-factory-3.1.0.tgz",
|
||||
"integrity": "sha512-K9onWy8yvWnQp2c+a227IFHv65ToDH4B4yoLEOuLs2xOp7BwtZCoIdVZbWVk93X1KvA7pBTtXCjDbwTcH7LCjQ==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-factory/-/applesauce-factory-4.0.0.tgz",
|
||||
"integrity": "sha512-Sqsg+bC7CkRXMxXLkO6YGoKxy/Aqtia9YenasS5qjPOQFmyFMwKRxaHCu6vX6KdpNSABusw0b9Tnn4gTh6CxLw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"applesauce-content": "^3.1.0",
|
||||
"applesauce-core": "^3.1.0",
|
||||
"applesauce-content": "^4.0.0",
|
||||
"applesauce-core": "^4.0.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"nostr-tools": "^2.13"
|
||||
},
|
||||
@@ -2158,51 +1981,15 @@
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-factory/node_modules/@cashu/cashu-ts": {
|
||||
"version": "2.0.0-rc1",
|
||||
"resolved": "https://registry.npmjs.org/@cashu/cashu-ts/-/cashu-ts-2.0.0-rc1.tgz",
|
||||
"integrity": "sha512-39459l7x/fUMEgOsCdGLLl6rMekO4nbv+wEuavmyElh8hgN8t66wcb29AJvdFTb6K3lPACKF2rs/jAlPYrN7Ng==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cashu/crypto": "^0.2.7",
|
||||
"@noble/curves": "^1.3.0",
|
||||
"@noble/hashes": "^1.3.3",
|
||||
"@scure/bip32": "^1.3.3",
|
||||
"buffer": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-factory/node_modules/applesauce-content": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-content/-/applesauce-content-3.1.0.tgz",
|
||||
"integrity": "sha512-dxXmEzMz5KQIdaKOVJg2ufphVPoECWa6l7NIQo5mXQGrjv3VrT5QY5x0MVWJWWcC4fRBwE8xIhJyfhIeosymMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cashu/cashu-ts": "2.0.0-rc1",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/unist": "^3.0.3",
|
||||
"applesauce-core": "^3.1.0",
|
||||
"mdast-util-find-and-replace": "^3.0.2",
|
||||
"nostr-tools": "~2.15",
|
||||
"remark": "^15.0.1",
|
||||
"remark-parse": "^11.0.0",
|
||||
"unified": "^11.0.5",
|
||||
"unist-util-visit-parents": "^6.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "lightning",
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-loaders": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-loaders/-/applesauce-loaders-3.1.0.tgz",
|
||||
"integrity": "sha512-9IY5RYqoXcIgAAdJNuMjMBr+CI85z1yj708C92UiP9YMQ4mrIIEvZbMmWLApBzRn5XsmmEa00a/iNlXpkRg9Sw==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-loaders/-/applesauce-loaders-4.0.0.tgz",
|
||||
"integrity": "sha512-yNlpzCeUlkpq1jehyHPre0C3ey9anMDTpPysqdV9Rca+U2QnAWduzQ+Eo8FVS1X9jZRD6s/gkLSnCnW1+kX7uQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"applesauce-core": "^3.1.0",
|
||||
"applesauce-core": "^4.0.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"nostr-tools": "~2.15",
|
||||
"nostr-tools": "~2.17",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"funding": {
|
||||
@@ -2211,18 +1998,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-react": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-react/-/applesauce-react-3.1.0.tgz",
|
||||
"integrity": "sha512-9zKbHOkXTGBLRe2uZvwAyPLTVPfelQQ7BvVTYHb2hg1JbhphMQqDSas3kaHBltt9ZCVh0xdv8JupmKWTUeCzag==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-react/-/applesauce-react-4.0.0.tgz",
|
||||
"integrity": "sha512-eVDUf3GL1j4bsL1Y8GsC/2sywajLu1oJioCNajUsm68hf5+zIR0rLHWaA4y0o5Rcctf/O4UbYkFztj1XHcuHgg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"applesauce-accounts": "^3.1.0",
|
||||
"applesauce-actions": "^3.1.0",
|
||||
"applesauce-content": "^3.1.0",
|
||||
"applesauce-core": "^3.1.0",
|
||||
"applesauce-factory": "^3.1.0",
|
||||
"applesauce-accounts": "^4.0.0",
|
||||
"applesauce-actions": "^4.0.0",
|
||||
"applesauce-content": "^4.0.0",
|
||||
"applesauce-core": "^4.0.0",
|
||||
"applesauce-factory": "^4.0.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"nostr-tools": "~2.15",
|
||||
"nostr-tools": "~2.17",
|
||||
"observable-hooks": "^4.2.4",
|
||||
"react": "^18.3.1",
|
||||
"rxjs": "^7.8.1"
|
||||
@@ -2232,52 +2019,16 @@
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-react/node_modules/@cashu/cashu-ts": {
|
||||
"version": "2.0.0-rc1",
|
||||
"resolved": "https://registry.npmjs.org/@cashu/cashu-ts/-/cashu-ts-2.0.0-rc1.tgz",
|
||||
"integrity": "sha512-39459l7x/fUMEgOsCdGLLl6rMekO4nbv+wEuavmyElh8hgN8t66wcb29AJvdFTb6K3lPACKF2rs/jAlPYrN7Ng==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cashu/crypto": "^0.2.7",
|
||||
"@noble/curves": "^1.3.0",
|
||||
"@noble/hashes": "^1.3.3",
|
||||
"@scure/bip32": "^1.3.3",
|
||||
"buffer": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-react/node_modules/applesauce-content": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-content/-/applesauce-content-3.1.0.tgz",
|
||||
"integrity": "sha512-dxXmEzMz5KQIdaKOVJg2ufphVPoECWa6l7NIQo5mXQGrjv3VrT5QY5x0MVWJWWcC4fRBwE8xIhJyfhIeosymMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cashu/cashu-ts": "2.0.0-rc1",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/unist": "^3.0.3",
|
||||
"applesauce-core": "^3.1.0",
|
||||
"mdast-util-find-and-replace": "^3.0.2",
|
||||
"nostr-tools": "~2.15",
|
||||
"remark": "^15.0.1",
|
||||
"remark-parse": "^11.0.0",
|
||||
"unified": "^11.0.5",
|
||||
"unist-util-visit-parents": "^6.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "lightning",
|
||||
"url": "lightning:nostrudel@geyser.fund"
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-relay": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-relay/-/applesauce-relay-3.1.0.tgz",
|
||||
"integrity": "sha512-YseV51O3pc9IIX9MoP4XrVmkUq6a0u8h7n/B4zg0Y3bCQEs415LbM3UwIwZzF1DAEnphOu2xXgkH/9QCg5HvFg==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-relay/-/applesauce-relay-4.0.0.tgz",
|
||||
"integrity": "sha512-qoWjh9dABdL7AuSe4cmKiyZhNvrVZBRXA1GQgWiKSynm+rNYP+6Rc4SDT3vndNMqx9jRKbL4jwvKeU5vkVpFRA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.7.1",
|
||||
"applesauce-core": "^3.1.0",
|
||||
"applesauce-core": "^4.0.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"nostr-tools": "~2.15",
|
||||
"nostr-tools": "~2.17",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"funding": {
|
||||
@@ -2286,18 +2037,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/applesauce-signers": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-signers/-/applesauce-signers-3.1.0.tgz",
|
||||
"integrity": "sha512-7loxZ3hKSAhDRDs9rtVP/MPBZRmSbutE7g8/ALnXe5ihytbKSdF+0L5NBd0fxpSLMvmd8wEFOha6LsT03I5RCQ==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/applesauce-signers/-/applesauce-signers-4.0.0.tgz",
|
||||
"integrity": "sha512-AHrPtH1Oy0l1OS7jwd/DfseUpOhTE8JhZIUIElcQgAlqE7Cgg5FO+LF7dWRPUNb3zn8P+mzEQN2wJhby84SNcA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.7.1",
|
||||
"@noble/secp256k1": "^1.7.1",
|
||||
"@scure/base": "^1.2.4",
|
||||
"applesauce-core": "^3.1.0",
|
||||
"applesauce-core": "^4.0.0",
|
||||
"debug": "^4.4.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"nostr-tools": "~2.15",
|
||||
"nostr-tools": "~2.17",
|
||||
"rxjs": "^7.8.2"
|
||||
},
|
||||
"funding": {
|
||||
@@ -2339,26 +2090,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/baseline-browser-mapping": {
|
||||
"version": "2.8.10",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.10.tgz",
|
||||
@@ -2426,30 +2157,6 @@
|
||||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
@@ -2592,6 +2299,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
|
||||
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@@ -2660,6 +2376,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dequal": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||
@@ -2708,6 +2433,61 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
|
||||
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.228",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.228.tgz",
|
||||
@@ -2715,6 +2495,18 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
||||
@@ -2768,7 +2560,6 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
@@ -3317,25 +3108,24 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
@@ -3498,6 +3288,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
@@ -4605,9 +4404,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nostr-tools": {
|
||||
"version": "2.15.2",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.15.2.tgz",
|
||||
"integrity": "sha512-utmqVVS4HMDiwhIgI6Cr+KqA4aUhF3Sb755iO/qCiqxc5H9JW/9Z3N1RO/jKWpjP6q/Vx0lru7IYuiPvk+2/ng==",
|
||||
"version": "2.17.0",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.17.0.tgz",
|
||||
"integrity": "sha512-lrvHM7cSaGhz7F0YuBvgHMoU2s8/KuThihDoOYk8w5gpVHTy0DeUCAgCN8uLGeuSl5MAWekJr9Dkfo5HClqO9w==",
|
||||
"license": "Unlicense",
|
||||
"dependencies": {
|
||||
"@noble/ciphers": "^0.5.1",
|
||||
@@ -4816,6 +4615,12 @@
|
||||
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/parse-srcset": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
|
||||
"integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
@@ -4860,7 +4665,6 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
@@ -4880,7 +4684,6 @@
|
||||
"version": "8.5.6",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -4909,7 +4712,6 @@
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -5037,6 +4839,53 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "7.9.3",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.3.tgz",
|
||||
"integrity": "sha512-4o2iWCFIwhI/eYAIL43+cjORXYn/aRQPgtFRRZb3VzoyQ5Uej0Bmqj7437L97N9NJW4wnicSwLOLS+yCXfAPgg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie": "^1.0.1",
|
||||
"set-cookie-parser": "^2.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
"react-dom": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "7.9.3",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.3.tgz",
|
||||
"integrity": "sha512-1QSbA0TGGFKTAc/aWjpfW/zoEukYfU4dc1dLkT/vvf54JoGMkW+fNA+3oyo2gWVW1GM7BxjJVHz5GnPJv40rvg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-router": "7.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
"react-dom": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/reading-time-estimator": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/reading-time-estimator/-/reading-time-estimator-1.14.0.tgz",
|
||||
"integrity": "sha512-EWLj21Ou07uUvZWE0suAGPvEebhp91ZABl8jhTzZXY/ziBOPXfQ4tZ1eHiUV7moQ1NJ1KJj9krWuFlnoMx0upA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sanitize-html": "^2.15.0"
|
||||
}
|
||||
},
|
||||
"node_modules/remark": {
|
||||
"version": "15.0.1",
|
||||
"resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz",
|
||||
@@ -5232,6 +5081,20 @@
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sanitize-html": {
|
||||
"version": "2.17.0",
|
||||
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.0.tgz",
|
||||
"integrity": "sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"deepmerge": "^4.2.2",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"htmlparser2": "^8.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"parse-srcset": "^1.0.2",
|
||||
"postcss": "^8.3.11"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.23.2",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
||||
@@ -5254,6 +5117,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/set-cookie-parser": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
||||
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
@@ -5291,7 +5160,6 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
||||
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":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAOnE,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,GACzF,GAAG,CAAC,MAAM,CAAC,GACX,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAEzC,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/F,MAAM,MAAM,QAAQ,GAAG;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG;IAChC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC5B,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IACnB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;AAEnD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC,MAAM,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACrB,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,SAAS,CAAC;AAI/C,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAcrE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,yBAEvC;AAED,eAAO,MAAM,cAAc,aAAc,MAAM,KAAG,MASjD,CAAC;AAEF,wBAAgB,sBAAsB,eAErC;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,kBAAkB,CAMxE;AAED,wBAAgB,mBAAmB,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,QAAQ,CAMpF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAarD"}
|
||||
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":";;;AACA,uDAAoD;AACpD,iDAA8C;AAC9C,wDAAsE;AACtE,+CAAmF;AACnF,oCAAiC;AA0EjC,MAAM,gBAAgB,GAAG,IAAA,kBAAU,EAAC,0DAA0D,CAAC,CAAC;AAEhG,SAAgB,WAAW,CAAC,MAAkB;IAC7C,MAAM,SAAS,GAAG,IAAA,eAAM,EAAC,eAAM,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAA,eAAM,EAAC,eAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC;YACJ,OAAO,YAAY,CAAC,IAAA,kBAAU,EAAC,eAAM,CAAC,MAAM,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACd,CAAC;IACF,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;AACzC,CAAC;AAdD,kCAcC;AAED,SAAgB,YAAY,CAAC,GAAW;IACvC,OAAO,qBAAS,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC;AAFD,oCAEC;AAEM,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAU,EAAE;IAC1D,IAAI,WAAmB,CAAC;IACxB,IAAI,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,WAAW,GAAG,IAAA,sBAAW,EAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3D,CAAC;SAAM,CAAC;QACP,6BAA6B;QAC7B,WAAW,GAAG,IAAA,wBAAa,EAAC,IAAA,8BAAmB,EAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,WAAW,CAAC;AACpB,CAAC,CAAC;AATW,QAAA,cAAc,kBASzB;AAEF,SAAgB,sBAAsB;IACrC,OAAO,qBAAS,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;AAC3C,CAAC;AAFD,wDAEC;AAED,SAAgB,iBAAiB,CAAC,QAAkB;IACnD,MAAM,kBAAkB,GAAuB,EAAE,CAAC;IAClD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACnC,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAA,kBAAU,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IACH,OAAO,kBAAkB,CAAC;AAC3B,CAAC;AAND,8CAMC;AAED,SAAgB,mBAAmB,CAAC,kBAAsC;IACzE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7C,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAA,kBAAU,EAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AACjB,CAAC;AAND,kDAMC;AAED,SAAgB,cAAc,CAAC,IAAc;IAC5C,MAAM,cAAc,GAAG,IAAI,CAAC;IAC5B,MAAM,SAAS,GAAG,CAAC,CAAmB,EAAoB,EAAE;QAC3D,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;SAC3D,GAAG,CAAC,SAAS,CAAC;SACd,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACxD,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,IAAA,kBAAU,EAAC,MAAM,CAAC,CAAC;SACvC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,UAAU,EAAE,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,IAAA,eAAM,EAAC,aAAa,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,OAAO,IAAI,GAAG,OAAO,CAAC;AACvB,CAAC;AAbD,wCAaC;AAED,SAAS,gBAAgB,CAAC,EAAc,EAAE,EAAc;IACvD,kCAAkC;IAClC,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IAC1D,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpB,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,WAAW,CAAC;AACpB,CAAC"}
|
||||
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":";;;AACA,uDAAoD;AACpD,iDAA8C;AAC9C,wDAAsE;AACtE,+CAAmF;AACnF,oCAAiC;AA0EjC,MAAM,gBAAgB,GAAG,IAAA,kBAAU,EAAC,0DAA0D,CAAC,CAAC;AAEhG,SAAgB,WAAW,CAAC,MAAkB;IAC7C,MAAM,SAAS,GAAG,IAAA,eAAM,EAAC,eAAM,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAA,eAAM,EAAC,eAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC;YACJ,OAAO,YAAY,CAAC,IAAA,kBAAU,EAAC,eAAM,CAAC,MAAM,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACd,CAAC;IACF,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;AACzC,CAAC;AAdD,kCAcC;AAED,SAAgB,YAAY,CAAC,GAAW;IACvC,OAAO,qBAAS,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC;AAFD,oCAEC;AAEM,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAU,EAAE;IAC1D,IAAI,WAAmB,CAAC;IACxB,IAAI,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,WAAW,GAAG,IAAA,sBAAW,EAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3D,CAAC;SAAM,CAAC;QACP,6BAA6B;QAC7B,WAAW,GAAG,IAAA,wBAAa,EAAC,IAAA,8BAAmB,EAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,WAAW,CAAC;AACpB,CAAC,CAAC;AATW,QAAA,cAAc,kBASzB;AAEF,SAAgB,sBAAsB;IACrC,OAAO,qBAAS,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;AAC3C,CAAC;AAFD,wDAEC;AAED,SAAgB,iBAAiB,CAAC,QAAkB;IACnD,MAAM,kBAAkB,GAAuB,EAAE,CAAC;IAClD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACnC,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAA,kBAAU,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IACH,OAAO,kBAAkB,CAAC;AAC3B,CAAC;AAND,8CAMC;AAED,SAAgB,mBAAmB,CAAC,kBAAsC;IACzE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7C,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAA,kBAAU,EAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AACjB,CAAC;AAND,kDAMC;AAED,SAAgB,cAAc,CAAC,IAAc;IAC5C,MAAM,cAAc,GAAG,IAAI,CAAC;IAC5B,MAAM,SAAS,GAAG,CAAC,CAAmB,EAAoB,EAAE;QAC3D,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;SAC3D,GAAG,CAAC,SAAS,CAAC;SACd,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACxD,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,IAAA,kBAAU,EAAC,MAAM,CAAC,CAAC;SACvC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,UAAU,EAAE,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,IAAA,eAAM,EAAC,aAAa,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,OAAO,IAAI,GAAG,OAAO,CAAC;AACvB,CAAC;AAbD,wCAaC;AAED,SAAS,gBAAgB,CAAC,EAAc,EAAE,EAAc;IACvD,kCAAkC;IAClC,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IAC1D,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpB,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,WAAW,CAAC;AACpB,CAAC"}
|
||||
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>;
|
||||
|
||||
37
node_modules/applesauce-core/dist/helpers/bookmarks.js
generated
vendored
37
node_modules/applesauce-core/dist/helpers/bookmarks.js
generated
vendored
@@ -1,6 +1,6 @@
|
||||
import { kinds } from "nostr-tools";
|
||||
import { getOrComputeCachedValue } from "./cache.js";
|
||||
import { getHiddenTags, isHiddenTagsLocked } from "./index.js";
|
||||
import { getHiddenTags, isHiddenTagsUnlocked, notifyEventUpdate, unlockHiddenTags, } from "./index.js";
|
||||
import { getAddressPointerFromATag, getCoordinateFromAddressPointer, getEventPointerFromETag, mergeAddressPointers, mergeEventPointers, } from "./pointers.js";
|
||||
export const BookmarkPublicSymbol = Symbol.for("bookmark-public");
|
||||
export const BookmarkHiddenSymbol = Symbol.for("bookmark-hidden");
|
||||
@@ -63,9 +63,34 @@ export function getBookmarks(bookmark) {
|
||||
export function getPublicBookmarks(bookmark) {
|
||||
return getOrComputeCachedValue(bookmark, BookmarkPublicSymbol, () => parseBookmarkTags(bookmark.tags));
|
||||
}
|
||||
/** Returns the bookmarks of the event if its unlocked */
|
||||
export function getHiddenBookmarks(bookmark) {
|
||||
if (isHiddenTagsLocked(bookmark))
|
||||
return undefined;
|
||||
return getOrComputeCachedValue(bookmark, BookmarkHiddenSymbol, () => parseBookmarkTags(getHiddenTags(bookmark)));
|
||||
/** Checks if the hidden bookmarks are unlocked */
|
||||
export function isHiddenBookmarksUnlocked(bookmark) {
|
||||
return isHiddenTagsUnlocked(bookmark) && Reflect.has(bookmark, BookmarkHiddenSymbol);
|
||||
}
|
||||
export function getHiddenBookmarks(bookmark) {
|
||||
if (isHiddenBookmarksUnlocked(bookmark))
|
||||
return bookmark[BookmarkHiddenSymbol];
|
||||
//get hidden tags
|
||||
const tags = getHiddenTags(bookmark);
|
||||
if (!tags)
|
||||
return undefined;
|
||||
// parse bookmarks
|
||||
const bookmarks = parseBookmarkTags(tags);
|
||||
// set cached value
|
||||
Reflect.set(bookmark, BookmarkHiddenSymbol, bookmarks);
|
||||
return bookmarks;
|
||||
}
|
||||
/** Unlocks the hidden bookmarks on a bookmarks event */
|
||||
export async function unlockHiddenBookmarks(bookmark, signer) {
|
||||
if (isHiddenBookmarksUnlocked(bookmark))
|
||||
return bookmark[BookmarkHiddenSymbol];
|
||||
// unlock hidden tags
|
||||
await unlockHiddenTags(bookmark, signer);
|
||||
// get hidden bookmarks
|
||||
const bookmarks = getHiddenBookmarks(bookmark);
|
||||
if (!bookmarks)
|
||||
throw new Error("Failed to unlock hidden bookmarks");
|
||||
// notify event store
|
||||
notifyEventUpdate(bookmark);
|
||||
return bookmarks;
|
||||
}
|
||||
|
||||
33
node_modules/applesauce-core/dist/helpers/comment.d.ts
generated
vendored
33
node_modules/applesauce-core/dist/helpers/comment.d.ts
generated
vendored
@@ -1,6 +1,9 @@
|
||||
import { NostrEvent } from "nostr-tools";
|
||||
import { ExternalPointer, ExternalIdentifiers } from "./external-id.js";
|
||||
import { KnownEvent } from "./index.js";
|
||||
export declare const COMMENT_KIND = 1111;
|
||||
/** Type for validated comment events */
|
||||
export type CommentEvent = KnownEvent<typeof COMMENT_KIND>;
|
||||
export type CommentEventPointer = {
|
||||
type: "event";
|
||||
id: string;
|
||||
@@ -22,30 +25,20 @@ export type CommentExternalPointer<T extends keyof ExternalIdentifiers> = Extern
|
||||
export type CommentPointer = CommentEventPointer | CommentAddressPointer | CommentExternalPointer<keyof ExternalIdentifiers>;
|
||||
export declare const CommentRootPointerSymbol: unique symbol;
|
||||
export declare const CommentReplyPointerSymbol: unique symbol;
|
||||
/**
|
||||
* Gets the EventPointer from an array of tags
|
||||
* @throws
|
||||
*/
|
||||
/** Gets the EventPointer from an array of tags */
|
||||
export declare function getCommentEventPointer(tags: string[][], root?: boolean): CommentEventPointer | null;
|
||||
/**
|
||||
* Gets the AddressPointer from an array of tags
|
||||
* @throws
|
||||
*/
|
||||
/** Gets the AddressPointer from an array of tags */
|
||||
export declare function getCommentAddressPointer(tags: string[][], root?: boolean): CommentAddressPointer | null;
|
||||
/**
|
||||
* Gets the ExternalPointer from an array of tags
|
||||
* @throws
|
||||
*/
|
||||
/** Gets the ExternalPointer from an array of tags */
|
||||
export declare function getCommentExternalPointer(tags: string[][], root?: boolean): CommentExternalPointer<keyof ExternalIdentifiers> | null;
|
||||
/**
|
||||
* Returns the root pointer for a comment
|
||||
* @throws
|
||||
*/
|
||||
/** Returns the root pointer for a comment */
|
||||
export declare function getCommentRootPointer(comment: CommentEvent): CommentPointer;
|
||||
export declare function getCommentRootPointer(comment: NostrEvent): CommentPointer | null;
|
||||
/**
|
||||
* Returns the reply pointer for a comment
|
||||
* @throws
|
||||
*/
|
||||
/** Returns the reply pointer for a comment */
|
||||
export declare function getCommentReplyPointer(comment: NostrEvent): CommentPointer | null;
|
||||
/** Checks if a pointer is a {@link CommentEventPointer} */
|
||||
export declare function isCommentEventPointer(pointer: any): pointer is CommentEventPointer;
|
||||
/** Checks if a pointer is a {@link CommentAddressPointer} */
|
||||
export declare function isCommentAddressPointer(pointer: any): pointer is CommentAddressPointer;
|
||||
/** Checks if a comment event is valid */
|
||||
export declare function isValidComment(comment: NostrEvent): comment is CommentEvent;
|
||||
|
||||
43
node_modules/applesauce-core/dist/helpers/comment.js
generated
vendored
43
node_modules/applesauce-core/dist/helpers/comment.js
generated
vendored
@@ -5,16 +5,14 @@ import { isSafeRelayURL } from "./relays.js";
|
||||
export const COMMENT_KIND = 1111;
|
||||
export const CommentRootPointerSymbol = Symbol.for("comment-root-pointer");
|
||||
export const CommentReplyPointerSymbol = Symbol.for("comment-reply-pointer");
|
||||
/**
|
||||
* Gets the EventPointer from an array of tags
|
||||
* @throws
|
||||
*/
|
||||
/** Gets the EventPointer from an array of tags */
|
||||
export function getCommentEventPointer(tags, root = false) {
|
||||
const eTag = tags.find((t) => t[0] === (root ? "E" : "e"));
|
||||
const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
|
||||
if (eTag) {
|
||||
// Missing kind tag, return null
|
||||
if (!kind)
|
||||
throw new Error("Missing kind tag");
|
||||
return null;
|
||||
// only the root pubkey can be gotten from the tags, since due to quotes and mentions there will be many "p" tags for replies
|
||||
const rootPubkey = root ? tags.find((t) => t[0] === "P")?.[1] : undefined;
|
||||
const pointer = {
|
||||
@@ -28,17 +26,15 @@ export function getCommentEventPointer(tags, root = false) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Gets the AddressPointer from an array of tags
|
||||
* @throws
|
||||
*/
|
||||
/** Gets the AddressPointer from an array of tags */
|
||||
export function getCommentAddressPointer(tags, root = false) {
|
||||
const aTag = tags.find((t) => t[0] === (root ? "A" : "a"));
|
||||
const eTag = tags.find((t) => t[0] === (root ? "E" : "e"));
|
||||
const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
|
||||
if (aTag) {
|
||||
// Missing kind tag, return null
|
||||
if (!kind)
|
||||
throw new Error("Missing kind tag");
|
||||
return null;
|
||||
const addressPointer = getAddressPointerFromATag(aTag);
|
||||
const pointer = {
|
||||
type: "address",
|
||||
@@ -52,16 +48,10 @@ export function getCommentAddressPointer(tags, root = false) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Gets the ExternalPointer from an array of tags
|
||||
* @throws
|
||||
*/
|
||||
/** Gets the ExternalPointer from an array of tags */
|
||||
export function getCommentExternalPointer(tags, root = false) {
|
||||
const iTag = tags.find((t) => t[0] === (root ? "I" : "i"));
|
||||
const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
|
||||
if (iTag) {
|
||||
if (!kind)
|
||||
throw new Error("Missing kind tag");
|
||||
return {
|
||||
type: "external",
|
||||
...getExternalPointerFromTag(iTag),
|
||||
@@ -69,13 +59,9 @@ export function getCommentExternalPointer(tags, root = false) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns the root pointer for a comment
|
||||
* @throws
|
||||
*/
|
||||
export function getCommentRootPointer(comment) {
|
||||
if (comment.kind !== COMMENT_KIND)
|
||||
throw new Error("Event is not a comment");
|
||||
return null;
|
||||
return getOrComputeCachedValue(comment, CommentRootPointerSymbol, () => {
|
||||
// check for address pointer first since it can also have E tags
|
||||
const A = getCommentAddressPointer(comment.tags, true);
|
||||
@@ -90,13 +76,10 @@ export function getCommentRootPointer(comment) {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Returns the reply pointer for a comment
|
||||
* @throws
|
||||
*/
|
||||
/** Returns the reply pointer for a comment */
|
||||
export function getCommentReplyPointer(comment) {
|
||||
if (comment.kind !== COMMENT_KIND)
|
||||
throw new Error("Event is not a comment");
|
||||
return null;
|
||||
return getOrComputeCachedValue(comment, CommentReplyPointerSymbol, () => {
|
||||
// check for address pointer first since it can also have E tags
|
||||
const A = getCommentAddressPointer(comment.tags, false);
|
||||
@@ -111,15 +94,21 @@ export function getCommentReplyPointer(comment) {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
/** Checks if a pointer is a {@link CommentEventPointer} */
|
||||
export function isCommentEventPointer(pointer) {
|
||||
return (Reflect.has(pointer, "id") &&
|
||||
Reflect.has(pointer, "kind") &&
|
||||
!Reflect.has(pointer, "identifier") &&
|
||||
typeof pointer.kind === "number");
|
||||
}
|
||||
/** Checks if a pointer is a {@link CommentAddressPointer} */
|
||||
export function isCommentAddressPointer(pointer) {
|
||||
return (Reflect.has(pointer, "identifier") &&
|
||||
Reflect.has(pointer, "pubkey") &&
|
||||
Reflect.has(pointer, "kind") &&
|
||||
typeof pointer.kind === "number");
|
||||
}
|
||||
/** Checks if a comment event is valid */
|
||||
export function isValidComment(comment) {
|
||||
return (comment.kind === COMMENT_KIND && getCommentRootPointer(comment) !== null && getCommentReplyPointer(comment) !== null);
|
||||
}
|
||||
|
||||
11
node_modules/applesauce-core/dist/helpers/contacts.d.ts
generated
vendored
11
node_modules/applesauce-core/dist/helpers/contacts.d.ts
generated
vendored
@@ -1,14 +1,23 @@
|
||||
import { NostrEvent } from "nostr-tools";
|
||||
import { ProfilePointer } from "nostr-tools/nip19";
|
||||
import { HiddenContentSigner } from "./hidden-content.js";
|
||||
export declare const ContactsRelaysSymbol: unique symbol;
|
||||
export declare const PublicContactsSymbol: unique symbol;
|
||||
export declare const HiddenContactsSymbol: unique symbol;
|
||||
export declare function getRelaysFromContactsEvent(event: NostrEvent): Map<string, "all" | "inbox" | "outbox"> | null;
|
||||
/** Type for contact events with unlocked hidden tags */
|
||||
export type UnlockedContacts = {
|
||||
[HiddenContactsSymbol]: ProfilePointer[];
|
||||
};
|
||||
export declare function getRelaysFromContactsEvent(event: NostrEvent): Map<string, "inbox" | "outbox" | "all"> | null;
|
||||
/** Merges any number of contact lists into a single list */
|
||||
export declare function mergeContacts(...pointers: (ProfilePointer | undefined | (ProfilePointer | undefined)[])[]): ProfilePointer[];
|
||||
/** Returns all public and hidden contacts from a contacts list event */
|
||||
export declare function getContacts(event: NostrEvent): ProfilePointer[];
|
||||
/** Returns only the public contacts from a contacts list event */
|
||||
export declare function getPublicContacts(event: NostrEvent): ProfilePointer[];
|
||||
/** Checks if the hidden contacts are unlocked */
|
||||
export declare function isHiddenContactsUnlocked<T extends NostrEvent>(event: T): event is T & UnlockedContacts;
|
||||
/** Returns only the hidden contacts from a contacts list event */
|
||||
export declare function getHiddenContacts(event: NostrEvent): ProfilePointer[] | undefined;
|
||||
/** Unlocks the hidden contacts */
|
||||
export declare function unlockHiddenContacts(event: NostrEvent, signer: HiddenContentSigner): Promise<ProfilePointer[]>;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user