feat: integrate applesauce-content for proper content parsing and rendering

- Install applesauce-content package for content parsing
- Use getParsedContent() to parse nostr content according to applesauce patterns
- Create proper TypeScript interfaces for ParsedNode and ParsedContent
- Add renderParsedContent() component to render parsed content with proper styling
- Handle mentions, links, and text content with appropriate styling
- Add CSS styles for nostr-mention and nostr-link classes
- Follow applesauce-content documentation patterns for content rendering
- Maintain type safety with proper interfaces instead of 'any' types

This follows the applesauce-content documentation exactly as shown
in the examples, providing proper content parsing and rendering.
This commit is contained in:
Gigi
2025-10-02 08:33:00 +02:00
parent b6721f685b
commit c1e0e82704
238 changed files with 1017 additions and 53124 deletions

309
node_modules/.package-lock.json generated vendored
View File

@@ -307,16 +307,17 @@
}
},
"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==",
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/@cashu/cashu-ts/-/cashu-ts-2.7.2.tgz",
"integrity": "sha512-AOwL6+10AA0syRf2mtRYgoTvAz31gE4MnElj9TLS9xG3k8Msxy27awBlCX5MsBpBgcZZoqWOReYEuUgnbN3IQQ==",
"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"
"@noble/curves": "^1.9.5",
"@noble/hashes": "^1.5.0",
"@scure/bip32": "^1.5.0"
},
"engines": {
"node": ">=22.4.0"
}
},
"node_modules/@cashu/crypto": {
@@ -332,6 +333,19 @@
"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",
@@ -1390,18 +1404,39 @@
}
},
"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==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
"integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "~1.8.0",
"@scure/base": "~1.2.5"
"@noble/hashes": "~1.3.0",
"@scure/base": "~1.1.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@scure/bip39/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/@scure/bip39/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/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -1862,18 +1897,18 @@
}
},
"node_modules/applesauce-content": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/applesauce-content/-/applesauce-content-3.1.0.tgz",
"integrity": "sha512-dxXmEzMz5KQIdaKOVJg2ufphVPoECWa6l7NIQo5mXQGrjv3VrT5QY5x0MVWJWWcC4fRBwE8xIhJyfhIeosymMQ==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/applesauce-content/-/applesauce-content-4.0.0.tgz",
"integrity": "sha512-2ZrhM/UCQkcZcAldXJX+KfWAPAtkoTXH5BwPhYpaMw0UgHjWX8mYiy/801PtLBr2gWkKd/Dw1obdNDcPUO3idw==",
"license": "MIT",
"dependencies": {
"@cashu/cashu-ts": "2.0.0-rc1",
"@cashu/cashu-ts": "^2.7.2",
"@types/hast": "^3.0.4",
"@types/mdast": "^4.0.4",
"@types/unist": "^3.0.3",
"applesauce-core": "^3.1.0",
"applesauce-core": "^4.0.0",
"mdast-util-find-and-replace": "^3.0.2",
"nostr-tools": "~2.15",
"nostr-tools": "~2.17",
"remark": "^15.0.1",
"remark-parse": "^11.0.0",
"unified": "^11.0.5",
@@ -1884,6 +1919,157 @@
"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": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/applesauce-core/-/applesauce-core-4.0.0.tgz",
"integrity": "sha512-cXg9lDU0PKpAeVw7FGN3jzKB/k9kX5YOI7uwzrZhibYB5PfpHAYRiVexxBuFdT2RNaDgQogXl75gV2hag5uLuw==",
"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.17",
"rxjs": "^7.8.1"
},
"funding": {
"type": "lightning",
"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",
@@ -1921,6 +2107,42 @@
"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",
@@ -1959,6 +2181,42 @@
"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",
@@ -3910,19 +4168,6 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-tools/node_modules/@scure/bip39": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
"integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "~1.3.0",
"@scure/base": "~1.1.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-wasm": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz",

View File

@@ -1,6 +0,0 @@
/node_modules
/dist
/test
/coverage
/.jest
jest.config.ts

View File

@@ -1,26 +0,0 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module",
"project": "tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/consistent-type-definitions": ["warn", "type"],
"@typescript-eslint/array-type": ["error", { "default": "generic" }],
"require-await": "off",
"@typescript-eslint/require-await": "error",
"@typescript-eslint/await-thenable": "warn",
"@typescript-eslint/consistent-type-exports": "warn",
"no-else-return": "warn"
},
"env": {
"browser": true,
"es2021": true
}
}

View File

@@ -1,5 +0,0 @@
dist
node_modules
package-lock.json
coverage
docs

View File

@@ -1,7 +0,0 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"pluginSearchDirs": ["."]
}

View File

