Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

better typedefs for some NUTs #1

Closed
Closed
Changes from 30 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
706c2e0
Update README.md
gandlafbtc Feb 20, 2024
bc6724a
Update README.md
gandlafbtc Feb 20, 2024
4bb76a4
Update README.md
gandlafbtc Feb 20, 2024
53f015a
NUT-06: new info endpoint with monkeypatch for old format, see https:…
callebtc Jul 15, 2024
042bf2b
npm run format
callebtc Jul 16, 2024
ff1f316
contact field explicit type
callebtc Jul 16, 2024
00d3bc6
add state enum changes of NUT-04 and NUT-05
callebtc Jul 16, 2024
a247b7f
console log instead of warnings
callebtc Jul 16, 2024
ef8111f
fix errors in test
callebtc Jul 16, 2024
15411d1
Merge pull request #148 from cashubtc/nut-05-add-state
callebtc Jul 16, 2024
de011a1
Merge branch 'nut-05-add-state' into nut-06-fix-contact
callebtc Jul 16, 2024
18855eb
refactor depercated contact handler
callebtc Jul 16, 2024
a752c0d
typo
callebtc Jul 16, 2024
f90eead
erge branch 'development' into nut-06-fix-contact
callebtc Jul 16, 2024
70e93f4
npm run format
callebtc Jul 16, 2024
559080d
Format checker in gihtub pipeline
callebtc Jul 16, 2024
0952172
test format mismatch, should fail
callebtc Jul 16, 2024
097f7ec
install dep[s
callebtc Jul 16, 2024
f34276c
fix format, should succeed
callebtc Jul 16, 2024
5b0f667
Merge pull request #149 from cashubtc/ci-add-prettier-check
callebtc Jul 16, 2024
1d315e2
Merge remote-tracking branch 'upstream/v1.0.0-rc.9-minibits' into fix…
KraXen72 Jul 16, 2024
46a53f5
improve type definitions for GetInfoResponse
KraXen72 Jul 16, 2024
aba81e5
fix definition of NUT15Entry in GetInfoResponse
KraXen72 Jul 16, 2024
6c6cf0d
Merge pull request #147 from cashubtc/nut-06-fix-contact
callebtc Jul 16, 2024
53c1af3
updated naming on mint / melt
Egge21M Jul 5, 2024
c5b509a
updated tests / all green
Egge21M Jul 5, 2024
13c115f
updated migration doc
Egge21M Jul 15, 2024
4ce0716
mint and wallet same naming
Egge21M Jul 16, 2024
4909e39
1.0.0-rc.10
Egge21M Jul 16, 2024
9d42535
implement nut17 type defs
KraXen72 Jul 16, 2024
142d671
remove unused import
callebtc Jul 16, 2024
55dc4fa
Merge pull request #145 from Egge21M/naming
callebtc Jul 16, 2024
16954c7
Merge branch 'main' into development
callebtc Jul 16, 2024
b99ad29
Merge pull request #150 from cashubtc/dev-sync-main-readme
callebtc Jul 16, 2024
3bd7cea
Merge branch 'development' into staging
Egge21M Jul 16, 2024
ce81a59
1.0.0-rc.11
Egge21M Jul 16, 2024
4e3869b
audit fix deps
gandlafbtc Jul 17, 2024
7c95ca4
1.0.0-rc.12
gandlafbtc Jul 17, 2024
7c582f9
Merge pull request #115 from cashubtc/staging
gandlafbtc Jul 17, 2024
4797c05
Update version.yml
gandlafbtc Jul 17, 2024
7dd0cad
Merge remote-tracking branch 'cashubtc/main' into fixed-typedef
KraXen72 Jul 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Format Check

on: [push]

jobs:
tests:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Check format
run: npm run check-format
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -68,4 +68,31 @@ const tokens = await wallet.mintTokens(64, mintQuote.quote);

Contributions are very welcome.

If you want to contribute, please open an Issue or a PR.
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

```
* `main`
|\
|\ \
| | * `hotfix`
| |
| * `staging`
| |\
| |\ \
| | | * `bugfix`
| | |
| | * `development`
| | |\
| | | * `feature1`
| | | |
| | |/
| | *
| | |\
| | | * `feature2`
| | |/
| |/
|/ (create new version)
```
4 changes: 2 additions & 2 deletions migration-1.0.0.md
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ To reduce complexity, simplify error handling and to prepare for token V4, this

Utility functions now have an `options` object for optional parameters, instead of passing them directly

**`requestMint(amount: number)` --> `mintQuote(amount: number)`**
**`requestMint(amount: number)` --> `createMintQuote(amount: number)`**
Now returns the following:

```typescript
@@ -51,7 +51,7 @@ where `request` is the invoice to be paid, and `quote` is the identifier used to

---

**`getMeltQuote(invoice: string)`** is now used to get fee estimation and conversion quotes instead of `getFee()` and returns:
**`createMeltQuote(invoice: string)`** is now used to get fee estimation and conversion quotes instead of `getFee()` and returns:

```typescript
type MeltQuoteResponse = {
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
"dev": "tsc --watch",
"lint": "eslint --ext .js,.ts . --fix",
"format": "prettier --write .",
"check-format": "prettier --check .",
"typedoc": "typedoc src/index.ts"
},
"keywords": [
78 changes: 52 additions & 26 deletions src/CashuMint.ts
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ import type {
CheckStateResponse,
GetInfoResponse,
MeltPayload,
MeltResponse,
MintActiveKeys,
MintAllKeysets,
PostRestoreResponse,
@@ -16,11 +15,21 @@ import type {
MintResponse,
PostRestorePayload,
MeltQuotePayload,
MeltQuoteResponse
MeltQuoteResponse,
MintContactInfo
} from './model/types/index.js';
import { MeltQuoteState } from './model/types/index.js';
import request from './request.js';
import { isObj, joinUrls, sanitizeUrl } from './utils.js';

import {
MeltQuoteResponsePaidDeprecated,
handleMeltQuoteResponseDeprecated
} from './legacy/nut-05.js';
import {
MintQuoteResponsePaidDeprecated,
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.
*/
@@ -48,7 +57,11 @@ class CashuMint {
customRequest?: typeof request
): Promise<GetInfoResponse> {
const requestInstance = customRequest || request;
return requestInstance<GetInfoResponse>({ endpoint: joinUrls(mintUrl, '/v1/info') });
const response = await requestInstance<GetInfoResponse>({
endpoint: joinUrls(mintUrl, '/v1/info')
});
const data = handleMintInfoContactFieldDeprecated(response);
return data;
}
/**
* fetches mints info at the /info endpoint
@@ -98,25 +111,27 @@ class CashuMint {
* @param customRequest
* @returns the mint will create and return a new mint quote containing a payment request for the specified amount and unit
*/
public static async mintQuote(
public static async createMintQuote(
mintUrl: string,
mintQuotePayload: MintQuotePayload,
customRequest?: typeof request
): Promise<MintQuoteResponse> {
const requestInstance = customRequest || request;
return requestInstance<MintQuoteResponse>({
const response = await requestInstance<MintQuoteResponse & MintQuoteResponsePaidDeprecated>({
endpoint: joinUrls(mintUrl, '/v1/mint/quote/bolt11'),
method: 'POST',
requestBody: mintQuotePayload
});
const data = handleMintQuoteResponseDeprecated(response);
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
*/
async mintQuote(mintQuotePayload: MintQuotePayload): Promise<MintQuoteResponse> {
return CashuMint.mintQuote(this._mintUrl, mintQuotePayload, this._customRequest);
async createMintQuote(mintQuotePayload: MintQuotePayload): Promise<MintQuoteResponse> {
return CashuMint.createMintQuote(this._mintUrl, mintQuotePayload, this._customRequest);
}

/**
@@ -126,24 +141,27 @@ class CashuMint {
* @param customRequest
* @returns the mint will create and return a Lightning invoice for the specified amount
*/
public static async getMintQuote(
public static async checkMintQuote(
mintUrl: string,
quote: string,
customRequest?: typeof request
): Promise<MintQuoteResponse> {
const requestInstance = customRequest || request;
return requestInstance<MintQuoteResponse>({
const response = await requestInstance<MintQuoteResponse & MintQuoteResponsePaidDeprecated>({
endpoint: joinUrls(mintUrl, '/v1/mint/quote/bolt11', quote),
method: 'GET'
});

const data = handleMintQuoteResponseDeprecated(response);
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
*/
async getMintQuote(quote: string): Promise<MintQuoteResponse> {
return CashuMint.getMintQuote(this._mintUrl, quote, this._customRequest);
async checkMintQuote(quote: string): Promise<MintQuoteResponse> {
return CashuMint.checkMintQuote(this._mintUrl, quote, this._customRequest);
}

/**
@@ -186,18 +204,20 @@ class CashuMint {
* @param MeltQuotePayload
* @returns
*/
public static async meltQuote(
public static async createMeltQuote(
mintUrl: string,
meltQuotePayload: MeltQuotePayload,
customRequest?: typeof request
): Promise<MeltQuoteResponse> {
const requestInstance = customRequest || request;
const data = await requestInstance<MeltQuoteResponse>({
const response = await requestInstance<MeltQuoteResponse & MeltQuoteResponsePaidDeprecated>({
endpoint: joinUrls(mintUrl, '/v1/melt/quote/bolt11'),
method: 'POST',
requestBody: meltQuotePayload
});

const data = handleMeltQuoteResponseDeprecated(response);

if (
!isObj(data) ||
typeof data?.amount !== 'number' ||
@@ -213,8 +233,8 @@ class CashuMint {
* @param MeltQuotePayload
* @returns
*/
async meltQuote(meltQuotePayload: MeltQuotePayload): Promise<MeltQuoteResponse> {
return CashuMint.meltQuote(this._mintUrl, meltQuotePayload, this._customRequest);
async createMeltQuote(meltQuotePayload: MeltQuotePayload): Promise<MeltQuoteResponse> {
return CashuMint.createMeltQuote(this._mintUrl, meltQuotePayload, this._customRequest);
}

/**
@@ -223,22 +243,26 @@ class CashuMint {
* @param quote Quote ID
* @returns
*/
public static async getMeltQuote(
public static async checkMeltQuote(
mintUrl: string,
quote: string,
customRequest?: typeof request
): Promise<MeltQuoteResponse> {
const requestInstance = customRequest || request;
const data = await requestInstance<MeltQuoteResponse>({
const response = await requestInstance<MeltQuoteResponse & MeltQuoteResponsePaidDeprecated>({
endpoint: joinUrls(mintUrl, '/v1/melt/quote/bolt11', quote),
method: 'GET'
});

const data = handleMeltQuoteResponseDeprecated(response);

if (
!isObj(data) ||
typeof data?.amount !== 'number' ||
typeof data?.fee_reserve !== 'number' ||
typeof data?.quote !== 'string'
typeof data?.quote !== 'string' ||
typeof data?.state !== 'string' ||
!Object.values(MeltQuoteState).includes(data.state)
) {
throw new Error('bad response');
}
@@ -250,8 +274,8 @@ class CashuMint {
* @param quote Quote ID
* @returns
*/
async getMeltQuote(quote: string): Promise<MeltQuoteResponse> {
return CashuMint.getMeltQuote(this._mintUrl, quote, this._customRequest);
async checkMeltQuote(quote: string): Promise<MeltQuoteResponse> {
return CashuMint.checkMeltQuote(this._mintUrl, quote, this._customRequest);
}

/**
@@ -265,18 +289,20 @@ class CashuMint {
mintUrl: string,
meltPayload: MeltPayload,
customRequest?: typeof request
): Promise<MeltResponse> {
): Promise<MeltQuoteResponse> {
const requestInstance = customRequest || request;
const data = await requestInstance<MeltResponse>({
const response = await requestInstance<MeltQuoteResponse & MeltQuoteResponsePaidDeprecated>({
endpoint: joinUrls(mintUrl, '/v1/melt/bolt11'),
method: 'POST',
requestBody: meltPayload
});

const data = handleMeltQuoteResponseDeprecated(response);

if (
!isObj(data) ||
typeof data?.paid !== 'boolean' ||
(data?.payment_preimage !== null && typeof data?.payment_preimage !== 'string')
typeof data?.state !== 'string' ||
!Object.values(MeltQuoteState).includes(data.state)
) {
throw new Error('bad response');
}
@@ -288,7 +314,7 @@ class CashuMint {
* @param meltPayload
* @returns
*/
async melt(meltPayload: MeltPayload): Promise<MeltResponse> {
async melt(meltPayload: MeltPayload): Promise<MeltQuoteResponse> {
return CashuMint.melt(this._mintUrl, meltPayload, this._customRequest);
}
/**
31 changes: 20 additions & 11 deletions src/CashuWallet.ts
Original file line number Diff line number Diff line change
@@ -19,7 +19,8 @@ import {
type Token,
type TokenEntry,
CheckStateEnum,
SerializedBlindedSignature
SerializedBlindedSignature,
MeltQuoteState
} from './model/types/index.js';
import {
bytesToNumber,
@@ -102,6 +103,14 @@ class CashuWallet {
this._unit = keys.unit;
}

/**
* Get information about the mint
* @returns mint info
*/
async getMintInfo() {
return this.mint.getInfo();
}

/**
* 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
@@ -332,21 +341,21 @@ class CashuWallet {
* @param amount Amount requesting for mint.
* @returns the mint will return a mint quote with a Lightning invoice for minting tokens of the specified amount and unit
*/
async mintQuote(amount: number) {
async createMintQuote(amount: number) {
const mintQuotePayload: MintQuotePayload = {
unit: this._unit,
amount: amount
};
return await this.mint.mintQuote(mintQuotePayload);
return await this.mint.createMintQuote(mintQuotePayload);
}

/**
* 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
*/
async getMintQuote(quote: string) {
return await this.mint.getMintQuote(quote);
async checkMintQuote(quote: string) {
return await this.mint.checkMintQuote(quote);
}

/**
@@ -388,12 +397,12 @@ class CashuWallet {
* @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
*/
async meltQuote(invoice: string): Promise<MeltQuoteResponse> {
async createMeltQuote(invoice: string): Promise<MeltQuoteResponse> {
const meltQuotePayload: MeltQuotePayload = {
unit: this._unit,
request: invoice
};
const meltQuote = await this.mint.meltQuote(meltQuotePayload);
const meltQuote = await this.mint.createMeltQuote(meltQuotePayload);
return meltQuote;
}

@@ -402,8 +411,8 @@ class CashuWallet {
* @param quote ID of the melt quote
* @returns the mint will return an existing melt quote
*/
async getMeltQuote(quote: string): Promise<MeltQuoteResponse> {
const meltQuote = await this.mint.getMeltQuote(quote);
async checkMeltQuote(quote: string): Promise<MeltQuoteResponse> {
const meltQuote = await this.mint.checkMeltQuote(quote);
return meltQuote;
}

@@ -439,7 +448,7 @@ class CashuWallet {
const meltResponse = await this.mint.melt(meltPayload);

return {
isPaid: meltResponse.paid ?? false,
isPaid: meltResponse.state === MeltQuoteState.PAID,
preimage: meltResponse.payment_preimage,
change: meltResponse?.change
? this.constructProofs(meltResponse.change, rs, secrets, keys)
@@ -467,7 +476,7 @@ class CashuWallet {
}
): Promise<MeltTokensResponse> {
if (!meltQuote) {
meltQuote = await this.mint.meltQuote({ unit: this._unit, request: invoice });
meltQuote = await this.mint.createMeltQuote({ unit: this._unit, request: invoice });
}
return await this.meltTokens(meltQuote, proofsToSend, {
keysetId: options?.keysetId,
Loading