v3 broken

This commit is contained in:
minibits-cash
2026-01-10 00:39:30 +01:00
parent d80232f700
commit 658e62cd75
28 changed files with 365 additions and 242 deletions
-1
View File
@@ -1 +0,0 @@
019b98cc-e66d-7947-b6a6-e253c1830c03
+39
View File
@@ -8,7 +8,46 @@ const { withSentryConfig } = require("@sentry/react-native/metro");
* @type {import('@react-native/metro-config').MetroConfig}
*/
const config = {
resolver: {
// Ensure Metro can resolve .cjs files (CommonJS modules)
sourceExts: ['jsx', 'js', 'ts', 'tsx', 'json', 'cjs'],
// Workaround for Unicode character issues in @noble/curves
// Files with Greek letters (β, α) cause "Property β does not exist" errors in Hermes
/*resolveRequest: (context, moduleName, platform) => {
// Force cashu-ts to use pre-built CJS bundle
if (moduleName === '@cashu/cashu-ts') {
return {
filePath: context.resolveRequest(context, '@cashu/cashu-ts/lib/cashu-ts.cjs', platform).filePath,
type: 'sourceFile',
};
}
// Block problematic @noble/curves files that contain Unicode characters
// Allow only essential modules needed for secp256k1
if (moduleName.startsWith('@noble/curves/')) {
const allowed = [
'secp256k1',
'abstract/modular',
'abstract/weierstrass',
'_shortw_utils',
'utils'
];
const isAllowed = allowed.some(path => moduleName.includes(path));
if (!isAllowed) {
// Return empty stub for blocked imports (contains Unicode chars incompatible with Hermes)
const stubPath = require('path').resolve(__dirname, 'node_modules/.metro-stub.js');
return {
filePath: stubPath,
type: 'sourceFile',
};
}
}
// Default resolution
return context.resolveRequest(context, moduleName, platform);
},*/
},
};
module.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "minibits_wallet",
"version": "0.3.4-beta.13",
"version": "0.3.4-beta.14",
"private": true,
"scripts": {
"android:clean": "cd android && ./gradlew clean",
@@ -21,7 +21,7 @@
"machine-translate": "npx @inlang/cli machine translate --project minibits.inlang"
},
"dependencies": {
"@cashu/cashu-ts": "minibits-cash/cashu-ts#e97b1a4ee9a7ddbb1468302c6996a9d6d3efcb6f",
"@cashu/cashu-ts": "3.2.2",
"@fortawesome/fontawesome-svg-core": "^7.1.0",
"@fortawesome/free-brands-svg-icons": "^7.1.0",
"@fortawesome/free-regular-svg-icons": "^7.1.0",
+31 -48
View File
@@ -1,53 +1,36 @@
diff --git a/node_modules/@scure/bip32/index.ts b/node_modules/@scure/bip32/index.ts
index 0c9c91c..14c9ae2 100644
--- a/node_modules/@scure/bip32/index.ts
+++ b/node_modules/@scure/bip32/index.ts
@@ -25,6 +25,7 @@ import { bytesToHex, concatBytes, createView, hexToBytes, utf8ToBytes } from '@n
diff --git a/node_modules/@scure/bip32/lib/esm/index.js b/node_modules/@scure/bip32/lib/esm/index.js
index ea306d0..c0ed23e 100644
--- a/node_modules/@scure/bip32/lib/esm/index.js
+++ b/node_modules/@scure/bip32/lib/esm/index.js
@@ -25,6 +25,8 @@ import { bytesToHex, concatBytes, createView, hexToBytes, utf8ToBytes } from '@n
import { secp256k1 as secp } from '@noble/curves/secp256k1';
import { mod } from '@noble/curves/abstract/modular';
import { createBase58check } from '@scure/base';
+import QuickCrypto from 'react-native-quick-crypto';
+import quickCrypto from 'react-native-quick-crypto'
+
const Point = secp.ProjectivePoint;
const base58check = createBase58check(sha256);
@@ -114,7 +115,8 @@ export class HDKey {
seed.length
);
}
- const I = hmac(sha512, MASTER_SECRET, seed);
+ // const I = hmac(sha512, MASTER_SECRET, seed);
+ const I = new Uint8Array(QuickCrypto.createHmac('sha512', MASTER_SECRET).update(seed).digest());
return new HDKey({
versions,
chainCode: I.slice(32),
@@ -237,7 +239,8 @@ export class HDKey {
// Normal child: serP(point(kpar)) || ser32(index)
data = concatBytes(this.pubKey, data);
}
- const I = hmac(sha512, this.chainCode, data);
+ //const I = hmac(sha512, this.chainCode, data);
+ const I = new Uint8Array(QuickCrypto.createHmac('sha512', this.chainCode).update(data).digest())
const childTweak = bytesToNumber(I.slice(0, 32));
const chainCode = I.slice(32);
if (!secp.utils.isValidPrivateKey(childTweak)) {
diff --git a/node_modules/@scure/bip32/package.json b/node_modules/@scure/bip32/package.json
index e866fba..6389575 100644
--- a/node_modules/@scure/bip32/package.json
+++ b/node_modules/@scure/bip32/package.json
@@ -6,15 +6,8 @@
"index.ts",
"./lib"
],
- "main": "./lib/index.js",
- "module": "./lib/esm/index.js",
+ "main": "./index.ts",
"types": "./lib/index.d.ts",
- "exports": {
- ".": {
- "import": "./lib/esm/index.js",
- "require": "./lib/index.js"
- }
- },
"dependencies": {
"@noble/curves": "~1.8.1",
"@noble/hashes": "~1.7.1",
function bytesToNumber(bytes) {
@@ -89,7 +91,9 @@ export class HDKey {
throw new Error('HDKey: seed length must be between 128 and 512 bits; 256 bits is advised, got ' +
seed.length);
}
- const I = hmac(sha512, MASTER_SECRET, seed);
+ // const I = hmac(sha512, MASTER_SECRET, seed);
+ console.log('[bip32.fromMasterSeed] Using ESM quickCrypto HMAC');
+ const I = new Uint8Array(quickCrypto.createHmac('sha512', MASTER_SECRET).update(seed).digest());
return new HDKey({
versions,
chainCode: I.slice(32),
@@ -206,7 +210,10 @@ export class HDKey {
// Normal child: serP(point(kpar)) || ser32(index)
data = concatBytes(this.pubKey, data);
}
- const I = hmac(sha512, this.chainCode, data);
+ // const I = hmac(sha512, this.chainCode, data);
+ console.log('[bip32.deriveChild] Using ESM quickCrypto HMAC');
+ const I = new Uint8Array(quickCrypto.createHmac('sha512', this.chainCode).update(data).digest())
+
const childTweak = bytesToNumber(I.slice(0, 32));
const chainCode = I.slice(32);
if (!secp.utils.isValidPrivateKey(childTweak)) {
+23 -2
View File
@@ -1,5 +1,26 @@
diff --git a/node_modules/@scure/bip39/esm/index.js b/node_modules/@scure/bip39/esm/index.js
index d5734b0..deb1491 100644
--- a/node_modules/@scure/bip39/esm/index.js
+++ b/node_modules/@scure/bip39/esm/index.js
@@ -32,6 +32,7 @@ import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2';
import { sha256, sha512 } from '@noble/hashes/sha2';
import { abytes, anumber, randomBytes } from '@noble/hashes/utils';
import { utils as baseUtils } from '@scure/base';
+import quickCrypto from 'react-native-quick-crypto'
// Japanese wordlist
const isJapanese = (wordlist) => wordlist[0] === '\u3042\u3044\u3053\u304f\u3057\u3093';
// Normalization replaces equivalent sequences of characters
@@ -157,5 +158,7 @@ export function mnemonicToSeed(mnemonic, passphrase = '') {
* // new Uint8Array([...64 bytes])
*/
export function mnemonicToSeedSync(mnemonic, passphrase = '') {
- return pbkdf2(sha512, normalize(mnemonic).nfkd, psalt(passphrase), { c: 2048, dkLen: 64 });
+ console.log('[bip39.mnemonicToSeedSync] Using ESM quickCrypto PBKDF2 Sync');
+ return new Uint8Array(quickCrypto.pbkdf2Sync(normalize(mnemonic).nfkd, psalt(passphrase), 2048, 64, 'sha512'));
+ //return pbkdf2(sha512, normalize(mnemonic).nfkd, psalt(passphrase), { c: 2048, dkLen: 64 });
}
diff --git a/node_modules/@scure/bip39/src/index.ts b/node_modules/@scure/bip39/src/index.ts
index 4284c3e..6ff83b2 100644
index 4284c3e..71e39e9 100644
--- a/node_modules/@scure/bip39/src/index.ts
+++ b/node_modules/@scure/bip39/src/index.ts
@@ -33,6 +33,7 @@ import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2';
@@ -16,7 +37,7 @@ index 4284c3e..6ff83b2 100644
export function mnemonicToSeedSync(mnemonic: string, passphrase = ''): Uint8Array {
- return pbkdf2(sha512, normalize(mnemonic).nfkd, psalt(passphrase), { c: 2048, dkLen: 64 });
+ // return pbkdf2(sha512, normalize(mnemonic).nfkd, psalt(passphrase), { c: 2048, dkLen: 64 });
+
+ console.log('[mnemonicToSeedSync] Using TS quickCrypto PBKDF2 Sync');
+ const updated = new Uint8Array(QuickCrypto.pbkdf2Sync(normalize(mnemonic).nfkd, psalt(passphrase), 2048, 64, 'sha512'));
+ // console.log('[@scure.bip39.mnemonicToSeedSync] Patched to use QuickCrypto.pbkdf2Sync')
+ return updated
+7 -6
View File
@@ -97,6 +97,12 @@ function App() {
if (isInternetReachable === true) {
if(userSettingsStore.isOnboarded === false) {
log.trace('[App] User not onboarded → new install, skipping device re-enrollment')
setIsDeviceAuthenticated(true)
return
}
if(authStore.isRefreshTokenExpired) {
log.trace('[App] Network is online and refresh token expired → attempting device re-enrollment')
@@ -110,12 +116,7 @@ function App() {
log.trace('[App] Device re-enrollment successful')
} catch (e: any) {
if (e.name !== Err.NOTFOUND_ERROR) {
log.error('[App] Device re-enrollment failed', { message: e.message })
} else {
// Expected on fresh install
userSettingsStore.setIsOnboarded(false)
}
log.error('[App] Device re-enrollment failed', { message: e.message })
} finally {
// Always unblock the app
setIsDeviceAuthenticated(true)
+2 -2
View File
@@ -3,7 +3,7 @@ import { View, ScrollView, LayoutAnimation, Platform, UIManager, ViewStyle } fro
import { BottomModal, Button, Icon, ListItem, Text } from '../components'
import AppError, { Err } from '../utils/AppError'
import { spacing, useThemeColor, colors } from '../theme'
import { isObj } from '@cashu/cashu-ts/src/utils'
import { CashuUtils } from '../services/cashu/cashuUtils'
import JSONTree from 'react-native-json-tree'
import Clipboard from '@react-native-clipboard/clipboard'
import { useStores } from '../models'
@@ -85,7 +85,7 @@ export const ErrorModal: FC<ErrorModalProps> = function ({ error }) {
/>
) : (
<>
{error.params && isObj(error.params) && (
{error.params && CashuUtils.isObj(error.params) && (
<>
{isParamsVisible ? (
<>
+2 -2
View File
@@ -4,7 +4,7 @@ import {
type GetInfoResponse,
type MintKeys as CashuMintKeys,
type MintKeyset as CashuMintKeyset,
CashuMint,
Mint as CashuMint,
} from '@cashu/cashu-ts'
import {colors, getRandomIconColor} from '../theme'
import { log } from '../services'
@@ -16,7 +16,7 @@ import { generateId } from '../utils/utils'
import { Proof } from './Proof'
import { CashuProof, CashuUtils } from '../services/cashu/cashuUtils'
ß
export type MintBalance = {
mintUrl: string
balances: {
+5 -3
View File
@@ -13,7 +13,9 @@ import {
import {log} from '../services/logService'
import AppError, { Err } from '../utils/AppError'
import {
CashuMint,
Mint as CashuMint,
GetKeysetsResponse,
GetKeysResponse,
MintActiveKeys,
MintAllKeysets,
type MintKeys as CashuMintKeys,
@@ -124,8 +126,8 @@ export const MintsStoreModel = types
const newMint = new CashuMint(mintUrl)
// get fresh keysets
const keySetResult: MintAllKeysets = yield newMint.getKeySets()
const keysResult: MintActiveKeys = yield newMint.getKeys()
const keySetResult: GetKeysetsResponse = yield newMint.getKeySets()
const keysResult: GetKeysResponse = yield newMint.getKeys()
const {keysets} = keySetResult
const {keysets: keys} = keysResult
+9 -1
View File
@@ -310,7 +310,7 @@ import {
log.error('[revertToSpendable]', 'Proof instance is not alive, aborting state update', { secret: proof.secret })
continue
}
proof.setMintUrl(updatedMintUrl)
}
}
@@ -321,6 +321,14 @@ import {
Database.updateProofsMintUrl(currentMintUrl, updatedMintUrl)
log.trace('[updateMintUrl] Updated mint URL in proofs')
},
// Action for importing proofs from backup without validation or side effects
importProofs(proofs: Proof[]) {
for (const proof of proofs) {
self.proofs.put(ProofModel.create(proof))
}
log.trace('[importProofs]', `Imported ${proofs.length} proofs from backup`)
},
}))
// ───────────────────── DERIVED VIEWS ─────────────────────
+113 -76
View File
@@ -1,20 +1,20 @@
import {Instance, SnapshotOut, types, flow, getRoot, getSnapshot} from 'mobx-state-tree'
import {
CashuMint,
CashuWallet,
MeltQuoteResponse,
setGlobalRequestOptions,
import {
Mint as CashuMint,
Wallet as CashuWallet,
MeltQuoteBolt11Response,
setGlobalRequestOptions,
type MintKeys,
type MintKeyset,
MintAllKeysets,
MintActiveKeys,
Token,
MeltProofsResponse,
MeltProofsResponse,
CheckStateEnum,
OutputAmounts,
MintQuoteResponse,
GetKeysetsResponse,
GetKeysResponse,
MintQuoteBolt11Response,
type ProofState,
type OperationCounters,
} from '@cashu/cashu-ts'
import { isObj } from '@cashu/cashu-ts/src/utils'
import { JS_BUNDLE_VERSION } from '@env'
import {KeyChain, MinibitsClient, WalletKeys} from '../services'
import {log} from '../services/logService'
@@ -25,7 +25,6 @@ import { Proof } from './Proof'
import { InFlightRequest, Mint } from './Mint'
import { getRootStore } from './helpers/getRootStore'
import { getUnixTime } from 'date-fns/getUnixTime'
//refresh
/*
@@ -43,7 +42,6 @@ export type ReceiveParams = {
token: string | Token,
options?: {
keysetId?: string;
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<CashuProof>;
counter?: number;
pubkey?: string;
@@ -57,7 +55,6 @@ export type SendParams = {
amount: number,
proofs: Array<CashuProof>,
options?: {
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<CashuProof>;
counter?: number;
pubkey?: string;
@@ -76,7 +73,6 @@ export type MintParams = {
quote: string,
options?: {
keysetId?: string;
outputAmounts?: OutputAmounts;
proofsWeHave?: Array<CashuProof>;
counter?: number;
pubkey?: string;
@@ -85,7 +81,7 @@ export type MintParams = {
export type MeltParams = {
meltQuote: MeltQuoteResponse,
meltQuote: MeltQuoteBolt11Response,
proofsToSend: Array<CashuProof>,
options?: {
keysetId?: string;
@@ -208,7 +204,7 @@ export const WalletStoreModel = types
const mint = self.mints.find(m => m.mintUrl === mintUrl)
if (mint) {
return mint
return mint as CashuMint
}
setGlobalRequestOptions({
@@ -255,7 +251,7 @@ export const WalletStoreModel = types
}
) {
// syncs mint model in wallet state and returns cashu-ts mint class instance
const cashuMint = yield self.getMint(mintUrl)
const cashuMint: CashuMint = yield self.getMint(mintUrl)
// get uptodate mint model from wallet state
const mintInstance = self.getMintModelInstance(mintUrl)
@@ -315,7 +311,7 @@ export const WalletStoreModel = types
if (seedWallet) {
log.trace('[WalletStore.getWallet]', 'Returning CACHED cashuWallet instance with seed', {mintUrl})
return seedWallet
return seedWallet as CashuWallet
}
const seed = yield self.getCachedSeed()
@@ -323,14 +319,14 @@ export const WalletStoreModel = types
const newSeedWallet = new CashuWallet(cashuMint, {
unit,
keys: mintInstance.keys,
keysets: mintInstance.keysets,
keysets: mintInstance.keysets,
keysetId: walletKeys.id,
bip39seed: seed
})
// Load uptodate mint info to wallet.mintInfo (NUTS support etc)
yield newSeedWallet.getMintInfo()
yield newSeedWallet.loadMint()
newSeedWallet.keysetId = walletKeys.id
self.seedWallets.push(newSeedWallet)
log.trace('[WalletStore.getWallet]', 'Returning NEW cashuWallet instance with seed', {mintUrl})
@@ -351,11 +347,11 @@ export const WalletStoreModel = types
const newWallet = new CashuWallet(cashuMint, {
unit,
keys: mintInstance.keys,
keysets: mintInstance.keysets,
keysets: mintInstance.keysets,
keysetId: walletKeys.id,
bip39seed: undefined
})
newWallet.keysetId = walletKeys.id
self.wallets.push(newWallet)
log.trace('[WalletStore.getWallet]', 'Returning NEW cashuWallet instance', {mintUrl})
@@ -365,7 +361,7 @@ export const WalletStoreModel = types
const cashuMint: CashuMint = yield self.getMint(mintUrl)
try {
const {keysets} = yield cashuMint.getKeySets() as Promise<MintAllKeysets> // all keysets
const {keysets} = yield cashuMint.getKeySets() as Promise<GetKeysetsResponse> // all keysets
return keysets as MintKeyset[]
} catch (e: any) {
let message = 'Could not connect to the selected mint.'
@@ -377,7 +373,7 @@ export const WalletStoreModel = types
const cashuMint: CashuMint = yield self.getMint(mintUrl)
try {
const {keysets} = yield cashuMint.getKeys() as Promise<MintActiveKeys> // all active keys
const {keysets} = yield cashuMint.getKeys() as Promise<GetKeysResponse> // all active keys
return keysets as MintKeys[]
} catch (e: any) {
let message = 'Could not connect to the selected mint.'
@@ -449,7 +445,7 @@ export const WalletStoreModel = types
}
}
if(cashuWallet.mintInfo.nuts['19'] && !options?.inFlightRequest) {
if(cashuWallet.getMintInfo().nuts['19'] && !options?.inFlightRequest) {
currentCounter.addInFlightRequest(transactionId, receiveParams)
}
@@ -540,7 +536,7 @@ export const WalletStoreModel = types
}
}
if(cashuWallet.mintInfo.nuts['19'] && !options?.inFlightRequest) {
if(cashuWallet.getMintInfo().nuts['19'] && !options?.inFlightRequest) {
currentCounter.addInFlightRequest(transactionId, sendParams)
}
@@ -588,31 +584,51 @@ export const WalletStoreModel = types
)
}
}),
getProofsStatesFromMint: flow(function* getProofsStatesFromMint(
getProofsStatesFromMint: flow(function* getProofsStatesFromMint(
mintUrl: string,
unit: MintUnit,
unit: MintUnit,
proofs: Proof[]
) {
try {
log.trace('[WalletStore.getProofsStatesFromMint] start', {mintUrl, unit})
const cashuWallet: CashuWallet = yield self.getWallet(mintUrl, unit, {withSeed: false})
const proofsByState: {[key in CheckStateEnum]: CashuProof[]} = yield cashuWallet.checkProofsStates(proofs)
const cashuWallet: CashuWallet = yield self.getWallet(mintUrl, unit, {withSeed: false})
// v3.x returns ProofState[] array, not grouped by state
const proofStatesArray: ProofState[] = yield cashuWallet.checkProofsStates(proofs)
// Transform array into grouped structure expected by the rest of the code
// Map proof states back to original proofs using secret matching
const proofsByState: {[key in CheckStateEnum]: CashuProof[]} = {
SPENT: [],
PENDING: [],
UNSPENT: []
}
// proofStatesArray is returned in the same order as input proofs
for (let i = 0; i < proofStatesArray.length; i++) {
const proofState = proofStatesArray[i]
const originalProof = proofs[i]
if (originalProof) {
proofsByState[proofState.state].push(originalProof as CashuProof)
}
}
log.trace('[WalletStore.getProofsStatesFromMint]', {mintUrl, proofsByState})
return proofsByState
} catch (e: any) {
} catch (e: any) {
let message = 'Could not get response from the mint.'
if (isOnionMint(mintUrl)) message += TorVPNSetupInstructions;
throw new AppError(
Err.MINT_ERROR,
message,
Err.MINT_ERROR,
message,
{
message: e.message,
caller: 'WalletStore.getProofsStatesFromMint',
mintUrl
caller: 'WalletStore.getProofsStatesFromMint',
mintUrl
}
)
}
@@ -625,8 +641,8 @@ export const WalletStoreModel = types
) {
try {
const cashuMint = yield self.getMint(mintUrl)
const mintQuoteResponse: MintQuoteResponse = yield cashuMint.createMintQuote({
unit,
const mintQuoteResponse: MintQuoteBolt11Response = yield cashuMint.createMintQuoteBolt11({
unit,
amount,
description
})
@@ -657,7 +673,7 @@ export const WalletStoreModel = types
) {
try {
const cashuMint: CashuMint = yield self.getMint(mintUrl)
const quoteResponse: MintQuoteResponse = yield cashuMint.checkMintQuote(
const quoteResponse: MintQuoteBolt11Response = yield cashuMint.checkMintQuoteBolt11(
quote
)
@@ -700,7 +716,7 @@ export const WalletStoreModel = types
throw new AppError(Err.VALIDATION_ERROR, 'Missing mint instance', {mintUrl})
}
const cashuWallet = yield self.getWallet(
const cashuWallet: CashuWallet = yield self.getWallet(
mintUrl,
unit,
{
@@ -714,34 +730,56 @@ export const WalletStoreModel = types
if(options && options.increaseCounterBy) {
currentCounter.increaseProofsCounter(options.increaseCounterBy)
}
log.debug('[WalletStore.mintProofs] counter', currentCounter.counter)
// Sync wallet's internal counter with our stored counter (v3.x)
yield cashuWallet.counters.advanceToAtLeast(cashuWallet.keysetId, currentCounter.counter)
const mintParams: MintParams = options?.inFlightRequest?.request || {
amount,
amount,
quote: mintQuote,
options: {
keysetId: cashuWallet.keysetId,
counter: currentCounter.counter
options: {
keysetId: cashuWallet.keysetId
// Note: counter is no longer passed in v3.x, wallet manages it internally
}
}
if(cashuWallet.mintInfo.nuts['19'] && !options?.inFlightRequest) {
}
if(cashuWallet.getMintInfo().nuts['19'] && !options?.inFlightRequest) {
currentCounter.addInFlightRequest(transactionId, mintParams)
}
try {
const proofs = yield cashuWallet.mintProofs(
let reservedCounters: OperationCounters | undefined = undefined
try {
const proofs = yield cashuWallet.mintProofsBolt11(
mintParams.amount,
mintParams.quote,
mintParams.options
{
keysetId: mintParams.options?.keysetId,
onCountersReserved: (info) => {
reservedCounters = info as OperationCounters
log.debug('[mintProofsBolt11] Counters reserved', info)
}
}
)
currentCounter.removeInFlightRequest(transactionId)
log.debug('[mintProofs]', {amount: mintParams.amount, quote: mintParams.quote, proofs})
currentCounter.removeInFlightRequest(transactionId)
// Update our counter to match what the wallet used (v3.x)
if (reservedCounters) {
currentCounter.counter = reservedCounters.next
log.debug('[mintProofs] Updated counter', {
keysetId: reservedCounters.keysetId,
start: reservedCounters.start,
count: reservedCounters.count,
next: reservedCounters.next
})
}
log.debug('[mintProofs]', {amount: mintParams.amount, quote: mintParams.quote, proofs})
return proofs
} catch (e: any) {
@@ -770,8 +808,8 @@ export const WalletStoreModel = types
encodedInvoice: string,
) {
try {
const cashuMint = yield self.getMint(mintUrl)
const lightningQuote: MeltQuoteResponse = yield cashuMint.createMeltQuote({
const cashuMint: CashuMint = yield self.getMint(mintUrl)
const lightningQuote: MeltQuoteBolt11Response = yield cashuMint.createMeltQuoteBolt11({
unit,
request: encodedInvoice
})
@@ -797,7 +835,7 @@ export const WalletStoreModel = types
payLightningMelt: flow(function* payLightningMelt(
mintUrl: string,
unit: MintUnit,
meltQuote: MeltQuoteResponse, // invoice is stored by mint by quote
meltQuote: MeltQuoteBolt11Response, // invoice is stored by mint by quote
proofsToMeltFrom: Proof[],
transactionId: number,
options?: {
@@ -849,13 +887,13 @@ export const WalletStoreModel = types
}
}
if(cashuWallet.mintInfo.nuts['19'] && !options?.inFlightRequest) {
if(cashuWallet.getMintInfo().nuts['19'] && !options?.inFlightRequest) {
currentCounter.addInFlightRequest(transactionId, meltParams)
}
try {
const meltResponse: MeltProofsResponse = yield cashuWallet.meltProofs(
try {
const meltResponse = yield cashuWallet.meltProofsBolt11(
meltParams.meltQuote,
meltParams.proofsToSend,
meltParams.options
@@ -865,7 +903,7 @@ export const WalletStoreModel = types
log.trace('[payLightningMelt]', {meltResponse})
// we normalize naming of returned parameters
return meltResponse
return meltResponse as MeltProofsResponse
} catch (e: any) {
if(!e.message.toLowerCase().includes('timeout') &&
@@ -896,7 +934,7 @@ export const WalletStoreModel = types
) {
try {
const cashuMint: CashuMint = yield self.getMint(mintUrl)
const quoteResponse: MeltQuoteResponse = yield cashuMint.checkMeltQuote(
const quoteResponse: MeltQuoteBolt11Response = yield cashuMint.checkMeltQuoteBolt11(
quote
)
@@ -920,7 +958,7 @@ export const WalletStoreModel = types
}),
recoverMeltQuoteChange: flow(function* recoverMeltQuoteChange(
mintUrl: string,
meltQuote: MeltQuoteResponse,
meltQuote: MeltQuoteBolt11Response,
transactionId: number
) {
try {
@@ -991,10 +1029,9 @@ export const WalletStoreModel = types
unit: 'sat', // just use default unit as we restore by keyset
keys: cashuMint.keys,
keysets: cashuMint.keysets,
keysetId,
bip39seed: seed
})
seedWallet.keysetId = keysetId
const count = Math.abs(indexTo - indexFrom)
@@ -1011,7 +1048,7 @@ export const WalletStoreModel = types
proofs: proofs || [] as Proof[]
}
} catch (e: any) {
throw new AppError(Err.MINT_ERROR, isObj(e.message) ? JSON.stringify(e.message) : e.message, {mintUrl})
throw new AppError(Err.MINT_ERROR, CashuUtils.isObj(e.message) ? JSON.stringify(e.message) : e.message, {mintUrl})
}
}),
getMintInfo: flow(function* getMintInfo(mintUrl: string) {
+2 -6
View File
@@ -35,7 +35,7 @@ import { MintsStoreSnapshot } from '../models/MintsStore'
import { ContactsStoreSnapshot } from '../models/ContactsStore'
import { CashuMint, MintActiveKeys } from '@cashu/cashu-ts'
import { StaticScreenProps, useNavigation } from '@react-navigation/native'
import { Proof, ProofModel } from '../models/Proof'
import { Proof } from '../models/Proof'
type Props = StaticScreenProps<undefined>
@@ -199,11 +199,7 @@ export const ImportBackupScreen = observer(function ImportBackupScreen({ route }
}
// applySnapshot(proofsStore, walletSnapshot.proofsStore)
for (const proof of walletSnapshot.proofsStore.proofs) {
proofsStore.proofs.put(
ProofModel.create(proof)
)
}
proofsStore.importProofs(walletSnapshot.proofsStore.proofs)
for(const secret of walletSnapshot.proofsStore.pendingByMintSecrets) {
proofsStore.pendingByMintSecrets.push(secret)
}
+2 -2
View File
@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react'
import { GetInfoResponse as CashuGetInfoResponse, SwapMethod } from '@cashu/cashu-ts'
import { isObj } from '@cashu/cashu-ts/src/utils'
import { CashuUtils } from '../services/cashu/cashuUtils'
import Clipboard from '@react-native-clipboard/clipboard'
import { observer } from 'mobx-react-lite'
import { getSnapshot } from 'mobx-state-tree'
@@ -529,7 +529,7 @@ function MintInfoDetails(props: { info: GetInfoResponse, popupMessage: (msg: str
text={translate('mintInfo_emptyValueParam', { param: key })}
/>
let stringValue = isObj(value) ? JSON.stringify(value) : value.toString() ?? ''
let stringValue = CashuUtils.isObj(value) ? JSON.stringify(value) : value.toString() ?? ''
let valueComponent = stringValue.trim() !== ''
? <Text size='xs' text={stringValue} />
: missingComponent;
+1 -2
View File
@@ -36,7 +36,6 @@ import { getSnapshot } from 'mobx-state-tree'
import { scale } from '@gocodingnow/rn-size-matters'
import { WalletUtils } from '../services/wallet/utils'
import { MintUnit, formatCurrency, getCurrency } from '../services/wallet/currency'
import { isObj } from '@cashu/cashu-ts/src/utils'
import { translate } from '../i18n'
import { WalletProfileRecord } from '../models/WalletProfileStore'
import { MnemonicInput } from './Recovery/MnemonicInput'
@@ -357,7 +356,7 @@ export const SeedRecoveryScreen = observer(function SeedRecoveryScreen({ route }
e.params = {mintUrl: selectedMintUrl}
}
log.error('[doRecovery]', {name: e.name, message: isObj(e.message) ? JSON.stringify(e.message) : e.message, params: e.params})
log.error('[doRecovery]', {name: e.name, message: CashuUtils.isObj(e.message) ? JSON.stringify(e.message) : e.message, params: e.params})
errors.push({name: e.name, message: e.message}) // TODO this could now be single error as we do not loop anymore
if (transaction) {
-4
View File
@@ -55,7 +55,6 @@ import { MemoInputCard } from '../components/MemoInputCard'
import { PaymentRequest as CashuPaymentRequest, PaymentRequestTransport, PaymentRequestTransportType, decodePaymentRequest, getDecodedToken } from '@cashu/cashu-ts'
import { ProfilePointer } from 'nostr-tools/nip19'
import { MINIBITS_NIP05_DOMAIN } from '@env'
import { SEND_TASK } from '../services/wallet/sendTask'
import FastImage from 'react-native-fast-image'
import { CurrencyAmount } from './Wallet/CurrencyAmount'
import { CashuUtils } from '../services/cashu/cashuUtils'
@@ -128,7 +127,6 @@ export const SendScreen = observer(function SendScreen({ route }: Props) {
const [isCashuPrWithDesc, setIsCashuPrWithDesc] = useState(false)
const [isNostrDMModalVisible, setIsNostrDMModalVisible] = useState(false)
const [isProofSelectorModalVisible, setIsProofSelectorModalVisible] = useState(false) // offline mode
const [isSendTaskSentToQueue, setIsSendTaskSentToQueue] = useState(false)
const [isResultModalVisible, setIsResultModalVisible] = useState(false)
const [isNostrDMSending, setIsNostrDMSending] = useState(false)
const [isNostrDMSuccess, setIsNostrDMSuccess] = useState(false)
@@ -770,8 +768,6 @@ export const SendScreen = observer(function SendScreen({ route }: Props) {
}
}
setIsSendTaskSentToQueue(true)
const result = await WalletTask.sendQueueAwaitable(
mintBalanceToSendFrom as MintBalance,
amountToSendInt,
@@ -255,7 +255,7 @@ export const TransactionListItem = observer(function (props: TransactionListProp
amountStyle={{color: txReceiveColor}}
/>
)}
{[TransactionStatus.ERROR, TransactionStatus.BLOCKED, TransactionStatus.PREPARED_OFFLINE, TransactionStatus.EXPIRED].includes(tx.status) && (
{[TransactionStatus.ERROR, TransactionStatus.BLOCKED, TransactionStatus.PREPARED_OFFLINE, TransactionStatus.PENDING, TransactionStatus.EXPIRED].includes(tx.status) && (
<CurrencyAmount
amount={tx.amount}
mintUnit={tx.unit}
+2 -2
View File
@@ -498,7 +498,7 @@ const onRequestLnurlInvoice = async function () {
amount: roundUp(lnurlPayParams.minSendable / 1000, 0),
currency: CurrencyCode.SAT
}))
return;
return
}
if (lnurlPayParams.maxSendable && amountSats > lnurlPayParams.maxSendable / 1000) {
@@ -506,7 +506,7 @@ const onRequestLnurlInvoice = async function () {
amount: roundDown(lnurlPayParams.maxSendable / 1000, 0),
currency: CurrencyCode.SAT
}))
return;
return
}
if (lnurlPayParams.payerData) {
+19 -3
View File
@@ -10,13 +10,27 @@ import AppError, {Err} from '../../utils/AppError'
import { getDecodedToken } from '@cashu/cashu-ts'
import {Proof} from '../../models/Proof'
import { log } from '../logService'
import { decodePaymentRequest, sumProofs } from '@cashu/cashu-ts/src/utils'
import { decodePaymentRequest } from '@cashu/cashu-ts'
import { NostrClient } from '../nostrService'
import { getUnixTime } from 'date-fns/getUnixTime'
import { getSnapshot, isStateTreeNode } from 'mobx-state-tree'
export {CashuProof}
/**
* Type guard to check if a value is an object
*/
const isObj = function(v: unknown): v is object {
return typeof v === 'object'
}
/**
* Sum the amounts of an array of proofs
*/
const sumProofs = function(proofs: CashuProof[]): number {
return proofs.reduce((acc: number, proof: CashuProof) => acc + proof.amount, 0)
}
const CASHU_URI_PREFIXES = [
'https://wallet.nutstash.app/#',
'https://wallet.cashu.me/?token=',
@@ -395,7 +409,7 @@ export const CashuUtils = {
findEncodedCashuPaymentRequestPayload,
extractEncodedCashuToken,
extractEncodedCashuPaymentRequest,
getProofsAmount,
getProofsAmount,
getMintsFromToken,
findExactMatch,
findMinExcess,
@@ -407,7 +421,9 @@ export const CashuUtils = {
getP2PKPubkeySecret,
getP2PKLocktime,
isTokenP2PKLocked,
isCollidingKeysetId
isCollidingKeysetId,
isObj,
sumProofs
}
+1
View File
@@ -90,6 +90,7 @@ const generateWalletKeys = function () {
const mnemonic = generateMnemonic()
const seedBytesArray = mnemonicToSeedSync(mnemonic)
const seed = Buffer.from(seedBytesArray).toString('base64')
log.trace('[generateWalletKeys] Seed generated from mnemonic (base64)', {seed})
const seedHash = QuickCrypto
.createHash('sha256')
.update(seedBytesArray)
+1 -2
View File
@@ -12,8 +12,7 @@ import { TransactionTaskResult } from '../walletService'
import { WalletUtils } from './utils'
import { MintUnit, formatCurrency, getCurrency } from './currency'
import { PaymentRequestPayload, Token, getDecodedToken } from '@cashu/cashu-ts'
import { getEncodedToken, getKeepAmounts } from '@cashu/cashu-ts/src/utils'
import { Proof } from '../../models/Proof'
import { getEncodedToken } from '@cashu/cashu-ts'
const {
mintsStore,
+1 -1
View File
@@ -10,7 +10,7 @@ import { TransactionTaskResult } from '../walletService'
import { WalletUtils } from './utils'
import { MintUnit } from './currency'
import { Token } from '@cashu/cashu-ts'
import { getEncodedToken, getKeepAmounts } from '@cashu/cashu-ts/src/utils'
import { getEncodedToken, getKeepAmounts } from '@cashu/cashu-ts'
const {
mintsStore,
+5 -5
View File
@@ -8,9 +8,9 @@ import {
import {rootStoreInstance} from '../../models'
import {CashuUtils, CashuProof} from '../cashu/cashuUtils'
import AppError, {Err} from '../../utils/AppError'
import {
CashuMint,
CashuWallet,
import {
Mint as CashuMint,
Wallet as CashuWallet,
CheckStateEnum,
MintKeyset,
ProofState,
@@ -144,7 +144,7 @@ export const sendTask = async function (
try {
log.trace('[send] Subscribing to onProofStateUpdates for proof', {secret: proofsToSend[0]})
const unsub = await wsWallet.onProofStateUpdates(
const unsub = await wsWallet.on.proofStateUpdates(
[proofsToSend[0]],
async (proofState: ProofState) => {
log.trace(`Websocket: proof state updated: ${proofState.state} with secret: ${proofsToSend[0].secret}`)
@@ -338,7 +338,7 @@ export const sendFromMintSync = async function (
*/
if(isSwapNeeded) {
// Calculate feeReserve from mint fee rate
const walletInstance = await walletStore.getWallet(mintUrl, unit, {withSeed: true})
const walletInstance = await walletStore.getWallet(mintUrl, unit, {withSeed: true}) as CashuWallet
swapFeeReserve = walletInstance.getFeesForProofs(proofsToSendFrom)
const amountWithFees = amountToSend + swapFeeReserve
+7 -3
View File
@@ -11,7 +11,11 @@ import { WalletUtils } from './utils'
import { MintUnit } from './currency'
import { NostrEvent } from '../nostrService'
import AppError, { Err } from '../../utils/AppError'
import { CashuMint, CashuWallet, MintQuoteResponse } from '@cashu/cashu-ts'
import {
MintQuoteBolt11Response,
Mint as CashuMint,
Wallet as CashuWallet,
} from '@cashu/cashu-ts'
import { addSeconds } from 'date-fns/addSeconds'
const {
@@ -125,9 +129,9 @@ export const topupTask = async function (
const wsWallet = new CashuWallet(wsMint)
try {
const unsub = await wsWallet.onMintQuotePaid(
const unsub = await wsWallet.on.mintQuotePaid(
mintQuote,
async (m: MintQuoteResponse) => {
async (m: MintQuoteBolt11Response) => {
log.trace(`Websocket: mint quote PAID: ${m.quote}`)
WalletTask.handlePendingQueue()
unsub()
+19 -16
View File
@@ -1,6 +1,6 @@
import {CashuUtils} from '../cashu/cashuUtils'
import AppError, {Err} from '../../utils/AppError'
import {MeltProofsResponse, MeltQuoteResponse, MeltQuoteState, getEncodedToken} from '@cashu/cashu-ts'
import {MeltProofsResponse, MeltQuoteBolt11Response, MeltQuoteResponse, MeltQuoteState, getEncodedToken} from '@cashu/cashu-ts'
import {rootStoreInstance} from '../../models'
import { TransactionTaskResult, WalletTask } from '../walletService'
import { MintBalance } from '../../models/Mint'
@@ -50,7 +50,8 @@ export const transferTask = async function (
let proofsToMeltFrom: Proof[] = []
let proofsToMeltFromAmount: number = 0
let meltFeeReserve: number = 0
let meltResponse: MeltProofsResponse
let meltResponse: MeltProofsResponse
let meltQuoteCheck: MeltQuoteBolt11Response
try {
@@ -247,7 +248,9 @@ export const transferTask = async function (
totalFeePaid = totalFeePaid - returnedAmount
lightningFeePaid = totalFeePaid - meltFeeReserve
}
}
meltQuoteCheck = await walletStore.checkLightningMeltQuote(mintUrl, meltQuote.quote)
const balanceAfter = proofsStore.getUnitBalance(unit)?.unitBalance
@@ -257,7 +260,7 @@ export const transferTask = async function (
lightningFeePaid,
meltFeePaid,
returnedAmount,
preimage: meltResponse.quote.payment_preimage,
preimage: meltQuoteCheck.payment_preimage,
createdAt: new Date(),
}
transactionData.push(completedDataItem)
@@ -273,8 +276,8 @@ export const transferTask = async function (
updatePayload.outputToken = outputToken
}
if (meltResponse.quote.payment_preimage) {
updatePayload.proof = meltResponse.quote.payment_preimage
if (meltQuoteCheck.payment_preimage) {
updatePayload.proof = meltQuoteCheck.payment_preimage
}
transaction.update(updatePayload)
@@ -287,8 +290,8 @@ export const transferTask = async function (
lightningFeePaid,
meltFeePaid,
totalFeePaid,
meltQuote: meltResponse.quote,
preimage: meltResponse.quote.payment_preimage,
meltQuote: meltQuoteCheck,
preimage: meltQuoteCheck.payment_preimage,
nwcEvent
} as TransactionTaskResult
@@ -330,31 +333,31 @@ export const transferTask = async function (
if (proofsToMeltFrom.length > 0) {
const refreshedMeltQuote = await walletStore.checkLightningMeltQuote(mintUrl, meltQuote.quote)
taskResult.meltQuote = refreshedMeltQuote
meltQuoteCheck = await walletStore.checkLightningMeltQuote(mintUrl, meltQuote.quote)
taskResult.meltQuote = meltQuoteCheck
if(refreshedMeltQuote.state === MeltQuoteState.PAID) {
if(meltQuoteCheck.state === MeltQuoteState.PAID) {
message = `Lightning invoice has been successfully paid, however some error occured: ${e.message}`
taskResult.preimage = refreshedMeltQuote.payment_preimage
taskResult.preimage = meltQuoteCheck.payment_preimage
taskResult.message = message
const {recoveredAmount} = await WalletTask.recoverMeltQuoteChange({
mintUrl,
meltQuote: refreshedMeltQuote,
meltQuote: meltQuoteCheck,
})
log.error('[transfer]', message, {
recoveredAmount,
error: e.message,
refreshedMeltQuote,
meltQuoteCheck,
unit,
transactionId: transaction.id
})
} else if(refreshedMeltQuote.state === MeltQuoteState.PENDING) {
} else if(meltQuoteCheck.state === MeltQuoteState.PENDING) {
message = 'Lightning payment did not complete in time. Your ecash will remain pending until the payment completes or fails.'
taskResult.message = message
@@ -362,7 +365,7 @@ export const transferTask = async function (
log.error('[transfer]', message, {
error: `${e.message}: ${e.params.message}`,
unit,
refreshedMeltQuote,
meltQuoteCheck,
transactionId: transaction.id
})
+2 -2
View File
@@ -1,10 +1,10 @@
import AppError from "../../utils/AppError"
import { isObj } from '@cashu/cashu-ts/src/utils'
import { CashuUtils } from '../cashu/cashuUtils'
const formatError = function (e: AppError) {
return {
name: e.name,
message: isObj(e.message) ? JSON.stringify(e.message) : e.message.slice(0, 200),
message: CashuUtils.isObj(e.message) ? JSON.stringify(e.message) : e.message.slice(0, 200),
params: e.params || {},
} as AppError
}
+18 -9
View File
@@ -15,7 +15,7 @@ import {CashuProof, CashuUtils} from './cashu/cashuUtils'
import {LightningUtils} from './lightning/lightningUtils'
import AppError, {Err} from '../utils/AppError'
import {MintBalance, MintStatus} from '../models/Mint'
import {MeltQuoteResponse, MeltQuoteState, MintQuoteState, PaymentRequestPayload, Token, getDecodedToken, getEncodedToken} from '@cashu/cashu-ts'
import {MeltQuoteBolt11Response, MeltQuoteResponse, MeltQuoteState, MintQuoteState, PaymentRequestPayload, Token, getDecodedToken, getEncodedToken} from '@cashu/cashu-ts'
import {Mint} from '../models/Mint'
import {pollerExists, stopPolling} from '../utils/poller'
import { NostrClient, NostrEvent, NostrProfile } from './nostrService'
@@ -40,7 +40,7 @@ import { MinibitsClient } from './minibitsService'
import { UnsignedEvent } from 'nostr-tools'
import { Platform } from 'react-native'
import { cashuPaymentRequestTask } from './wallet/cashuPaymentRequestTask'
import { decodePaymentRequest } from '@cashu/cashu-ts/src/utils'
import { decodePaymentRequest } from '@cashu/cashu-ts'
@@ -168,7 +168,7 @@ export interface TransactionTaskResult extends WalletTaskResult {
swapFeePaid?: number
lightningFeePaid?: number
meltFeePaid?: number
meltQuote?: MeltQuoteResponse
meltQuote?: MeltQuoteBolt11Response
nwcEvent?: NostrEvent
}
@@ -1636,7 +1636,16 @@ const handleInFlightByMintTask = async (mint: Mint): Promise<WalletTaskResult> =
// ─── TRANSFER (melt / lightning out retry) ─────────────
case TransactionType.TRANSFER: {
const { quote, change } = await walletStore.payLightningMelt(
const meltQuoteCheck = await walletStore.checkLightningMeltQuote(mintUrl, inFlight.request.meltQuote)
if(meltQuoteCheck.state === MeltQuoteState.PAID || meltQuoteCheck.state === MeltQuoteState.PENDING) {
log.debug('[handleInFlightByMintTask] Melt quote already PAID or PENDING', { tId: tx.id })
// TODO recover change if any
counter.removeInFlightRequest(inFlight.transactionId)
break
}
const { change } = await walletStore.payLightningMelt(
mintUrl,
unit,
inFlight.request.meltQuote,
@@ -1667,9 +1676,9 @@ const handleInFlightByMintTask = async (mint: Mint): Promise<WalletTaskResult> =
tx.update({ outputToken })
}
if (quote.payment_preimage) {
/*if (quote.payment_preimage) {
tx.update({ proof: quote.payment_preimage })
}
}*/
const inputAmount = CashuUtils.getProofsAmount(inFlight.request.proofsToSend)
const changeAmount = CashuUtils.getProofsAmount(change)
@@ -1680,7 +1689,7 @@ const handleInFlightByMintTask = async (mint: Mint): Promise<WalletTaskResult> =
txData.push({
status: TransactionStatus.COMPLETED,
changeAmount,
preimage: quote.payment_preimage,
//preimage: quote.payment_preimage,
createdAt: new Date(),
})
@@ -2060,7 +2069,7 @@ const recoverMintQuote = async (
const recoverMeltQuoteChange = async (
params: {
mintUrl: string
meltQuote: string | MeltQuoteResponse
meltQuote: string | MeltQuoteBolt11Response
}
): Promise<{ recoveredAmount: number }> => {
const { mintUrl, meltQuote } = params
@@ -2073,7 +2082,7 @@ const recoverMintQuote = async (
log.trace('[recoverMeltQuoteChange] start', { mintUrl, meltQuote })
const meltQuoteResponse: MeltQuoteResponse =
const meltQuoteResponse: MeltQuoteBolt11Response =
typeof meltQuote === 'string'
? await walletStore.checkLightningMeltQuote(mintUrl, meltQuote)
: meltQuote
+1 -1
View File
@@ -25,7 +25,7 @@ export enum Err {
}
export class AppError extends Error {
public readonly code: Err
public readonly code: number | undefined
public readonly params?: Record<string, any>
public readonly caller?: string
+50 -40
View File
@@ -2722,28 +2722,14 @@ __metadata:
languageName: node
linkType: hard
"@cashu/cashu-ts@minibits-cash/cashu-ts#e97b1a4ee9a7ddbb1468302c6996a9d6d3efcb6f":
version: 2.4.0
resolution: "@cashu/cashu-ts@https://github.com/minibits-cash/cashu-ts.git#commit=e97b1a4ee9a7ddbb1468302c6996a9d6d3efcb6f"
"@cashu/cashu-ts@npm:3.2.2":
version: 3.2.2
resolution: "@cashu/cashu-ts@npm:3.2.2"
dependencies:
"@cashu/crypto": ^0.3.4
"@noble/curves": ^1.3.0
"@noble/hashes": ^1.3.3
buffer: ^6.0.3
checksum: 68d46ceb9c60e9cef305aad86534c08b23de434de1efcd217d00c73bdf84704801c3cd700901903256de5a408caf029cea7886e9a303dd423027f08184bc1cb5
languageName: node
linkType: hard
"@cashu/crypto@npm:^0.3.4":
version: 0.3.4
resolution: "@cashu/crypto@npm:0.3.4"
dependencies:
"@noble/curves": ^1.6.0
"@noble/hashes": ^1.5.0
"@scure/bip32": ^1.5.0
"@scure/bip39": ^1.4.0
buffer: ^6.0.3
checksum: 634afdd9d8fb262cd3db415794661ba5810f4ba1e64d1af0972c9a9b0a8c45106710a00ee25949014a361458ef544bdfcafe926c548c95b05fff9a41600d34a3
"@noble/curves": ^2.0.1
"@noble/hashes": ^2.0.1
"@scure/bip32": ^2.0.1
checksum: 49516a22f3afbf249c52d0f36a9e6513948b763af94c703a05375b513b0d3f90bb1feaade201214d315f5a26305e182ee00493634519ad9b69c7bd44615de11c
languageName: node
linkType: hard
@@ -5299,12 +5285,12 @@ __metadata:
languageName: node
linkType: hard
"@noble/curves@npm:^1.3.0, @noble/curves@npm:^1.6.0, @noble/curves@npm:~1.8.1":
version: 1.8.1
resolution: "@noble/curves@npm:1.8.1"
"@noble/curves@npm:2.0.1, @noble/curves@npm:^2.0.1":
version: 2.0.1
resolution: "@noble/curves@npm:2.0.1"
dependencies:
"@noble/hashes": 1.7.1
checksum: 4143f1248ed57c1ae46dfef5c692a91383e5830420b9c72d3ff1061aa9ebbf8999297da6d2aed8a9716fef8e6b1f5a45737feeab02abf55ca2a4f514bf9339ec
"@noble/hashes": 2.0.1
checksum: b6844f350d629bb6de55d3a123bc148403901c8b8eed77d2132a389d080d553242bcf1e06913bf51f51e395849ec70b9a8e8902c19e562ea3c6538bb0240d92f
languageName: node
linkType: hard
@@ -5317,6 +5303,15 @@ __metadata:
languageName: node
linkType: hard
"@noble/curves@npm:~1.8.1":
version: 1.8.1
resolution: "@noble/curves@npm:1.8.1"
dependencies:
"@noble/hashes": 1.7.1
checksum: 4143f1248ed57c1ae46dfef5c692a91383e5830420b9c72d3ff1061aa9ebbf8999297da6d2aed8a9716fef8e6b1f5a45737feeab02abf55ca2a4f514bf9339ec
languageName: node
linkType: hard
"@noble/hashes@npm:1.3.1":
version: 1.3.1
resolution: "@noble/hashes@npm:1.3.1"
@@ -5331,13 +5326,20 @@ __metadata:
languageName: node
linkType: hard
"@noble/hashes@npm:1.7.1, @noble/hashes@npm:^1.3.3, @noble/hashes@npm:^1.5.0, @noble/hashes@npm:~1.7.1":
"@noble/hashes@npm:1.7.1, @noble/hashes@npm:^1.3.3, @noble/hashes@npm:~1.7.1":
version: 1.7.1
resolution: "@noble/hashes@npm:1.7.1"
checksum: 4f1b56428a10323feef17e4f437c9093556cb18db06f94d254043fadb69c3da8475f96eb3f8322d41e8670117d7486475a8875e68265c2839f60fd03edd6a616
languageName: node
linkType: hard
"@noble/hashes@npm:2.0.1, @noble/hashes@npm:^2.0.1":
version: 2.0.1
resolution: "@noble/hashes@npm:2.0.1"
checksum: aea67a671ca464027cd512d07666a804bd99abc343ba98c93ee8463a1c870c5594f8de468279ef3c60f3b23b6330db9f1a92bd23723b8a911ec73bddc9420248
languageName: node
linkType: hard
"@noble/hashes@npm:^1.1.5, @noble/hashes@npm:~1.8.0":
version: 1.8.0
resolution: "@noble/hashes@npm:1.8.0"
@@ -6275,6 +6277,13 @@ __metadata:
languageName: node
linkType: hard
"@scure/base@npm:2.0.0":
version: 2.0.0
resolution: "@scure/base@npm:2.0.0"
checksum: 15d10f154256f52bb3e02b63cdf93b6df6db3814fa4c61a8bb2d339831aec7859609fb715b93c7fc852755f0fe67fb6411664c06159745711bf38af3b10ab93e
languageName: node
linkType: hard
"@scure/base@npm:~1.1.0":
version: 1.1.9
resolution: "@scure/base@npm:1.1.9"
@@ -6282,7 +6291,7 @@ __metadata:
languageName: node
linkType: hard
"@scure/base@npm:~1.2.2, @scure/base@npm:~1.2.4":
"@scure/base@npm:~1.2.2":
version: 1.2.4
resolution: "@scure/base@npm:1.2.4"
checksum: db554eb550a1bd17684af9282e1ad751050a13d4add0e83ad61cc496680d7d1c1c1120ca780e72935a293bb59721c20a006a53a5eec6f6b5bdcd702cf27c8cae
@@ -6307,7 +6316,7 @@ __metadata:
languageName: node
linkType: hard
"@scure/bip32@npm:1.6.2, @scure/bip32@npm:^1.5.0":
"@scure/bip32@npm:1.6.2":
version: 1.6.2
resolution: "@scure/bip32@npm:1.6.2"
dependencies:
@@ -6318,6 +6327,17 @@ __metadata:
languageName: node
linkType: hard
"@scure/bip32@npm:^2.0.1":
version: 2.0.1
resolution: "@scure/bip32@npm:2.0.1"
dependencies:
"@noble/curves": 2.0.1
"@noble/hashes": 2.0.1
"@scure/base": 2.0.0
checksum: 5e6c7b455c4a5599673d5fa1b7edc1b3655fe2f7b8388dc19ebe4a89adb9c80c511215d4af624eb774c63c216fd8b7bb8fecf1eb8c3d5e979e279c7542657a42
languageName: node
linkType: hard
"@scure/bip39@npm:1.2.1":
version: 1.2.1
resolution: "@scure/bip39@npm:1.2.1"
@@ -6338,16 +6358,6 @@ __metadata:
languageName: node
linkType: hard
"@scure/bip39@npm:^1.4.0":
version: 1.5.4
resolution: "@scure/bip39@npm:1.5.4"
dependencies:
"@noble/hashes": ~1.7.1
"@scure/base": ~1.2.4
checksum: 744f302559ad05ee6ea4928572ac8f0b5443e8068fd53234c9c2e158814e910a043c54f0688d05546decadd2ff66e0d0c76355d10e103a28cb8f44efe140857a
languageName: node
linkType: hard
"@sentry-internal/browser-utils@npm:10.26.0":
version: 10.26.0
resolution: "@sentry-internal/browser-utils@npm:10.26.0"
@@ -14456,7 +14466,7 @@ __metadata:
"@babel/plugin-proposal-export-namespace-from": ^7.18.9
"@babel/preset-env": ^7.25.3
"@babel/runtime": ^7.25.0
"@cashu/cashu-ts": "minibits-cash/cashu-ts#e97b1a4ee9a7ddbb1468302c6996a9d6d3efcb6f"
"@cashu/cashu-ts": 3.2.2
"@fortawesome/fontawesome-svg-core": ^7.1.0
"@fortawesome/free-brands-svg-icons": ^7.1.0
"@fortawesome/free-regular-svg-icons": ^7.1.0