diff --git a/README.md b/README.md index 816b993..4d69669 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,8 @@ If you want to run your private instance of nutstash where tokens are synced wit 1. change `/tmp/nutstash/nutstash-data` in `docker-compose.yml` to your preferred location. 1. change the owner of the directory to `1000` ===> `sudo chown -R 1000:1000 [directory-path]` 1. start nutstash with: `docker-compose up --build -d` -1. activate the options to sync to server in nutstash settings +1. activate the options to sync to server in nutstash settings + ## Contributing Read [this guide](/docs/contribute.md) on how to contribute. diff --git a/docker-compose.yml b/docker-compose.yml index 11b0ce3..ce098aa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,4 +17,4 @@ services: - /tmp/nutstash/nutstash-data:/app/data volumes: - nutstash-data: + nutstash-data: diff --git a/package-lock.json b/package-lock.json index 283f85d..f4cb903 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "svelte-cashu-wallet", - "version": "0.1.11", + "version": "0.1.12", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "svelte-cashu-wallet", - "version": "0.1.11", + "version": "0.1.12", "dependencies": { "@sveltejs/adapter-node": "^1.2.3", "daisyui": "^2.46.1", @@ -15,7 +15,7 @@ "ws": "^8.12.0" }, "devDependencies": { - "@cashu/cashu-ts": "0.7.0", + "@cashu/cashu-ts": "0.8.0-rc.3", "@sveltejs/adapter-auto": "^1.0.1", "@sveltejs/kit": "^1.0.0", "@typescript-eslint/eslint-plugin": "^5.45.0", @@ -40,14 +40,14 @@ } }, "node_modules/@cashu/cashu-ts": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cashu/cashu-ts/-/cashu-ts-0.7.0.tgz", - "integrity": "sha512-z7PtdI6NlctVWZwAe2Kj/9yyWYWJKRZ2tw9zFkGOfkH8qxEsEWqiaVQtXQpB6QydVdEIxs+U/qlyaDHCpiIp4g==", + "version": "0.8.0-rc.3", + "resolved": "https://registry.npmjs.org/@cashu/cashu-ts/-/cashu-ts-0.8.0-rc.3.tgz", + "integrity": "sha512-O0BaUFXkKypgNH9vllPh19Sk9+2bU9NzqfF6nQgJP8ZgFDYd9p1Pefn8TQv/8rltfXuMIIOv/qZgrCvJuZE6rQ==", "dev": true, "dependencies": { "@gandlaf21/bolt11-decode": "^3.0.6", - "@noble/secp256k1": "^1.7.0", - "axios": "^1.2.1", + "@noble/curves": "^1.0.0", + "axios": "^1.4.0", "buffer": "^6.0.3" } }, @@ -157,6 +157,33 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@noble/curves": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", + "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "1.3.0" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, "node_modules/@noble/hashes": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-0.5.9.tgz", @@ -906,9 +933,9 @@ } }, "node_modules/axios": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz", - "integrity": "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -4004,14 +4031,14 @@ }, "dependencies": { "@cashu/cashu-ts": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cashu/cashu-ts/-/cashu-ts-0.7.0.tgz", - "integrity": "sha512-z7PtdI6NlctVWZwAe2Kj/9yyWYWJKRZ2tw9zFkGOfkH8qxEsEWqiaVQtXQpB6QydVdEIxs+U/qlyaDHCpiIp4g==", + "version": "0.8.0-rc.3", + "resolved": "https://registry.npmjs.org/@cashu/cashu-ts/-/cashu-ts-0.8.0-rc.3.tgz", + "integrity": "sha512-O0BaUFXkKypgNH9vllPh19Sk9+2bU9NzqfF6nQgJP8ZgFDYd9p1Pefn8TQv/8rltfXuMIIOv/qZgrCvJuZE6rQ==", "dev": true, "requires": { "@gandlaf21/bolt11-decode": "^3.0.6", - "@noble/secp256k1": "^1.7.0", - "axios": "^1.2.1", + "@noble/curves": "^1.0.0", + "axios": "^1.4.0", "buffer": "^6.0.3" } }, @@ -4093,6 +4120,23 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@noble/curves": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", + "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", + "dev": true, + "requires": { + "@noble/hashes": "1.3.0" + }, + "dependencies": { + "@noble/hashes": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", + "dev": true + } + } + }, "@noble/hashes": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-0.5.9.tgz", @@ -4580,9 +4624,9 @@ } }, "axios": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz", - "integrity": "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "dev": true, "requires": { "follow-redirects": "^1.15.0", diff --git a/package.json b/package.json index b544607..c87b04e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte-cashu-wallet", - "version": "0.1.11", + "version": "0.1.12", "private": true, "scripts": { "dev": "vite dev", @@ -14,7 +14,7 @@ "format": "prettier --plugin-search-dir . --write ." }, "devDependencies": { - "@cashu/cashu-ts": "0.7.0", + "@cashu/cashu-ts": "0.8.0-rc.3", "@sveltejs/adapter-auto": "^1.0.1", "@sveltejs/kit": "^1.0.0", "@typescript-eslint/eslint-plugin": "^5.45.0", diff --git a/src/actions/walletActions.ts b/src/actions/walletActions.ts new file mode 100644 index 0000000..473fa10 --- /dev/null +++ b/src/actions/walletActions.ts @@ -0,0 +1,39 @@ +import { deriveKeysetId, type MintKeys } from '@cashu/cashu-ts'; +import type { Mint } from '../model/mint'; +import { mints } from '../stores/mints'; +import { get } from 'svelte/store'; +import { toast } from '../stores/toasts'; + +// export const send = async () => { + +// } + +// export const mint = async () => { + +// } + +// export const receive = async () => { + +// } + +// export const melt = async () => { + +// } + +export const updateMintKeys = (mint: Mint, newKeys: MintKeys) => { + const allMints = [...get(mints)]; + const toBeUpdated = allMints.find((m) => mint.mintURL === m.mintURL); + if (!toBeUpdated) { + toast( + 'error', + 'the keys of this mint have changed, but could not be updated in the wallet', + 'Error' + ); + throw new Error('could not update mint keys'); + } + toBeUpdated.keys = newKeys; + const newKeyset = deriveKeysetId(newKeys); + toBeUpdated.keysets = [newKeyset, ...toBeUpdated.keysets]; + mints.set(allMints); + toast('info', 'the new keyset ID is: ' + newKeyset, 'The keys of this mint have rotated'); +}; diff --git a/src/comp/Setting.svelte b/src/comp/Setting.svelte index 076a731..a8db973 100644 --- a/src/comp/Setting.svelte +++ b/src/comp/Setting.svelte @@ -59,7 +59,7 @@ History {#if PUBLIC_SELFHOSTED} - + {/if}
Cashu
diff --git a/src/comp/elements/CoinSelection.svelte b/src/comp/elements/CoinSelection.svelte index f0d590f..c2e3dc1 100644 --- a/src/comp/elements/CoinSelection.svelte +++ b/src/comp/elements/CoinSelection.svelte @@ -2,7 +2,7 @@ import type { Mint } from '../../model/mint'; import AvailableTokensTable from '../tokens/AvailableTokensTable.svelte'; import { getAmountForTokenSet } from '../util/walletUtils'; - import type { Proof } from "@cashu/cashu-ts"; + import type { Proof } from '@cashu/cashu-ts'; export let mint: Mint; export let amount: number = 0; diff --git a/src/comp/elements/ScanLN.svelte b/src/comp/elements/ScanLN.svelte index faa138c..e50eccd 100644 --- a/src/comp/elements/ScanLN.svelte +++ b/src/comp/elements/ScanLN.svelte @@ -8,7 +8,7 @@ let qrScanner: Html5QrcodeScanner; - function onScanSuccess(decodedText:string, decodedResult: any) { + function onScanSuccess(decodedText: string, decodedResult: any) { // handle the scanned code as you like, for example: scannedlnInvoice = decodedText; if (browser) { diff --git a/src/comp/elements/ScanNpub.svelte b/src/comp/elements/ScanNpub.svelte index 311cebb..707dc03 100644 --- a/src/comp/elements/ScanNpub.svelte +++ b/src/comp/elements/ScanNpub.svelte @@ -7,7 +7,7 @@ let qrScanner: Html5QrcodeScanner; - function onScanSuccess(decodedText: string, decodedResult:any) { + function onScanSuccess(decodedText: string, decodedResult: any) { // handle the scanned code as you like, for example: scannedNpub = decodedText; if (browser) { diff --git a/src/comp/elements/SelfhostedSetting.svelte b/src/comp/elements/SelfhostedSetting.svelte index bd231e5..41dcc9e 100644 --- a/src/comp/elements/SelfhostedSetting.svelte +++ b/src/comp/elements/SelfhostedSetting.svelte @@ -7,63 +7,60 @@ let isMintsChecked = false; let isTokensChecked = false; - let isLoading = false + let isLoading = false; const handleToggleSync = () => { if (!$selfhostedSyncTokens) { toast('info', 'Reload app to activate', 'Sync tokens to server'); } }; - const restoreFromServer= async () =>{ - isLoading = true - try { - if (isMintsChecked) { - await restoreMints() - } - if (isTokensChecked) { - await restoreTokens() - } - toast('success', 'Successfully restored from server','Done!') - } catch (error) { - console.log(error) - toast('error', 'Error while restoring from server','Could not restore') - } finally { - isLoading = false - } - modalOpen = false - } + const restoreFromServer = async () => { + isLoading = true; + try { + if (isMintsChecked) { + await restoreMints(); + } + if (isTokensChecked) { + await restoreTokens(); + } + toast('success', 'Successfully restored from server', 'Done!'); + } catch (error) { + console.log(error); + toast('error', 'Error while restoring from server', 'Could not restore'); + } finally { + isLoading = false; + } + modalOpen = false; + }; - const restoreMints =async () => { + const restoreMints = async () => { try { - const data = await fetch("/api/backup/mints") - const mintsFromServer = await data.json() + const data = await fetch('/api/backup/mints'); + const mintsFromServer = await data.json(); if (!mintsFromServer) { - toast('warning', 'no mints found on server','Mints not restored') - return + toast('warning', 'no mints found on server', 'Mints not restored'); + return; } - mints.set(mintsFromServer) + mints.set(mintsFromServer); } catch (error) { - console.error(error) - toast('error', 'error while mints restoring from server','Server error') + console.error(error); + toast('error', 'error while mints restoring from server', 'Server error'); } - } + }; - const restoreTokens =async () => { + const restoreTokens = async () => { try { - const data = await fetch("/api/backup/tokens") - const tokensFromServer = await data.json() + const data = await fetch('/api/backup/tokens'); + const tokensFromServer = await data.json(); if (!tokensFromServer) { - toast('warning', 'no tokens found on server','Tokens not restored') - return + toast('warning', 'no tokens found on server', 'Tokens not restored'); + return; } - token.set(tokensFromServer) - + token.set(tokensFromServer); } catch (error) { - console.error(error) - toast('error', 'error while tokens restoring from server','Server error') - + console.error(error); + toast('error', 'error while tokens restoring from server', 'Server error'); } - } - + };
Selfhosted
@@ -78,7 +75,7 @@ on:click={handleToggleSync} /> -
+
@@ -93,11 +90,19 @@ Tokens - +
- + diff --git a/src/comp/mint/MintRow.svelte b/src/comp/mint/MintRow.svelte index 766138f..317c82f 100644 --- a/src/comp/mint/MintRow.svelte +++ b/src/comp/mint/MintRow.svelte @@ -7,7 +7,7 @@ import { toast } from '../../stores/toasts'; import { CashuMint } from '@cashu/cashu-ts'; import { browser } from '$app/environment'; - + export let mintIndex: number; export let mint: Mint; export let activeMint; @@ -56,7 +56,7 @@ }; const copyShareLink = () => { - const text = encodeURI('https://wallet.nutstash.app'+ '/?mint=' + mint.mintURL); + const text = encodeURI('https://wallet.nutstash.app' + '/?mint=' + mint.mintURL); if (browser) { if (document.queryCommandSupported && document.queryCommandSupported('copy')) { var textarea = document.createElement('textarea'); diff --git a/src/comp/mint/MintSwap.svelte b/src/comp/mint/MintSwap.svelte index 69b65ed..d388dbf 100644 --- a/src/comp/mint/MintSwap.svelte +++ b/src/comp/mint/MintSwap.svelte @@ -6,6 +6,7 @@ import { toast } from '../../stores/toasts'; import { CashuMint, CashuWallet } from '@cashu/cashu-ts'; import LoadingCenter from '../LoadingCenter.svelte'; + import { updateMintKeys } from '../../actions/walletActions'; export let active; let swapOutMint: Mint; @@ -37,13 +38,13 @@ try { isPrepare = true; const cashuSwapInMint = new CashuMint(swapInMint.mintURL); - const cashuSwapInWallet = new CashuWallet(swapInMint.keys, cashuSwapInMint); + const cashuSwapInWallet = new CashuWallet(cashuSwapInMint, swapInMint.keys); const { pr, hash } = await cashuSwapInWallet.requestMint(swapAmount); paymentHash = hash; invoice = pr; const cashuSwapOutMint = new CashuMint(swapOutMint.mintURL); - const cashuSwapOutWallet = new CashuWallet(swapOutMint.keys, cashuSwapOutMint); + const cashuSwapOutWallet = new CashuWallet(cashuSwapOutMint, swapInMint.keys); const loadedFees = await cashuSwapOutWallet.getFee(pr); if (loadedFees + swapAmount > availableTokens) { @@ -68,18 +69,24 @@ try { isPerform = true; const cashuSwapInMint = new CashuMint(swapInMint.mintURL); - const cashuSwapInWallet = new CashuWallet(swapInMint.keys, cashuSwapInMint); + const cashuSwapInWallet = new CashuWallet(cashuSwapInMint, swapInMint.keys); const cashuSwapOutMint = new CashuMint(swapOutMint.mintURL); - const cashuSwapOutWallet = new CashuWallet(swapOutMint.keys, cashuSwapOutMint); + const cashuSwapOutWallet = new CashuWallet(cashuSwapOutMint, swapOutMint.keys); const proofsToSend = getTokensToSend( swapAmount + fees, getTokensForMint(swapOutMint, $token) ); - const { returnChange, send } = await cashuSwapOutWallet.send(swapAmount + fees, proofsToSend); - + const { + returnChange, + send, + newKeys: newOutKeys + } = await cashuSwapOutWallet.send(swapAmount + fees, proofsToSend); + if (newOutKeys) { + updateMintKeys(swapOutMint, newOutKeys); + } console.log(send); // remove sent tokens from storage token.update((state) => { @@ -88,8 +95,15 @@ if (returnChange) { token.update((state) => [...returnChange, ...state]); } - const { isPaid, preimage, change } = await cashuSwapOutWallet.payLnInvoice(invoice, send); - + const { + isPaid, + preimage, + change, + newKeys: newInKeys + } = await cashuSwapOutWallet.payLnInvoice(invoice, send); + if (newInKeys) { + updateMintKeys(swapOutMint, newInKeys); + } if (!isPaid) { token.update((state) => [...send, ...state]); isPerform = false; @@ -104,7 +118,13 @@ token.update((state) => [...change, ...state]); } - const newProofs = await cashuSwapInWallet.requestTokens(swapAmount, paymentHash); + const { proofs: newProofs, newKeys } = await cashuSwapInWallet.requestTokens( + swapAmount, + paymentHash + ); + if (newKeys) { + updateMintKeys(swapOutMint, newKeys); + } token.update((state) => [...newProofs, ...state]); toast('success', 'The swap has successfully been completed', 'Swap complete'); isPerform = false; diff --git a/src/comp/mint/Minting.svelte b/src/comp/mint/Minting.svelte index 34e7701..5fcf5d9 100644 --- a/src/comp/mint/Minting.svelte +++ b/src/comp/mint/Minting.svelte @@ -12,7 +12,8 @@ import { getKeysetsOfTokens } from '../util/walletUtils'; import { mintRequests } from '../../stores/mintReqs'; import { onMount } from 'svelte'; - import type { Proof } from "@cashu/cashu-ts"; + import type { Proof } from '@cashu/cashu-ts'; + import { updateMintKeys } from '../../actions/walletActions'; export let mint: Mint; export let active; @@ -42,7 +43,7 @@ mintingHash = mintReq?.paymentHash; qrCode = mintReq?.invoice; const cashuMint = new CashuMint(mint.mintURL); - wallet = new CashuWallet(mint.keys, cashuMint); + wallet = new CashuWallet(cashuMint, mint.keys); mintTokens(); } }); @@ -52,12 +53,17 @@ isComplete = false; isLoading = true; const cashuMint = new CashuMint(mint.mintURL); - wallet = new CashuWallet(mint.keys, cashuMint); + wallet = new CashuWallet(cashuMint, mint.keys); const { pr, hash } = await wallet.requestMint(mintAmount); mintingHash = hash; qrCode = pr; mintRequests.update((state) => [ - { invoice: qrCode??'', mintUrl: mint.mintURL, isCompleted: false, paymentHash: mintingHash??'' }, + { + invoice: qrCode ?? '', + mintUrl: mint.mintURL, + isCompleted: false, + paymentHash: mintingHash ?? '' + }, ...state ]); await mintTokens(); @@ -72,8 +78,10 @@ try { if (wallet && mintingHash) { isPolling = true; - const tokens: Array = await wallet.requestTokens(mintAmount, mintingHash); - console.log(tokens); + const { proofs: tokens, newKeys } = await wallet.requestTokens(mintAmount, mintingHash); + if (newKeys) { + updateMintKeys(mint, newKeys); + } token.update((state) => [...state, ...tokens]); history.update((state) => [ diff --git a/src/comp/plugin/NostrSocket.svelte b/src/comp/plugin/NostrSocket.svelte index 57fa441..0ce87ac 100644 --- a/src/comp/plugin/NostrSocket.svelte +++ b/src/comp/plugin/NostrSocket.svelte @@ -21,8 +21,7 @@ const getPubKey = async (): Promise => { return $useExternalNostrKey - ? - await window.nostr.getPublicKey() + ? await window.nostr.getPublicKey() : await Promise.resolve($nostrPubKey); }; @@ -92,8 +91,7 @@ return; } const decodedMessage = $useExternalNostrKey - ? - await window.nostr.nip04.decrypt(event.pubkey, event.content) + ? await window.nostr.nip04.decrypt(event.pubkey, event.content) : await nostrTools.nip04.decrypt($nostrPrivKey, event.pubkey, event.content); let token; diff --git a/src/comp/plugin/StorageManager.svelte b/src/comp/plugin/StorageManager.svelte index 84e6565..0c3def0 100644 --- a/src/comp/plugin/StorageManager.svelte +++ b/src/comp/plugin/StorageManager.svelte @@ -3,12 +3,12 @@ //todo update stores without reloading window if (browser) { window.addEventListener('storage', (e) => { - if (!e.key ) { - return + if (!e.key) { + return; } console.log(`Key Changed: ${e.key}`); console.log(`New Value: ${e.newValue}`); - window.localStorage.setItem(e.key, e.newValue??''); + window.localStorage.setItem(e.key, e.newValue ?? ''); window.location.reload(); }); } diff --git a/src/comp/tokens/InboxRow.svelte b/src/comp/tokens/InboxRow.svelte index 20f7973..2dc9777 100644 --- a/src/comp/tokens/InboxRow.svelte +++ b/src/comp/tokens/InboxRow.svelte @@ -19,6 +19,7 @@ import type { Contact } from '../../model/contact'; import type { Mint } from '../../model/mint'; import { onMount } from 'svelte'; + import { updateMintKeys } from '../../actions/walletActions'; export let nostrMessage: NostrMessage; export let i: number; @@ -98,13 +99,16 @@ } const cashuMint: CashuMint = new CashuMint(mint.mintURL); - const cashuWallet: CashuWallet = new CashuWallet(mint.keys, cashuMint); + const cashuWallet: CashuWallet = new CashuWallet(cashuMint, mint.keys); const encodedProofs = getEncodedToken(nostrMessage.token); isLoading = true; //todo tokens with errors are not handled - const { proofs, tokensWithErrors } = await cashuWallet.receive(encodedProofs); - + const { token: tokens, tokensWithErrors, newKeys } = await cashuWallet.receive(encodedProofs); + if (newKeys) { + updateMintKeys(mint, newKeys); + } + const proofs = tokens.token.map((t) => t.proofs).flat(); token.update((state) => [...proofs, ...state]); nostrMessages.update((state) => { diff --git a/src/comp/tokens/InboxTable.svelte b/src/comp/tokens/InboxTable.svelte index 0228db5..d5e84f0 100644 --- a/src/comp/tokens/InboxTable.svelte +++ b/src/comp/tokens/InboxTable.svelte @@ -7,6 +7,7 @@ import { token } from '../../stores/tokens'; import { getAmountForTokenSet } from '../util/walletUtils'; import InboxRow from './InboxRow.svelte'; + import { updateMintKeys } from '../../actions/walletActions'; $: page = 20; $: nostrMessagesSub = $nostrMessages.slice(0, page); @@ -41,14 +42,22 @@ }; } - const wallet = new CashuWallet(keys, mint); + const wallet = new CashuWallet(mint, keys); //todo: does not handle multiple tokens correctly const spentProofs = await wallet.checkProofsSpent(nM.token.token[0].proofs); const proofsToReceive = nM.token.token[0].proofs.filter((p) => !spentProofs.includes(p)); if (proofsToReceive.length > 0) { - const { proofs, tokensWithErrors } = await wallet.receive(getEncodedToken(nM.token)); - + const { + token: tokens, + tokensWithErrors, + newKeys + } = await wallet.receive(getEncodedToken(nM.token)); + const storedMint = $mints.find((m) => mint.mintUrl === m.mintURL); + if (newKeys && storedMint) { + updateMintKeys(storedMint, newKeys); + } + const proofs = tokens.token.map((t) => t.proofs).flat(); token.update((state) => [...proofs, ...state]); totalReceived += getAmountForTokenSet(proofs); if (tokensWithErrors) { diff --git a/src/comp/tokens/TokenRow.svelte b/src/comp/tokens/TokenRow.svelte index 920e45e..e2a483d 100644 --- a/src/comp/tokens/TokenRow.svelte +++ b/src/comp/tokens/TokenRow.svelte @@ -9,6 +9,7 @@ import { pendingTokens } from '../../stores/pendingtokens'; import { browser } from '$app/environment'; import type { Mint } from '../../model/mint'; + import { updateMintKeys } from '../../actions/walletActions'; export let mint: Mint | undefined; export let isSelected = false; @@ -26,7 +27,7 @@ } const cashuMint: CashuMint = new CashuMint(mint.mintURL); - const cashuWallet: CashuWallet = new CashuWallet(mint.keys, cashuMint); + const cashuWallet: CashuWallet = new CashuWallet(cashuMint, mint.keys); try { await checkTokenSpent(); try { @@ -34,7 +35,15 @@ const encodedProofs = getEncodedToken({ token: [{ proofs: [token], mint: getMintForToken(token, $mints)?.mintURL }] }); - const { proofs, tokensWithErrors } = await cashuWallet.receive(encodedProofs); + const { + token: tokens, + tokensWithErrors, + newKeys + } = await cashuWallet.receive(encodedProofs); + const proofs = tokens.token.map((t) => t.proofs).flat(); + if (newKeys) { + updateMintKeys(mint, newKeys); + } if (tokensWithErrors) { throw new Error('could not redeem token'); } @@ -76,7 +85,7 @@ try { const cashuMint: CashuMint = new CashuMint(mint.mintURL); - const cashuWallet: CashuWallet = new CashuWallet(mint.keys, cashuMint); + const cashuWallet: CashuWallet = new CashuWallet(cashuMint, mint.keys); const spentProofs = await cashuWallet.checkProofsSpent([token]); let hasBeenReceived = false; if (!$pendingTokens.includes(token)) { diff --git a/src/comp/util/walletUtils.ts b/src/comp/util/walletUtils.ts index 5cb4617..19bd2f4 100644 --- a/src/comp/util/walletUtils.ts +++ b/src/comp/util/walletUtils.ts @@ -1,7 +1,6 @@ import type { Mint } from '../../../src/model/mint'; import type { Proof } from '@cashu/cashu-ts'; - /** * returns a subset of tokens, so that not all tokens are sent to mint for smaller amounts. * @param amount diff --git a/src/comp/wallet/Melting.svelte b/src/comp/wallet/Melting.svelte index 293456e..462d248 100644 --- a/src/comp/wallet/Melting.svelte +++ b/src/comp/wallet/Melting.svelte @@ -1,5 +1,5 @@