mirror of
https://github.com/minibits-cash/minibits_wallet.git
synced 2026-10-05 19:28:26 +00:00
v3 broken
This commit is contained in:
Vendored
-1
@@ -1 +0,0 @@
|
||||
019b98cc-e66d-7947-b6a6-e253c1830c03
|
||||
@@ -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
@@ -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",
|
||||
|
||||
@@ -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
|
||||
);
|
||||
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);
|
||||
+ const I = new Uint8Array(QuickCrypto.createHmac('sha512', MASTER_SECRET).update(seed).digest());
|
||||
+ 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),
|
||||
@@ -237,7 +239,8 @@ export class HDKey {
|
||||
@@ -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);
|
||||
+ const I = new Uint8Array(QuickCrypto.createHmac('sha512', this.chainCode).update(data).digest())
|
||||
+ 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)) {
|
||||
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",
|
||||
|
||||
@@ -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
|
||||
|
||||
+6
-5
@@ -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)
|
||||
}
|
||||
} finally {
|
||||
// Always unblock the app
|
||||
setIsDeviceAuthenticated(true)
|
||||
|
||||
@@ -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
@@ -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: {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 ─────────────────────
|
||||
|
||||
+80
-43
@@ -1,20 +1,20 @@
|
||||
import {Instance, SnapshotOut, types, flow, getRoot, getSnapshot} from 'mobx-state-tree'
|
||||
import {
|
||||
CashuMint,
|
||||
CashuWallet,
|
||||
MeltQuoteResponse,
|
||||
Mint as CashuMint,
|
||||
Wallet as CashuWallet,
|
||||
MeltQuoteBolt11Response,
|
||||
setGlobalRequestOptions,
|
||||
type MintKeys,
|
||||
type MintKeyset,
|
||||
MintAllKeysets,
|
||||
MintActiveKeys,
|
||||
Token,
|
||||
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()
|
||||
@@ -324,13 +320,13 @@ export const WalletStoreModel = types
|
||||
unit,
|
||||
keys: mintInstance.keys,
|
||||
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})
|
||||
@@ -352,10 +348,10 @@ export const WalletStoreModel = types
|
||||
unit,
|
||||
keys: mintInstance.keys,
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -597,7 +593,27 @@ export const WalletStoreModel = types
|
||||
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)
|
||||
|
||||
// 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})
|
||||
|
||||
@@ -625,7 +641,7 @@ export const WalletStoreModel = types
|
||||
) {
|
||||
try {
|
||||
const cashuMint = yield self.getMint(mintUrl)
|
||||
const mintQuoteResponse: MintQuoteResponse = yield cashuMint.createMintQuote({
|
||||
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,
|
||||
{
|
||||
@@ -717,29 +733,51 @@ export const WalletStoreModel = types
|
||||
|
||||
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,
|
||||
quote: mintQuote,
|
||||
options: {
|
||||
keysetId: cashuWallet.keysetId,
|
||||
counter: currentCounter.counter
|
||||
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)
|
||||
}
|
||||
|
||||
let reservedCounters: OperationCounters | undefined = undefined
|
||||
|
||||
try {
|
||||
|
||||
const proofs = yield cashuWallet.mintProofs(
|
||||
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)
|
||||
|
||||
// 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
|
||||
@@ -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(
|
||||
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,11 +1029,10 @@ 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)
|
||||
|
||||
const {proofs} = yield seedWallet.restore(
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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=',
|
||||
@@ -407,7 +421,9 @@ export const CashuUtils = {
|
||||
getP2PKPubkeySecret,
|
||||
getP2PKLocktime,
|
||||
isTokenP2PKLocked,
|
||||
isCollidingKeysetId
|
||||
isCollidingKeysetId,
|
||||
isObj,
|
||||
sumProofs
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -9,8 +9,8 @@ import {rootStoreInstance} from '../../models'
|
||||
import {CashuUtils, CashuProof} from '../cashu/cashuUtils'
|
||||
import AppError, {Err} from '../../utils/AppError'
|
||||
import {
|
||||
CashuMint,
|
||||
CashuWallet,
|
||||
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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
@@ -51,6 +51,7 @@ export const transferTask = async function (
|
||||
let proofsToMeltFromAmount: number = 0
|
||||
let meltFeeReserve: number = 0
|
||||
let meltResponse: MeltProofsResponse
|
||||
let meltQuoteCheck: MeltQuoteBolt11Response
|
||||
|
||||
try {
|
||||
|
||||
@@ -249,6 +250,8 @@ export const transferTask = async function (
|
||||
lightningFeePaid = totalFeePaid - meltFeeReserve
|
||||
}
|
||||
|
||||
meltQuoteCheck = await walletStore.checkLightningMeltQuote(mintUrl, meltQuote.quote)
|
||||
|
||||
const balanceAfter = proofsStore.getUnitBalance(unit)?.unitBalance
|
||||
|
||||
// build consolidated update payload
|
||||
@@ -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
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user