@@ -21,6 +21,7 @@ Wallet Features:
- [x] receiving tokens
- [x] melting tokens
- [x] check if tokens are spent
- [x] payment methods: bolt11, bolt12
- [ ] ...
Implemented [NUTs](https://github.com/cashubtc/nuts/):
@@ -36,6 +37,9 @@ Implemented [NUTs](https://github.com/cashubtc/nuts/):
- [x] [NUT-08](https://github.com/cashubtc/nuts/blob/main/08.md)
- [x] [NUT-09](https://github.com/cashubtc/nuts/blob/main/09.md)
- [x] [NUT-11](https://github.com/cashubtc/nuts/blob/main/11.md)
- [x] [NUT-18](https://github.com/cashubtc/nuts/blob/main/18.md)
- [x] [NUT-23](https://github.com/cashubtc/nuts/blob/main/23.md)
- [x] [NUT-25](https://github.com/cashubtc/nuts/blob/main/25.md)
Supported token formats:
@@ -46,7 +50,7 @@ Supported token formats:
## Usage
Go to the [docs](https://cashubtc.github.io/cashu-ts/docs) for detailed usage, or have a look at the [integration tests](./test/integration.test.ts) for examples on how to implement a wallet.
Go to the [docs](https://cashubtc.github.io/cashu-ts/docs/main) for detailed usage, or have a look at the [integration tests](./test/integration.test.ts) for examples on how to implement a wallet.
### Install
@@ -54,13 +58,26 @@ Go to the [docs](https://cashubtc.github.io/cashu-ts/docs) for detailed usage, o
npm i @cashu/cashu-ts
```
### Logging
By default, cashu-ts does not log to the console. If you want to enable logging for debugging purposes, you can set the `logger` option when creating a wallet or mint. A `ConsoleLogger` is provided, or you can wrap your existing logger to conform to the `Logger` interface:
```typescript
import { CashuMint, CashuWallet, ConsoleLogger, LogLevel } from '@cashu/cashu-ts';
const mintUrl = 'http://localhost:3338';
const mintLogger = new ConsoleLogger(LogLevel.ERROR);
const mint = new CashuMint(mintUrl, undefined, { logger: mintLogger }); // Enable logging for the mint
const walletLogger = new ConsoleLogger(LogLevel.DEBUG);
const wallet = new CashuWallet(mint, { logger: walletLogger }); // Enable logging for the wallet
```
### Examples
#### Mint tokens
```typescript
import { CashuMint, CashuWallet, MintQuoteState } from '@cashu/cashu-ts';
const mintUrl = 'http://localhost:3338'; // the mint URL
const mintUrl = 'http://localhost:3338';
const mint = new CashuMint(mintUrl);
const wallet = new CashuWallet(mint);
await wallet.loadMint(); // persist wallet.keys and wallet.keysets to avoid calling loadMint() in the future
@@ -68,7 +85,7 @@ const mintQuote = await wallet.createMintQuote(64);
// pay the invoice here before you continue...
const mintQuoteChecked = await wallet.checkMintQuote(mintQuote.quote);
if (mintQuoteChecked.state == MintQuoteState.PAID) {
const { proofs } = await wallet.mintProofs(64, mintQuote.quote);
const proofs = await wallet.mintProofs(64, mintQuote.quote);
}
```
@@ -88,7 +105,7 @@ const amountToSend = meltQuote.amount + meltQuote.fee_reserve;
// if no appropriate amount can be selected offline. We must include potential
// ecash fees that the mint might require to melt the resulting proofsToSend later.
const { keep: proofsToKeep, send: proofsToSend } = await wallet.send(amountToSend, proofs, {
includeFees: true
includeFees: true,
});
// store proofsToKeep in wallet ..
@@ -101,13 +118,55 @@ const meltResponse = await wallet.meltProofs(meltQuote, proofsToSend);
```typescript
// we assume that `wallet` already minted `proofs`, as above
const { keep, send } = await wallet.send(32, proofs);
const token = getEncodedTokenV4({ token: [{ mint: mintUrl, proofs: send }] });
const token = getEncodedTokenV4({ mint: mintUrl, proofs: send });
console.log(token);
const wallet2 = new CashuWallet(mint); // receiving wallet
const receiveProofs = await wallet2.receive(token);
```
#### Get token data
```typescript
try {
const decodedToken = getDecodedToken(token);
console.log(decodedToken); // { mint: "https://mint.0xchat.com", unit: "sat", proofs: [...] }
} catch (_) {
console.log('Invalid token');
}
```
#### BOLT12 (Reusable Offers)
BOLT12 enables reusable Lightning offers that can be paid multiple times, unlike BOLT11 invoices which are single-use. Key differences:
- **Reusable**: Same offer can receive multiple payments
- **Amount flexibility**: Offers can be amountless (payer chooses amount)
```typescript
// Create reusable BOLT12 offer
const bolt12Quote = await wallet.createMintQuoteBolt12(bytesToHex(pubkey), {
amount: 1000, // Optional: omit to create an amountless offer
description: 'My reusable offer', // The mint must signal in their settings that offers with a description are supported
});
// Pay a BOLT12 offer
const meltQuote = await wallet.createMeltQuoteBolt12(offer, 1000000); // amount in msat
const { keep, send } = await wallet.send(meltQuote.amount + meltQuote.fee_reserve, proofs);
const { change } = await wallet.meltProofsBolt12(meltQuote, send);
// Mint from accumulated BOLT12 payments
const updatedQuote = await wallet.checkMintQuoteBolt12(bolt12Quote.quote);
const availableAmount = updatedQuote.amount_paid - updatedQuote.amount_issued;
if (availableAmount > 0) {
const newProofs = await wallet.mintProofsBolt12(
availableAmount,
updatedQuote,
bytesToHex(privateKey),
);
}
```
## Contribute
Contributions are very welcome.
@@ -115,28 +174,13 @@ Contributions are very welcome.
If you want to contribute, please open an Issue or a PR.
If you open a PR, please do so from the `development` branch as the base branch.
### Version
## Release strategy
```
* `main`
|\
|\ \
| | * `hotfix`
| |
| * `staging`
| |\
| |\ \
| | | * `bugfix`
| | |
| | * `development`
| | |\
| | | * `feature1`
| | | |
| | |/
| | *
| | |\
| | | * `feature2`
| | |/
| |/
|/ (create new version)
```
Features and fixes should be implemented by branching off `development`. Hotfixes can be implemented by branching off a given `tag`. A new release can be created if at least one new feature or fix has been added to the `development` branch. If the release has breaking API changes, the major version must be incremented (X.0.0). If not, the release can increment the minor version (0.X.0). Patches and hotfixes increment the patch version (0.0.X). To create a new release, the following steps must be taken:
1. `git checkout development && git pull` Checkout and pull latest changes from `development`
2. `npm version <major | minor | patch>` create new release commit & tag
3. `git push && git push --tags` push commit and tag
4. Create a new release on github, targeting the newly created tag
5. The CI will build and deploy to npm, with provenance
6. `git checkout main && git pull && git merge <tag>` After creating a new version, merge the tag into `main`

View File

@@ -1,166 +0,0 @@
import type { CheckStatePayload, CheckStateResponse, GetInfoResponse, MeltPayload, MintActiveKeys, MintAllKeysets, PostRestoreResponse, MintQuoteResponse, SerializedBlindedMessage, SwapPayload, SwapResponse, MintQuotePayload, MintPayload, MintResponse, PostRestorePayload, MeltQuotePayload, MeltQuoteResponse } from './model/types/index.js';
import request from './request.js';
/**
* Class represents Cashu Mint API. This class contains Lower level functions that are implemented by CashuWallet.
*/
declare class CashuMint {
private _mintUrl;
private _customRequest?;
/**
* @param _mintUrl requires mint URL to create this object
* @param _customRequest if passed, use custom request implementation for network communication with the mint
*/
constructor(_mintUrl: string, _customRequest?: typeof request);
get mintUrl(): string;
/**
* fetches mints info at the /info endpoint
* @param mintUrl
* @param customRequest
*/
static getInfo(mintUrl: string, customRequest?: typeof request): Promise<GetInfoResponse>;
/**
* fetches mints info at the /info endpoint
*/
getInfo(): Promise<GetInfoResponse>;
/**
* Performs a swap operation with ecash inputs and outputs.
* @param mintUrl
* @param swapPayload payload containing inputs and outputs
* @param customRequest
* @returns signed outputs
*/
static swap(mintUrl: string, swapPayload: SwapPayload, customRequest?: typeof request): Promise<SwapResponse>;
/**
* Performs a swap operation with ecash inputs and outputs.
* @param swapPayload payload containing inputs and outputs
* @returns signed outputs
*/
swap(swapPayload: SwapPayload): Promise<SwapResponse>;
/**
* Requests a new mint quote from the mint.
* @param mintUrl
* @param mintQuotePayload Payload for creating a new mint quote
* @param customRequest
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
static createMintQuote(mintUrl: string, mintQuotePayload: MintQuotePayload, customRequest?: typeof request): Promise<MintQuoteResponse>;
/**
* Requests a new mint quote from the mint.
* @param mintQuotePayload Payload for creating a new mint quote
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
createMintQuote(mintQuotePayload: MintQuotePayload): Promise<MintQuoteResponse>;
/**
* Gets an existing mint quote from the mint.
* @param mintUrl
* @param quote Quote ID
* @param customRequest
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
static checkMintQuote(mintUrl: string, quote: string, customRequest?: typeof request): Promise<MintQuoteResponse>;
/**
* Gets an existing mint quote from the mint.
* @param quote Quote ID
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
checkMintQuote(quote: string): Promise<MintQuoteResponse>;
/**
* Mints new tokens by requesting blind signatures on the provided outputs.
* @param mintUrl
* @param mintPayload Payload containing the outputs to get blind signatures on
* @param customRequest
* @returns serialized blinded signatures
*/
static mint(mintUrl: string, mintPayload: MintPayload, customRequest?: typeof request): Promise<MintResponse>;
/**
* Mints new tokens by requesting blind signatures on the provided outputs.
* @param mintPayload Payload containing the outputs to get blind signatures on
* @returns serialized blinded signatures
*/
mint(mintPayload: MintPayload): Promise<MintResponse>;
/**
* Requests a new melt quote from the mint.
* @param mintUrl
* @param MeltQuotePayload
* @returns
*/
static createMeltQuote(mintUrl: string, meltQuotePayload: MeltQuotePayload, customRequest?: typeof request): Promise<MeltQuoteResponse>;
/**
* Requests a new melt quote from the mint.
* @param MeltQuotePayload
* @returns
*/
createMeltQuote(meltQuotePayload: MeltQuotePayload): Promise<MeltQuoteResponse>;
/**
* Gets an existing melt quote.
* @param mintUrl
* @param quote Quote ID
* @returns
*/
static checkMeltQuote(mintUrl: string, quote: string, customRequest?: typeof request): Promise<MeltQuoteResponse>;
/**
* Gets an existing melt quote.
* @param quote Quote ID
* @returns
*/
checkMeltQuote(quote: string): Promise<MeltQuoteResponse>;
/**
* Requests the mint to pay for a Bolt11 payment request by providing ecash as inputs to be spent. The inputs contain the amount and the fee_reserves for a Lightning payment. The payload can also contain blank outputs in order to receive back overpaid Lightning fees.
* @param mintUrl
* @param meltPayload
* @param customRequest
* @returns
*/
static melt(mintUrl: string, meltPayload: MeltPayload, customRequest?: typeof request): Promise<MeltQuoteResponse>;
/**
* Ask mint to perform a melt operation. This pays a lightning invoice and destroys tokens matching its amount + fees
* @param meltPayload
* @returns
*/
melt(meltPayload: MeltPayload): Promise<MeltQuoteResponse>;
/**
* Checks if specific proofs have already been redeemed
* @param mintUrl
* @param checkPayload
* @param customRequest
* @returns redeemed and unredeemed ordered list of booleans
*/
static check(mintUrl: string, checkPayload: CheckStatePayload, customRequest?: typeof request): Promise<CheckStateResponse>;
/**
* Get the mints public keys
* @param mintUrl
* @param keysetId optional param to get the keys for a specific keyset. If not specified, the keys from all active keysets are fetched
* @param customRequest
* @returns
*/
static getKeys(mintUrl: string, keysetId?: string, customRequest?: typeof request): Promise<MintActiveKeys>;
/**
* Get the mints public keys
* @param keysetId optional param to get the keys for a specific keyset. If not specified, the keys from all active keysets are fetched
* @returns the mints public keys
*/
getKeys(keysetId?: string, mintUrl?: string): Promise<MintActiveKeys>;
/**
* Get the mints keysets in no specific order
* @param mintUrl
* @param customRequest
* @returns all the mints past and current keysets.
*/
static getKeySets(mintUrl: string, customRequest?: typeof request): Promise<MintAllKeysets>;
/**
* Get the mints keysets in no specific order
* @returns all the mints past and current keysets.
*/
getKeySets(): Promise<MintAllKeysets>;
/**
* Checks if specific proofs have already been redeemed
* @param checkPayload
* @returns redeemed and unredeemed ordered list of booleans
*/
check(checkPayload: CheckStatePayload): Promise<CheckStateResponse>;
static restore(mintUrl: string, restorePayload: PostRestorePayload, customRequest?: typeof request): Promise<PostRestoreResponse>;
restore(restorePayload: {
outputs: Array<SerializedBlindedMessage>;
}): Promise<PostRestoreResponse>;
}
export { CashuMint };

View File

@@ -1,544 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CashuMint = void 0;
var index_js_1 = require("./model/types/index.js");
var request_js_1 = __importDefault(require("./request.js"));
var utils_js_1 = require("./utils.js");
var nut_05_js_1 = require("./legacy/nut-05.js");
var nut_04_js_1 = require("./legacy/nut-04.js");
var nut_06_js_1 = require("./legacy/nut-06.js");
/**
* Class represents Cashu Mint API. This class contains Lower level functions that are implemented by CashuWallet.
*/
var CashuMint = /** @class */ (function () {
/**
* @param _mintUrl requires mint URL to create this object
* @param _customRequest if passed, use custom request implementation for network communication with the mint
*/
function CashuMint(_mintUrl, _customRequest) {
this._mintUrl = _mintUrl;
this._customRequest = _customRequest;
this._mintUrl = (0, utils_js_1.sanitizeUrl)(_mintUrl);
this._customRequest = _customRequest;
}
Object.defineProperty(CashuMint.prototype, "mintUrl", {
get: function () {
return this._mintUrl;
},
enumerable: false,
configurable: true
});
/**
* fetches mints info at the /info endpoint
* @param mintUrl
* @param customRequest
*/
CashuMint.getInfo = function (mintUrl, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/info')
})];
case 1:
response = _a.sent();
data = (0, nut_06_js_1.handleMintInfoContactFieldDeprecated)(response);
return [2 /*return*/, data];
}
});
});
};
/**
* fetches mints info at the /info endpoint
*/
CashuMint.prototype.getInfo = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.getInfo(this._mintUrl, this._customRequest)];
});
});
};
/**
* Performs a swap operation with ecash inputs and outputs.
* @param mintUrl
* @param swapPayload payload containing inputs and outputs
* @param customRequest
* @returns signed outputs
*/
CashuMint.swap = function (mintUrl, swapPayload, customRequest) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/swap'),
method: 'POST',
requestBody: swapPayload
})];
case 1:
data = _b.sent();
if (!(0, utils_js_1.isObj)(data) || !Array.isArray(data === null || data === void 0 ? void 0 : data.signatures)) {
throw new Error((_a = data.detail) !== null && _a !== void 0 ? _a : 'bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Performs a swap operation with ecash inputs and outputs.
* @param swapPayload payload containing inputs and outputs
* @returns signed outputs
*/
CashuMint.prototype.swap = function (swapPayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.swap(this._mintUrl, swapPayload, this._customRequest)];
});
});
};
/**
* Requests a new mint quote from the mint.
* @param mintUrl
* @param mintQuotePayload Payload for creating a new mint quote
* @param customRequest
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
CashuMint.createMintQuote = function (mintUrl, mintQuotePayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/mint/quote/bolt11'),
method: 'POST',
requestBody: mintQuotePayload
})];
case 1:
response = _a.sent();
data = (0, nut_04_js_1.handleMintQuoteResponseDeprecated)(response);
return [2 /*return*/, data];
}
});
});
};
/**
* Requests a new mint quote from the mint.
* @param mintQuotePayload Payload for creating a new mint quote
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
CashuMint.prototype.createMintQuote = function (mintQuotePayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.createMintQuote(this._mintUrl, mintQuotePayload, this._customRequest)];
});
});
};
/**
* Gets an existing mint quote from the mint.
* @param mintUrl
* @param quote Quote ID
* @param customRequest
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
CashuMint.checkMintQuote = function (mintUrl, quote, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/mint/quote/bolt11', quote),
method: 'GET'
})];
case 1:
response = _a.sent();
data = (0, nut_04_js_1.handleMintQuoteResponseDeprecated)(response);
return [2 /*return*/, data];
}
});
});
};
/**
* Gets an existing mint quote from the mint.
* @param quote Quote ID
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
CashuMint.prototype.checkMintQuote = function (quote) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.checkMintQuote(this._mintUrl, quote, this._customRequest)];
});
});
};
/**
* Mints new tokens by requesting blind signatures on the provided outputs.
* @param mintUrl
* @param mintPayload Payload containing the outputs to get blind signatures on
* @param customRequest
* @returns serialized blinded signatures
*/
CashuMint.mint = function (mintUrl, mintPayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/mint/bolt11'),
method: 'POST',
requestBody: mintPayload
})];
case 1:
data = _a.sent();
if (!(0, utils_js_1.isObj)(data) || !Array.isArray(data === null || data === void 0 ? void 0 : data.signatures)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Mints new tokens by requesting blind signatures on the provided outputs.
* @param mintPayload Payload containing the outputs to get blind signatures on
* @returns serialized blinded signatures
*/
CashuMint.prototype.mint = function (mintPayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.mint(this._mintUrl, mintPayload, this._customRequest)];
});
});
};
/**
* Requests a new melt quote from the mint.
* @param mintUrl
* @param MeltQuotePayload
* @returns
*/
CashuMint.createMeltQuote = function (mintUrl, meltQuotePayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/melt/quote/bolt11'),
method: 'POST',
requestBody: meltQuotePayload
})];
case 1:
response = _a.sent();
data = (0, nut_05_js_1.handleMeltQuoteResponseDeprecated)(response);
if (!(0, utils_js_1.isObj)(data) ||
typeof (data === null || data === void 0 ? void 0 : data.amount) !== 'number' ||
typeof (data === null || data === void 0 ? void 0 : data.fee_reserve) !== 'number' ||
typeof (data === null || data === void 0 ? void 0 : data.quote) !== 'string') {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Requests a new melt quote from the mint.
* @param MeltQuotePayload
* @returns
*/
CashuMint.prototype.createMeltQuote = function (meltQuotePayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.createMeltQuote(this._mintUrl, meltQuotePayload, this._customRequest)];
});
});
};
/**
* Gets an existing melt quote.
* @param mintUrl
* @param quote Quote ID
* @returns
*/
CashuMint.checkMeltQuote = function (mintUrl, quote, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/melt/quote/bolt11', quote),
method: 'GET'
})];
case 1:
response = _a.sent();
data = (0, nut_05_js_1.handleMeltQuoteResponseDeprecated)(response);
if (!(0, utils_js_1.isObj)(data) ||
typeof (data === null || data === void 0 ? void 0 : data.amount) !== 'number' ||
typeof (data === null || data === void 0 ? void 0 : data.fee_reserve) !== 'number' ||
typeof (data === null || data === void 0 ? void 0 : data.quote) !== 'string' ||
typeof (data === null || data === void 0 ? void 0 : data.state) !== 'string' ||
!Object.values(index_js_1.MeltQuoteState).includes(data.state)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Gets an existing melt quote.
* @param quote Quote ID
* @returns
*/
CashuMint.prototype.checkMeltQuote = function (quote) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.checkMeltQuote(this._mintUrl, quote, this._customRequest)];
});
});
};
/**
* Requests the mint to pay for a Bolt11 payment request by providing ecash as inputs to be spent. The inputs contain the amount and the fee_reserves for a Lightning payment. The payload can also contain blank outputs in order to receive back overpaid Lightning fees.
* @param mintUrl
* @param meltPayload
* @param customRequest
* @returns
*/
CashuMint.melt = function (mintUrl, meltPayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/melt/bolt11'),
method: 'POST',
requestBody: meltPayload
})];
case 1:
response = _a.sent();
data = (0, nut_05_js_1.handleMeltQuoteResponseDeprecated)(response);
if (!(0, utils_js_1.isObj)(data) ||
typeof (data === null || data === void 0 ? void 0 : data.state) !== 'string' ||
!Object.values(index_js_1.MeltQuoteState).includes(data.state)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Ask mint to perform a melt operation. This pays a lightning invoice and destroys tokens matching its amount + fees
* @param meltPayload
* @returns
*/
CashuMint.prototype.melt = function (meltPayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.melt(this._mintUrl, meltPayload, this._customRequest)];
});
});
};
/**
* Checks if specific proofs have already been redeemed
* @param mintUrl
* @param checkPayload
* @param customRequest
* @returns redeemed and unredeemed ordered list of booleans
*/
CashuMint.check = function (mintUrl, checkPayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/checkstate'),
method: 'POST',
requestBody: checkPayload
})];
case 1:
data = _a.sent();
if (!(0, utils_js_1.isObj)(data) || !Array.isArray(data === null || data === void 0 ? void 0 : data.states)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Get the mints public keys
* @param mintUrl
* @param keysetId optional param to get the keys for a specific keyset. If not specified, the keys from all active keysets are fetched
* @param customRequest
* @returns
*/
CashuMint.getKeys = function (mintUrl, keysetId, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
// backwards compatibility for base64 encoded keyset ids
if (keysetId) {
// make the keysetId url safe
keysetId = keysetId.replace(/\//g, '_').replace(/\+/g, '-');
}
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: keysetId ? (0, utils_js_1.joinUrls)(mintUrl, '/v1/keys', keysetId) : (0, utils_js_1.joinUrls)(mintUrl, '/v1/keys')
})];
case 1:
data = _a.sent();
if (!(0, utils_js_1.isObj)(data) || !Array.isArray(data.keysets)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Get the mints public keys
* @param keysetId optional param to get the keys for a specific keyset. If not specified, the keys from all active keysets are fetched
* @returns the mints public keys
*/
CashuMint.prototype.getKeys = function (keysetId, mintUrl) {
return __awaiter(this, void 0, void 0, function () {
var allKeys;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, CashuMint.getKeys(mintUrl || this._mintUrl, keysetId, this._customRequest)];
case 1:
allKeys = _a.sent();
return [2 /*return*/, allKeys];
}
});
});
};
/**
* Get the mints keysets in no specific order
* @param mintUrl
* @param customRequest
* @returns all the mints past and current keysets.
*/
CashuMint.getKeySets = function (mintUrl, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance;
return __generator(this, function (_a) {
requestInstance = customRequest || request_js_1.default;
return [2 /*return*/, requestInstance({ endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/keysets') })];
});
});
};
/**
* Get the mints keysets in no specific order
* @returns all the mints past and current keysets.
*/
CashuMint.prototype.getKeySets = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.getKeySets(this._mintUrl, this._customRequest)];
});
});
};
/**
* Checks if specific proofs have already been redeemed
* @param checkPayload
* @returns redeemed and unredeemed ordered list of booleans
*/
CashuMint.prototype.check = function (checkPayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.check(this._mintUrl, checkPayload, this._customRequest)];
});
});
};
CashuMint.restore = function (mintUrl, restorePayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request_js_1.default;
return [4 /*yield*/, requestInstance({
endpoint: (0, utils_js_1.joinUrls)(mintUrl, '/v1/restore'),
method: 'POST',
requestBody: restorePayload
})];
case 1:
data = _a.sent();
if (!(0, utils_js_1.isObj)(data) || !Array.isArray(data === null || data === void 0 ? void 0 : data.outputs) || !Array.isArray(data === null || data === void 0 ? void 0 : data.promises)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
CashuMint.prototype.restore = function (restorePayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.restore(this._mintUrl, restorePayload, this._customRequest)];
});
});
};
return CashuMint;
}());
exports.CashuMint = CashuMint;

View File

@@ -1,287 +0,0 @@
import { CashuMint } from './CashuMint.js';
import { type MeltQuoteResponse, type MintKeys, type MintKeyset, type MeltProofsResponse, type Proof, type SendResponse, type Token, GetInfoResponse, OutputAmounts, ProofState } from './model/types/index.js';
/**
* Class that represents a Cashu wallet.
* This class should act as the entry point for this library
*/
declare class CashuWallet {
private _keys;
private _keysetId;
private _keysets;
private _seed;
private _unit;
private _mintInfo;
private _denominationTarget;
mint: CashuMint;
/**
* @param mint Cashu mint instance is used to make api calls
* @param options.unit optionally set unit (default is 'sat')
* @param options.keys public keys from the mint (will be fetched from mint if not provided)
* @param options.keysets keysets from the mint (will be fetched from mint if not provided)
* @param options.mintInfo mint info from the mint (will be fetched from mint if not provided)
* @param options.denominationTarget target number proofs per denomination (default: see @constant DEFAULT_DENOMINATION_TARGET)
* @param options.bip39seed BIP39 seed for deterministic secrets.
* This can lead to poor performance, in which case the seed should be directly provided
*/
constructor(mint: CashuMint, options?: {
unit?: string;
keys?: Array<MintKeys> | MintKeys;
keysets?: Array<MintKeyset>;
mintInfo?: GetInfoResponse;
bip39seed?: Uint8Array;
denominationTarget?: number;
});
get unit(): string;
get keys(): Map<string, MintKeys>;
get keysetId(): string;
set keysetId(keysetId: string);
get keysets(): Array<MintKeyset>;
get mintInfo(): GetInfoResponse;
/**
* Get information about the mint
* @returns mint info
*/
getMintInfo(): Promise<GetInfoResponse>;
/**
* Load mint information, keysets and keys. This function can be called if no keysets are passed in the constructor
*/
loadMint(): Promise<void>;
/**
* Choose a keyset to activate based on the lowest input fee
*
* Note: this function will filter out deprecated base64 keysets
*
* @param keysets keysets to choose from
* @returns active keyset
*/
getActiveKeyset(keysets: Array<MintKeyset>): MintKeyset;
/**
* Get keysets from the mint with the unit of the wallet
* @returns keysets with wallet's unit
*/
getKeySets(): Promise<Array<MintKeyset>>;
/**
* Get all active keys from the mint and set the keyset with the lowest fees as the active wallet keyset.
* @returns keyset
*/
getAllKeys(): Promise<Array<MintKeys>>;
/**
* Get public keys from the mint. If keys were already fetched, it will return those.
*
* If `keysetId` is set, it will fetch and return that specific keyset.
* Otherwise, we select an active keyset with the unit of the wallet.
*
* @param keysetId optional keysetId to get keys for
* @param forceRefresh? if set to true, it will force refresh the keyset from the mint
* @returns keyset
*/
getKeys(keysetId?: string, forceRefresh?: boolean): Promise<MintKeys>;
/**
* Receive an encoded or raw Cashu token (only supports single tokens. It will only process the first token in the token array)
* @param {(string|Token)} token - Cashu token, either as string or decoded
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the @param token secrets if set
* @returns New token with newly created proofs, token entries that had errors
*/
receive(token: string | Token, options?: {
keysetId?: string;
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<Proof>;
counter?: number;
pubkey?: string;
privkey?: string;
}): Promise<Array<Proof>>;
/**
* Send proofs of a given amount, by providing at least the required amount of proofs
* @param amount amount to send
* @param proofs array of proofs (accumulated amount of proofs must be >= than amount)
* @param options.outputAmounts? optionally specify the output's amounts to keep and send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the output secrets if set
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.offline? optionally send proofs offline.
* @param options.includeFees? optionally include fees in the response.
* @returns {SendResponse}
*/
send(amount: number, proofs: Array<Proof>, options?: {
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<Proof>;
counter?: number;
pubkey?: string;
privkey?: string;
keysetId?: string;
offline?: boolean;
includeFees?: boolean;
}): Promise<SendResponse>;
selectProofsToSend(proofs: Array<Proof>, amountToSend: number, includeFees?: boolean): SendResponse;
/**
* calculates the fees based on inputs (proofs)
* @param proofs input proofs to calculate fees for
* @returns fee amount
*/
getFeesForProofs(proofs: Array<Proof>): number;
/**
* calculates the fees based on inputs for a given keyset
* @param nInputs number of inputs
* @param keysetId keysetId used to lookup `input_fee_ppk`
* @returns fee amount
*/
getFeesForKeyset(nInputs: number, keysetId: string): number;
/**
* Splits and creates sendable tokens
* if no amount is specified, the amount is implied by the cumulative amount of all proofs
* if both amount and preference are set, but the preference cannot fulfill the amount, then we use the default split
* @param amount amount to send while performing the optimal split (least proofs possible). can be set to undefined if preference is set
* @param proofs proofs matching that amount
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.includeFees? include estimated fees for the receiver to receive the proofs
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the @param proofs secrets if set
* @returns promise of the change- and send-proofs
*/
swap(amount: number, proofs: Array<Proof>, options?: {
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<Proof>;
counter?: number;
pubkey?: string;
privkey?: string;
keysetId?: string;
includeFees?: boolean;
}): Promise<SendResponse>;
/**
* Regenerates
* @param start set starting point for count (first cycle for each keyset should usually be 0)
* @param count set number of blinded messages that should be generated
* @param options.keysetId set a custom keysetId to restore from. keysetIds can be loaded with `CashuMint.getKeySets()`
* @returns proofs
*/
restore(start: number, count: number, options?: {
keysetId?: string;
}): Promise<{
proofs: Array<Proof>;
}>;
/**
* Requests a mint quote form the mint. Response returns a Lightning payment request for the requested given amount and unit.
* @param amount Amount requesting for mint.
* @param description optional description for the mint quote
* @returns the mint will return a mint quote with a Lightning invoice for minting tokens of the specified amount and unit
*/
createMintQuote(amount: number, description?: string): Promise<import("./model/types/index.js").MintQuoteResponse>;
/**
* Gets an existing mint quote from the mint.
* @param quote Quote ID
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
checkMintQuote(quote: string): Promise<import("./model/types/index.js").MintQuoteResponse>;
/**
* Mint proofs for a given mint quote
* @param amount amount to request
* @param quote ID of mint quote
* @param options.keysetId? optionally set keysetId for blank outputs for returned change.
* @param options.preference? Deprecated. Use `outputAmounts` instead. Optional preference for splitting proofs into specific amounts.
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns proofs
*/
mintProofs(amount: number, quote: string, options?: {
keysetId?: string;
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<Proof>;
counter?: number;
pubkey?: string;
}): Promise<{
proofs: Array<Proof>;
}>;
/**
* Requests a melt quote from the mint. Response returns amount and fees for a given unit in order to pay a Lightning invoice.
* @param invoice LN invoice that needs to get a fee estimate
* @returns the mint will create and return a melt quote for the invoice with an amount and fee reserve
*/
createMeltQuote(invoice: string): Promise<MeltQuoteResponse>;
/**
* Return an existing melt quote from the mint.
* @param quote ID of the melt quote
* @returns the mint will return an existing melt quote
*/
checkMeltQuote(quote: string): Promise<MeltQuoteResponse>;
/**
* Melt proofs for a melt quote. proofsToSend must be at least amount+fee_reserve form the melt quote. This function does not perform coin selection!.
* Returns melt quote and change proofs
* @param meltQuote ID of the melt quote
* @param proofsToSend proofs to melt
* @param options.keysetId? optionally set keysetId for blank outputs for returned change.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.privkey? optionally set a private key to unlock P2PK locked secrets
* @returns
*/
meltProofs(meltQuote: MeltQuoteResponse, proofsToSend: Array<Proof>, options?: {
keysetId?: string;
counter?: number;
privkey?: string;
}): Promise<MeltProofsResponse>;
/**
* Creates a split payload
* @param amount amount to send
* @param proofsToSend proofs to split*
* @param outputAmounts? optionally specify the output's amounts to keep and to send.
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param privkey? will create a signature on the @param proofsToSend secrets if set
* @returns
*/
private createSwapPayload;
/**
* Get an array of the states of proofs from the mint (as an array of CheckStateEnum's)
* @param proofs (only the `secret` field is required)
* @returns
*/
checkProofsStates(proofs: Array<Proof>): Promise<Array<ProofState>>;
/**
* Creates blinded messages for a given amount
* @param amount amount to create blinded messages for
* @param split optional preference for splitting proofs into specific amounts. overrides amount param
* @param keyksetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns blinded messages, secrets, rs, and amounts
*/
private createRandomBlindedMessages;
/**
* Creates blinded messages for a according to @param amounts
* @param amount array of amounts to create blinded messages for
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param keyksetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns blinded messages, secrets, rs, and amounts
*/
private createBlindedMessages;
/**
* Creates NUT-08 blank outputs (fee returns) for a given fee reserve
* See: https://github.com/cashubtc/nuts/blob/main/08.md
* @param amount amount to cover with blank outputs
* @param keysetId mint keysetId
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @returns blinded messages, secrets, and rs
*/
private createBlankOutputs;
/**
* construct proofs from @params promises, @params rs, @params secrets, and @params keyset
* @param promises array of serialized blinded signatures
* @param rs arrays of binding factors
* @param secrets array of secrets
* @param keyset mint keyset
* @returns array of serialized proofs
*/
private constructProofs;
}
export { CashuWallet };

View File

@@ -1,944 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CashuWallet = void 0;
var utils_1 = require("@noble/hashes/utils");
var BlindedMessage_js_1 = require("./model/BlindedMessage.js");
var utils_js_1 = require("./utils.js");
var common_1 = require("@cashu/crypto/modules/common");
var client_1 = require("@cashu/crypto/modules/client");
var NUT09_1 = require("@cashu/crypto/modules/client/NUT09");
var NUT11_1 = require("@cashu/crypto/modules/client/NUT11");
/**
* The default number of proofs per denomination to keep in a wallet.
*/
var DEFAULT_DENOMINATION_TARGET = 3;
/**
* The default unit for the wallet, if not specified in constructor.
*/
var DEFAULT_UNIT = 'sat';
/**
* Class that represents a Cashu wallet.
* This class should act as the entry point for this library
*/
var CashuWallet = /** @class */ (function () {
/**
* @param mint Cashu mint instance is used to make api calls
* @param options.unit optionally set unit (default is 'sat')
* @param options.keys public keys from the mint (will be fetched from mint if not provided)
* @param options.keysets keysets from the mint (will be fetched from mint if not provided)
* @param options.mintInfo mint info from the mint (will be fetched from mint if not provided)
* @param options.denominationTarget target number proofs per denomination (default: see @constant DEFAULT_DENOMINATION_TARGET)
* @param options.bip39seed BIP39 seed for deterministic secrets.
* This can lead to poor performance, in which case the seed should be directly provided
*/
function CashuWallet(mint, options) {
var _this = this;
this._keys = new Map();
this._keysets = [];
this._seed = undefined;
this._unit = DEFAULT_UNIT;
this._mintInfo = undefined;
this._denominationTarget = DEFAULT_DENOMINATION_TARGET;
this.mint = mint;
var keys = [];
if ((options === null || options === void 0 ? void 0 : options.keys) && !Array.isArray(options.keys)) {
keys = [options.keys];
}
else if ((options === null || options === void 0 ? void 0 : options.keys) && Array.isArray(options === null || options === void 0 ? void 0 : options.keys)) {
keys = options === null || options === void 0 ? void 0 : options.keys;
}
if (keys)
keys.forEach(function (key) { return _this._keys.set(key.id, key); });
if (options === null || options === void 0 ? void 0 : options.unit)
this._unit = options === null || options === void 0 ? void 0 : options.unit;
if (options === null || options === void 0 ? void 0 : options.keysets)
this._keysets = options.keysets;
if (options === null || options === void 0 ? void 0 : options.denominationTarget) {
this._denominationTarget = options.denominationTarget;
}
if (options === null || options === void 0 ? void 0 : options.bip39seed) {
if (options.bip39seed instanceof Uint8Array) {
this._seed = options.bip39seed;
return;
}
throw new Error('bip39seed must be a valid UInt8Array');
}
}
Object.defineProperty(CashuWallet.prototype, "unit", {
get: function () {
return this._unit;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CashuWallet.prototype, "keys", {
get: function () {
return this._keys;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CashuWallet.prototype, "keysetId", {
get: function () {
if (!this._keysetId) {
throw new Error('No keysetId set');
}
return this._keysetId;
},
set: function (keysetId) {
this._keysetId = keysetId;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CashuWallet.prototype, "keysets", {
get: function () {
return this._keysets;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CashuWallet.prototype, "mintInfo", {
get: function () {
if (!this._mintInfo) {
throw new Error('Mint info not loaded');
}
return this._mintInfo;
},
enumerable: false,
configurable: true
});
/**
* Get information about the mint
* @returns mint info
*/
CashuWallet.prototype.getMintInfo = function () {
return __awaiter(this, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this;
return [4 /*yield*/, this.mint.getInfo()];
case 1:
_a._mintInfo = _b.sent();
return [2 /*return*/, this._mintInfo];
}
});
});
};
/**
* Load mint information, keysets and keys. This function can be called if no keysets are passed in the constructor
*/
CashuWallet.prototype.loadMint = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getMintInfo()];
case 1:
_a.sent();
return [4 /*yield*/, this.getKeySets()];
case 2:
_a.sent();
return [4 /*yield*/, this.getKeys()];
case 3:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Choose a keyset to activate based on the lowest input fee
*
* Note: this function will filter out deprecated base64 keysets
*
* @param keysets keysets to choose from
* @returns active keyset
*/
CashuWallet.prototype.getActiveKeyset = function (keysets) {
var activeKeysets = keysets.filter(function (k) { return k.active; });
// we only consider keyset IDs that start with "00"
activeKeysets = activeKeysets.filter(function (k) { return k.id.startsWith('00'); });
var activeKeyset = activeKeysets.sort(function (a, b) { var _a, _b; return ((_a = a.input_fee_ppk) !== null && _a !== void 0 ? _a : 0) - ((_b = b.input_fee_ppk) !== null && _b !== void 0 ? _b : 0); })[0];
if (!activeKeyset) {
throw new Error('No active keyset found');
}
return activeKeyset;
};
/**
* Get keysets from the mint with the unit of the wallet
* @returns keysets with wallet's unit
*/
CashuWallet.prototype.getKeySets = function () {
return __awaiter(this, void 0, void 0, function () {
var allKeysets, unitKeysets;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.mint.getKeySets()];
case 1:
allKeysets = _a.sent();
unitKeysets = allKeysets.keysets.filter(function (k) { return k.unit === _this._unit; });
this._keysets = unitKeysets;
return [2 /*return*/, this._keysets];
}
});
});
};
/**
* Get all active keys from the mint and set the keyset with the lowest fees as the active wallet keyset.
* @returns keyset
*/
CashuWallet.prototype.getAllKeys = function () {
return __awaiter(this, void 0, void 0, function () {
var keysets;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.mint.getKeys()];
case 1:
keysets = _a.sent();
this._keys = new Map(keysets.keysets.map(function (k) { return [k.id, k]; }));
this.keysetId = this.getActiveKeyset(this._keysets).id;
return [2 /*return*/, keysets.keysets];
}
});
});
};
/**
* Get public keys from the mint. If keys were already fetched, it will return those.
*
* If `keysetId` is set, it will fetch and return that specific keyset.
* Otherwise, we select an active keyset with the unit of the wallet.
*
* @param keysetId optional keysetId to get keys for
* @param forceRefresh? if set to true, it will force refresh the keyset from the mint
* @returns keyset
*/
CashuWallet.prototype.getKeys = function (keysetId, forceRefresh) {
return __awaiter(this, void 0, void 0, function () {
var localKeyset, keys;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(!(this._keysets.length > 0) || forceRefresh)) return [3 /*break*/, 2];
return [4 /*yield*/, this.getKeySets()];
case 1:
_a.sent();
_a.label = 2;
case 2:
// no keyset id is chosen, let's choose one
if (!keysetId) {
localKeyset = this.getActiveKeyset(this._keysets);
keysetId = localKeyset.id;
}
if (!!this._keysets.find(function (k) { return k.id === keysetId; })) return [3 /*break*/, 4];
return [4 /*yield*/, this.getKeySets()];
case 3:
_a.sent();
if (!this._keysets.find(function (k) { return k.id === keysetId; })) {
throw new Error("could not initialize keys. No keyset with id '".concat(keysetId, "' found"));
}
_a.label = 4;
case 4:
if (!!this._keys.get(keysetId)) return [3 /*break*/, 6];
return [4 /*yield*/, this.mint.getKeys(keysetId)];
case 5:
keys = _a.sent();
this._keys.set(keysetId, keys.keysets[0]);
_a.label = 6;
case 6:
// set and return
this.keysetId = keysetId;
return [2 /*return*/, this._keys.get(keysetId)];
}
});
});
};
/**
* Receive an encoded or raw Cashu token (only supports single tokens. It will only process the first token in the token array)
* @param {(string|Token)} token - Cashu token, either as string or decoded
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the @param token secrets if set
* @returns New token with newly created proofs, token entries that had errors
*/
CashuWallet.prototype.receive = function (token, options) {
return __awaiter(this, void 0, void 0, function () {
var keys, amount, _a, payload, blindingData, signatures, freshProofs;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (typeof token === 'string') {
token = (0, utils_js_1.getDecodedToken)(token);
}
return [4 /*yield*/, this.getKeys(options === null || options === void 0 ? void 0 : options.keysetId)];
case 1:
keys = _b.sent();
amount = (0, utils_js_1.sumProofs)(token.proofs) - this.getFeesForProofs(token.proofs);
_a = this.createSwapPayload(amount, token.proofs, keys, options === null || options === void 0 ? void 0 : options.outputAmounts, options === null || options === void 0 ? void 0 : options.counter, options === null || options === void 0 ? void 0 : options.pubkey, options === null || options === void 0 ? void 0 : options.privkey), payload = _a.payload, blindingData = _a.blindingData;
return [4 /*yield*/, this.mint.swap(payload)];
case 2:
signatures = (_b.sent()).signatures;
freshProofs = this.constructProofs(signatures, blindingData.blindingFactors, blindingData.secrets, keys);
return [2 /*return*/, freshProofs];
}
});
});
};
/**
* Send proofs of a given amount, by providing at least the required amount of proofs
* @param amount amount to send
* @param proofs array of proofs (accumulated amount of proofs must be >= than amount)
* @param options.outputAmounts? optionally specify the output's amounts to keep and send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the output secrets if set
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.offline? optionally send proofs offline.
* @param options.includeFees? optionally include fees in the response.
* @returns {SendResponse}
*/
CashuWallet.prototype.send = function (amount, proofs, options) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var _b, keepProofsOffline, sendProofOffline, expectedFee, _c, keepProofsSelect, sendProofs, _d, keep, send, keepProofs;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
if ((0, utils_js_1.sumProofs)(proofs) < amount) {
throw new Error('Not enough funds available to send');
}
_b = this.selectProofsToSend(proofs, amount, options === null || options === void 0 ? void 0 : options.includeFees), keepProofsOffline = _b.keep, sendProofOffline = _b.send;
expectedFee = (options === null || options === void 0 ? void 0 : options.includeFees) ? this.getFeesForProofs(sendProofOffline) : 0;
if (!(!(options === null || options === void 0 ? void 0 : options.offline) &&
((0, utils_js_1.sumProofs)(sendProofOffline) != amount + expectedFee || // if the exact amount cannot be selected
(options === null || options === void 0 ? void 0 : options.outputAmounts) ||
(options === null || options === void 0 ? void 0 : options.pubkey) ||
(options === null || options === void 0 ? void 0 : options.privkey) ||
(options === null || options === void 0 ? void 0 : options.keysetId))) // these options require a swap
) return [3 /*break*/, 2]; // these options require a swap
_c = this.selectProofsToSend(proofs, amount, true), keepProofsSelect = _c.keep, sendProofs = _c.send;
(_a = options === null || options === void 0 ? void 0 : options.proofsWeHave) === null || _a === void 0 ? void 0 : _a.push.apply(_a, keepProofsSelect);
return [4 /*yield*/, this.swap(amount, sendProofs, options)];
case 1:
_d = _e.sent(), keep = _d.keep, send = _d.send;
keepProofs = keepProofsSelect.concat(keep);
return [2 /*return*/, { keep: keepProofs, send: send }];
case 2:
if ((0, utils_js_1.sumProofs)(sendProofOffline) < amount + expectedFee) {
throw new Error('Not enough funds available to send');
}
return [2 /*return*/, { keep: keepProofsOffline, send: sendProofOffline }];
}
});
});
};
CashuWallet.prototype.selectProofsToSend = function (proofs, amountToSend, includeFees) {
var sortedProofs = proofs.sort(function (a, b) { return a.amount - b.amount; });
var smallerProofs = sortedProofs
.filter(function (p) { return p.amount <= amountToSend; })
.sort(function (a, b) { return b.amount - a.amount; });
var biggerProofs = sortedProofs
.filter(function (p) { return p.amount > amountToSend; })
.sort(function (a, b) { return a.amount - b.amount; });
var nextBigger = biggerProofs[0];
if (!smallerProofs.length && nextBigger) {
return {
keep: proofs.filter(function (p) { return p.secret !== nextBigger.secret; }),
send: [nextBigger]
};
}
if (!smallerProofs.length && !nextBigger) {
return { keep: proofs, send: [] };
}
var remainder = amountToSend;
var selectedProofs = [smallerProofs[0]];
var returnedProofs = [];
var feePPK = includeFees ? this.getFeesForProofs(selectedProofs) : 0;
remainder -= selectedProofs[0].amount - feePPK / 1000;
if (remainder > 0) {
var _a = this.selectProofsToSend(smallerProofs.slice(1), remainder, includeFees), keep = _a.keep, send = _a.send;
selectedProofs.push.apply(selectedProofs, send);
returnedProofs.push.apply(returnedProofs, keep);
}
var selectedFeePPK = includeFees ? this.getFeesForProofs(selectedProofs) : 0;
if ((0, utils_js_1.sumProofs)(selectedProofs) < amountToSend + selectedFeePPK && nextBigger) {
selectedProofs = [nextBigger];
}
return {
keep: proofs.filter(function (p) { return !selectedProofs.includes(p); }),
send: selectedProofs
};
};
/**
* calculates the fees based on inputs (proofs)
* @param proofs input proofs to calculate fees for
* @returns fee amount
*/
CashuWallet.prototype.getFeesForProofs = function (proofs) {
var _this = this;
if (!this._keysets.length) {
throw new Error('Could not calculate fees. No keysets found');
}
var keysetIds = new Set(proofs.map(function (p) { return p.id; }));
keysetIds.forEach(function (id) {
if (!_this._keysets.find(function (k) { return k.id === id; })) {
throw new Error("Could not calculate fees. No keyset found with id: ".concat(id));
}
});
var fees = Math.floor(Math.max((proofs.reduce(function (total, curr) { var _a; return total + (((_a = _this._keysets.find(function (k) { return k.id === curr.id; })) === null || _a === void 0 ? void 0 : _a.input_fee_ppk) || 0); }, 0) +
999) /
1000, 0));
return fees;
};
/**
* calculates the fees based on inputs for a given keyset
* @param nInputs number of inputs
* @param keysetId keysetId used to lookup `input_fee_ppk`
* @returns fee amount
*/
CashuWallet.prototype.getFeesForKeyset = function (nInputs, keysetId) {
var _a;
var fees = Math.floor(Math.max((nInputs * (((_a = this._keysets.find(function (k) { return k.id === keysetId; })) === null || _a === void 0 ? void 0 : _a.input_fee_ppk) || 0) +
999) /
1000, 0));
return fees;
};
/**
* Splits and creates sendable tokens
* if no amount is specified, the amount is implied by the cumulative amount of all proofs
* if both amount and preference are set, but the preference cannot fulfill the amount, then we use the default split
* @param amount amount to send while performing the optimal split (least proofs possible). can be set to undefined if preference is set
* @param proofs proofs matching that amount
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.includeFees? include estimated fees for the receiver to receive the proofs
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the @param proofs secrets if set
* @returns promise of the change- and send-proofs
*/
CashuWallet.prototype.swap = function (amount, proofs, options) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function () {
var keyset, proofsToSend, amountToSend, amountAvailable, amountToKeep, sendAmounts, outputFee, sendAmountsFee, keepAmounts, _d, payload, blindingData, signatures, swapProofs, splitProofsToKeep, splitProofsToSend, amountToKeepCounter;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
if (!options)
options = {};
return [4 /*yield*/, this.getKeys(options.keysetId)];
case 1:
keyset = _e.sent();
proofsToSend = proofs;
amountToSend = amount;
amountAvailable = (0, utils_js_1.sumProofs)(proofs);
amountToKeep = amountAvailable - amountToSend - this.getFeesForProofs(proofsToSend);
sendAmounts = ((_a = options === null || options === void 0 ? void 0 : options.outputAmounts) === null || _a === void 0 ? void 0 : _a.sendAmounts) || (0, utils_js_1.splitAmount)(amountToSend, keyset.keys);
// include the fees to spend the the outputs of the swap
if (options === null || options === void 0 ? void 0 : options.includeFees) {
outputFee = this.getFeesForKeyset(sendAmounts.length, keyset.id);
sendAmountsFee = (0, utils_js_1.splitAmount)(outputFee, keyset.keys);
while (this.getFeesForKeyset(sendAmounts.concat(sendAmountsFee).length, keyset.id) > outputFee) {
outputFee++;
sendAmountsFee = (0, utils_js_1.splitAmount)(outputFee, keyset.keys);
}
sendAmounts = sendAmounts.concat(sendAmountsFee);
amountToSend += outputFee;
amountToKeep -= outputFee;
}
if (options && !((_b = options.outputAmounts) === null || _b === void 0 ? void 0 : _b.keepAmounts) && options.proofsWeHave) {
keepAmounts = (0, utils_js_1.getKeepAmounts)(options.proofsWeHave, amountToKeep, keyset.keys, this._denominationTarget);
}
else if (options.outputAmounts) {
if (((_c = options.outputAmounts.keepAmounts) === null || _c === void 0 ? void 0 : _c.reduce(function (a, b) { return a + b; }, 0)) !=
amountToKeep) {
throw new Error('Keep amounts do not match amount to keep');
}
keepAmounts = options.outputAmounts.keepAmounts;
}
if (amountToSend + this.getFeesForProofs(proofsToSend) > amountAvailable) {
console.error("Not enough funds available (".concat(amountAvailable, ") for swap amountToSend: ").concat(amountToSend, " + fee: ").concat(this.getFeesForProofs(proofsToSend), " | length: ").concat(proofsToSend.length));
throw new Error("Not enough funds available for swap");
}
if (amountToSend + this.getFeesForProofs(proofsToSend) + amountToKeep != amountAvailable) {
throw new Error('Amounts do not match for swap');
}
options.outputAmounts = {
keepAmounts: keepAmounts,
sendAmounts: sendAmounts
};
_d = this.createSwapPayload(amountToSend, proofsToSend, keyset, options === null || options === void 0 ? void 0 : options.outputAmounts, options === null || options === void 0 ? void 0 : options.counter, options === null || options === void 0 ? void 0 : options.pubkey, options === null || options === void 0 ? void 0 : options.privkey), payload = _d.payload, blindingData = _d.blindingData;
return [4 /*yield*/, this.mint.swap(payload)];
case 2:
signatures = (_e.sent()).signatures;
swapProofs = this.constructProofs(signatures, blindingData.blindingFactors, blindingData.secrets, keyset);
splitProofsToKeep = [];
splitProofsToSend = [];
amountToKeepCounter = 0;
swapProofs.forEach(function (proof) {
if (amountToKeepCounter < amountToKeep) {
amountToKeepCounter += proof.amount;
splitProofsToKeep.push(proof);
return;
}
splitProofsToSend.push(proof);
});
return [2 /*return*/, {
keep: splitProofsToKeep,
send: splitProofsToSend
}];
}
});
});
};
/**
* Regenerates
* @param start set starting point for count (first cycle for each keyset should usually be 0)
* @param count set number of blinded messages that should be generated
* @param options.keysetId set a custom keysetId to restore from. keysetIds can be loaded with `CashuMint.getKeySets()`
* @returns proofs
*/
CashuWallet.prototype.restore = function (start, count, options) {
return __awaiter(this, void 0, void 0, function () {
var keys, amounts, _a, blindedMessages, blindingFactors, secrets, _b, outputs, promises, validBlindingFactors, validSecrets;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, this.getKeys(options === null || options === void 0 ? void 0 : options.keysetId)];
case 1:
keys = _c.sent();
if (!this._seed) {
throw new Error('CashuWallet must be initialized with a seed to use restore');
}
amounts = Array(count).fill(0);
_a = this.createBlindedMessages(amounts, keys.id, start), blindedMessages = _a.blindedMessages, blindingFactors = _a.blindingFactors, secrets = _a.secrets;
return [4 /*yield*/, this.mint.restore({ outputs: blindedMessages })];
case 2:
_b = _c.sent(), outputs = _b.outputs, promises = _b.promises;
validBlindingFactors = blindingFactors.filter(function (_, i) {
return outputs.map(function (o) { return o.B_; }).includes(blindedMessages[i].B_);
});
validSecrets = secrets.filter(function (_, i) {
return outputs.map(function (o) { return o.B_; }).includes(blindedMessages[i].B_);
});
return [2 /*return*/, {
proofs: this.constructProofs(promises, validBlindingFactors, validSecrets, keys)
}];
}
});
});
};
/**
* Requests a mint quote form the mint. Response returns a Lightning payment request for the requested given amount and unit.
* @param amount Amount requesting for mint.
* @param description optional description for the mint quote
* @returns the mint will return a mint quote with a Lightning invoice for minting tokens of the specified amount and unit
*/
CashuWallet.prototype.createMintQuote = function (amount, description) {
return __awaiter(this, void 0, void 0, function () {
var mintQuotePayload;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mintQuotePayload = {
unit: this._unit,
amount: amount,
description: description
};
return [4 /*yield*/, this.mint.createMintQuote(mintQuotePayload)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Gets an existing mint quote from the mint.
* @param quote Quote ID
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
CashuWallet.prototype.checkMintQuote = function (quote) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.mint.checkMintQuote(quote)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Mint proofs for a given mint quote
* @param amount amount to request
* @param quote ID of mint quote
* @param options.keysetId? optionally set keysetId for blank outputs for returned change.
* @param options.preference? Deprecated. Use `outputAmounts` instead. Optional preference for splitting proofs into specific amounts.
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns proofs
*/
CashuWallet.prototype.mintProofs = function (amount, quote, options) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var keyset, _b, blindedMessages, secrets, blindingFactors, mintPayload, signatures;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, this.getKeys(options === null || options === void 0 ? void 0 : options.keysetId)];
case 1:
keyset = _c.sent();
if (!(options === null || options === void 0 ? void 0 : options.outputAmounts) && (options === null || options === void 0 ? void 0 : options.proofsWeHave)) {
options.outputAmounts = {
keepAmounts: (0, utils_js_1.getKeepAmounts)(options.proofsWeHave, amount, keyset.keys, this._denominationTarget),
sendAmounts: []
};
}
_b = this.createRandomBlindedMessages(amount, keyset, (_a = options === null || options === void 0 ? void 0 : options.outputAmounts) === null || _a === void 0 ? void 0 : _a.keepAmounts, options === null || options === void 0 ? void 0 : options.counter, options === null || options === void 0 ? void 0 : options.pubkey), blindedMessages = _b.blindedMessages, secrets = _b.secrets, blindingFactors = _b.blindingFactors;
mintPayload = {
outputs: blindedMessages,
quote: quote
};
return [4 /*yield*/, this.mint.mint(mintPayload)];
case 2:
signatures = (_c.sent()).signatures;
return [2 /*return*/, {
proofs: this.constructProofs(signatures, blindingFactors, secrets, keyset)
}];
}
});
});
};
/**
* Requests a melt quote from the mint. Response returns amount and fees for a given unit in order to pay a Lightning invoice.
* @param invoice LN invoice that needs to get a fee estimate
* @returns the mint will create and return a melt quote for the invoice with an amount and fee reserve
*/
CashuWallet.prototype.createMeltQuote = function (invoice) {
return __awaiter(this, void 0, void 0, function () {
var meltQuotePayload, meltQuote;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
meltQuotePayload = {
unit: this._unit,
request: invoice
};
return [4 /*yield*/, this.mint.createMeltQuote(meltQuotePayload)];
case 1:
meltQuote = _a.sent();
return [2 /*return*/, meltQuote];
}
});
});
};
/**
* Return an existing melt quote from the mint.
* @param quote ID of the melt quote
* @returns the mint will return an existing melt quote
*/
CashuWallet.prototype.checkMeltQuote = function (quote) {
return __awaiter(this, void 0, void 0, function () {
var meltQuote;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.mint.checkMeltQuote(quote)];
case 1:
meltQuote = _a.sent();
return [2 /*return*/, meltQuote];
}
});
});
};
/**
* Melt proofs for a melt quote. proofsToSend must be at least amount+fee_reserve form the melt quote. This function does not perform coin selection!.
* Returns melt quote and change proofs
* @param meltQuote ID of the melt quote
* @param proofsToSend proofs to melt
* @param options.keysetId? optionally set keysetId for blank outputs for returned change.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.privkey? optionally set a private key to unlock P2PK locked secrets
* @returns
*/
CashuWallet.prototype.meltProofs = function (meltQuote, proofsToSend, options) {
return __awaiter(this, void 0, void 0, function () {
var keys, _a, blindedMessages, secrets, blindingFactors, meltPayload, meltResponse, change;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.getKeys(options === null || options === void 0 ? void 0 : options.keysetId)];
case 1:
keys = _b.sent();
_a = this.createBlankOutputs((0, utils_js_1.sumProofs)(proofsToSend) - meltQuote.amount, keys.id, options === null || options === void 0 ? void 0 : options.counter), blindedMessages = _a.blindedMessages, secrets = _a.secrets, blindingFactors = _a.blindingFactors;
if ((options === null || options === void 0 ? void 0 : options.privkey) != undefined) {
proofsToSend = (0, NUT11_1.getSignedProofs)(proofsToSend.map(function (p) {
return {
amount: p.amount,
C: (0, common_1.pointFromHex)(p.C),
id: p.id,
secret: new TextEncoder().encode(p.secret)
};
}), options.privkey).map(function (p) { return (0, client_1.serializeProof)(p); });
}
meltPayload = {
quote: meltQuote.quote,
inputs: proofsToSend,
outputs: __spreadArray([], blindedMessages, true)
};
return [4 /*yield*/, this.mint.melt(meltPayload)];
case 2:
meltResponse = _b.sent();
change = [];
if (meltResponse.change) {
change = this.constructProofs(meltResponse.change, blindingFactors, secrets, keys);
}
return [2 /*return*/, {
quote: meltResponse,
change: change
}];
}
});
});
};
/**
* Creates a split payload
* @param amount amount to send
* @param proofsToSend proofs to split*
* @param outputAmounts? optionally specify the output's amounts to keep and to send.
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param privkey? will create a signature on the @param proofsToSend secrets if set
* @returns
*/
CashuWallet.prototype.createSwapPayload = function (amount, proofsToSend, keyset, outputAmounts, counter, pubkey, privkey) {
var totalAmount = proofsToSend.reduce(function (total, curr) { return total + curr.amount; }, 0);
if (outputAmounts && outputAmounts.sendAmounts && !outputAmounts.keepAmounts) {
outputAmounts.keepAmounts = (0, utils_js_1.splitAmount)(totalAmount - amount - this.getFeesForProofs(proofsToSend), keyset.keys);
}
var keepBlindedMessages = this.createRandomBlindedMessages(totalAmount - amount - this.getFeesForProofs(proofsToSend), keyset, outputAmounts === null || outputAmounts === void 0 ? void 0 : outputAmounts.keepAmounts, counter);
if (this._seed && counter) {
counter = counter + keepBlindedMessages.secrets.length;
}
var sendBlindedMessages = this.createRandomBlindedMessages(amount, keyset, outputAmounts === null || outputAmounts === void 0 ? void 0 : outputAmounts.sendAmounts, counter, pubkey);
if (privkey) {
proofsToSend = (0, NUT11_1.getSignedProofs)(proofsToSend.map(function (p) {
return {
amount: p.amount,
C: (0, common_1.pointFromHex)(p.C),
id: p.id,
secret: new TextEncoder().encode(p.secret)
};
}), privkey).map(function (p) { return (0, client_1.serializeProof)(p); });
}
// join keepBlindedMessages and sendBlindedMessages
var blindingData = {
blindedMessages: __spreadArray(__spreadArray([], keepBlindedMessages.blindedMessages, true), sendBlindedMessages.blindedMessages, true),
secrets: __spreadArray(__spreadArray([], keepBlindedMessages.secrets, true), sendBlindedMessages.secrets, true),
blindingFactors: __spreadArray(__spreadArray([], keepBlindedMessages.blindingFactors, true), sendBlindedMessages.blindingFactors, true)
};
var payload = {
inputs: proofsToSend,
outputs: __spreadArray([], blindingData.blindedMessages, true)
};
return { payload: payload, blindingData: blindingData };
};
/**
* Get an array of the states of proofs from the mint (as an array of CheckStateEnum's)
* @param proofs (only the `secret` field is required)
* @returns
*/
CashuWallet.prototype.checkProofsStates = function (proofs) {
return __awaiter(this, void 0, void 0, function () {
var enc, Ys, BATCH_SIZE, states, _loop_1, this_1, i;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
enc = new TextEncoder();
Ys = proofs.map(function (p) { return (0, common_1.hashToCurve)(enc.encode(p.secret)).toHex(true); });
BATCH_SIZE = 100;
states = [];
_loop_1 = function (i) {
var YsSlice, batchStates, stateMap, j, state;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
YsSlice = Ys.slice(i, i + BATCH_SIZE);
return [4 /*yield*/, this_1.mint.check({
Ys: YsSlice
})];
case 1:
batchStates = (_b.sent()).states;
stateMap = {};
batchStates.forEach(function (s) {
stateMap[s.Y] = s;
});
for (j = 0; j < YsSlice.length; j++) {
state = stateMap[YsSlice[j]];
if (!state) {
throw new Error('Could not find state for proof with Y: ' + YsSlice[j]);
}
states.push(state);
}
return [2 /*return*/];
}
});
};
this_1 = this;
i = 0;
_a.label = 1;
case 1:
if (!(i < Ys.length)) return [3 /*break*/, 4];
return [5 /*yield**/, _loop_1(i)];
case 2:
_a.sent();
_a.label = 3;
case 3:
i += BATCH_SIZE;
return [3 /*break*/, 1];
case 4: return [2 /*return*/, states];
}
});
});
};
/**
* Creates blinded messages for a given amount
* @param amount amount to create blinded messages for
* @param split optional preference for splitting proofs into specific amounts. overrides amount param
* @param keyksetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns blinded messages, secrets, rs, and amounts
*/
CashuWallet.prototype.createRandomBlindedMessages = function (amount, keyset, split, counter, pubkey) {
var amounts = (0, utils_js_1.splitAmount)(amount, keyset.keys, split);
return this.createBlindedMessages(amounts, keyset.id, counter, pubkey);
};
/**
* Creates blinded messages for a according to @param amounts
* @param amount array of amounts to create blinded messages for
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param keyksetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns blinded messages, secrets, rs, and amounts
*/
CashuWallet.prototype.createBlindedMessages = function (amounts, keysetId, counter, pubkey) {
// if we atempt to create deterministic messages without a _seed, abort.
if (counter != undefined && !this._seed) {
throw new Error('Cannot create deterministic messages without seed. Instantiate CashuWallet with a bip39seed, or omit counter param.');
}
var blindedMessages = [];
var secrets = [];
var blindingFactors = [];
for (var i = 0; i < amounts.length; i++) {
var deterministicR = undefined;
var secretBytes = undefined;
if (pubkey) {
secretBytes = (0, NUT11_1.createP2PKsecret)(pubkey);
}
else if (this._seed && counter != undefined) {
secretBytes = (0, NUT09_1.deriveSecret)(this._seed, keysetId, counter + i);
deterministicR = (0, utils_js_1.bytesToNumber)((0, NUT09_1.deriveBlindingFactor)(this._seed, keysetId, counter + i));
}
else {
secretBytes = (0, utils_1.randomBytes)(32);
}
if (!pubkey) {
var secretHex = (0, utils_1.bytesToHex)(secretBytes);
secretBytes = new TextEncoder().encode(secretHex);
}
secrets.push(secretBytes);
var _a = (0, client_1.blindMessage)(secretBytes, deterministicR), B_ = _a.B_, r = _a.r;
blindingFactors.push(r);
var blindedMessage = new BlindedMessage_js_1.BlindedMessage(amounts[i], B_, keysetId);
blindedMessages.push(blindedMessage.getSerializedBlindedMessage());
}
return { blindedMessages: blindedMessages, secrets: secrets, blindingFactors: blindingFactors, amounts: amounts };
};
/**
* Creates NUT-08 blank outputs (fee returns) for a given fee reserve
* See: https://github.com/cashubtc/nuts/blob/main/08.md
* @param amount amount to cover with blank outputs
* @param keysetId mint keysetId
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @returns blinded messages, secrets, and rs
*/
CashuWallet.prototype.createBlankOutputs = function (amount, keysetId, counter) {
var count = Math.ceil(Math.log2(amount)) || 1;
//Prevent count from being -Infinity
if (count < 0) {
count = 0;
}
var amounts = count ? Array(count).fill(1) : [];
var _a = this.createBlindedMessages(amounts, keysetId, counter), blindedMessages = _a.blindedMessages, blindingFactors = _a.blindingFactors, secrets = _a.secrets;
return { blindedMessages: blindedMessages, secrets: secrets, blindingFactors: blindingFactors };
};
/**
* construct proofs from @params promises, @params rs, @params secrets, and @params keyset
* @param promises array of serialized blinded signatures
* @param rs arrays of binding factors
* @param secrets array of secrets
* @param keyset mint keyset
* @returns array of serialized proofs
*/
CashuWallet.prototype.constructProofs = function (promises, rs, secrets, keyset) {
return promises
.map(function (p, i) {
var blindSignature = { id: p.id, amount: p.amount, C_: (0, common_1.pointFromHex)(p.C_) };
var r = rs[i];
var secret = secrets[i];
var A = (0, common_1.pointFromHex)(keyset.keys[p.amount]);
return (0, client_1.constructProofFromPromise)(blindSignature, r, secret, A);
})
.map(function (p) { return (0, client_1.serializeProof)(p); });
};
return CashuWallet;
}());
exports.CashuWallet = CashuWallet;

View File

@@ -1,6 +0,0 @@
declare function encodeUint8toBase64(uint8array: Uint8Array): string;
declare function encodeUint8toBase64Url(bytes: Uint8Array): string;
declare function encodeBase64toUint8(base64String: string): Uint8Array;
declare function encodeJsonToBase64(jsonObj: unknown): string;
declare function encodeBase64ToJson<T extends object>(base64String: string): T;
export { encodeUint8toBase64, encodeUint8toBase64Url, encodeBase64toUint8, encodeJsonToBase64, encodeBase64ToJson };

View File

@@ -1,39 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeBase64ToJson = exports.encodeJsonToBase64 = exports.encodeBase64toUint8 = exports.encodeUint8toBase64Url = exports.encodeUint8toBase64 = void 0;
var buffer_1 = require("buffer");
function encodeUint8toBase64(uint8array) {
return buffer_1.Buffer.from(uint8array).toString('base64');
}
exports.encodeUint8toBase64 = encodeUint8toBase64;
function encodeUint8toBase64Url(bytes) {
return buffer_1.Buffer.from(bytes)
.toString('base64')
.replace(/\+/g, '-') // Replace + with -
.replace(/\//g, '_') // Replace / with _
.replace(/=+$/, ''); // Remove padding characters
}
exports.encodeUint8toBase64Url = encodeUint8toBase64Url;
function encodeBase64toUint8(base64String) {
return buffer_1.Buffer.from(base64String, 'base64');
}
exports.encodeBase64toUint8 = encodeBase64toUint8;
function encodeJsonToBase64(jsonObj) {
var jsonString = JSON.stringify(jsonObj);
return base64urlFromBase64(buffer_1.Buffer.from(jsonString).toString('base64'));
}
exports.encodeJsonToBase64 = encodeJsonToBase64;
function encodeBase64ToJson(base64String) {
var jsonString = buffer_1.Buffer.from(base64urlToBase64(base64String), 'base64').toString();
var jsonObj = JSON.parse(jsonString);
return jsonObj;
}
exports.encodeBase64ToJson = encodeBase64ToJson;
function base64urlToBase64(str) {
return str.replace(/-/g, '+').replace(/_/g, '/').split('=')[0];
// .replace(/./g, '=');
}
function base64urlFromBase64(str) {
return str.replace(/\+/g, '-').replace(/\//g, '_').split('=')[0];
// .replace(/=/g, '.');
}

View File

@@ -1,9 +0,0 @@
type SimpleValue = boolean | null | undefined;
export type ResultObject = {
[key: string]: ResultValue;
};
export type ResultValue = SimpleValue | number | string | Uint8Array | Array<ResultValue> | ResultObject;
export type ValidDecodedType = Extract<ResultValue, ResultObject>;
export declare function encodeCBOR(value: any): Uint8Array;
export declare function decodeCBOR(data: Uint8Array): ResultValue;
export {};

View File

@@ -1,282 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeCBOR = exports.encodeCBOR = void 0;
function isResultKeyType(value) {
return typeof value === 'number' || typeof value === 'string';
}
function encodeCBOR(value) {
var buffer = [];
encodeItem(value, buffer);
return new Uint8Array(buffer);
}
exports.encodeCBOR = encodeCBOR;
function encodeItem(value, buffer) {
if (value === null) {
buffer.push(0xf6);
}
else if (value === undefined) {
buffer.push(0xf7);
}
else if (typeof value === 'boolean') {
buffer.push(value ? 0xf5 : 0xf4);
}
else if (typeof value === 'number') {
encodeUnsigned(value, buffer);
}
else if (typeof value === 'string') {
encodeString(value, buffer);
}
else if (Array.isArray(value)) {
encodeArray(value, buffer);
}
else if (value instanceof Uint8Array) {
encodeByteString(value, buffer);
}
else if (typeof value === 'object') {
encodeObject(value, buffer);
}
else {
throw new Error('Unsupported type');
}
}
function encodeUnsigned(value, buffer) {
if (value < 24) {
buffer.push(value);
}
else if (value < 256) {
buffer.push(0x18, value);
}
else if (value < 65536) {
buffer.push(0x19, value >> 8, value & 0xff);
}
else if (value < 4294967296) {
buffer.push(0x1a, value >> 24, (value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff);
}
else {
throw new Error('Unsupported integer size');
}
}
function encodeByteString(value, buffer) {
var length = value.length;
if (length < 24) {
buffer.push(0x40 + length);
}
else if (length < 256) {
buffer.push(0x58, length);
}
else if (length < 65536) {
buffer.push(0x59, (length >> 8) & 0xff, length & 0xff);
}
else if (length < 4294967296) {
buffer.push(0x5a, (length >> 24) & 0xff, (length >> 16) & 0xff, (length >> 8) & 0xff, length & 0xff);
}
else {
throw new Error('Byte string too long to encode');
}
for (var i = 0; i < value.length; i++) {
buffer.push(value[i]);
}
}
function encodeString(value, buffer) {
var utf8 = new TextEncoder().encode(value);
var length = utf8.length;
if (length < 24) {
buffer.push(0x60 + length);
}
else if (length < 256) {
buffer.push(0x78, length);
}
else if (length < 65536) {
buffer.push(0x79, (length >> 8) & 0xff, length & 0xff);
}
else if (length < 4294967296) {
buffer.push(0x7a, (length >> 24) & 0xff, (length >> 16) & 0xff, (length >> 8) & 0xff, length & 0xff);
}
else {
throw new Error('String too long to encode');
}
for (var i = 0; i < utf8.length; i++) {
buffer.push(utf8[i]);
}
}
function encodeArray(value, buffer) {
var length = value.length;
if (length < 24) {
buffer.push(0x80 | length);
}
else if (length < 256) {
buffer.push(0x98, length);
}
else if (length < 65536) {
buffer.push(0x99, length >> 8, length & 0xff);
}
else {
throw new Error('Unsupported array length');
}
for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
var item = value_1[_i];
encodeItem(item, buffer);
}
}
function encodeObject(value, buffer) {
var keys = Object.keys(value);
encodeUnsigned(keys.length, buffer);
buffer[buffer.length - 1] |= 0xa0;
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
encodeString(key, buffer);
encodeItem(value[key], buffer);
}
}
function decodeCBOR(data) {
var view = new DataView(data.buffer, data.byteOffset, data.byteLength);
var result = decodeItem(view, 0);
return result.value;
}
exports.decodeCBOR = decodeCBOR;
function decodeItem(view, offset) {
if (offset >= view.byteLength) {
throw new Error('Unexpected end of data');
}
var initialByte = view.getUint8(offset++);
var majorType = initialByte >> 5;
var additionalInfo = initialByte & 0x1f;
switch (majorType) {
case 0:
return decodeUnsigned(view, offset, additionalInfo);
case 1:
return decodeSigned(view, offset, additionalInfo);
case 2:
return decodeByteString(view, offset, additionalInfo);
case 3:
return decodeString(view, offset, additionalInfo);
case 4:
return decodeArray(view, offset, additionalInfo);
case 5:
return decodeMap(view, offset, additionalInfo);
case 7:
return decodeSimpleAndFloat(view, offset, additionalInfo);
default:
throw new Error("Unsupported major type: ".concat(majorType));
}
}
function decodeLength(view, offset, additionalInfo) {
if (additionalInfo < 24)
return { value: additionalInfo, offset: offset };
if (additionalInfo === 24)
return { value: view.getUint8(offset++), offset: offset };
if (additionalInfo === 25) {
var value = view.getUint16(offset, false);
offset += 2;
return { value: value, offset: offset };
}
if (additionalInfo === 26) {
var value = view.getUint32(offset, false);
offset += 4;
return { value: value, offset: offset };
}
if (additionalInfo === 27) {
var hi = view.getUint32(offset, false);
var lo = view.getUint32(offset + 4, false);
offset += 8;
return { value: hi * Math.pow(2, 32) + lo, offset: offset };
}
throw new Error("Unsupported length: ".concat(additionalInfo));
}
function decodeUnsigned(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), value = _a.value, newOffset = _a.offset;
return { value: value, offset: newOffset };
}
function decodeSigned(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), value = _a.value, newOffset = _a.offset;
return { value: -1 - value, offset: newOffset };
}
function decodeByteString(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), length = _a.value, newOffset = _a.offset;
if (newOffset + length > view.byteLength) {
throw new Error('Byte string length exceeds data length');
}
var value = new Uint8Array(view.buffer, view.byteOffset + newOffset, length);
return { value: value, offset: newOffset + length };
}
function decodeString(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), length = _a.value, newOffset = _a.offset;
if (newOffset + length > view.byteLength) {
throw new Error('String length exceeds data length');
}
var bytes = new Uint8Array(view.buffer, view.byteOffset + newOffset, length);
var value = new TextDecoder().decode(bytes);
return { value: value, offset: newOffset + length };
}
function decodeArray(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), length = _a.value, newOffset = _a.offset;
var array = [];
var currentOffset = newOffset;
for (var i = 0; i < length; i++) {
var result = decodeItem(view, currentOffset);
array.push(result.value);
currentOffset = result.offset;
}
return { value: array, offset: currentOffset };
}
function decodeMap(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), length = _a.value, newOffset = _a.offset;
var map = {};
var currentOffset = newOffset;
for (var i = 0; i < length; i++) {
var keyResult = decodeItem(view, currentOffset);
if (!isResultKeyType(keyResult.value)) {
throw new Error('Invalid key type');
}
var valueResult = decodeItem(view, keyResult.offset);
map[keyResult.value] = valueResult.value;
currentOffset = valueResult.offset;
}
return { value: map, offset: currentOffset };
}
function decodeFloat16(uint16) {
var exponent = (uint16 & 0x7c00) >> 10;
var fraction = uint16 & 0x03ff;
var sign = uint16 & 0x8000 ? -1 : 1;
if (exponent === 0) {
return sign * Math.pow(2, -14) * (fraction / 1024);
}
else if (exponent === 0x1f) {
return fraction ? NaN : sign * Infinity;
}
return sign * Math.pow(2, (exponent - 15)) * (1 + fraction / 1024);
}
function decodeSimpleAndFloat(view, offset, additionalInfo) {
if (additionalInfo < 24) {
switch (additionalInfo) {
case 20:
return { value: false, offset: offset };
case 21:
return { value: true, offset: offset };
case 22:
return { value: null, offset: offset };
case 23:
return { value: undefined, offset: offset };
default:
throw new Error("Unknown simple value: ".concat(additionalInfo));
}
}
if (additionalInfo === 24)
return { value: view.getUint8(offset++), offset: offset };
if (additionalInfo === 25) {
var value = decodeFloat16(view.getUint16(offset, false));
offset += 2;
return { value: value, offset: offset };
}
if (additionalInfo === 26) {
var value = view.getFloat32(offset, false);
offset += 4;
return { value: value, offset: offset };
}
if (additionalInfo === 27) {
var value = view.getFloat64(offset, false);
offset += 8;
return { value: value, offset: offset };
}
throw new Error("Unknown simple or float value: ".concat(additionalInfo));
}

View File

@@ -1,7 +0,0 @@
import { CashuMint } from './CashuMint.js';
import { CashuWallet } from './CashuWallet.js';
import { PaymentRequest } from './model/PaymentRequest.js';
import { setGlobalRequestOptions } from './request.js';
import { getEncodedToken, getEncodedTokenV4, getDecodedToken, deriveKeysetId, decodePaymentRequest } from './utils.js';
export * from './model/types/index.js';
export { CashuMint, CashuWallet, PaymentRequest, getDecodedToken, getEncodedToken, getEncodedTokenV4, decodePaymentRequest, deriveKeysetId, setGlobalRequestOptions };

View File

@@ -1,32 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setGlobalRequestOptions = exports.deriveKeysetId = exports.decodePaymentRequest = exports.getEncodedTokenV4 = exports.getEncodedToken = exports.getDecodedToken = exports.PaymentRequest = exports.CashuWallet = exports.CashuMint = void 0;
var CashuMint_js_1 = require("./CashuMint.js");
Object.defineProperty(exports, "CashuMint", { enumerable: true, get: function () { return CashuMint_js_1.CashuMint; } });
var CashuWallet_js_1 = require("./CashuWallet.js");
Object.defineProperty(exports, "CashuWallet", { enumerable: true, get: function () { return CashuWallet_js_1.CashuWallet; } });
var PaymentRequest_js_1 = require("./model/PaymentRequest.js");
Object.defineProperty(exports, "PaymentRequest", { enumerable: true, get: function () { return PaymentRequest_js_1.PaymentRequest; } });
var request_js_1 = require("./request.js");
Object.defineProperty(exports, "setGlobalRequestOptions", { enumerable: true, get: function () { return request_js_1.setGlobalRequestOptions; } });
var utils_js_1 = require("./utils.js");
Object.defineProperty(exports, "getEncodedToken", { enumerable: true, get: function () { return utils_js_1.getEncodedToken; } });
Object.defineProperty(exports, "getEncodedTokenV4", { enumerable: true, get: function () { return utils_js_1.getEncodedTokenV4; } });
Object.defineProperty(exports, "getDecodedToken", { enumerable: true, get: function () { return utils_js_1.getDecodedToken; } });
Object.defineProperty(exports, "deriveKeysetId", { enumerable: true, get: function () { return utils_js_1.deriveKeysetId; } });
Object.defineProperty(exports, "decodePaymentRequest", { enumerable: true, get: function () { return utils_js_1.decodePaymentRequest; } });
__exportStar(require("./model/types/index.js"), exports);

View File

@@ -1,5 +0,0 @@
import type { MintQuoteResponse } from '../model/types/index.js';
export type MintQuoteResponsePaidDeprecated = {
paid?: boolean;
};
export declare function handleMintQuoteResponseDeprecated(response: MintQuoteResponse & MintQuoteResponsePaidDeprecated): MintQuoteResponse;

View File

@@ -1,15 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleMintQuoteResponseDeprecated = void 0;
var index_js_1 = require("../model/types/index.js");
function handleMintQuoteResponseDeprecated(response) {
// if the response MeltQuoteResponse has a "paid" flag, we monkey patch it to the state enum
if (!response.state) {
console.warn("Field 'state' not found in MintQuoteResponse. Update NUT-04 of mint: https://github.com/cashubtc/nuts/pull/141)");
if (typeof response.paid === 'boolean') {
response.state = response.paid ? index_js_1.MintQuoteState.PAID : index_js_1.MintQuoteState.UNPAID;
}
}
return response;
}
exports.handleMintQuoteResponseDeprecated = handleMintQuoteResponseDeprecated;

View File

@@ -1,5 +0,0 @@
import type { MeltQuoteResponse } from '../model/types/index.js';
export type MeltQuoteResponsePaidDeprecated = {
paid?: boolean;
};
export declare function handleMeltQuoteResponseDeprecated(response: MeltQuoteResponse & MeltQuoteResponsePaidDeprecated): MeltQuoteResponse;

View File

@@ -1,15 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleMeltQuoteResponseDeprecated = void 0;
var index_js_1 = require("../model/types/index.js");
function handleMeltQuoteResponseDeprecated(response) {
// if the response MeltQuoteResponse has a "paid" flag, we monkey patch it to the state enum
if (!response.state) {
console.warn("Field 'state' not found in MeltQuoteResponse. Update NUT-05 of mint: https://github.com/cashubtc/nuts/pull/136)");
if (typeof response.paid === 'boolean') {
response.state = response.paid ? index_js_1.MeltQuoteState.PAID : index_js_1.MeltQuoteState.UNPAID;
}
}
return response;
}
exports.handleMeltQuoteResponseDeprecated = handleMeltQuoteResponseDeprecated;

View File

@@ -1,2 +0,0 @@
import type { GetInfoResponse } from '../model/types/index.js';
export declare function handleMintInfoContactFieldDeprecated(data: GetInfoResponse): GetInfoResponse;

View File

@@ -1,21 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleMintInfoContactFieldDeprecated = void 0;
function handleMintInfoContactFieldDeprecated(data) {
// Monkey patch old contact field ["email", "me@mail.com"] Array<[string, string]>; to new contact field [{method: "email", info: "me@mail.com"}] Array<MintContactInfo>
// This is to maintain backwards compatibility with older versions of the mint
if (Array.isArray(data === null || data === void 0 ? void 0 : data.contact) && (data === null || data === void 0 ? void 0 : data.contact.length) > 0) {
data.contact = data.contact.map(function (contact) {
if (Array.isArray(contact) &&
contact.length === 2 &&
typeof contact[0] === 'string' &&
typeof contact[1] === 'string') {
console.warn("Mint returned deprecated 'contact' field: Update NUT-06: https://github.com/cashubtc/nuts/pull/117");
return { method: contact[0], info: contact[1] };
}
return contact;
});
}
return data;
}
exports.handleMintInfoContactFieldDeprecated = handleMintInfoContactFieldDeprecated;

View File

@@ -1,10 +0,0 @@
import { SerializedBlindedMessage } from './types/index.js';
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
declare class BlindedMessage {
amount: number;
B_: ProjPointType<bigint>;
id: string;
constructor(amount: number, B_: ProjPointType<bigint>, id: string);
getSerializedBlindedMessage(): SerializedBlindedMessage;
}
export { BlindedMessage };

View File

@@ -1,15 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlindedMessage = void 0;
var BlindedMessage = /** @class */ (function () {
function BlindedMessage(amount, B_, id) {
this.amount = amount;
this.B_ = B_;
this.id = id;
}
BlindedMessage.prototype.getSerializedBlindedMessage = function () {
return { amount: this.amount, B_: this.B_.toHex(true), id: this.id };
};
return BlindedMessage;
}());
exports.BlindedMessage = BlindedMessage;

View File

@@ -1,10 +0,0 @@
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
import { SerializedBlindedSignature } from './types/index.js';
declare class BlindedSignature {
id: string;
amount: number;
C_: ProjPointType<bigint>;
constructor(id: string, amount: number, C_: ProjPointType<bigint>);
getSerializedBlindedSignature(): SerializedBlindedSignature;
}
export { BlindedSignature };

View File

@@ -1,15 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlindedSignature = void 0;
var BlindedSignature = /** @class */ (function () {
function BlindedSignature(id, amount, C_) {
this.id = id;
this.amount = amount;
this.C_ = C_;
}
BlindedSignature.prototype.getSerializedBlindedSignature = function () {
return { id: this.id, amount: this.amount, C_: this.C_.toHex(true) };
};
return BlindedSignature;
}());
exports.BlindedSignature = BlindedSignature;

View File

@@ -1,4 +0,0 @@
export declare class HttpResponseError extends Error {
status: number;
constructor(message: string, status: number);
}

View File

@@ -1,28 +0,0 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpResponseError = void 0;
var HttpResponseError = /** @class */ (function (_super) {
__extends(HttpResponseError, _super);
function HttpResponseError(message, status) {
var _this = _super.call(this, message) || this;
_this.status = status;
return _this;
}
return HttpResponseError;
}(Error));
exports.HttpResponseError = HttpResponseError;

View File

@@ -1,14 +0,0 @@
import { PaymentRequestTransport, PaymentRequestTransportType } from './types';
export declare class PaymentRequest {
transport: Array<PaymentRequestTransport>;
id?: string;
amount?: number;
unit?: string;
mints?: Array<string>;
description?: string;
singleUse: boolean;
constructor(transport: Array<PaymentRequestTransport>, id?: string, amount?: number, unit?: string, mints?: Array<string>, description?: string, singleUse?: boolean);
toEncodedRequest(): string;
getTransport(type: PaymentRequestTransportType): PaymentRequestTransport;
static fromEncodedRequest(encodedRequest: string): PaymentRequest;
}

View File

@@ -1,63 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PaymentRequest = void 0;
var base64_1 = require("../base64");
var cbor_1 = require("../cbor");
var buffer_1 = require("buffer");
var PaymentRequest = /** @class */ (function () {
function PaymentRequest(transport, id, amount, unit, mints, description, singleUse) {
if (singleUse === void 0) { singleUse = false; }
this.transport = transport;
this.id = id;
this.amount = amount;
this.unit = unit;
this.mints = mints;
this.description = description;
this.singleUse = singleUse;
}
PaymentRequest.prototype.toEncodedRequest = function () {
var rawRequest = {
t: this.transport.map(function (t) { return ({ t: t.type, a: t.target, g: t.tags }); })
};
if (this.id) {
rawRequest.i = this.id;
}
if (this.amount) {
rawRequest.a = this.amount;
}
if (this.unit) {
rawRequest.u = this.unit;
}
if (this.mints) {
rawRequest.m = this.mints;
}
if (this.description) {
rawRequest.d = this.description;
}
if (this.singleUse) {
rawRequest.s = this.singleUse;
}
var data = (0, cbor_1.encodeCBOR)(rawRequest);
var encodedData = buffer_1.Buffer.from(data).toString('base64');
return 'creq' + 'A' + encodedData;
};
PaymentRequest.prototype.getTransport = function (type) {
return this.transport.find(function (t) { return t.type === type; });
};
PaymentRequest.fromEncodedRequest = function (encodedRequest) {
if (!encodedRequest.startsWith('creq')) {
throw new Error('unsupported pr: invalid prefix');
}
var version = encodedRequest[4];
if (version !== 'A') {
throw new Error('unsupported pr version');
}
var encodedData = encodedRequest.slice(5);
var data = (0, base64_1.encodeBase64toUint8)(encodedData);
var decoded = (0, cbor_1.decodeCBOR)(data);
var transports = decoded.t.map(function (t) { return ({ type: t.t, target: t.a, tags: t.g }); });
return new PaymentRequest(transports, decoded.i, decoded.a, decoded.u, decoded.m, decoded.d, decoded.s);
};
return PaymentRequest;
}());
exports.PaymentRequest = PaymentRequest;

View File

@@ -1,17 +0,0 @@
import { BlindedMessage } from './BlindedMessage.js';
import { Proof } from './types/index.js';
declare class Split {
proofs: Array<Proof>;
amount: number;
outputs: Array<BlindedMessage>;
constructor(proofs: Array<Proof>, amount: number, outputs: Array<BlindedMessage>);
getSerializedSplit(): {
proofs: Proof[];
amount: number;
outputs: {
amount: number;
B_: string;
}[];
};
}
export { Split };

View File

@@ -1,21 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Split = void 0;
var Split = /** @class */ (function () {
function Split(proofs, amount, outputs) {
this.proofs = proofs;
this.amount = amount;
this.outputs = outputs;
}
Split.prototype.getSerializedSplit = function () {
return {
proofs: this.proofs,
amount: this.amount,
outputs: this.outputs.map(function (blindedMessage) {
return { amount: blindedMessage.amount, B_: blindedMessage.B_.toHex(true) };
})
};
};
return Split;
}());
exports.Split = Split;

View File

@@ -1,15 +0,0 @@
export * from './mint/index';
export * from './wallet/index';
export type OutputAmounts = {
sendAmounts: Array<number>;
keepAmounts?: Array<number>;
};
export type InvoiceData = {
paymentRequest: string;
amountInSats?: number;
amountInMSats?: number;
timestamp?: number;
paymentHash?: string;
memo?: string;
expiry?: number;
};

View File

@@ -1,18 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./mint/index"), exports);
__exportStar(require("./wallet/index"), exports);

View File

@@ -1,18 +0,0 @@
import { SerializedBlindedMessage } from '../wallet';
export * from './responses';
export * from './keys';
/**
* Payload that needs to be sent to the mint when checking for spendable proofs
*/
export type CheckStatePayload = {
/**
* The Y = hash_to_curve(secret) of the proofs to be checked.
*/
Ys: Array<string>;
};
/**
* Request to mint at /v1/restore endpoint
*/
export type PostRestorePayload = {
outputs: Array<SerializedBlindedMessage>;
};

View File

@@ -1,18 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./responses"), exports);
__exportStar(require("./keys"), exports);

View File

@@ -1,62 +0,0 @@
/**
* Public keys are a dictionary of number and string. The number represents the amount that the key signs for.
*/
export type Keys = {
[amount: number]: string;
};
/**
* An array of mint keysets
*/
export type MintActiveKeys = {
/**
* Keysets
*/
keysets: Array<MintKeys>;
};
/**
* An array of mint keyset entries.
*/
export type MintAllKeysets = {
/**
* Keysets
*/
keysets: Array<MintKeyset>;
};
/**
* A mint keyset.
*/
export type MintKeys = {
/**
* Keyset ID
*/
id: string;
/**
* Unit of the keyset.
*/
unit: string;
/**
* Public keys are a dictionary of number and string. The number represents the amount that the key signs for.
*/
keys: Keys;
};
/**
* A mint keyset entry.
*/
export type MintKeyset = {
/**
* Keyset ID
*/
id: string;
/**
* Unit of the keyset.
*/
unit: string;
/**
* Whether the keyset is active or not.
*/
active: boolean;
/**
* Input fee for keyset (in ppk)
*/
input_fee_ppk?: number;
};

View File

@@ -1,2 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -1,202 +0,0 @@
import { SerializedBlindedMessage } from '../wallet';
/**
* Cashu api error
*/
export type ApiError = {
/**
* Error message
*/
error?: string;
/**
* HTTP error code
*/
code?: number;
/**
* Detailed error message
*/
detail?: string;
};
/**
* Entries of CheckStateResponse with state of the proof
*/
export type ProofState = {
Y: string;
state: CheckStateEnum;
witness: string | null;
};
/**
* Enum for the state of a proof
*/
export declare enum CheckStateEnum {
UNSPENT = "UNSPENT",
PENDING = "PENDING",
SPENT = "SPENT"
}
/**
* Response when checking proofs if they are spendable. Should not rely on this for receiving, since it can be easily cheated.
*/
export type CheckStateResponse = {
/**
*
*/
states: Array<ProofState>;
} & ApiError;
/**
* Response from mint at /info endpoint
*/
export type GetInfoResponse = {
name: string;
pubkey: string;
version: string;
description?: string;
description_long?: string;
contact: Array<MintContactInfo>;
nuts: {
'4': {
methods: Array<SwapMethod>;
disabled: boolean;
};
'5': {
methods: Array<SwapMethod>;
disabled: boolean;
};
'7'?: {
supported: boolean;
};
'8'?: {
supported: boolean;
};
'9'?: {
supported: boolean;
};
'10'?: {
supported: boolean;
};
'11'?: {
supported: boolean;
};
'12'?: {
supported: boolean;
};
'13'?: {
supported: boolean;
};
};
motd?: string;
};
/**
* Response from the mint after requesting a melt quote
*/
export type MeltQuoteResponse = {
/**
* Quote ID
*/
quote: string;
/**
* Amount to be melted
*/
amount: number;
/**
* Fee reserve to be added to the amount
*/
fee_reserve: number;
/**
* State of the melt quote
*/
state: MeltQuoteState;
/**
* Timestamp of when the quote expires
*/
expiry: number;
/**
* preimage of the paid invoice. is null if it the invoice has not been paid yet. can be null, depending on which LN-backend the mint uses
*/
payment_preimage: string | null;
/**
* Return/Change from overpaid fees. This happens due to Lighting fee estimation being inaccurate
*/
change?: Array<SerializedBlindedSignature>;
} & ApiError;
export declare enum MeltQuoteState {
UNPAID = "UNPAID",
PENDING = "PENDING",
PAID = "PAID"
}
export type MintContactInfo = {
method: string;
info: string;
};
export declare enum MintQuoteState {
UNPAID = "UNPAID",
PAID = "PAID",
ISSUED = "ISSUED"
}
/**
* Response from the mint after requesting a mint
*/
export type MintQuoteResponse = {
/**
* Payment request
*/
request: string;
/**
* Quote ID
*/
quote: string;
/**
* State of the mint quote
*/
state: MintQuoteState;
/**
* Timestamp of when the quote expires
*/
expiry: number;
} & ApiError;
/**
* Response from the mint after requesting a mint
*/
export type MintResponse = {
signatures: Array<SerializedBlindedSignature>;
} & ApiError;
/**
* Response from mint at /v1/restore endpoint
*/
export type PostRestoreResponse = {
outputs: Array<SerializedBlindedMessage>;
promises: Array<SerializedBlindedSignature>;
};
/**
* Blinded signature as it is received from the mint
*/
export type SerializedBlindedSignature = {
/**
* keyset id for indicating which public key was used to sign the blinded message
*/
id: string;
/**
* Amount denominated in Satoshi
*/
amount: number;
/**
* Blinded signature
*/
C_: string;
};
/**
* Ecash to other MoE swap method, displayed in @type {GetInfoResponse}
*/
export type SwapMethod = {
method: string;
unit: string;
min_amount: number;
max_amount: number;
};
/**
* Response from the mint after performing a split action
*/
export type SwapResponse = {
/**
* represents the outputs after the split
*/
signatures: Array<SerializedBlindedSignature>;
} & ApiError;

View File

@@ -1,24 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MintQuoteState = exports.MeltQuoteState = exports.CheckStateEnum = void 0;
/**
* Enum for the state of a proof
*/
var CheckStateEnum;
(function (CheckStateEnum) {
CheckStateEnum["UNSPENT"] = "UNSPENT";
CheckStateEnum["PENDING"] = "PENDING";
CheckStateEnum["SPENT"] = "SPENT";
})(CheckStateEnum = exports.CheckStateEnum || (exports.CheckStateEnum = {}));
var MeltQuoteState;
(function (MeltQuoteState) {
MeltQuoteState["UNPAID"] = "UNPAID";
MeltQuoteState["PENDING"] = "PENDING";
MeltQuoteState["PAID"] = "PAID";
})(MeltQuoteState = exports.MeltQuoteState || (exports.MeltQuoteState = {}));
var MintQuoteState;
(function (MintQuoteState) {
MintQuoteState["UNPAID"] = "UNPAID";
MintQuoteState["PAID"] = "PAID";
MintQuoteState["ISSUED"] = "ISSUED";
})(MintQuoteState = exports.MintQuoteState || (exports.MintQuoteState = {}));

View File

@@ -1,58 +0,0 @@
export * from './payloads';
export * from './responses';
export * from './tokens';
export * from './paymentRequests';
/**
* represents a single Cashu proof.
*/
export type Proof = {
/**
* Keyset id, used to link proofs to a mint an its MintKeys.
*/
id: string;
/**
* Amount denominated in Satoshis. Has to match the amount of the mints signing key.
*/
amount: number;
/**
* The initial secret that was (randomly) chosen for the creation of this proof.
*/
secret: string;
/**
* The unblinded signature for this secret, signed by the mints private key.
*/
C: string;
};
/**
* response when after receiving a single TokenEntry
*/
export type ReceiveTokenEntryResponse = {
/**
* Received proofs
*/
proofs: Array<Proof>;
};
/**
* Payload that needs to be sent to the mint when paying a lightning invoice.
*/
export type PaymentPayload = {
/**
* Payment request/Lighting invoice that should get paid by the mint.
*/
pr: string;
/**
* Proofs, matching Lightning invoices amount + fees.
*/
proofs: Array<Proof>;
};
/**
* @deprecated Token V2
* should no longer be used
*/
export type TokenV2 = {
proofs: Array<Proof>;
mints: Array<{
url: string;
ids: Array<string>;
}>;
};

View File

@@ -1,20 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./payloads"), exports);
__exportStar(require("./responses"), exports);
__exportStar(require("./tokens"), exports);
__exportStar(require("./paymentRequests"), exports);

View File

@@ -1,108 +0,0 @@
import { Proof } from './index';
/**
* Data that the library needs to hold in memory while it awaits the blinded signatures for the mint. It is later used for unblinding the signatures.
*/
export type BlindingData = {
/**
* Blinded messages sent to the mint for signing.
*/
blindedMessages: Array<SerializedBlindedMessage>;
/**
* secrets, kept client side for constructing proofs later.
*/
secrets: Array<Uint8Array>;
/**
* Blinding factor used for blinding messages and unblinding signatures after they are received from the mint.
*/
blindingFactors: Array<bigint>;
};
/**
* Payload that needs to be sent to the mint when melting. Includes Return for overpaid fees
*/
export type MeltPayload = {
/**
* ID of the melt quote
*/
quote: string;
/**
* Inputs (Proofs) to be melted
*/
inputs: Array<Proof>;
/**
* Blank outputs (blinded messages) that can be filled by the mint to return overpaid fees
*/
outputs: Array<SerializedBlindedMessage>;
};
/**
* Payload that needs to be send to the mint to request a melt quote
*/
export type MeltQuotePayload = {
/**
* Unit to be melted
*/
unit: string;
/**
* Request to be melted to
*/
request: string;
};
/**
* Payload that needs to be sent to the mint when requesting a mint
*/
export type MintPayload = {
/**
* Quote ID received from the mint.
*/
quote: string;
/**
* Outputs (blinded messages) to be signed by the mint.
*/
outputs: Array<SerializedBlindedMessage>;
};
/**
* Payload that needs to be sent to the mint when requesting a mint
*/
export type MintQuotePayload = {
/**
* Unit to be minted
*/
unit: string;
/**
* Amount to be minted
*/
amount: number;
/**
* Description for the invoice
*/
description?: string;
};
/**
* Payload that needs to be sent to the mint when performing a split action
*/
export type SwapPayload = {
/**
* Inputs to the split operation
*/
inputs: Array<Proof>;
/**
* Outputs (blinded messages) to be signed by the mint
*/
outputs: Array<SerializedBlindedMessage>;
};
/**
* blinded message for sending to the mint
*/
export type SerializedBlindedMessage = {
/**
* amount
*/
amount: number;
/**
* Blinded message
*/
B_: string;
/**
* Keyset id
*/
id: string;
};

View File

@@ -1,2 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -1,31 +0,0 @@
import { Proof } from './index';
export type RawTransport = {
t: PaymentRequestTransportType;
a: string;
g?: Array<Array<string>>;
};
export type RawPaymentRequest = {
i?: string;
a?: number;
u?: string;
s?: boolean;
m?: Array<string>;
d?: string;
t: Array<RawTransport>;
};
export type PaymentRequestTransport = {
type: PaymentRequestTransportType;
target: string;
tags?: Array<Array<string>>;
};
export declare enum PaymentRequestTransportType {
POST = "post",
NOSTR = "nostr"
}
export type PaymentRequestPayload = {
id?: string;
memo?: string;
unit: string;
mint: string;
proofs: Array<Proof>;
};

View File

@@ -1,8 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PaymentRequestTransportType = void 0;
var PaymentRequestTransportType;
(function (PaymentRequestTransportType) {
PaymentRequestTransportType["POST"] = "post";
PaymentRequestTransportType["NOSTR"] = "nostr";
})(PaymentRequestTransportType = exports.PaymentRequestTransportType || (exports.PaymentRequestTransportType = {}));

View File

@@ -1,41 +0,0 @@
import { MeltQuoteResponse } from '../mint';
import { Proof, Token } from './index';
/**
* Response after paying a Lightning invoice
*/
export type MeltProofsResponse = {
/**
* if false, the proofs have not been invalidated and the payment can be tried later again with the same proofs
*/
quote: MeltQuoteResponse;
/**
* Return/Change from overpaid fees. This happens due to Lighting fee estimation being inaccurate
*/
change: Array<Proof>;
};
/**
* Response when receiving a complete token.
*/
export type ReceiveResponse = {
/**
* Successfully received Cashu Token
*/
token: Token;
/**
* TokenEntries that had errors. No error will be thrown, but clients can choose to handle tokens with errors accordingly.
*/
tokensWithErrors: Token | undefined;
};
/**
* response after sending
*/
export type SendResponse = {
/**
* Proofs that exceeded the needed amount
*/
keep: Array<Proof>;
/**
* Proofs to be sent, matching the chosen amount
*/
send: Array<Proof>;
};

View File

@@ -1,2 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -1,104 +0,0 @@
import { Proof } from './index';
/**
* A Cashu token
*/
export type Token = {
/**
* the mints URL
*/
mint: string;
/**
* a list of proofs
*/
proofs: Array<Proof>;
/**
* a message to send along with the token
*/
memo?: string;
/**
* the unit of the token
*/
unit?: string;
};
/**
* Template for a Proof inside a V4 Token
*/
export type V4ProofTemplate = {
/**
* Amount
*/
a: number;
/**
* Secret
*/
s: string;
/**
* Signature
*/
c: Uint8Array;
};
/**
* TokenEntry in a V4 Token
*/
export type V4InnerToken = {
/**
* ID
*/
i: Uint8Array;
/**
* Proofs
*/
p: Array<V4ProofTemplate>;
};
/**
* Template for a V4 Token
*/
export type TokenV4Template = {
/**
* TokenEntries
*/
t: Array<V4InnerToken>;
/**
* Memo
*/
d: string;
/**
* Mint Url
*/
m: string;
/**
* Unit
*/
u: string;
};
/**
* A Cashu token
*/
export type DeprecatedToken = {
/**
* token entries
*/
token: Array<TokenEntry>;
/**
* a message to send along with the token
*/
memo?: string;
/**
* the unit of the token
*/
unit?: string;
};
/**
* TokenEntry that stores proofs and mints
*/
type TokenEntry = {
/**
* a list of proofs
*/
proofs: Array<Proof>;
/**
* the mints URL
*/
mint: string;
};
export {};

View File

@@ -1,2 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -1,13 +0,0 @@
type RequestArgs = {
endpoint: string;
requestBody?: Record<string, unknown>;
headers?: Record<string, string>;
};
type RequestOptions = RequestArgs & Omit<RequestInit, 'body' | 'headers'>;
/**
* An object containing any custom settings that you want to apply to the global fetch method.
* @param options See possible options here: https://developer.mozilla.org/en-US/docs/Web/API/fetch#options
*/
export declare function setGlobalRequestOptions(options: Partial<RequestOptions>): void;
export default function request<T>(options: RequestOptions): Promise<T>;
export {};

View File

@@ -1,115 +0,0 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setGlobalRequestOptions = void 0;
var Errors_1 = require("./model/Errors");
var globalRequestOptions = {};
/**
* An object containing any custom settings that you want to apply to the global fetch method.
* @param options See possible options here: https://developer.mozilla.org/en-US/docs/Web/API/fetch#options
*/
function setGlobalRequestOptions(options) {
globalRequestOptions = options;
}
exports.setGlobalRequestOptions = setGlobalRequestOptions;
function _request(_a) {
var endpoint = _a.endpoint, requestBody = _a.requestBody, requestHeaders = _a.headers, options = __rest(_a, ["endpoint", "requestBody", "headers"]);
return __awaiter(this, void 0, void 0, function () {
var body, headers, response, _b, error, detail, err_1;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
body = requestBody ? JSON.stringify(requestBody) : undefined;
headers = __assign(__assign({ Accept: 'application/json, text/plain, */*' }, (body ? { 'Content-Type': 'application/json' } : undefined)), requestHeaders);
return [4 /*yield*/, fetch(endpoint, __assign({ body: body, headers: headers }, options))];
case 1:
response = _c.sent();
if (!!response.ok) return [3 /*break*/, 3];
return [4 /*yield*/, response.json().catch(function () { return ({ error: 'bad response' }); })];
case 2:
_b = _c.sent(), error = _b.error, detail = _b.detail;
throw new Errors_1.HttpResponseError(error || detail || 'bad response', response.status);
case 3:
_c.trys.push([3, 5, , 6]);
return [4 /*yield*/, response.json()];
case 4: return [2 /*return*/, _c.sent()];
case 5:
err_1 = _c.sent();
console.error('Failed to parse HTTP response', err_1);
throw new Errors_1.HttpResponseError('bad response', response.status);
case 6: return [2 /*return*/];
}
});
});
}
function request(options) {
return __awaiter(this, void 0, void 0, function () {
var data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, _request(__assign(__assign({}, options), globalRequestOptions))];
case 1:
data = _a.sent();
return [2 /*return*/, data];
}
});
});
}
exports.default = request;

View File

@@ -1,98 +0,0 @@
import { Keys, Proof, Token } from './model/types/index.js';
import { PaymentRequest } from './model/PaymentRequest.js';
/**
* Splits the amount into denominations of the provided @param keyset
* @param value amount to split
* @param keyset keys to look up split amounts
* @param split? optional custom split amounts
* @param order? optional order for split amounts (default: "asc")
* @returns Array of split amounts
* @throws Error if @param split amount is greater than @param value amount
*/
export declare function splitAmount(value: number, keyset: Keys, split?: Array<number>, order?: 'desc' | 'asc'): Array<number>;
/**
* Creates a list of amounts to keep based on the proofs we have and the proofs we want to reach.
* @param proofsWeHave complete set of proofs stored (from current mint)
* @param amountToKeep amount to keep
* @param keys keys of current keyset
* @param targetCount the target number of proofs to reach
* @returns an array of amounts to keep
*/
export declare function getKeepAmounts(proofsWeHave: Array<Proof>, amountToKeep: number, keys: Keys, targetCount: number): Array<number>;
/**
* returns the amounts in the keyset sorted by the order specified
* @param keyset to search in
* @param order order to sort the amounts in
* @returns the amounts in the keyset sorted by the order specified
*/
export declare function getKeysetAmounts(keyset: Keys, order?: 'asc' | 'desc'): Array<number>;
/**
* Checks if the provided amount is in the keyset.
* @param amount amount to check
* @param keyset to search in
* @returns true if the amount is in the keyset, false otherwise
*/
export declare function hasCorrespondingKey(amount: number, keyset: Keys): boolean;
/**
* Converts a bytes array to a number.
* @param bytes to convert to number
* @returns number
*/
export declare function bytesToNumber(bytes: Uint8Array): bigint;
/**
* Converts a hex string to a number.
* @param hex to convert to number
* @returns number
*/
export declare function hexToNumber(hex: string): bigint;
/**
* Checks wether a proof or a list of proofs contains a non-hex id
* @param p Proof or list of proofs
* @returns boolean
*/
export declare function hasNonHexId(p: Proof | Array<Proof>): boolean;
export declare function bigIntStringify<T>(_key: unknown, value: T): string | T;
/**
* Helper function to encode a v3 cashu token
* @param token to encode
* @returns encoded token
*/
export declare function getEncodedTokenV3(token: Token): string;
/**
* Helper function to encode a cashu token (defaults to v4 if keyset id allows it)
* @param token
* @param [opts]
*/
export declare function getEncodedToken(token: Token, opts?: {
version: 3 | 4;
}): string;
export declare function getEncodedTokenV4(token: Token): string;
/**
* Helper function to decode cashu tokens into object
* @param token an encoded cashu token (cashuAey...)
* @returns cashu token object
*/
export declare function getDecodedToken(token: string): Token;
/**
* Helper function to decode different versions of cashu tokens into an object
* @param token an encoded cashu token (cashuAey...)
* @returns cashu Token object
*/
export declare function handleTokens(token: string): Token;
/**
* Returns the keyset id of a set of keys
* @param keys keys object to derive keyset id from
* @returns
*/
export declare function deriveKeysetId(keys: Keys): string;
export declare function mergeUInt8Arrays(a1: Uint8Array, a2: Uint8Array): Uint8Array;
export declare function sortProofsById(proofs: Array<Proof>): Proof[];
export declare function isObj(v: unknown): v is object;
export declare function checkResponse(data: {
error?: string;
detail?: string;
}): void;
export declare function joinUrls(...parts: Array<string>): string;
export declare function sanitizeUrl(url: string): string;
export declare function sumProofs(proofs: Array<Proof>): number;
export declare function decodePaymentRequest(paymentRequest: string): PaymentRequest;

View File

@@ -1,344 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodePaymentRequest = exports.sumProofs = exports.sanitizeUrl = exports.joinUrls = exports.checkResponse = exports.isObj = exports.sortProofsById = exports.mergeUInt8Arrays = exports.deriveKeysetId = exports.handleTokens = exports.getDecodedToken = exports.getEncodedTokenV4 = exports.getEncodedToken = exports.getEncodedTokenV3 = exports.bigIntStringify = exports.hasNonHexId = exports.hexToNumber = exports.bytesToNumber = exports.hasCorrespondingKey = exports.getKeysetAmounts = exports.getKeepAmounts = exports.splitAmount = void 0;
var base64_js_1 = require("./base64.js");
var Constants_js_1 = require("./utils/Constants.js");
var utils_1 = require("@noble/curves/abstract/utils");
var sha256_1 = require("@noble/hashes/sha256");
var cbor_js_1 = require("./cbor.js");
var PaymentRequest_js_1 = require("./model/PaymentRequest.js");
/**
* Splits the amount into denominations of the provided @param keyset
* @param value amount to split
* @param keyset keys to look up split amounts
* @param split? optional custom split amounts
* @param order? optional order for split amounts (default: "asc")
* @returns Array of split amounts
* @throws Error if @param split amount is greater than @param value amount
*/
function splitAmount(value, keyset, split, order) {
if (split) {
if (split.reduce(function (a, b) { return a + b; }, 0) > value) {
throw new Error("Split is greater than total amount: ".concat(split.reduce(function (a, b) { return a + b; }, 0), " > ").concat(value));
}
split.forEach(function (amt) {
if (!hasCorrespondingKey(amt, keyset)) {
throw new Error('Provided amount preferences do not match the amounts of the mint keyset.');
}
});
value =
value -
split.reduce(function (curr, acc) {
return curr + acc;
}, 0);
}
else {
split = [];
}
var sortedKeyAmounts = getKeysetAmounts(keyset);
sortedKeyAmounts.forEach(function (amt) {
var q = Math.floor(value / amt);
for (var i = 0; i < q; ++i)
split === null || split === void 0 ? void 0 : split.push(amt);
value %= amt;
});
return split.sort(function (a, b) { return (order === 'desc' ? b - a : a - b); });
}
exports.splitAmount = splitAmount;
/**
* Creates a list of amounts to keep based on the proofs we have and the proofs we want to reach.
* @param proofsWeHave complete set of proofs stored (from current mint)
* @param amountToKeep amount to keep
* @param keys keys of current keyset
* @param targetCount the target number of proofs to reach
* @returns an array of amounts to keep
*/
function getKeepAmounts(proofsWeHave, amountToKeep, keys, targetCount) {
// determines amounts we need to reach the targetCount for each amount based on the amounts of the proofs we have
// it tries to select amounts so that the proofs we have and the proofs we want reach the targetCount
var amountsWeWant = [];
var amountsWeHave = proofsWeHave.map(function (p) { return p.amount; });
var sortedKeyAmounts = getKeysetAmounts(keys, 'asc');
sortedKeyAmounts.forEach(function (amt) {
var countWeHave = amountsWeHave.filter(function (a) { return a === amt; }).length;
var countWeWant = Math.max(targetCount - countWeHave, 0);
for (var i = 0; i < countWeWant; ++i) {
if (amountsWeWant.reduce(function (a, b) { return a + b; }, 0) + amt > amountToKeep) {
break;
}
amountsWeWant.push(amt);
}
});
// use splitAmount to fill the rest between the sum of amountsWeHave and amountToKeep
var amountDiff = amountToKeep - amountsWeWant.reduce(function (a, b) { return a + b; }, 0);
if (amountDiff) {
var remainingAmounts = splitAmount(amountDiff, keys);
remainingAmounts.forEach(function (amt) {
amountsWeWant.push(amt);
});
}
var sortedAmountsWeWant = amountsWeWant.sort(function (a, b) { return a - b; });
return sortedAmountsWeWant;
}
exports.getKeepAmounts = getKeepAmounts;
/**
* returns the amounts in the keyset sorted by the order specified
* @param keyset to search in
* @param order order to sort the amounts in
* @returns the amounts in the keyset sorted by the order specified
*/
function getKeysetAmounts(keyset, order) {
if (order === void 0) { order = 'desc'; }
if (order == 'desc') {
return Object.keys(keyset)
.map(function (k) { return parseInt(k); })
.sort(function (a, b) { return b - a; });
}
return Object.keys(keyset)
.map(function (k) { return parseInt(k); })
.sort(function (a, b) { return a - b; });
}
exports.getKeysetAmounts = getKeysetAmounts;
/**
* Checks if the provided amount is in the keyset.
* @param amount amount to check
* @param keyset to search in
* @returns true if the amount is in the keyset, false otherwise
*/
function hasCorrespondingKey(amount, keyset) {
return amount in keyset;
}
exports.hasCorrespondingKey = hasCorrespondingKey;
/**
* Converts a bytes array to a number.
* @param bytes to convert to number
* @returns number
*/
function bytesToNumber(bytes) {
return hexToNumber((0, utils_1.bytesToHex)(bytes));
}
exports.bytesToNumber = bytesToNumber;
/**
* Converts a hex string to a number.
* @param hex to convert to number
* @returns number
*/
function hexToNumber(hex) {
return BigInt("0x".concat(hex));
}
exports.hexToNumber = hexToNumber;
function isValidHex(str) {
return /^[a-f0-9]*$/i.test(str);
}
/**
* Checks wether a proof or a list of proofs contains a non-hex id
* @param p Proof or list of proofs
* @returns boolean
*/
function hasNonHexId(p) {
if (Array.isArray(p)) {
return p.some(function (proof) { return !isValidHex(proof.id); });
}
return isValidHex(p.id);
}
exports.hasNonHexId = hasNonHexId;
//used for json serialization
function bigIntStringify(_key, value) {
return typeof value === 'bigint' ? value.toString() : value;
}
exports.bigIntStringify = bigIntStringify;
/**
* Helper function to encode a v3 cashu token
* @param token to encode
* @returns encoded token
*/
function getEncodedTokenV3(token) {
var v3TokenObj = { token: [{ mint: token.mint, proofs: token.proofs }] };
if (token.unit) {
v3TokenObj.unit = token.unit;
}
if (token.memo) {
v3TokenObj.memo = token.memo;
}
return Constants_js_1.TOKEN_PREFIX + Constants_js_1.TOKEN_VERSION + (0, base64_js_1.encodeJsonToBase64)(v3TokenObj);
}
exports.getEncodedTokenV3 = getEncodedTokenV3;
/**
* Helper function to encode a cashu token (defaults to v4 if keyset id allows it)
* @param token
* @param [opts]
*/
function getEncodedToken(token, opts) {
var nonHex = hasNonHexId(token.proofs);
if (nonHex || (opts === null || opts === void 0 ? void 0 : opts.version) === 3) {
if ((opts === null || opts === void 0 ? void 0 : opts.version) === 4) {
throw new Error('can not encode to v4 token if proofs contain non-hex keyset id');
}
return getEncodedTokenV3(token);
}
return getEncodedTokenV4(token);
}
exports.getEncodedToken = getEncodedToken;
function getEncodedTokenV4(token) {
var nonHex = hasNonHexId(token.proofs);
if (nonHex) {
throw new Error('can not encode to v4 token if proofs contain non-hex keyset id');
}
var idMap = {};
var mint = token.mint;
for (var i = 0; i < token.proofs.length; i++) {
var proof = token.proofs[i];
if (idMap[proof.id]) {
idMap[proof.id].push(proof);
}
else {
idMap[proof.id] = [proof];
}
}
var tokenTemplate = {
m: mint,
u: token.unit || 'sat',
t: Object.keys(idMap).map(function (id) { return ({
i: (0, utils_1.hexToBytes)(id),
p: idMap[id].map(function (p) { return ({ a: p.amount, s: p.secret, c: (0, utils_1.hexToBytes)(p.C) }); })
}); })
};
if (token.memo) {
tokenTemplate.d = token.memo;
}
var encodedData = (0, cbor_js_1.encodeCBOR)(tokenTemplate);
var prefix = 'cashu';
var version = 'B';
var base64Data = (0, base64_js_1.encodeUint8toBase64Url)(encodedData);
return prefix + version + base64Data;
}
exports.getEncodedTokenV4 = getEncodedTokenV4;
/**
* Helper function to decode cashu tokens into object
* @param token an encoded cashu token (cashuAey...)
* @returns cashu token object
*/
function getDecodedToken(token) {
// remove prefixes
var uriPrefixes = ['web+cashu://', 'cashu://', 'cashu:', 'cashu'];
uriPrefixes.forEach(function (prefix) {
if (!token.startsWith(prefix)) {
return;
}
token = token.slice(prefix.length);
});
return handleTokens(token);
}
exports.getDecodedToken = getDecodedToken;
/**
* Helper function to decode different versions of cashu tokens into an object
* @param token an encoded cashu token (cashuAey...)
* @returns cashu Token object
*/
function handleTokens(token) {
var version = token.slice(0, 1);
var encodedToken = token.slice(1);
if (version === 'A') {
var parsedV3Token = (0, base64_js_1.encodeBase64ToJson)(encodedToken);
if (parsedV3Token.token.length > 1) {
throw new Error('Multi entry token are not supported');
}
var entry = parsedV3Token.token[0];
var tokenObj = {
mint: entry.mint,
proofs: entry.proofs,
unit: parsedV3Token.unit || 'sat'
};
if (parsedV3Token.memo) {
tokenObj.memo = parsedV3Token.memo;
}
return tokenObj;
}
else if (version === 'B') {
var uInt8Token = (0, base64_js_1.encodeBase64toUint8)(encodedToken);
var tokenData = (0, cbor_js_1.decodeCBOR)(uInt8Token);
var proofs_1 = [];
tokenData.t.forEach(function (t) {
return t.p.forEach(function (p) {
proofs_1.push({
secret: p.s,
C: (0, utils_1.bytesToHex)(p.c),
amount: p.a,
id: (0, utils_1.bytesToHex)(t.i)
});
});
});
var decodedToken = { mint: tokenData.m, proofs: proofs_1, unit: tokenData.u || 'sat' };
if (tokenData.d) {
decodedToken.memo = tokenData.d;
}
return decodedToken;
}
throw new Error('Token version is not supported');
}
exports.handleTokens = handleTokens;
/**
* Returns the keyset id of a set of keys
* @param keys keys object to derive keyset id from
* @returns
*/
function deriveKeysetId(keys) {
var pubkeysConcat = Object.entries(keys)
.sort(function (a, b) { return +a[0] - +b[0]; })
.map(function (_a) {
var pubKey = _a[1];
return (0, utils_1.hexToBytes)(pubKey);
})
.reduce(function (prev, curr) { return mergeUInt8Arrays(prev, curr); }, new Uint8Array());
var hash = (0, sha256_1.sha256)(pubkeysConcat);
var hashHex = Buffer.from(hash).toString('hex').slice(0, 14);
return '00' + hashHex;
}
exports.deriveKeysetId = deriveKeysetId;
function mergeUInt8Arrays(a1, a2) {
// sum of individual array lengths
var mergedArray = new Uint8Array(a1.length + a2.length);
mergedArray.set(a1);
mergedArray.set(a2, a1.length);
return mergedArray;
}
exports.mergeUInt8Arrays = mergeUInt8Arrays;
function sortProofsById(proofs) {
return proofs.sort(function (a, b) { return a.id.localeCompare(b.id); });
}
exports.sortProofsById = sortProofsById;
function isObj(v) {
return typeof v === 'object';
}
exports.isObj = isObj;
function checkResponse(data) {
if (!isObj(data))
return;
if ('error' in data && data.error) {
throw new Error(data.error);
}
if ('detail' in data && data.detail) {
throw new Error(data.detail);
}
}
exports.checkResponse = checkResponse;
function joinUrls() {
var parts = [];
for (var _i = 0; _i < arguments.length; _i++) {
parts[_i] = arguments[_i];
}
return parts.map(function (part) { return part.replace(/(^\/+|\/+$)/g, ''); }).join('/');
}
exports.joinUrls = joinUrls;
function sanitizeUrl(url) {
return url.replace(/\/$/, '');
}
exports.sanitizeUrl = sanitizeUrl;
function sumProofs(proofs) {
return proofs.reduce(function (acc, proof) { return acc + proof.amount; }, 0);
}
exports.sumProofs = sumProofs;
function decodePaymentRequest(paymentRequest) {
return PaymentRequest_js_1.PaymentRequest.fromEncodedRequest(paymentRequest);
}
exports.decodePaymentRequest = decodePaymentRequest;

View File

@@ -1,6 +0,0 @@
/**
* per protocol definition since tokenV3 tokens have a prefix and a version number
*/
declare const TOKEN_VERSION = "A";
declare const TOKEN_PREFIX = "cashu";
export { TOKEN_VERSION, TOKEN_PREFIX };

View File

@@ -1,10 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TOKEN_PREFIX = exports.TOKEN_VERSION = void 0;
/**
* per protocol definition since tokenV3 tokens have a prefix and a version number
*/
var TOKEN_VERSION = 'A';
exports.TOKEN_VERSION = TOKEN_VERSION;
var TOKEN_PREFIX = 'cashu';
exports.TOKEN_PREFIX = TOKEN_PREFIX;

View File

@@ -1,166 +0,0 @@
import type { CheckStatePayload, CheckStateResponse, GetInfoResponse, MeltPayload, MintActiveKeys, MintAllKeysets, PostRestoreResponse, MintQuoteResponse, SerializedBlindedMessage, SwapPayload, SwapResponse, MintQuotePayload, MintPayload, MintResponse, PostRestorePayload, MeltQuotePayload, MeltQuoteResponse } from './model/types/index.js';
import request from './request.js';
/**
* Class represents Cashu Mint API. This class contains Lower level functions that are implemented by CashuWallet.
*/
declare class CashuMint {
private _mintUrl;
private _customRequest?;
/**
* @param _mintUrl requires mint URL to create this object
* @param _customRequest if passed, use custom request implementation for network communication with the mint
*/
constructor(_mintUrl: string, _customRequest?: typeof request | undefined);
get mintUrl(): string;
/**
* fetches mints info at the /info endpoint
* @param mintUrl
* @param customRequest
*/
static getInfo(mintUrl: string, customRequest?: typeof request): Promise<GetInfoResponse>;
/**
* fetches mints info at the /info endpoint
*/
getInfo(): Promise<GetInfoResponse>;
/**
* Performs a swap operation with ecash inputs and outputs.
* @param mintUrl
* @param swapPayload payload containing inputs and outputs
* @param customRequest
* @returns signed outputs
*/
static swap(mintUrl: string, swapPayload: SwapPayload, customRequest?: typeof request): Promise<SwapResponse>;
/**
* Performs a swap operation with ecash inputs and outputs.
* @param swapPayload payload containing inputs and outputs
* @returns signed outputs
*/
swap(swapPayload: SwapPayload): Promise<SwapResponse>;
/**
* Requests a new mint quote from the mint.
* @param mintUrl
* @param mintQuotePayload Payload for creating a new mint quote
* @param customRequest
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
static createMintQuote(mintUrl: string, mintQuotePayload: MintQuotePayload, customRequest?: typeof request): Promise<MintQuoteResponse>;
/**
* Requests a new mint quote from the mint.
* @param mintQuotePayload Payload for creating a new mint quote
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
createMintQuote(mintQuotePayload: MintQuotePayload): Promise<MintQuoteResponse>;
/**
* Gets an existing mint quote from the mint.
* @param mintUrl
* @param quote Quote ID
* @param customRequest
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
static checkMintQuote(mintUrl: string, quote: string, customRequest?: typeof request): Promise<MintQuoteResponse>;
/**
* Gets an existing mint quote from the mint.
* @param quote Quote ID
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
checkMintQuote(quote: string): Promise<MintQuoteResponse>;
/**
* Mints new tokens by requesting blind signatures on the provided outputs.
* @param mintUrl
* @param mintPayload Payload containing the outputs to get blind signatures on
* @param customRequest
* @returns serialized blinded signatures
*/
static mint(mintUrl: string, mintPayload: MintPayload, customRequest?: typeof request): Promise<MintResponse>;
/**
* Mints new tokens by requesting blind signatures on the provided outputs.
* @param mintPayload Payload containing the outputs to get blind signatures on
* @returns serialized blinded signatures
*/
mint(mintPayload: MintPayload): Promise<MintResponse>;
/**
* Requests a new melt quote from the mint.
* @param mintUrl
* @param MeltQuotePayload
* @returns
*/
static createMeltQuote(mintUrl: string, meltQuotePayload: MeltQuotePayload, customRequest?: typeof request): Promise<MeltQuoteResponse>;
/**
* Requests a new melt quote from the mint.
* @param MeltQuotePayload
* @returns
*/
createMeltQuote(meltQuotePayload: MeltQuotePayload): Promise<MeltQuoteResponse>;
/**
* Gets an existing melt quote.
* @param mintUrl
* @param quote Quote ID
* @returns
*/
static checkMeltQuote(mintUrl: string, quote: string, customRequest?: typeof request): Promise<MeltQuoteResponse>;
/**
* Gets an existing melt quote.
* @param quote Quote ID
* @returns
*/
checkMeltQuote(quote: string): Promise<MeltQuoteResponse>;
/**
* Requests the mint to pay for a Bolt11 payment request by providing ecash as inputs to be spent. The inputs contain the amount and the fee_reserves for a Lightning payment. The payload can also contain blank outputs in order to receive back overpaid Lightning fees.
* @param mintUrl
* @param meltPayload
* @param customRequest
* @returns
*/
static melt(mintUrl: string, meltPayload: MeltPayload, customRequest?: typeof request): Promise<MeltQuoteResponse>;
/**
* Ask mint to perform a melt operation. This pays a lightning invoice and destroys tokens matching its amount + fees
* @param meltPayload
* @returns
*/
melt(meltPayload: MeltPayload): Promise<MeltQuoteResponse>;
/**
* Checks if specific proofs have already been redeemed
* @param mintUrl
* @param checkPayload
* @param customRequest
* @returns redeemed and unredeemed ordered list of booleans
*/
static check(mintUrl: string, checkPayload: CheckStatePayload, customRequest?: typeof request): Promise<CheckStateResponse>;
/**
* Get the mints public keys
* @param mintUrl
* @param keysetId optional param to get the keys for a specific keyset. If not specified, the keys from all active keysets are fetched
* @param customRequest
* @returns
*/
static getKeys(mintUrl: string, keysetId?: string, customRequest?: typeof request): Promise<MintActiveKeys>;
/**
* Get the mints public keys
* @param keysetId optional param to get the keys for a specific keyset. If not specified, the keys from all active keysets are fetched
* @returns the mints public keys
*/
getKeys(keysetId?: string, mintUrl?: string): Promise<MintActiveKeys>;
/**
* Get the mints keysets in no specific order
* @param mintUrl
* @param customRequest
* @returns all the mints past and current keysets.
*/
static getKeySets(mintUrl: string, customRequest?: typeof request): Promise<MintAllKeysets>;
/**
* Get the mints keysets in no specific order
* @returns all the mints past and current keysets.
*/
getKeySets(): Promise<MintAllKeysets>;
/**
* Checks if specific proofs have already been redeemed
* @param checkPayload
* @returns redeemed and unredeemed ordered list of booleans
*/
check(checkPayload: CheckStatePayload): Promise<CheckStateResponse>;
static restore(mintUrl: string, restorePayload: PostRestorePayload, customRequest?: typeof request): Promise<PostRestoreResponse>;
restore(restorePayload: {
outputs: Array<SerializedBlindedMessage>;
}): Promise<PostRestoreResponse>;
}
export { CashuMint };

View File

@@ -1,539 +0,0 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { MeltQuoteState } from './model/types/index.js';
import request from './request.js';
import { isObj, joinUrls, sanitizeUrl } from './utils.js';
import { handleMeltQuoteResponseDeprecated } from './legacy/nut-05.js';
import { handleMintQuoteResponseDeprecated } from './legacy/nut-04.js';
import { handleMintInfoContactFieldDeprecated } from './legacy/nut-06.js';
/**
* Class represents Cashu Mint API. This class contains Lower level functions that are implemented by CashuWallet.
*/
var CashuMint = /** @class */ (function () {
/**
* @param _mintUrl requires mint URL to create this object
* @param _customRequest if passed, use custom request implementation for network communication with the mint
*/
function CashuMint(_mintUrl, _customRequest) {
this._mintUrl = _mintUrl;
this._customRequest = _customRequest;
this._mintUrl = sanitizeUrl(_mintUrl);
this._customRequest = _customRequest;
}
Object.defineProperty(CashuMint.prototype, "mintUrl", {
get: function () {
return this._mintUrl;
},
enumerable: false,
configurable: true
});
/**
* fetches mints info at the /info endpoint
* @param mintUrl
* @param customRequest
*/
CashuMint.getInfo = function (mintUrl, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/info')
})];
case 1:
response = _a.sent();
data = handleMintInfoContactFieldDeprecated(response);
return [2 /*return*/, data];
}
});
});
};
/**
* fetches mints info at the /info endpoint
*/
CashuMint.prototype.getInfo = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.getInfo(this._mintUrl, this._customRequest)];
});
});
};
/**
* Performs a swap operation with ecash inputs and outputs.
* @param mintUrl
* @param swapPayload payload containing inputs and outputs
* @param customRequest
* @returns signed outputs
*/
CashuMint.swap = function (mintUrl, swapPayload, customRequest) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/swap'),
method: 'POST',
requestBody: swapPayload
})];
case 1:
data = _b.sent();
if (!isObj(data) || !Array.isArray(data === null || data === void 0 ? void 0 : data.signatures)) {
throw new Error((_a = data.detail) !== null && _a !== void 0 ? _a : 'bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Performs a swap operation with ecash inputs and outputs.
* @param swapPayload payload containing inputs and outputs
* @returns signed outputs
*/
CashuMint.prototype.swap = function (swapPayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.swap(this._mintUrl, swapPayload, this._customRequest)];
});
});
};
/**
* Requests a new mint quote from the mint.
* @param mintUrl
* @param mintQuotePayload Payload for creating a new mint quote
* @param customRequest
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
CashuMint.createMintQuote = function (mintUrl, mintQuotePayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/mint/quote/bolt11'),
method: 'POST',
requestBody: mintQuotePayload
})];
case 1:
response = _a.sent();
data = handleMintQuoteResponseDeprecated(response);
return [2 /*return*/, data];
}
});
});
};
/**
* Requests a new mint quote from the mint.
* @param mintQuotePayload Payload for creating a new mint quote
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
CashuMint.prototype.createMintQuote = function (mintQuotePayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.createMintQuote(this._mintUrl, mintQuotePayload, this._customRequest)];
});
});
};
/**
* Gets an existing mint quote from the mint.
* @param mintUrl
* @param quote Quote ID
* @param customRequest
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
CashuMint.checkMintQuote = function (mintUrl, quote, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/mint/quote/bolt11', quote),
method: 'GET'
})];
case 1:
response = _a.sent();
data = handleMintQuoteResponseDeprecated(response);
return [2 /*return*/, data];
}
});
});
};
/**
* Gets an existing mint quote from the mint.
* @param quote Quote ID
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
CashuMint.prototype.checkMintQuote = function (quote) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.checkMintQuote(this._mintUrl, quote, this._customRequest)];
});
});
};
/**
* Mints new tokens by requesting blind signatures on the provided outputs.
* @param mintUrl
* @param mintPayload Payload containing the outputs to get blind signatures on
* @param customRequest
* @returns serialized blinded signatures
*/
CashuMint.mint = function (mintUrl, mintPayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/mint/bolt11'),
method: 'POST',
requestBody: mintPayload
})];
case 1:
data = _a.sent();
if (!isObj(data) || !Array.isArray(data === null || data === void 0 ? void 0 : data.signatures)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Mints new tokens by requesting blind signatures on the provided outputs.
* @param mintPayload Payload containing the outputs to get blind signatures on
* @returns serialized blinded signatures
*/
CashuMint.prototype.mint = function (mintPayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.mint(this._mintUrl, mintPayload, this._customRequest)];
});
});
};
/**
* Requests a new melt quote from the mint.
* @param mintUrl
* @param MeltQuotePayload
* @returns
*/
CashuMint.createMeltQuote = function (mintUrl, meltQuotePayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/melt/quote/bolt11'),
method: 'POST',
requestBody: meltQuotePayload
})];
case 1:
response = _a.sent();
data = handleMeltQuoteResponseDeprecated(response);
if (!isObj(data) ||
typeof (data === null || data === void 0 ? void 0 : data.amount) !== 'number' ||
typeof (data === null || data === void 0 ? void 0 : data.fee_reserve) !== 'number' ||
typeof (data === null || data === void 0 ? void 0 : data.quote) !== 'string') {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Requests a new melt quote from the mint.
* @param MeltQuotePayload
* @returns
*/
CashuMint.prototype.createMeltQuote = function (meltQuotePayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.createMeltQuote(this._mintUrl, meltQuotePayload, this._customRequest)];
});
});
};
/**
* Gets an existing melt quote.
* @param mintUrl
* @param quote Quote ID
* @returns
*/
CashuMint.checkMeltQuote = function (mintUrl, quote, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/melt/quote/bolt11', quote),
method: 'GET'
})];
case 1:
response = _a.sent();
data = handleMeltQuoteResponseDeprecated(response);
if (!isObj(data) ||
typeof (data === null || data === void 0 ? void 0 : data.amount) !== 'number' ||
typeof (data === null || data === void 0 ? void 0 : data.fee_reserve) !== 'number' ||
typeof (data === null || data === void 0 ? void 0 : data.quote) !== 'string' ||
typeof (data === null || data === void 0 ? void 0 : data.state) !== 'string' ||
!Object.values(MeltQuoteState).includes(data.state)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Gets an existing melt quote.
* @param quote Quote ID
* @returns
*/
CashuMint.prototype.checkMeltQuote = function (quote) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.checkMeltQuote(this._mintUrl, quote, this._customRequest)];
});
});
};
/**
* Requests the mint to pay for a Bolt11 payment request by providing ecash as inputs to be spent. The inputs contain the amount and the fee_reserves for a Lightning payment. The payload can also contain blank outputs in order to receive back overpaid Lightning fees.
* @param mintUrl
* @param meltPayload
* @param customRequest
* @returns
*/
CashuMint.melt = function (mintUrl, meltPayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, response, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/melt/bolt11'),
method: 'POST',
requestBody: meltPayload
})];
case 1:
response = _a.sent();
data = handleMeltQuoteResponseDeprecated(response);
if (!isObj(data) ||
typeof (data === null || data === void 0 ? void 0 : data.state) !== 'string' ||
!Object.values(MeltQuoteState).includes(data.state)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Ask mint to perform a melt operation. This pays a lightning invoice and destroys tokens matching its amount + fees
* @param meltPayload
* @returns
*/
CashuMint.prototype.melt = function (meltPayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.melt(this._mintUrl, meltPayload, this._customRequest)];
});
});
};
/**
* Checks if specific proofs have already been redeemed
* @param mintUrl
* @param checkPayload
* @param customRequest
* @returns redeemed and unredeemed ordered list of booleans
*/
CashuMint.check = function (mintUrl, checkPayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/checkstate'),
method: 'POST',
requestBody: checkPayload
})];
case 1:
data = _a.sent();
if (!isObj(data) || !Array.isArray(data === null || data === void 0 ? void 0 : data.states)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Get the mints public keys
* @param mintUrl
* @param keysetId optional param to get the keys for a specific keyset. If not specified, the keys from all active keysets are fetched
* @param customRequest
* @returns
*/
CashuMint.getKeys = function (mintUrl, keysetId, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
// backwards compatibility for base64 encoded keyset ids
if (keysetId) {
// make the keysetId url safe
keysetId = keysetId.replace(/\//g, '_').replace(/\+/g, '-');
}
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: keysetId ? joinUrls(mintUrl, '/v1/keys', keysetId) : joinUrls(mintUrl, '/v1/keys')
})];
case 1:
data = _a.sent();
if (!isObj(data) || !Array.isArray(data.keysets)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
/**
* Get the mints public keys
* @param keysetId optional param to get the keys for a specific keyset. If not specified, the keys from all active keysets are fetched
* @returns the mints public keys
*/
CashuMint.prototype.getKeys = function (keysetId, mintUrl) {
return __awaiter(this, void 0, void 0, function () {
var allKeys;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, CashuMint.getKeys(mintUrl || this._mintUrl, keysetId, this._customRequest)];
case 1:
allKeys = _a.sent();
return [2 /*return*/, allKeys];
}
});
});
};
/**
* Get the mints keysets in no specific order
* @param mintUrl
* @param customRequest
* @returns all the mints past and current keysets.
*/
CashuMint.getKeySets = function (mintUrl, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance;
return __generator(this, function (_a) {
requestInstance = customRequest || request;
return [2 /*return*/, requestInstance({ endpoint: joinUrls(mintUrl, '/v1/keysets') })];
});
});
};
/**
* Get the mints keysets in no specific order
* @returns all the mints past and current keysets.
*/
CashuMint.prototype.getKeySets = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.getKeySets(this._mintUrl, this._customRequest)];
});
});
};
/**
* Checks if specific proofs have already been redeemed
* @param checkPayload
* @returns redeemed and unredeemed ordered list of booleans
*/
CashuMint.prototype.check = function (checkPayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.check(this._mintUrl, checkPayload, this._customRequest)];
});
});
};
CashuMint.restore = function (mintUrl, restorePayload, customRequest) {
return __awaiter(this, void 0, void 0, function () {
var requestInstance, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
requestInstance = customRequest || request;
return [4 /*yield*/, requestInstance({
endpoint: joinUrls(mintUrl, '/v1/restore'),
method: 'POST',
requestBody: restorePayload
})];
case 1:
data = _a.sent();
if (!isObj(data) || !Array.isArray(data === null || data === void 0 ? void 0 : data.outputs) || !Array.isArray(data === null || data === void 0 ? void 0 : data.promises)) {
throw new Error('bad response');
}
return [2 /*return*/, data];
}
});
});
};
CashuMint.prototype.restore = function (restorePayload) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, CashuMint.restore(this._mintUrl, restorePayload, this._customRequest)];
});
});
};
return CashuMint;
}());
export { CashuMint };
//# sourceMappingURL=CashuMint.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,287 +0,0 @@
import { CashuMint } from './CashuMint.js';
import { type MeltQuoteResponse, type MintKeys, type MintKeyset, type MeltProofsResponse, type Proof, type SendResponse, type Token, GetInfoResponse, OutputAmounts, ProofState } from './model/types/index.js';
/**
* Class that represents a Cashu wallet.
* This class should act as the entry point for this library
*/
declare class CashuWallet {
private _keys;
private _keysetId;
private _keysets;
private _seed;
private _unit;
private _mintInfo;
private _denominationTarget;
mint: CashuMint;
/**
* @param mint Cashu mint instance is used to make api calls
* @param options.unit optionally set unit (default is 'sat')
* @param options.keys public keys from the mint (will be fetched from mint if not provided)
* @param options.keysets keysets from the mint (will be fetched from mint if not provided)
* @param options.mintInfo mint info from the mint (will be fetched from mint if not provided)
* @param options.denominationTarget target number proofs per denomination (default: see @constant DEFAULT_DENOMINATION_TARGET)
* @param options.bip39seed BIP39 seed for deterministic secrets.
* This can lead to poor performance, in which case the seed should be directly provided
*/
constructor(mint: CashuMint, options?: {
unit?: string;
keys?: Array<MintKeys> | MintKeys;
keysets?: Array<MintKeyset>;
mintInfo?: GetInfoResponse;
bip39seed?: Uint8Array;
denominationTarget?: number;
});
get unit(): string;
get keys(): Map<string, MintKeys>;
get keysetId(): string;
set keysetId(keysetId: string);
get keysets(): Array<MintKeyset>;
get mintInfo(): GetInfoResponse;
/**
* Get information about the mint
* @returns mint info
*/
getMintInfo(): Promise<GetInfoResponse>;
/**
* Load mint information, keysets and keys. This function can be called if no keysets are passed in the constructor
*/
loadMint(): Promise<void>;
/**
* Choose a keyset to activate based on the lowest input fee
*
* Note: this function will filter out deprecated base64 keysets
*
* @param keysets keysets to choose from
* @returns active keyset
*/
getActiveKeyset(keysets: Array<MintKeyset>): MintKeyset;
/**
* Get keysets from the mint with the unit of the wallet
* @returns keysets with wallet's unit
*/
getKeySets(): Promise<Array<MintKeyset>>;
/**
* Get all active keys from the mint and set the keyset with the lowest fees as the active wallet keyset.
* @returns keyset
*/
getAllKeys(): Promise<Array<MintKeys>>;
/**
* Get public keys from the mint. If keys were already fetched, it will return those.
*
* If `keysetId` is set, it will fetch and return that specific keyset.
* Otherwise, we select an active keyset with the unit of the wallet.
*
* @param keysetId optional keysetId to get keys for
* @param forceRefresh? if set to true, it will force refresh the keyset from the mint
* @returns keyset
*/
getKeys(keysetId?: string, forceRefresh?: boolean): Promise<MintKeys>;
/**
* Receive an encoded or raw Cashu token (only supports single tokens. It will only process the first token in the token array)
* @param {(string|Token)} token - Cashu token, either as string or decoded
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the @param token secrets if set
* @returns New token with newly created proofs, token entries that had errors
*/
receive(token: string | Token, options?: {
keysetId?: string;
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<Proof>;
counter?: number;
pubkey?: string;
privkey?: string;
}): Promise<Array<Proof>>;
/**
* Send proofs of a given amount, by providing at least the required amount of proofs
* @param amount amount to send
* @param proofs array of proofs (accumulated amount of proofs must be >= than amount)
* @param options.outputAmounts? optionally specify the output's amounts to keep and send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the output secrets if set
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.offline? optionally send proofs offline.
* @param options.includeFees? optionally include fees in the response.
* @returns {SendResponse}
*/
send(amount: number, proofs: Array<Proof>, options?: {
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<Proof>;
counter?: number;
pubkey?: string;
privkey?: string;
keysetId?: string;
offline?: boolean;
includeFees?: boolean;
}): Promise<SendResponse>;
selectProofsToSend(proofs: Array<Proof>, amountToSend: number, includeFees?: boolean): SendResponse;
/**
* calculates the fees based on inputs (proofs)
* @param proofs input proofs to calculate fees for
* @returns fee amount
*/
getFeesForProofs(proofs: Array<Proof>): number;
/**
* calculates the fees based on inputs for a given keyset
* @param nInputs number of inputs
* @param keysetId keysetId used to lookup `input_fee_ppk`
* @returns fee amount
*/
getFeesForKeyset(nInputs: number, keysetId: string): number;
/**
* Splits and creates sendable tokens
* if no amount is specified, the amount is implied by the cumulative amount of all proofs
* if both amount and preference are set, but the preference cannot fulfill the amount, then we use the default split
* @param amount amount to send while performing the optimal split (least proofs possible). can be set to undefined if preference is set
* @param proofs proofs matching that amount
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.includeFees? include estimated fees for the receiver to receive the proofs
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the @param proofs secrets if set
* @returns promise of the change- and send-proofs
*/
swap(amount: number, proofs: Array<Proof>, options?: {
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<Proof>;
counter?: number;
pubkey?: string;
privkey?: string;
keysetId?: string;
includeFees?: boolean;
}): Promise<SendResponse>;
/**
* Regenerates
* @param start set starting point for count (first cycle for each keyset should usually be 0)
* @param count set number of blinded messages that should be generated
* @param options.keysetId set a custom keysetId to restore from. keysetIds can be loaded with `CashuMint.getKeySets()`
* @returns proofs
*/
restore(start: number, count: number, options?: {
keysetId?: string;
}): Promise<{
proofs: Array<Proof>;
}>;
/**
* Requests a mint quote form the mint. Response returns a Lightning payment request for the requested given amount and unit.
* @param amount Amount requesting for mint.
* @param description optional description for the mint quote
* @returns the mint will return a mint quote with a Lightning invoice for minting tokens of the specified amount and unit
*/
createMintQuote(amount: number, description?: string): Promise<import("./model/types/index.js").MintQuoteResponse>;
/**
* Gets an existing mint quote from the mint.
* @param quote Quote ID
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
checkMintQuote(quote: string): Promise<import("./model/types/index.js").MintQuoteResponse>;
/**
* Mint proofs for a given mint quote
* @param amount amount to request
* @param quote ID of mint quote
* @param options.keysetId? optionally set keysetId for blank outputs for returned change.
* @param options.preference? Deprecated. Use `outputAmounts` instead. Optional preference for splitting proofs into specific amounts.
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns proofs
*/
mintProofs(amount: number, quote: string, options?: {
keysetId?: string;
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<Proof>;
counter?: number;
pubkey?: string;
}): Promise<{
proofs: Array<Proof>;
}>;
/**
* Requests a melt quote from the mint. Response returns amount and fees for a given unit in order to pay a Lightning invoice.
* @param invoice LN invoice that needs to get a fee estimate
* @returns the mint will create and return a melt quote for the invoice with an amount and fee reserve
*/
createMeltQuote(invoice: string): Promise<MeltQuoteResponse>;
/**
* Return an existing melt quote from the mint.
* @param quote ID of the melt quote
* @returns the mint will return an existing melt quote
*/
checkMeltQuote(quote: string): Promise<MeltQuoteResponse>;
/**
* Melt proofs for a melt quote. proofsToSend must be at least amount+fee_reserve form the melt quote. This function does not perform coin selection!.
* Returns melt quote and change proofs
* @param meltQuote ID of the melt quote
* @param proofsToSend proofs to melt
* @param options.keysetId? optionally set keysetId for blank outputs for returned change.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.privkey? optionally set a private key to unlock P2PK locked secrets
* @returns
*/
meltProofs(meltQuote: MeltQuoteResponse, proofsToSend: Array<Proof>, options?: {
keysetId?: string;
counter?: number;
privkey?: string;
}): Promise<MeltProofsResponse>;
/**
* Creates a split payload
* @param amount amount to send
* @param proofsToSend proofs to split*
* @param outputAmounts? optionally specify the output's amounts to keep and to send.
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param privkey? will create a signature on the @param proofsToSend secrets if set
* @returns
*/
private createSwapPayload;
/**
* Get an array of the states of proofs from the mint (as an array of CheckStateEnum's)
* @param proofs (only the `secret` field is required)
* @returns
*/
checkProofsStates(proofs: Array<Proof>): Promise<Array<ProofState>>;
/**
* Creates blinded messages for a given amount
* @param amount amount to create blinded messages for
* @param split optional preference for splitting proofs into specific amounts. overrides amount param
* @param keyksetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns blinded messages, secrets, rs, and amounts
*/
private createRandomBlindedMessages;
/**
* Creates blinded messages for a according to @param amounts
* @param amount array of amounts to create blinded messages for
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param keyksetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns blinded messages, secrets, rs, and amounts
*/
private createBlindedMessages;
/**
* Creates NUT-08 blank outputs (fee returns) for a given fee reserve
* See: https://github.com/cashubtc/nuts/blob/main/08.md
* @param amount amount to cover with blank outputs
* @param keysetId mint keysetId
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @returns blinded messages, secrets, and rs
*/
private createBlankOutputs;
/**
* construct proofs from @params promises, @params rs, @params secrets, and @params keyset
* @param promises array of serialized blinded signatures
* @param rs arrays of binding factors
* @param secrets array of secrets
* @param keyset mint keyset
* @returns array of serialized proofs
*/
private constructProofs;
}
export { CashuWallet };

View File

@@ -1,942 +0,0 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import { bytesToHex, randomBytes } from '@noble/hashes/utils';
import { BlindedMessage } from './model/BlindedMessage.js';
import { bytesToNumber, getDecodedToken, splitAmount, sumProofs, getKeepAmounts } from './utils.js';
import { hashToCurve, pointFromHex } from '@cashu/crypto/modules/common';
import { blindMessage, constructProofFromPromise, serializeProof } from '@cashu/crypto/modules/client';
import { deriveBlindingFactor, deriveSecret } from '@cashu/crypto/modules/client/NUT09';
import { createP2PKsecret, getSignedProofs } from '@cashu/crypto/modules/client/NUT11';
/**
* The default number of proofs per denomination to keep in a wallet.
*/
var DEFAULT_DENOMINATION_TARGET = 3;
/**
* The default unit for the wallet, if not specified in constructor.
*/
var DEFAULT_UNIT = 'sat';
/**
* Class that represents a Cashu wallet.
* This class should act as the entry point for this library
*/
var CashuWallet = /** @class */ (function () {
/**
* @param mint Cashu mint instance is used to make api calls
* @param options.unit optionally set unit (default is 'sat')
* @param options.keys public keys from the mint (will be fetched from mint if not provided)
* @param options.keysets keysets from the mint (will be fetched from mint if not provided)
* @param options.mintInfo mint info from the mint (will be fetched from mint if not provided)
* @param options.denominationTarget target number proofs per denomination (default: see @constant DEFAULT_DENOMINATION_TARGET)
* @param options.bip39seed BIP39 seed for deterministic secrets.
* This can lead to poor performance, in which case the seed should be directly provided
*/
function CashuWallet(mint, options) {
var _this = this;
this._keys = new Map();
this._keysets = [];
this._seed = undefined;
this._unit = DEFAULT_UNIT;
this._mintInfo = undefined;
this._denominationTarget = DEFAULT_DENOMINATION_TARGET;
this.mint = mint;
var keys = [];
if ((options === null || options === void 0 ? void 0 : options.keys) && !Array.isArray(options.keys)) {
keys = [options.keys];
}
else if ((options === null || options === void 0 ? void 0 : options.keys) && Array.isArray(options === null || options === void 0 ? void 0 : options.keys)) {
keys = options === null || options === void 0 ? void 0 : options.keys;
}
if (keys)
keys.forEach(function (key) { return _this._keys.set(key.id, key); });
if (options === null || options === void 0 ? void 0 : options.unit)
this._unit = options === null || options === void 0 ? void 0 : options.unit;
if (options === null || options === void 0 ? void 0 : options.keysets)
this._keysets = options.keysets;
if (options === null || options === void 0 ? void 0 : options.denominationTarget) {
this._denominationTarget = options.denominationTarget;
}
if (options === null || options === void 0 ? void 0 : options.bip39seed) {
if (options.bip39seed instanceof Uint8Array) {
this._seed = options.bip39seed;
return;
}
throw new Error('bip39seed must be a valid UInt8Array');
}
}
Object.defineProperty(CashuWallet.prototype, "unit", {
get: function () {
return this._unit;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CashuWallet.prototype, "keys", {
get: function () {
return this._keys;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CashuWallet.prototype, "keysetId", {
get: function () {
if (!this._keysetId) {
throw new Error('No keysetId set');
}
return this._keysetId;
},
set: function (keysetId) {
this._keysetId = keysetId;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CashuWallet.prototype, "keysets", {
get: function () {
return this._keysets;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CashuWallet.prototype, "mintInfo", {
get: function () {
if (!this._mintInfo) {
throw new Error('Mint info not loaded');
}
return this._mintInfo;
},
enumerable: false,
configurable: true
});
/**
* Get information about the mint
* @returns mint info
*/
CashuWallet.prototype.getMintInfo = function () {
return __awaiter(this, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this;
return [4 /*yield*/, this.mint.getInfo()];
case 1:
_a._mintInfo = _b.sent();
return [2 /*return*/, this._mintInfo];
}
});
});
};
/**
* Load mint information, keysets and keys. This function can be called if no keysets are passed in the constructor
*/
CashuWallet.prototype.loadMint = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getMintInfo()];
case 1:
_a.sent();
return [4 /*yield*/, this.getKeySets()];
case 2:
_a.sent();
return [4 /*yield*/, this.getKeys()];
case 3:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Choose a keyset to activate based on the lowest input fee
*
* Note: this function will filter out deprecated base64 keysets
*
* @param keysets keysets to choose from
* @returns active keyset
*/
CashuWallet.prototype.getActiveKeyset = function (keysets) {
var activeKeysets = keysets.filter(function (k) { return k.active; });
// we only consider keyset IDs that start with "00"
activeKeysets = activeKeysets.filter(function (k) { return k.id.startsWith('00'); });
var activeKeyset = activeKeysets.sort(function (a, b) { var _a, _b; return ((_a = a.input_fee_ppk) !== null && _a !== void 0 ? _a : 0) - ((_b = b.input_fee_ppk) !== null && _b !== void 0 ? _b : 0); })[0];
if (!activeKeyset) {
throw new Error('No active keyset found');
}
return activeKeyset;
};
/**
* Get keysets from the mint with the unit of the wallet
* @returns keysets with wallet's unit
*/
CashuWallet.prototype.getKeySets = function () {
return __awaiter(this, void 0, void 0, function () {
var allKeysets, unitKeysets;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.mint.getKeySets()];
case 1:
allKeysets = _a.sent();
unitKeysets = allKeysets.keysets.filter(function (k) { return k.unit === _this._unit; });
this._keysets = unitKeysets;
return [2 /*return*/, this._keysets];
}
});
});
};
/**
* Get all active keys from the mint and set the keyset with the lowest fees as the active wallet keyset.
* @returns keyset
*/
CashuWallet.prototype.getAllKeys = function () {
return __awaiter(this, void 0, void 0, function () {
var keysets;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.mint.getKeys()];
case 1:
keysets = _a.sent();
this._keys = new Map(keysets.keysets.map(function (k) { return [k.id, k]; }));
this.keysetId = this.getActiveKeyset(this._keysets).id;
return [2 /*return*/, keysets.keysets];
}
});
});
};
/**
* Get public keys from the mint. If keys were already fetched, it will return those.
*
* If `keysetId` is set, it will fetch and return that specific keyset.
* Otherwise, we select an active keyset with the unit of the wallet.
*
* @param keysetId optional keysetId to get keys for
* @param forceRefresh? if set to true, it will force refresh the keyset from the mint
* @returns keyset
*/
CashuWallet.prototype.getKeys = function (keysetId, forceRefresh) {
return __awaiter(this, void 0, void 0, function () {
var localKeyset, keys;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(!(this._keysets.length > 0) || forceRefresh)) return [3 /*break*/, 2];
return [4 /*yield*/, this.getKeySets()];
case 1:
_a.sent();
_a.label = 2;
case 2:
// no keyset id is chosen, let's choose one
if (!keysetId) {
localKeyset = this.getActiveKeyset(this._keysets);
keysetId = localKeyset.id;
}
if (!!this._keysets.find(function (k) { return k.id === keysetId; })) return [3 /*break*/, 4];
return [4 /*yield*/, this.getKeySets()];
case 3:
_a.sent();
if (!this._keysets.find(function (k) { return k.id === keysetId; })) {
throw new Error("could not initialize keys. No keyset with id '".concat(keysetId, "' found"));
}
_a.label = 4;
case 4:
if (!!this._keys.get(keysetId)) return [3 /*break*/, 6];
return [4 /*yield*/, this.mint.getKeys(keysetId)];
case 5:
keys = _a.sent();
this._keys.set(keysetId, keys.keysets[0]);
_a.label = 6;
case 6:
// set and return
this.keysetId = keysetId;
return [2 /*return*/, this._keys.get(keysetId)];
}
});
});
};
/**
* Receive an encoded or raw Cashu token (only supports single tokens. It will only process the first token in the token array)
* @param {(string|Token)} token - Cashu token, either as string or decoded
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the @param token secrets if set
* @returns New token with newly created proofs, token entries that had errors
*/
CashuWallet.prototype.receive = function (token, options) {
return __awaiter(this, void 0, void 0, function () {
var keys, amount, _a, payload, blindingData, signatures, freshProofs;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (typeof token === 'string') {
token = getDecodedToken(token);
}
return [4 /*yield*/, this.getKeys(options === null || options === void 0 ? void 0 : options.keysetId)];
case 1:
keys = _b.sent();
amount = sumProofs(token.proofs) - this.getFeesForProofs(token.proofs);
_a = this.createSwapPayload(amount, token.proofs, keys, options === null || options === void 0 ? void 0 : options.outputAmounts, options === null || options === void 0 ? void 0 : options.counter, options === null || options === void 0 ? void 0 : options.pubkey, options === null || options === void 0 ? void 0 : options.privkey), payload = _a.payload, blindingData = _a.blindingData;
return [4 /*yield*/, this.mint.swap(payload)];
case 2:
signatures = (_b.sent()).signatures;
freshProofs = this.constructProofs(signatures, blindingData.blindingFactors, blindingData.secrets, keys);
return [2 /*return*/, freshProofs];
}
});
});
};
/**
* Send proofs of a given amount, by providing at least the required amount of proofs
* @param amount amount to send
* @param proofs array of proofs (accumulated amount of proofs must be >= than amount)
* @param options.outputAmounts? optionally specify the output's amounts to keep and send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the output secrets if set
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.offline? optionally send proofs offline.
* @param options.includeFees? optionally include fees in the response.
* @returns {SendResponse}
*/
CashuWallet.prototype.send = function (amount, proofs, options) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var _b, keepProofsOffline, sendProofOffline, expectedFee, _c, keepProofsSelect, sendProofs, _d, keep, send, keepProofs;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
if (sumProofs(proofs) < amount) {
throw new Error('Not enough funds available to send');
}
_b = this.selectProofsToSend(proofs, amount, options === null || options === void 0 ? void 0 : options.includeFees), keepProofsOffline = _b.keep, sendProofOffline = _b.send;
expectedFee = (options === null || options === void 0 ? void 0 : options.includeFees) ? this.getFeesForProofs(sendProofOffline) : 0;
if (!(!(options === null || options === void 0 ? void 0 : options.offline) &&
(sumProofs(sendProofOffline) != amount + expectedFee || // if the exact amount cannot be selected
(options === null || options === void 0 ? void 0 : options.outputAmounts) ||
(options === null || options === void 0 ? void 0 : options.pubkey) ||
(options === null || options === void 0 ? void 0 : options.privkey) ||
(options === null || options === void 0 ? void 0 : options.keysetId))) // these options require a swap
) return [3 /*break*/, 2]; // these options require a swap
_c = this.selectProofsToSend(proofs, amount, true), keepProofsSelect = _c.keep, sendProofs = _c.send;
(_a = options === null || options === void 0 ? void 0 : options.proofsWeHave) === null || _a === void 0 ? void 0 : _a.push.apply(_a, keepProofsSelect);
return [4 /*yield*/, this.swap(amount, sendProofs, options)];
case 1:
_d = _e.sent(), keep = _d.keep, send = _d.send;
keepProofs = keepProofsSelect.concat(keep);
return [2 /*return*/, { keep: keepProofs, send: send }];
case 2:
if (sumProofs(sendProofOffline) < amount + expectedFee) {
throw new Error('Not enough funds available to send');
}
return [2 /*return*/, { keep: keepProofsOffline, send: sendProofOffline }];
}
});
});
};
CashuWallet.prototype.selectProofsToSend = function (proofs, amountToSend, includeFees) {
var sortedProofs = proofs.sort(function (a, b) { return a.amount - b.amount; });
var smallerProofs = sortedProofs
.filter(function (p) { return p.amount <= amountToSend; })
.sort(function (a, b) { return b.amount - a.amount; });
var biggerProofs = sortedProofs
.filter(function (p) { return p.amount > amountToSend; })
.sort(function (a, b) { return a.amount - b.amount; });
var nextBigger = biggerProofs[0];
if (!smallerProofs.length && nextBigger) {
return {
keep: proofs.filter(function (p) { return p.secret !== nextBigger.secret; }),
send: [nextBigger]
};
}
if (!smallerProofs.length && !nextBigger) {
return { keep: proofs, send: [] };
}
var remainder = amountToSend;
var selectedProofs = [smallerProofs[0]];
var returnedProofs = [];
var feePPK = includeFees ? this.getFeesForProofs(selectedProofs) : 0;
remainder -= selectedProofs[0].amount - feePPK / 1000;
if (remainder > 0) {
var _a = this.selectProofsToSend(smallerProofs.slice(1), remainder, includeFees), keep = _a.keep, send = _a.send;
selectedProofs.push.apply(selectedProofs, send);
returnedProofs.push.apply(returnedProofs, keep);
}
var selectedFeePPK = includeFees ? this.getFeesForProofs(selectedProofs) : 0;
if (sumProofs(selectedProofs) < amountToSend + selectedFeePPK && nextBigger) {
selectedProofs = [nextBigger];
}
return {
keep: proofs.filter(function (p) { return !selectedProofs.includes(p); }),
send: selectedProofs
};
};
/**
* calculates the fees based on inputs (proofs)
* @param proofs input proofs to calculate fees for
* @returns fee amount
*/
CashuWallet.prototype.getFeesForProofs = function (proofs) {
var _this = this;
if (!this._keysets.length) {
throw new Error('Could not calculate fees. No keysets found');
}
var keysetIds = new Set(proofs.map(function (p) { return p.id; }));
keysetIds.forEach(function (id) {
if (!_this._keysets.find(function (k) { return k.id === id; })) {
throw new Error("Could not calculate fees. No keyset found with id: ".concat(id));
}
});
var fees = Math.floor(Math.max((proofs.reduce(function (total, curr) { var _a; return total + (((_a = _this._keysets.find(function (k) { return k.id === curr.id; })) === null || _a === void 0 ? void 0 : _a.input_fee_ppk) || 0); }, 0) +
999) /
1000, 0));
return fees;
};
/**
* calculates the fees based on inputs for a given keyset
* @param nInputs number of inputs
* @param keysetId keysetId used to lookup `input_fee_ppk`
* @returns fee amount
*/
CashuWallet.prototype.getFeesForKeyset = function (nInputs, keysetId) {
var _a;
var fees = Math.floor(Math.max((nInputs * (((_a = this._keysets.find(function (k) { return k.id === keysetId; })) === null || _a === void 0 ? void 0 : _a.input_fee_ppk) || 0) +
999) /
1000, 0));
return fees;
};
/**
* Splits and creates sendable tokens
* if no amount is specified, the amount is implied by the cumulative amount of all proofs
* if both amount and preference are set, but the preference cannot fulfill the amount, then we use the default split
* @param amount amount to send while performing the optimal split (least proofs possible). can be set to undefined if preference is set
* @param proofs proofs matching that amount
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.keysetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param options.includeFees? include estimated fees for the receiver to receive the proofs
* @param options.proofsWeHave? optionally provide all currently stored proofs of this mint. Cashu-ts will use them to derive the optimal output amounts
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param options.privkey? will create a signature on the @param proofs secrets if set
* @returns promise of the change- and send-proofs
*/
CashuWallet.prototype.swap = function (amount, proofs, options) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function () {
var keyset, proofsToSend, amountToSend, amountAvailable, amountToKeep, sendAmounts, outputFee, sendAmountsFee, keepAmounts, _d, payload, blindingData, signatures, swapProofs, splitProofsToKeep, splitProofsToSend, amountToKeepCounter;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
if (!options)
options = {};
return [4 /*yield*/, this.getKeys(options.keysetId)];
case 1:
keyset = _e.sent();
proofsToSend = proofs;
amountToSend = amount;
amountAvailable = sumProofs(proofs);
amountToKeep = amountAvailable - amountToSend - this.getFeesForProofs(proofsToSend);
sendAmounts = ((_a = options === null || options === void 0 ? void 0 : options.outputAmounts) === null || _a === void 0 ? void 0 : _a.sendAmounts) || splitAmount(amountToSend, keyset.keys);
// include the fees to spend the the outputs of the swap
if (options === null || options === void 0 ? void 0 : options.includeFees) {
outputFee = this.getFeesForKeyset(sendAmounts.length, keyset.id);
sendAmountsFee = splitAmount(outputFee, keyset.keys);
while (this.getFeesForKeyset(sendAmounts.concat(sendAmountsFee).length, keyset.id) > outputFee) {
outputFee++;
sendAmountsFee = splitAmount(outputFee, keyset.keys);
}
sendAmounts = sendAmounts.concat(sendAmountsFee);
amountToSend += outputFee;
amountToKeep -= outputFee;
}
if (options && !((_b = options.outputAmounts) === null || _b === void 0 ? void 0 : _b.keepAmounts) && options.proofsWeHave) {
keepAmounts = getKeepAmounts(options.proofsWeHave, amountToKeep, keyset.keys, this._denominationTarget);
}
else if (options.outputAmounts) {
if (((_c = options.outputAmounts.keepAmounts) === null || _c === void 0 ? void 0 : _c.reduce(function (a, b) { return a + b; }, 0)) !=
amountToKeep) {
throw new Error('Keep amounts do not match amount to keep');
}
keepAmounts = options.outputAmounts.keepAmounts;
}
if (amountToSend + this.getFeesForProofs(proofsToSend) > amountAvailable) {
console.error("Not enough funds available (".concat(amountAvailable, ") for swap amountToSend: ").concat(amountToSend, " + fee: ").concat(this.getFeesForProofs(proofsToSend), " | length: ").concat(proofsToSend.length));
throw new Error("Not enough funds available for swap");
}
if (amountToSend + this.getFeesForProofs(proofsToSend) + amountToKeep != amountAvailable) {
throw new Error('Amounts do not match for swap');
}
options.outputAmounts = {
keepAmounts: keepAmounts,
sendAmounts: sendAmounts
};
_d = this.createSwapPayload(amountToSend, proofsToSend, keyset, options === null || options === void 0 ? void 0 : options.outputAmounts, options === null || options === void 0 ? void 0 : options.counter, options === null || options === void 0 ? void 0 : options.pubkey, options === null || options === void 0 ? void 0 : options.privkey), payload = _d.payload, blindingData = _d.blindingData;
return [4 /*yield*/, this.mint.swap(payload)];
case 2:
signatures = (_e.sent()).signatures;
swapProofs = this.constructProofs(signatures, blindingData.blindingFactors, blindingData.secrets, keyset);
splitProofsToKeep = [];
splitProofsToSend = [];
amountToKeepCounter = 0;
swapProofs.forEach(function (proof) {
if (amountToKeepCounter < amountToKeep) {
amountToKeepCounter += proof.amount;
splitProofsToKeep.push(proof);
return;
}
splitProofsToSend.push(proof);
});
return [2 /*return*/, {
keep: splitProofsToKeep,
send: splitProofsToSend
}];
}
});
});
};
/**
* Regenerates
* @param start set starting point for count (first cycle for each keyset should usually be 0)
* @param count set number of blinded messages that should be generated
* @param options.keysetId set a custom keysetId to restore from. keysetIds can be loaded with `CashuMint.getKeySets()`
* @returns proofs
*/
CashuWallet.prototype.restore = function (start, count, options) {
return __awaiter(this, void 0, void 0, function () {
var keys, amounts, _a, blindedMessages, blindingFactors, secrets, _b, outputs, promises, validBlindingFactors, validSecrets;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, this.getKeys(options === null || options === void 0 ? void 0 : options.keysetId)];
case 1:
keys = _c.sent();
if (!this._seed) {
throw new Error('CashuWallet must be initialized with a seed to use restore');
}
amounts = Array(count).fill(0);
_a = this.createBlindedMessages(amounts, keys.id, start), blindedMessages = _a.blindedMessages, blindingFactors = _a.blindingFactors, secrets = _a.secrets;
return [4 /*yield*/, this.mint.restore({ outputs: blindedMessages })];
case 2:
_b = _c.sent(), outputs = _b.outputs, promises = _b.promises;
validBlindingFactors = blindingFactors.filter(function (_, i) {
return outputs.map(function (o) { return o.B_; }).includes(blindedMessages[i].B_);
});
validSecrets = secrets.filter(function (_, i) {
return outputs.map(function (o) { return o.B_; }).includes(blindedMessages[i].B_);
});
return [2 /*return*/, {
proofs: this.constructProofs(promises, validBlindingFactors, validSecrets, keys)
}];
}
});
});
};
/**
* Requests a mint quote form the mint. Response returns a Lightning payment request for the requested given amount and unit.
* @param amount Amount requesting for mint.
* @param description optional description for the mint quote
* @returns the mint will return a mint quote with a Lightning invoice for minting tokens of the specified amount and unit
*/
CashuWallet.prototype.createMintQuote = function (amount, description) {
return __awaiter(this, void 0, void 0, function () {
var mintQuotePayload;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mintQuotePayload = {
unit: this._unit,
amount: amount,
description: description
};
return [4 /*yield*/, this.mint.createMintQuote(mintQuotePayload)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Gets an existing mint quote from the mint.
* @param quote Quote ID
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
CashuWallet.prototype.checkMintQuote = function (quote) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.mint.checkMintQuote(quote)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Mint proofs for a given mint quote
* @param amount amount to request
* @param quote ID of mint quote
* @param options.keysetId? optionally set keysetId for blank outputs for returned change.
* @param options.preference? Deprecated. Use `outputAmounts` instead. Optional preference for splitting proofs into specific amounts.
* @param options.outputAmounts? optionally specify the output's amounts to keep and to send.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns proofs
*/
CashuWallet.prototype.mintProofs = function (amount, quote, options) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var keyset, _b, blindedMessages, secrets, blindingFactors, mintPayload, signatures;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, this.getKeys(options === null || options === void 0 ? void 0 : options.keysetId)];
case 1:
keyset = _c.sent();
if (!(options === null || options === void 0 ? void 0 : options.outputAmounts) && (options === null || options === void 0 ? void 0 : options.proofsWeHave)) {
options.outputAmounts = {
keepAmounts: getKeepAmounts(options.proofsWeHave, amount, keyset.keys, this._denominationTarget),
sendAmounts: []
};
}
_b = this.createRandomBlindedMessages(amount, keyset, (_a = options === null || options === void 0 ? void 0 : options.outputAmounts) === null || _a === void 0 ? void 0 : _a.keepAmounts, options === null || options === void 0 ? void 0 : options.counter, options === null || options === void 0 ? void 0 : options.pubkey), blindedMessages = _b.blindedMessages, secrets = _b.secrets, blindingFactors = _b.blindingFactors;
mintPayload = {
outputs: blindedMessages,
quote: quote
};
return [4 /*yield*/, this.mint.mint(mintPayload)];
case 2:
signatures = (_c.sent()).signatures;
return [2 /*return*/, {
proofs: this.constructProofs(signatures, blindingFactors, secrets, keyset)
}];
}
});
});
};
/**
* Requests a melt quote from the mint. Response returns amount and fees for a given unit in order to pay a Lightning invoice.
* @param invoice LN invoice that needs to get a fee estimate
* @returns the mint will create and return a melt quote for the invoice with an amount and fee reserve
*/
CashuWallet.prototype.createMeltQuote = function (invoice) {
return __awaiter(this, void 0, void 0, function () {
var meltQuotePayload, meltQuote;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
meltQuotePayload = {
unit: this._unit,
request: invoice
};
return [4 /*yield*/, this.mint.createMeltQuote(meltQuotePayload)];
case 1:
meltQuote = _a.sent();
return [2 /*return*/, meltQuote];
}
});
});
};
/**
* Return an existing melt quote from the mint.
* @param quote ID of the melt quote
* @returns the mint will return an existing melt quote
*/
CashuWallet.prototype.checkMeltQuote = function (quote) {
return __awaiter(this, void 0, void 0, function () {
var meltQuote;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.mint.checkMeltQuote(quote)];
case 1:
meltQuote = _a.sent();
return [2 /*return*/, meltQuote];
}
});
});
};
/**
* Melt proofs for a melt quote. proofsToSend must be at least amount+fee_reserve form the melt quote. This function does not perform coin selection!.
* Returns melt quote and change proofs
* @param meltQuote ID of the melt quote
* @param proofsToSend proofs to melt
* @param options.keysetId? optionally set keysetId for blank outputs for returned change.
* @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param options.privkey? optionally set a private key to unlock P2PK locked secrets
* @returns
*/
CashuWallet.prototype.meltProofs = function (meltQuote, proofsToSend, options) {
return __awaiter(this, void 0, void 0, function () {
var keys, _a, blindedMessages, secrets, blindingFactors, meltPayload, meltResponse, change;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.getKeys(options === null || options === void 0 ? void 0 : options.keysetId)];
case 1:
keys = _b.sent();
_a = this.createBlankOutputs(sumProofs(proofsToSend) - meltQuote.amount, keys.id, options === null || options === void 0 ? void 0 : options.counter), blindedMessages = _a.blindedMessages, secrets = _a.secrets, blindingFactors = _a.blindingFactors;
if ((options === null || options === void 0 ? void 0 : options.privkey) != undefined) {
proofsToSend = getSignedProofs(proofsToSend.map(function (p) {
return {
amount: p.amount,
C: pointFromHex(p.C),
id: p.id,
secret: new TextEncoder().encode(p.secret)
};
}), options.privkey).map(function (p) { return serializeProof(p); });
}
meltPayload = {
quote: meltQuote.quote,
inputs: proofsToSend,
outputs: __spreadArray([], blindedMessages, true)
};
return [4 /*yield*/, this.mint.melt(meltPayload)];
case 2:
meltResponse = _b.sent();
change = [];
if (meltResponse.change) {
change = this.constructProofs(meltResponse.change, blindingFactors, secrets, keys);
}
return [2 /*return*/, {
quote: meltResponse,
change: change
}];
}
});
});
};
/**
* Creates a split payload
* @param amount amount to send
* @param proofsToSend proofs to split*
* @param outputAmounts? optionally specify the output's amounts to keep and to send.
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @param privkey? will create a signature on the @param proofsToSend secrets if set
* @returns
*/
CashuWallet.prototype.createSwapPayload = function (amount, proofsToSend, keyset, outputAmounts, counter, pubkey, privkey) {
var totalAmount = proofsToSend.reduce(function (total, curr) { return total + curr.amount; }, 0);
if (outputAmounts && outputAmounts.sendAmounts && !outputAmounts.keepAmounts) {
outputAmounts.keepAmounts = splitAmount(totalAmount - amount - this.getFeesForProofs(proofsToSend), keyset.keys);
}
var keepBlindedMessages = this.createRandomBlindedMessages(totalAmount - amount - this.getFeesForProofs(proofsToSend), keyset, outputAmounts === null || outputAmounts === void 0 ? void 0 : outputAmounts.keepAmounts, counter);
if (this._seed && counter) {
counter = counter + keepBlindedMessages.secrets.length;
}
var sendBlindedMessages = this.createRandomBlindedMessages(amount, keyset, outputAmounts === null || outputAmounts === void 0 ? void 0 : outputAmounts.sendAmounts, counter, pubkey);
if (privkey) {
proofsToSend = getSignedProofs(proofsToSend.map(function (p) {
return {
amount: p.amount,
C: pointFromHex(p.C),
id: p.id,
secret: new TextEncoder().encode(p.secret)
};
}), privkey).map(function (p) { return serializeProof(p); });
}
// join keepBlindedMessages and sendBlindedMessages
var blindingData = {
blindedMessages: __spreadArray(__spreadArray([], keepBlindedMessages.blindedMessages, true), sendBlindedMessages.blindedMessages, true),
secrets: __spreadArray(__spreadArray([], keepBlindedMessages.secrets, true), sendBlindedMessages.secrets, true),
blindingFactors: __spreadArray(__spreadArray([], keepBlindedMessages.blindingFactors, true), sendBlindedMessages.blindingFactors, true)
};
var payload = {
inputs: proofsToSend,
outputs: __spreadArray([], blindingData.blindedMessages, true)
};
return { payload: payload, blindingData: blindingData };
};
/**
* Get an array of the states of proofs from the mint (as an array of CheckStateEnum's)
* @param proofs (only the `secret` field is required)
* @returns
*/
CashuWallet.prototype.checkProofsStates = function (proofs) {
return __awaiter(this, void 0, void 0, function () {
var enc, Ys, BATCH_SIZE, states, _loop_1, this_1, i;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
enc = new TextEncoder();
Ys = proofs.map(function (p) { return hashToCurve(enc.encode(p.secret)).toHex(true); });
BATCH_SIZE = 100;
states = [];
_loop_1 = function (i) {
var YsSlice, batchStates, stateMap, j, state;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
YsSlice = Ys.slice(i, i + BATCH_SIZE);
return [4 /*yield*/, this_1.mint.check({
Ys: YsSlice
})];
case 1:
batchStates = (_b.sent()).states;
stateMap = {};
batchStates.forEach(function (s) {
stateMap[s.Y] = s;
});
for (j = 0; j < YsSlice.length; j++) {
state = stateMap[YsSlice[j]];
if (!state) {
throw new Error('Could not find state for proof with Y: ' + YsSlice[j]);
}
states.push(state);
}
return [2 /*return*/];
}
});
};
this_1 = this;
i = 0;
_a.label = 1;
case 1:
if (!(i < Ys.length)) return [3 /*break*/, 4];
return [5 /*yield**/, _loop_1(i)];
case 2:
_a.sent();
_a.label = 3;
case 3:
i += BATCH_SIZE;
return [3 /*break*/, 1];
case 4: return [2 /*return*/, states];
}
});
});
};
/**
* Creates blinded messages for a given amount
* @param amount amount to create blinded messages for
* @param split optional preference for splitting proofs into specific amounts. overrides amount param
* @param keyksetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns blinded messages, secrets, rs, and amounts
*/
CashuWallet.prototype.createRandomBlindedMessages = function (amount, keyset, split, counter, pubkey) {
var amounts = splitAmount(amount, keyset.keys, split);
return this.createBlindedMessages(amounts, keyset.id, counter, pubkey);
};
/**
* Creates blinded messages for a according to @param amounts
* @param amount array of amounts to create blinded messages for
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @param keyksetId? override the keysetId derived from the current mintKeys with a custom one. This should be a keyset that was fetched from the `/keysets` endpoint
* @param pubkey? optionally locks ecash to pubkey. Will not be deterministic, even if counter is set!
* @returns blinded messages, secrets, rs, and amounts
*/
CashuWallet.prototype.createBlindedMessages = function (amounts, keysetId, counter, pubkey) {
// if we atempt to create deterministic messages without a _seed, abort.
if (counter != undefined && !this._seed) {
throw new Error('Cannot create deterministic messages without seed. Instantiate CashuWallet with a bip39seed, or omit counter param.');
}
var blindedMessages = [];
var secrets = [];
var blindingFactors = [];
for (var i = 0; i < amounts.length; i++) {
var deterministicR = undefined;
var secretBytes = undefined;
if (pubkey) {
secretBytes = createP2PKsecret(pubkey);
}
else if (this._seed && counter != undefined) {
secretBytes = deriveSecret(this._seed, keysetId, counter + i);
deterministicR = bytesToNumber(deriveBlindingFactor(this._seed, keysetId, counter + i));
}
else {
secretBytes = randomBytes(32);
}
if (!pubkey) {
var secretHex = bytesToHex(secretBytes);
secretBytes = new TextEncoder().encode(secretHex);
}
secrets.push(secretBytes);
var _a = blindMessage(secretBytes, deterministicR), B_ = _a.B_, r = _a.r;
blindingFactors.push(r);
var blindedMessage = new BlindedMessage(amounts[i], B_, keysetId);
blindedMessages.push(blindedMessage.getSerializedBlindedMessage());
}
return { blindedMessages: blindedMessages, secrets: secrets, blindingFactors: blindingFactors, amounts: amounts };
};
/**
* Creates NUT-08 blank outputs (fee returns) for a given fee reserve
* See: https://github.com/cashubtc/nuts/blob/main/08.md
* @param amount amount to cover with blank outputs
* @param keysetId mint keysetId
* @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect
* @returns blinded messages, secrets, and rs
*/
CashuWallet.prototype.createBlankOutputs = function (amount, keysetId, counter) {
var count = Math.ceil(Math.log2(amount)) || 1;
//Prevent count from being -Infinity
if (count < 0) {
count = 0;
}
var amounts = count ? Array(count).fill(1) : [];
var _a = this.createBlindedMessages(amounts, keysetId, counter), blindedMessages = _a.blindedMessages, blindingFactors = _a.blindingFactors, secrets = _a.secrets;
return { blindedMessages: blindedMessages, secrets: secrets, blindingFactors: blindingFactors };
};
/**
* construct proofs from @params promises, @params rs, @params secrets, and @params keyset
* @param promises array of serialized blinded signatures
* @param rs arrays of binding factors
* @param secrets array of secrets
* @param keyset mint keyset
* @returns array of serialized proofs
*/
CashuWallet.prototype.constructProofs = function (promises, rs, secrets, keyset) {
return promises
.map(function (p, i) {
var blindSignature = { id: p.id, amount: p.amount, C_: pointFromHex(p.C_) };
var r = rs[i];
var secret = secrets[i];
var A = pointFromHex(keyset.keys[p.amount]);
return constructProofFromPromise(blindSignature, r, secret, A);
})
.map(function (p) { return serializeProof(p); });
};
return CashuWallet;
}());
export { CashuWallet };
//# sourceMappingURL=CashuWallet.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +0,0 @@
declare function encodeUint8toBase64(uint8array: Uint8Array): string;
declare function encodeUint8toBase64Url(bytes: Uint8Array): string;
declare function encodeBase64toUint8(base64String: string): Uint8Array;
declare function encodeJsonToBase64(jsonObj: unknown): string;
declare function encodeBase64ToJson<T extends object>(base64String: string): T;
export { encodeUint8toBase64, encodeUint8toBase64Url, encodeBase64toUint8, encodeJsonToBase64, encodeBase64ToJson };

View File

@@ -1,33 +0,0 @@
import { Buffer } from 'buffer';
function encodeUint8toBase64(uint8array) {
return Buffer.from(uint8array).toString('base64');
}
function encodeUint8toBase64Url(bytes) {
return Buffer.from(bytes)
.toString('base64')
.replace(/\+/g, '-') // Replace + with -
.replace(/\//g, '_') // Replace / with _
.replace(/=+$/, ''); // Remove padding characters
}
function encodeBase64toUint8(base64String) {
return Buffer.from(base64String, 'base64');
}
function encodeJsonToBase64(jsonObj) {
var jsonString = JSON.stringify(jsonObj);
return base64urlFromBase64(Buffer.from(jsonString).toString('base64'));
}
function encodeBase64ToJson(base64String) {
var jsonString = Buffer.from(base64urlToBase64(base64String), 'base64').toString();
var jsonObj = JSON.parse(jsonString);
return jsonObj;
}
function base64urlToBase64(str) {
return str.replace(/-/g, '+').replace(/_/g, '/').split('=')[0];
// .replace(/./g, '=');
}
function base64urlFromBase64(str) {
return str.replace(/\+/g, '-').replace(/\//g, '_').split('=')[0];
// .replace(/=/g, '.');
}
export { encodeUint8toBase64, encodeUint8toBase64Url, encodeBase64toUint8, encodeJsonToBase64, encodeBase64ToJson };
//# sourceMappingURL=base64.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"base64.js","sourceRoot":"","sources":["../../../src/base64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,SAAS,mBAAmB,CAAC,UAAsB;IAClD,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAiB;IAChD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;SACvB,QAAQ,CAAC,QAAQ,CAAC;SAClB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,mBAAmB;SACvC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,mBAAmB;SACvC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,4BAA4B;AACnD,CAAC;AAED,SAAS,mBAAmB,CAAC,YAAoB;IAChD,OAAO,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB;IAC3C,IAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,kBAAkB,CAAmB,YAAoB;IACjE,IAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrF,IAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAM,CAAC;IAC5C,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,uBAAuB;AACxB,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACvC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,uBAAuB;AACxB,CAAC;AAED,OAAO,EACN,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,CAAC"}

View File

@@ -1,9 +0,0 @@
type SimpleValue = boolean | null | undefined;
export type ResultObject = {
[key: string]: ResultValue;
};
export type ResultValue = SimpleValue | number | string | Uint8Array | Array<ResultValue> | ResultObject;
export type ValidDecodedType = Extract<ResultValue, ResultObject>;
export declare function encodeCBOR(value: any): Uint8Array;
export declare function decodeCBOR(data: Uint8Array): ResultValue;
export {};

View File

@@ -1,278 +0,0 @@
function isResultKeyType(value) {
return typeof value === 'number' || typeof value === 'string';
}
export function encodeCBOR(value) {
var buffer = [];
encodeItem(value, buffer);
return new Uint8Array(buffer);
}
function encodeItem(value, buffer) {
if (value === null) {
buffer.push(0xf6);
}
else if (value === undefined) {
buffer.push(0xf7);
}
else if (typeof value === 'boolean') {
buffer.push(value ? 0xf5 : 0xf4);
}
else if (typeof value === 'number') {
encodeUnsigned(value, buffer);
}
else if (typeof value === 'string') {
encodeString(value, buffer);
}
else if (Array.isArray(value)) {
encodeArray(value, buffer);
}
else if (value instanceof Uint8Array) {
encodeByteString(value, buffer);
}
else if (typeof value === 'object') {
encodeObject(value, buffer);
}
else {
throw new Error('Unsupported type');
}
}
function encodeUnsigned(value, buffer) {
if (value < 24) {
buffer.push(value);
}
else if (value < 256) {
buffer.push(0x18, value);
}
else if (value < 65536) {
buffer.push(0x19, value >> 8, value & 0xff);
}
else if (value < 4294967296) {
buffer.push(0x1a, value >> 24, (value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff);
}
else {
throw new Error('Unsupported integer size');
}
}
function encodeByteString(value, buffer) {
var length = value.length;
if (length < 24) {
buffer.push(0x40 + length);
}
else if (length < 256) {
buffer.push(0x58, length);
}
else if (length < 65536) {
buffer.push(0x59, (length >> 8) & 0xff, length & 0xff);
}
else if (length < 4294967296) {
buffer.push(0x5a, (length >> 24) & 0xff, (length >> 16) & 0xff, (length >> 8) & 0xff, length & 0xff);
}
else {
throw new Error('Byte string too long to encode');
}
for (var i = 0; i < value.length; i++) {
buffer.push(value[i]);
}
}
function encodeString(value, buffer) {
var utf8 = new TextEncoder().encode(value);
var length = utf8.length;
if (length < 24) {
buffer.push(0x60 + length);
}
else if (length < 256) {
buffer.push(0x78, length);
}
else if (length < 65536) {
buffer.push(0x79, (length >> 8) & 0xff, length & 0xff);
}
else if (length < 4294967296) {
buffer.push(0x7a, (length >> 24) & 0xff, (length >> 16) & 0xff, (length >> 8) & 0xff, length & 0xff);
}
else {
throw new Error('String too long to encode');
}
for (var i = 0; i < utf8.length; i++) {
buffer.push(utf8[i]);
}
}
function encodeArray(value, buffer) {
var length = value.length;
if (length < 24) {
buffer.push(0x80 | length);
}
else if (length < 256) {
buffer.push(0x98, length);
}
else if (length < 65536) {
buffer.push(0x99, length >> 8, length & 0xff);
}
else {
throw new Error('Unsupported array length');
}
for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
var item = value_1[_i];
encodeItem(item, buffer);
}
}
function encodeObject(value, buffer) {
var keys = Object.keys(value);
encodeUnsigned(keys.length, buffer);
buffer[buffer.length - 1] |= 0xa0;
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
encodeString(key, buffer);
encodeItem(value[key], buffer);
}
}
export function decodeCBOR(data) {
var view = new DataView(data.buffer, data.byteOffset, data.byteLength);
var result = decodeItem(view, 0);
return result.value;
}
function decodeItem(view, offset) {
if (offset >= view.byteLength) {
throw new Error('Unexpected end of data');
}
var initialByte = view.getUint8(offset++);
var majorType = initialByte >> 5;
var additionalInfo = initialByte & 0x1f;
switch (majorType) {
case 0:
return decodeUnsigned(view, offset, additionalInfo);
case 1:
return decodeSigned(view, offset, additionalInfo);
case 2:
return decodeByteString(view, offset, additionalInfo);
case 3:
return decodeString(view, offset, additionalInfo);
case 4:
return decodeArray(view, offset, additionalInfo);
case 5:
return decodeMap(view, offset, additionalInfo);
case 7:
return decodeSimpleAndFloat(view, offset, additionalInfo);
default:
throw new Error("Unsupported major type: ".concat(majorType));
}
}
function decodeLength(view, offset, additionalInfo) {
if (additionalInfo < 24)
return { value: additionalInfo, offset: offset };
if (additionalInfo === 24)
return { value: view.getUint8(offset++), offset: offset };
if (additionalInfo === 25) {
var value = view.getUint16(offset, false);
offset += 2;
return { value: value, offset: offset };
}
if (additionalInfo === 26) {
var value = view.getUint32(offset, false);
offset += 4;
return { value: value, offset: offset };
}
if (additionalInfo === 27) {
var hi = view.getUint32(offset, false);
var lo = view.getUint32(offset + 4, false);
offset += 8;
return { value: hi * Math.pow(2, 32) + lo, offset: offset };
}
throw new Error("Unsupported length: ".concat(additionalInfo));
}
function decodeUnsigned(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), value = _a.value, newOffset = _a.offset;
return { value: value, offset: newOffset };
}
function decodeSigned(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), value = _a.value, newOffset = _a.offset;
return { value: -1 - value, offset: newOffset };
}
function decodeByteString(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), length = _a.value, newOffset = _a.offset;
if (newOffset + length > view.byteLength) {
throw new Error('Byte string length exceeds data length');
}
var value = new Uint8Array(view.buffer, view.byteOffset + newOffset, length);
return { value: value, offset: newOffset + length };
}
function decodeString(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), length = _a.value, newOffset = _a.offset;
if (newOffset + length > view.byteLength) {
throw new Error('String length exceeds data length');
}
var bytes = new Uint8Array(view.buffer, view.byteOffset + newOffset, length);
var value = new TextDecoder().decode(bytes);
return { value: value, offset: newOffset + length };
}
function decodeArray(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), length = _a.value, newOffset = _a.offset;
var array = [];
var currentOffset = newOffset;
for (var i = 0; i < length; i++) {
var result = decodeItem(view, currentOffset);
array.push(result.value);
currentOffset = result.offset;
}
return { value: array, offset: currentOffset };
}
function decodeMap(view, offset, additionalInfo) {
var _a = decodeLength(view, offset, additionalInfo), length = _a.value, newOffset = _a.offset;
var map = {};
var currentOffset = newOffset;
for (var i = 0; i < length; i++) {
var keyResult = decodeItem(view, currentOffset);
if (!isResultKeyType(keyResult.value)) {
throw new Error('Invalid key type');
}
var valueResult = decodeItem(view, keyResult.offset);
map[keyResult.value] = valueResult.value;
currentOffset = valueResult.offset;
}
return { value: map, offset: currentOffset };
}
function decodeFloat16(uint16) {
var exponent = (uint16 & 0x7c00) >> 10;
var fraction = uint16 & 0x03ff;
var sign = uint16 & 0x8000 ? -1 : 1;
if (exponent === 0) {
return sign * Math.pow(2, -14) * (fraction / 1024);
}
else if (exponent === 0x1f) {
return fraction ? NaN : sign * Infinity;
}
return sign * Math.pow(2, (exponent - 15)) * (1 + fraction / 1024);
}
function decodeSimpleAndFloat(view, offset, additionalInfo) {
if (additionalInfo < 24) {
switch (additionalInfo) {
case 20:
return { value: false, offset: offset };
case 21:
return { value: true, offset: offset };
case 22:
return { value: null, offset: offset };
case 23:
return { value: undefined, offset: offset };
default:
throw new Error("Unknown simple value: ".concat(additionalInfo));
}
}
if (additionalInfo === 24)
return { value: view.getUint8(offset++), offset: offset };
if (additionalInfo === 25) {
var value = decodeFloat16(view.getUint16(offset, false));
offset += 2;
return { value: value, offset: offset };
}
if (additionalInfo === 26) {
var value = view.getFloat32(offset, false);
offset += 4;
return { value: value, offset: offset };
}
if (additionalInfo === 27) {
var value = view.getFloat64(offset, false);
offset += 8;
return { value: value, offset: offset };
}
throw new Error("Unknown simple or float value: ".concat(additionalInfo));
}
//# sourceMappingURL=cbor.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +0,0 @@
import { CashuMint } from './CashuMint.js';
import { CashuWallet } from './CashuWallet.js';
import { PaymentRequest } from './model/PaymentRequest.js';
import { setGlobalRequestOptions } from './request.js';
import { getEncodedToken, getEncodedTokenV4, getDecodedToken, deriveKeysetId, decodePaymentRequest } from './utils.js';
export * from './model/types/index.js';
export { CashuMint, CashuWallet, PaymentRequest, getDecodedToken, getEncodedToken, getEncodedTokenV4, decodePaymentRequest, deriveKeysetId, setGlobalRequestOptions };

View File

@@ -1,8 +0,0 @@
import { CashuMint } from './CashuMint.js';
import { CashuWallet } from './CashuWallet.js';
import { PaymentRequest } from './model/PaymentRequest.js';
import { setGlobalRequestOptions } from './request.js';
import { getEncodedToken, getEncodedTokenV4, getDecodedToken, deriveKeysetId, decodePaymentRequest } from './utils.js';
export * from './model/types/index.js';
export { CashuMint, CashuWallet, PaymentRequest, getDecodedToken, getEncodedToken, getEncodedTokenV4, decodePaymentRequest, deriveKeysetId, setGlobalRequestOptions };
//# sourceMappingURL=index.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,MAAM,YAAY,CAAC;AAEpB,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EACN,SAAS,EACT,WAAW,EACX,cAAc,EACd,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,uBAAuB,EACvB,CAAC"}

View File

@@ -1,5 +0,0 @@
import type { MintQuoteResponse } from '../model/types/index.js';
export type MintQuoteResponsePaidDeprecated = {
paid?: boolean;
};
export declare function handleMintQuoteResponseDeprecated(response: MintQuoteResponse & MintQuoteResponsePaidDeprecated): MintQuoteResponse;

View File

@@ -1,12 +0,0 @@
import { MintQuoteState } from '../model/types/index.js';
export function handleMintQuoteResponseDeprecated(response) {
// if the response MeltQuoteResponse has a "paid" flag, we monkey patch it to the state enum
if (!response.state) {
console.warn("Field 'state' not found in MintQuoteResponse. Update NUT-04 of mint: https://github.com/cashubtc/nuts/pull/141)");
if (typeof response.paid === 'boolean') {
response.state = response.paid ? MintQuoteState.PAID : MintQuoteState.UNPAID;
}
}
return response;
}
//# sourceMappingURL=nut-04.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"nut-04.js","sourceRoot":"","sources":["../../../../src/legacy/nut-04.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAMzD,MAAM,UAAU,iCAAiC,CAChD,QAA6D;IAE7D,4FAA4F;IAC5F,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;QACpB,OAAO,CAAC,IAAI,CACX,iHAAiH,CACjH,CAAC;QACF,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE;YACvC,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC;SAC7E;KACD;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC"}

View File

@@ -1,5 +0,0 @@
import type { MeltQuoteResponse } from '../model/types/index.js';
export type MeltQuoteResponsePaidDeprecated = {
paid?: boolean;
};
export declare function handleMeltQuoteResponseDeprecated(response: MeltQuoteResponse & MeltQuoteResponsePaidDeprecated): MeltQuoteResponse;

View File

@@ -1,12 +0,0 @@
import { MeltQuoteState } from '../model/types/index.js';
export function handleMeltQuoteResponseDeprecated(response) {
// if the response MeltQuoteResponse has a "paid" flag, we monkey patch it to the state enum
if (!response.state) {
console.warn("Field 'state' not found in MeltQuoteResponse. Update NUT-05 of mint: https://github.com/cashubtc/nuts/pull/136)");
if (typeof response.paid === 'boolean') {
response.state = response.paid ? MeltQuoteState.PAID : MeltQuoteState.UNPAID;
}
}
return response;
}
//# sourceMappingURL=nut-05.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"nut-05.js","sourceRoot":"","sources":["../../../../src/legacy/nut-05.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAMzD,MAAM,UAAU,iCAAiC,CAChD,QAA6D;IAE7D,4FAA4F;IAC5F,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;QACpB,OAAO,CAAC,IAAI,CACX,iHAAiH,CACjH,CAAC;QACF,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE;YACvC,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC;SAC7E;KACD;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC"}

View File

@@ -1,2 +0,0 @@
import type { GetInfoResponse } from '../model/types/index.js';
export declare function handleMintInfoContactFieldDeprecated(data: GetInfoResponse): GetInfoResponse;

View File

@@ -1,18 +0,0 @@
export function handleMintInfoContactFieldDeprecated(data) {
// Monkey patch old contact field ["email", "me@mail.com"] Array<[string, string]>; to new contact field [{method: "email", info: "me@mail.com"}] Array<MintContactInfo>
// This is to maintain backwards compatibility with older versions of the mint
if (Array.isArray(data === null || data === void 0 ? void 0 : data.contact) && (data === null || data === void 0 ? void 0 : data.contact.length) > 0) {
data.contact = data.contact.map(function (contact) {
if (Array.isArray(contact) &&
contact.length === 2 &&
typeof contact[0] === 'string' &&
typeof contact[1] === 'string') {
console.warn("Mint returned deprecated 'contact' field: Update NUT-06: https://github.com/cashubtc/nuts/pull/117");
return { method: contact[0], info: contact[1] };
}
return contact;
});
}
return data;
}
//# sourceMappingURL=nut-06.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"nut-06.js","sourceRoot":"","sources":["../../../../src/legacy/nut-06.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oCAAoC,CAAC,IAAqB;IACzE,wKAAwK;IACxK,8EAA8E;IAC9E,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,CAAC,IAAI,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,CAAC,MAAM,IAAG,CAAC,EAAE;QAC7D,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAC,OAAwB;YACxD,IACC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBACtB,OAAO,CAAC,MAAM,KAAK,CAAC;gBACpB,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ;gBAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,EAC7B;gBACD,OAAO,CAAC,IAAI,CACX,oGAAoG,CACpG,CAAC;gBACF,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAqB,CAAC;aACnE;YACD,OAAO,OAAO,CAAC;QAChB,CAAC,CAAC,CAAC;KACH;IACD,OAAO,IAAI,CAAC;AACb,CAAC"}

View File

@@ -1,10 +0,0 @@
import { SerializedBlindedMessage } from './types/index.js';
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
declare class BlindedMessage {
amount: number;
B_: ProjPointType<bigint>;
id: string;
constructor(amount: number, B_: ProjPointType<bigint>, id: string);
getSerializedBlindedMessage(): SerializedBlindedMessage;
}
export { BlindedMessage };

View File

@@ -1,13 +0,0 @@
var BlindedMessage = /** @class */ (function () {
function BlindedMessage(amount, B_, id) {
this.amount = amount;
this.B_ = B_;
this.id = id;
}
BlindedMessage.prototype.getSerializedBlindedMessage = function () {
return { amount: this.amount, B_: this.B_.toHex(true), id: this.id };
};
return BlindedMessage;
}());
export { BlindedMessage };
//# sourceMappingURL=BlindedMessage.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"BlindedMessage.js","sourceRoot":"","sources":["../../../../src/model/BlindedMessage.ts"],"names":[],"mappings":"AAGA;IAIC,wBAAY,MAAc,EAAE,EAAyB,EAAE,EAAU;QAChE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACd,CAAC;IACD,oDAA2B,GAA3B;QACC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;IACtE,CAAC;IACF,qBAAC;AAAD,CAAC,AAZD,IAYC;AACD,OAAO,EAAE,cAAc,EAAE,CAAC"}

View File

@@ -1,10 +0,0 @@
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
import { SerializedBlindedSignature } from './types/index.js';
declare class BlindedSignature {
id: string;
amount: number;
C_: ProjPointType<bigint>;
constructor(id: string, amount: number, C_: ProjPointType<bigint>);
getSerializedBlindedSignature(): SerializedBlindedSignature;
}
export { BlindedSignature };

View File

@@ -1,13 +0,0 @@
var BlindedSignature = /** @class */ (function () {
function BlindedSignature(id, amount, C_) {
this.id = id;
this.amount = amount;
this.C_ = C_;
}
BlindedSignature.prototype.getSerializedBlindedSignature = function () {
return { id: this.id, amount: this.amount, C_: this.C_.toHex(true) };
};
return BlindedSignature;
}());
export { BlindedSignature };
//# sourceMappingURL=BlindedSignature.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"BlindedSignature.js","sourceRoot":"","sources":["../../../../src/model/BlindedSignature.ts"],"names":[],"mappings":"AAGA;IAKC,0BAAY,EAAU,EAAE,MAAc,EAAE,EAAyB;QAChE,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACd,CAAC;IAED,wDAA6B,GAA7B;QACC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IACtE,CAAC;IACF,uBAAC;AAAD,CAAC,AAdD,IAcC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}

View File

@@ -1,4 +0,0 @@
export declare class HttpResponseError extends Error {
status: number;
constructor(message: string, status: number);
}

View File

@@ -1,26 +0,0 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var HttpResponseError = /** @class */ (function (_super) {
__extends(HttpResponseError, _super);
function HttpResponseError(message, status) {
var _this = _super.call(this, message) || this;
_this.status = status;
return _this;
}
return HttpResponseError;
}(Error));
export { HttpResponseError };
//# sourceMappingURL=Errors.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"Errors.js","sourceRoot":"","sources":["../../../../src/model/Errors.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;IAAuC,qCAAK;IAE3C,2BAAY,OAAe,EAAE,MAAc;QAA3C,YACC,kBAAM,OAAO,CAAC,SAEd;QADA,KAAI,CAAC,MAAM,GAAG,MAAM,CAAC;;IACtB,CAAC;IACF,wBAAC;AAAD,CAAC,AAND,CAAuC,KAAK,GAM3C"}

View File

@@ -1,14 +0,0 @@
import { PaymentRequestTransport, PaymentRequestTransportType } from './types';
export declare class PaymentRequest {
transport: Array<PaymentRequestTransport>;
id?: string | undefined;
amount?: number | undefined;
unit?: string | undefined;
mints?: string[] | undefined;
description?: string | undefined;
singleUse: boolean;
constructor(transport: Array<PaymentRequestTransport>, id?: string | undefined, amount?: number | undefined, unit?: string | undefined, mints?: string[] | undefined, description?: string | undefined, singleUse?: boolean);
toEncodedRequest(): string;
getTransport(type: PaymentRequestTransportType): PaymentRequestTransport | undefined;
static fromEncodedRequest(encodedRequest: string): PaymentRequest;
}

View File

@@ -1,61 +0,0 @@
import { encodeBase64toUint8 } from '../base64';
import { decodeCBOR, encodeCBOR } from '../cbor';
import { Buffer } from 'buffer';
var PaymentRequest = /** @class */ (function () {
function PaymentRequest(transport, id, amount, unit, mints, description, singleUse) {
if (singleUse === void 0) { singleUse = false; }
this.transport = transport;
this.id = id;
this.amount = amount;
this.unit = unit;
this.mints = mints;
this.description = description;
this.singleUse = singleUse;
}
PaymentRequest.prototype.toEncodedRequest = function () {
var rawRequest = {
t: this.transport.map(function (t) { return ({ t: t.type, a: t.target, g: t.tags }); })
};
if (this.id) {
rawRequest.i = this.id;
}
if (this.amount) {
rawRequest.a = this.amount;
}
if (this.unit) {
rawRequest.u = this.unit;
}
if (this.mints) {
rawRequest.m = this.mints;
}
if (this.description) {
rawRequest.d = this.description;
}
if (this.singleUse) {
rawRequest.s = this.singleUse;
}
var data = encodeCBOR(rawRequest);
var encodedData = Buffer.from(data).toString('base64');
return 'creq' + 'A' + encodedData;
};
PaymentRequest.prototype.getTransport = function (type) {
return this.transport.find(function (t) { return t.type === type; });
};
PaymentRequest.fromEncodedRequest = function (encodedRequest) {
if (!encodedRequest.startsWith('creq')) {
throw new Error('unsupported pr: invalid prefix');
}
var version = encodedRequest[4];
if (version !== 'A') {
throw new Error('unsupported pr version');
}
var encodedData = encodedRequest.slice(5);
var data = encodeBase64toUint8(encodedData);
var decoded = decodeCBOR(data);
var transports = decoded.t.map(function (t) { return ({ type: t.t, target: t.a, tags: t.g }); });
return new PaymentRequest(transports, decoded.i, decoded.a, decoded.u, decoded.m, decoded.d, decoded.s);
};
return PaymentRequest;
}());
export { PaymentRequest };
//# sourceMappingURL=PaymentRequest.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"PaymentRequest.js","sourceRoot":"","sources":["../../../../src/model/PaymentRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAOjD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC;IACC,wBACQ,SAAyC,EACzC,EAAW,EACX,MAAe,EACf,IAAa,EACb,KAAqB,EACrB,WAAoB,EACpB,SAA0B;QAA1B,0BAAA,EAAA,iBAA0B;QAN1B,cAAS,GAAT,SAAS,CAAgC;QACzC,OAAE,GAAF,EAAE,CAAS;QACX,WAAM,GAAN,MAAM,CAAS;QACf,SAAI,GAAJ,IAAI,CAAS;QACb,UAAK,GAAL,KAAK,CAAgB;QACrB,gBAAW,GAAX,WAAW,CAAS;QACpB,cAAS,GAAT,SAAS,CAAiB;IAC/B,CAAC;IAEJ,yCAAgB,GAAhB;QACC,IAAM,UAAU,GAAsB;YACrC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAC,CAA0B,IAAK,OAAA,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAvC,CAAuC,CAAC;SAC9F,CAAC;QACF,IAAI,IAAI,CAAC,EAAE,EAAE;YACZ,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;SACvB;QACD,IAAI,IAAI,CAAC,MAAM,EAAE;YAChB,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;SAC3B;QACD,IAAI,IAAI,CAAC,IAAI,EAAE;YACd,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;SACzB;QACD,IAAI,IAAI,CAAC,KAAK,EAAE;YACf,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;SAC1B;QACD,IAAI,IAAI,CAAC,WAAW,EAAE;YACrB,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;SAChC;QACD,IAAI,IAAI,CAAC,SAAS,EAAE;YACnB,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;SAC9B;QAED,IAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;QACpC,IAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzD,OAAO,MAAM,GAAG,GAAG,GAAG,WAAW,CAAC;IACnC,CAAC;IAED,qCAAY,GAAZ,UAAa,IAAiC;QAC7C,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAC,CAA0B,IAAK,OAAA,CAAC,CAAC,IAAI,KAAK,IAAI,EAAf,CAAe,CAAC,CAAC;IAC7E,CAAC;IAEM,iCAAkB,GAAzB,UAA0B,cAAsB;QAC/C,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;YACvC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;SAClD;QACD,IAAM,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,OAAO,KAAK,GAAG,EAAE;YACpB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;SAC1C;QACD,IAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,IAAM,IAAI,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAsB,CAAC;QACtD,IAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,UAAC,CAAe,IAAK,OAAA,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAvC,CAAuC,CAAC,CAAC;QAC/F,OAAO,IAAI,cAAc,CACxB,UAAU,EACV,OAAO,CAAC,CAAC,EACT,OAAO,CAAC,CAAC,EACT,OAAO,CAAC,CAAC,EACT,OAAO,CAAC,CAAC,EACT,OAAO,CAAC,CAAC,EACT,OAAO,CAAC,CAAC,CACT,CAAC;IACH,CAAC;IACF,qBAAC;AAAD,CAAC,AAjED,IAiEC"}

View File

@@ -1,17 +0,0 @@
import { BlindedMessage } from './BlindedMessage.js';
import { Proof } from './types/index.js';
declare class Split {
proofs: Array<Proof>;
amount: number;
outputs: Array<BlindedMessage>;
constructor(proofs: Array<Proof>, amount: number, outputs: Array<BlindedMessage>);
getSerializedSplit(): {
proofs: Proof[];
amount: number;
outputs: {
amount: number;
B_: string;
}[];
};
}
export { Split };

View File

@@ -1,19 +0,0 @@
var Split = /** @class */ (function () {
function Split(proofs, amount, outputs) {
this.proofs = proofs;
this.amount = amount;
this.outputs = outputs;
}
Split.prototype.getSerializedSplit = function () {
return {
proofs: this.proofs,
amount: this.amount,
outputs: this.outputs.map(function (blindedMessage) {
return { amount: blindedMessage.amount, B_: blindedMessage.B_.toHex(true) };
})
};
};
return Split;
}());
export { Split };
//# sourceMappingURL=Split.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"Split.js","sourceRoot":"","sources":["../../../../src/model/Split.ts"],"names":[],"mappings":"AAGA;IAIC,eAAY,MAAoB,EAAE,MAAc,EAAE,OAA8B;QAC/E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IACD,kCAAkB,GAAlB;QACC,OAAO;YACN,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAC,cAA8B;gBACxD,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7E,CAAC,CAAC;SACF,CAAC;IACH,CAAC;IACF,YAAC;AAAD,CAAC,AAlBD,IAkBC;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}

View File

@@ -1,15 +0,0 @@
export * from './mint/index';
export * from './wallet/index';
export type OutputAmounts = {
sendAmounts: Array<number>;
keepAmounts?: Array<number>;
};
export type InvoiceData = {
paymentRequest: string;
amountInSats?: number;
amountInMSats?: number;
timestamp?: number;
paymentHash?: string;
memo?: string;
expiry?: number;
};

View File

@@ -1,3 +0,0 @@
export * from './mint/index';
export * from './wallet/index';
//# sourceMappingURL=index.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/model/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}

View File

@@ -1,18 +0,0 @@
import { SerializedBlindedMessage } from '../wallet';
export * from './responses';
export * from './keys';
/**
* Payload that needs to be sent to the mint when checking for spendable proofs
*/
export type CheckStatePayload = {
/**
* The Y = hash_to_curve(secret) of the proofs to be checked.
*/
Ys: Array<string>;
};
/**
* Request to mint at /v1/restore endpoint
*/
export type PostRestorePayload = {
outputs: Array<SerializedBlindedMessage>;
};

View File

@@ -1,3 +0,0 @@
export * from './responses';
export * from './keys';
//# sourceMappingURL=index.js.map

Some files were not shown because too many files have changed in this diff Show More