Skip to content

Commit

Permalink
add CBOR token v4 support with cashu-ts 1.1.0-rc1 from branch v1.1.0-…
Browse files Browse the repository at this point in the history
…rc1-fix-base64url
  • Loading branch information
callebtc committed Aug 28, 2024
1 parent be7f227 commit c908459
Show file tree
Hide file tree
Showing 71 changed files with 8,815 additions and 4,100 deletions.
739 changes: 428 additions & 311 deletions package-lock.json

Large diffs are not rendered by default.

57 changes: 29 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,50 +21,51 @@
"@capacitor/core": "^6.0.0",
"@capacitor/ios": "^6.0.0",
"@cashu/cashu-ts": "file:src/contrib/cashu-ts",
"@cashu/crypto": "^0.2.7",
"@chenfengyuan/vue-qrcode": "^2.0.0",
"@gandlaf21/bc-ur": "^1.1.12",
"@noble/hashes": "^1.3.0",
"@noble/hashes": "^1.4.0",
"@noble/secp256k1": "^2.1.0",
"@nostr-dev-kit/ndk": "^2.8.1",
"@quasar/extras": "^1.16.11",
"@quasar/icongenie": "^4.0.0",
"@vueuse/core": "^10.0.2",
"axios": "^1.3.3",
"@vueuse/core": "^10.9.0",
"axios": "^1.6.8",
"bech32": "^2.0.0",
"core-js": "^3.6.5",
"core-js": "^3.37.0",
"date-fns": "^3.6.0",
"light-bolt11-decoder": "^3.1.1",
"nostr-tools": "^2.5.2",
"pinia": "^2.0.35",
"pinia": "^2.1.7",
"qr-scanner": "^1.4.2",
"qrcode": "^1.5.1",
"quasar": "^2.15.4",
"qrcode": "^1.5.3",
"quasar": "^2.16.2",
"underscore": "^1.13.6",
"vue": "^3.2.47",
"vue-router": "^4.0.0"
"vue": "^3.4.27",
"vue-router": "^4.3.2"
},
"devDependencies": {
"@quasar/app-vite": "^1.8.5",
"@types/node": "^20.2.1",
"@quasar/app-vite": "^1.9.3",
"@types/node": "^20.12.11",
"@types/underscore": "^1.11.15",
"@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.6",
"@vue/test-utils": "^2.0.0",
"autoprefixer": "^10.4.14",
"electron": "^23.1.1",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@vue/test-utils": "^2.4.6",
"autoprefixer": "^10.4.19",
"electron": "^23.3.13",
"electron-packager": "^15.5.2",
"eslint": "^8.10.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-vue": "^9.0.0",
"prettier": "^2.5.1",
"typescript": "^5.0.4",
"workbox-build": "^6.5.4",
"workbox-cacheable-response": "^6.5.4",
"workbox-core": "^6.5.4",
"workbox-expiration": "^6.5.4",
"workbox-precaching": "^6.5.4",
"workbox-routing": "^6.5.4",
"workbox-strategies": "^6.5.4"
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-vue": "^9.26.0",
"prettier": "^2.8.8",
"typescript": "^5.4.5",
"workbox-build": "^6.6.1",
"workbox-cacheable-response": "^6.6.1",
"workbox-core": "^6.6.1",
"workbox-expiration": "^6.6.1",
"workbox-precaching": "^6.6.1",
"workbox-routing": "^6.6.1",
"workbox-strategies": "^6.6.1"
},
"engines": {
"node": ">=16.11.0",
Expand Down
34 changes: 19 additions & 15 deletions src/components/ReceiveTokenDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
? addMintBlocking
? 'Adding mint ...'
: 'Receive'
: 'Add mint'
: 'Add mint and receive'
"
>
</q-btn>
Expand Down Expand Up @@ -179,6 +179,7 @@ export default defineComponent({
"generateKeypair",
"showLastKey",
]),
...mapActions(useMintsStore, ["addMint"]),
knowThisMintOfTokenJson: function (tokenJson) {
const mintStore = useMintsStore();
// check if we have all mints
Expand Down Expand Up @@ -214,20 +215,23 @@ export default defineComponent({
}
// check if we have all mints
if (!this.knowThisMintOfTokenJson(tokenJson)) {
// pop up add mint dialog warning
// hack! The "add mint" component is in SettingsView which may now
// have been loaded yet. We switch the tab to settings to make sure
// that it loads. Remove this code when the TrustMintComnent is refactored!
uIStore.setTab("mints");
// hide the receive dialog
receiveStore.showReceiveTokens = false;
// set the mint to add
this.addMintData = { url: token.getMint(tokenJson) };
// show the add mint dialog
this.showAddMintDialog = true;
// show the token receive dialog again for the next attempt
receiveStore.showReceiveTokens = true;
return;
// // pop up add mint dialog warning
// // hack! The "add mint" component is in SettingsView which may now
// // have been loaded yet. We switch the tab to settings to make sure
// // that it loads. Remove this code when the TrustMintComnent is refactored!
// uIStore.setTab("mints");
// // hide the receive dialog
// receiveStore.showReceiveTokens = false;
// // set the mint to add
// this.addMintData = { url: token.getMint(tokenJson) };
// // show the add mint dialog
// this.showAddMintDialog = true;
// // show the token receive dialog again for the next attempt
// receiveStore.showReceiveTokens = true;
// return;
// add the mint
await this.addMint( { url: token.getMint(tokenJson) });
}
// redeem the token
await this.redeem(receiveStore.receiveData.tokensBase64);
Expand Down
33 changes: 30 additions & 3 deletions src/components/SendTokenDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,9 @@
</vue-qrcode>
</q-responsive>
</div>
<div class="q-pb-xs q-ba-none q-gutter-sm" v-if="showAnimatedQR">
<div class="q-pb-xs q-ba-none q-gutter-sm">
<q-btn
v-if="showAnimatedQR"
flat
style="font-size: 12px"
color="grey"
Expand All @@ -219,6 +220,7 @@
Speed: {{ fragmentSpeedLabel }}
</q-btn>
<q-btn
v-if="showAnimatedQR"
flat
style="font-size: 12px"
class="q-ma-none"
Expand All @@ -228,6 +230,13 @@
<q-icon name="zoom_in" style="margin-right: 8px"></q-icon>
Size: {{ fragmentLengthLabel }}
</q-btn>
<q-badge
:color="!isV4Token ? 'primary' : 'grey'"
:label="isV4Token ? 'V4' : 'V3'"
class="q-my-sm q-mx-md"
@click="toggleTokenEncoding"
:outline="isV4Token"
/>
</div>
<q-card-section class="q-pa-sm">
<div class="row justify-center">
Expand Down Expand Up @@ -342,6 +351,7 @@ import { Buffer } from "buffer";
import { useCameraStore } from "src/stores/camera";
import { useP2PKStore } from "src/stores/p2pk";
import TokenInformation from "components/TokenInformation.vue";
import { getDecodedToken, getEncodedTokenV4, getEncodedToken } from "@cashu/cashu-ts";
import { mapActions, mapState, mapWritableState } from "pinia";
import ChooseMint from "components/ChooseMint.vue";
Expand Down Expand Up @@ -378,6 +388,7 @@ export default defineComponent({
fragmentIntervalFast: 150,
framentInervalSlow: 500,
fragmentSpeedLabel: "F",
isV4Token: false,
};
},
computed: {
Expand Down Expand Up @@ -464,6 +475,8 @@ export default defineComponent({
this.qrCodeFragment = "";
this.startQrCodeLoop();
}
// set isV4Token to true if token starts with 'cashuB'
this.isV4Token = val.startsWith("cashuB");
},
showSendTokens: function (val) {
if (val) {
Expand Down Expand Up @@ -531,6 +544,7 @@ export default defineComponent({
const ur = UR.fromBuffer(messageBuffer);
const firstSeqNum = 0;
this.encoder = new UREncoder(ur, this.currentFragmentLength, firstSeqNum);
clearInterval(this.qrInterval);
this.qrInterval = setInterval(() => {
this.qrCodeFragment = this.encoder.nextPart();
}, this.currentFragmentInterval);
Expand All @@ -554,7 +568,6 @@ export default defineComponent({
"### this.currentFragmentInterval",
this.currentFragmentInterval
);
clearInterval(this.qrInterval);
this.startQrCodeLoop();
},
changeSize: function () {
Expand All @@ -570,9 +583,23 @@ export default defineComponent({
this.fragmentLengthLabel = "M";
}
console.log("### this.currentFragmentLength", this.currentFragmentLength);
clearInterval(this.qrInterval);
this.startQrCodeLoop();
},
toggleTokenEncoding: function () {
const decodedToken = getDecodedToken(this.sendData.tokensBase64);
// if the token starts with 'cashuA', it is a v3 token
// if it starts with 'cashuB', it is a v4 token
if (this.sendData.tokensBase64.startsWith("cashuA")) {
this.sendData.tokensBase64 = getEncodedTokenV4(
decodedToken
);
} else {
this.sendData.tokensBase64 = getEncodedToken(
decodedToken
);
}
},
deleteThisToken: function () {
this.deleteToken(this.sendData.tokensBase64);
this.showSendTokens = false;
Expand Down
2 changes: 1 addition & 1 deletion src/components/TokenInformation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<q-icon name="toll" size="xs" class="q-mr-sm" />
<strong>{{ displayUnit }} </strong>
</q-chip>
<q-chip outline class="q-pa-md">
<q-chip outline class="q-pa-md q-ml-md">
<q-icon name="account_balance" size="xs" class="q-mr-xs" />
{{ tokenMintUrl }}
<q-spinner-hourglass v-if="addMintBlocking" size="sm" class="q-ml-sm" />
Expand Down
62 changes: 58 additions & 4 deletions src/contrib/cashu-ts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,73 @@ Go to the [docs](https://cashubtc.github.io/cashu-ts/docs) for detailed usage, o
npm i @cashu/cashu-ts
```

### Example
### Examples

#### Mint tokens

```typescript
import { CashuMint, CashuWallet, getEncodedToken } from '@cashu/cashu-ts';
import { CashuMint, CashuWallet, MintQuoteState } from '@cashu/cashu-ts';
const mintUrl = 'http://localhost:3338'; // the mint URL
const mint = new CashuMint(mintUrl);
const wallet = new CashuWallet(mint);
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.mintTokens(64, mintQuote.quote);
}
```

#### Melt tokens

```typescript
import { CashuMint, CashuWallet } from '@cashu/cashu-ts';
const mintUrl = 'http://localhost:3338'; // the mint URL
const mint = new CashuMint(mintUrl);
const wallet = new CashuWallet(mint);
const mintQuote = await wallet.mintQuote(64);
const tokens = await wallet.mintTokens(64, mintQuote.quote);

const invoice = 'lnbc......'; // Lightning invoice to pay
const meltQuote = await wallet.createMeltQuote(invoice);
const amountToSend = meltQuote.amount + meltQuote.fee_reserve;

// in a real wallet, we would coin select the correct amount of proofs from the wallet's storage
// instead of that, here we swap `proofs` with the mint to get the correct amount of proofs
const { returnChange: proofsToKeep, send: proofsToSend } = await wallet.send(amountToSend, proofs);
// store proofsToKeep in wallet ..

const meltResponse = await wallet.meltTokens(meltQuote, proofsToSend);
// store meltResponse.change in wallet ..
```

## Contribute

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

```
* `main`
|\
|\ \
| | * `hotfix`
| |
| * `staging`
| |\
| |\ \
| | | * `bugfix`
| | |
| | * `development`
| | |\
| | | * `feature1`
| | | |
| | |/
| | *
| | |\
| | | * `feature2`
| | |/
| |/
|/ (create new version)
```
3 changes: 2 additions & 1 deletion src/contrib/cashu-ts/cashu-ts.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"editor.formatOnSave": true,
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": true,
"editor.codeActionsOnSave": ["source.fixAll.eslint"]
"editor.codeActionsOnSave": ["source.fixAll.eslint"],
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"launch": {
"version": "0.2.0",
Expand Down
Loading

0 comments on commit c908459

Please sign in to comment.