diff --git a/package.json b/package.json
index 7c84661b..34ca5261 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "minibits_wallet",
- "version": "0.1.10-beta.4",
+ "version": "0.1.10-beta.5",
"private": true,
"scripts": {
"android:clean": "cd android && ./gradlew clean",
@@ -19,8 +19,7 @@
"postinstall": "patch-package --exclude 'nothing'"
},
"dependencies": {
- "@cashu/cashu-ts": "minibits-cash/cashu-ts#commit=8dcac7ce6d192c419aee5547f0db03c23b593a57",
- "@exodus/borc": "^2.1.1",
+ "@cashu/cashu-ts": "minibits-cash/cashu-ts#cashu-ts-2.0",
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-brands-svg-icons": "^6.6.0",
"@fortawesome/free-regular-svg-icons": "^6.6.0",
diff --git a/src/models/Mint.ts b/src/models/Mint.ts
index 86d87602..9d0362b5 100644
--- a/src/models/Mint.ts
+++ b/src/models/Mint.ts
@@ -14,8 +14,8 @@ import AppError, { Err } from '../utils/AppError'
import { MintUnit, MintUnits } from '../services/wallet/currency'
import { getRootStore } from './helpers/getRootStore'
import { generateId } from '../utils/utils'
-import { ProofV3 } from '../services/cashu/cashuUtils'
import { Proof } from './Proof'
+import { CashuProof } from '../services/cashu/cashuUtils'
export type MintBalance = {
@@ -369,7 +369,7 @@ export const MintModel = types
self.proofsCounters = cast(self.proofsCounters)
},
- getMintFeeReserve(proofs: ProofV3[] | Proof[]): number {
+ getMintFeeReserve(proofs: CashuProof[] | Proof[]): number {
// Find the corresponding keyset for each proof and sum the input fees
const totalInputFees = proofs.reduce((sum, proof) => {
const keyset = self.keysets.find(k => k.id === proof.id)
diff --git a/src/models/WalletStore.ts b/src/models/WalletStore.ts
index 2b06b30b..7fee3090 100644
--- a/src/models/WalletStore.ts
+++ b/src/models/WalletStore.ts
@@ -1,30 +1,31 @@
import {Instance, SnapshotOut, types, flow, getRoot, getSnapshot} from 'mobx-state-tree'
-import {
- AmountPreference,
+import {
CashuMint,
CashuWallet,
- MeltQuoteResponse,
- MeltTokensResponse,
- setGlobalRequestOptions,
- deriveSeedFromMnemonic,
+ MeltQuoteResponse,
+ setGlobalRequestOptions,
type MintKeys,
type MintKeyset,
MintAllKeysets,
- MintActiveKeys
+ MintActiveKeys,
+ OutputAmounts,
+ Token,
+ MeltProofsResponse,
+ ProofState,
+ CheckStateEnum
} from '@cashu/cashu-ts'
-import { debounce } from "lodash"
+import { isObj } from '@cashu/cashu-ts/src/utils'
import { JS_BUNDLE_VERSION } from '@env'
import {KeyChain, MinibitsClient} from '../services'
import {log} from '../services/logService'
import AppError, { Err } from '../utils/AppError'
import { Currencies, CurrencyCode, MintUnit } from '../services/wallet/currency'
-import { CashuUtils, ProofV3, TokenV3 } from '../services/cashu/cashuUtils'
+import { CashuProof, CashuUtils } from '../services/cashu/cashuUtils'
import { Proof } from './Proof'
-import { isObj } from '@cashu/cashu-ts/src/utils'
+
import { Mint } from './Mint'
import { getRootStore } from './helpers/getRootStore'
-import { getUnixTime } from 'date-fns/getUnixTime'
-import { boolean } from 'mobx-state-tree/dist/internal'
+import {deriveSeedFromMnemonic} from '@cashu/crypto/modules/client/NUT09'
/*
Not persisted, in-memory only model of the cashu-ts wallet instances and seed.
@@ -136,7 +137,7 @@ export const WalletStoreModel = types
return new Uint8Array(Buffer.from(self.seedBase64, 'base64'))
}
- const seed = yield KeyChain.loadSeed()
+ const seed: Uint8Array = yield KeyChain.loadSeed()
if (!seed) {
return undefined
@@ -218,8 +219,7 @@ export const WalletStoreModel = types
// syncs mint model in wallet state and returns cashu-ts mint class instance
const cashuMint = yield self.getMint(mintUrl)
- // get uptodate mint model from wallet state
- // const mintsStore = getRootStore(self).mintsStore
+ // get uptodate mint model from wallet state
const mintInstance = self.getMintModelInstance(mintUrl)
if(!mintInstance) {
throw new AppError(Err.NOTFOUND_ERROR, 'Mint not found in the wallet state.', {
@@ -234,7 +234,7 @@ export const WalletStoreModel = types
const requestedKeys = mintInstance.keys!.find((k: MintKeys) => k.id === options.keysetId)
if(!requestedKeys) {
- throw new AppError(Err.NOTFOUND_ERROR, 'Wallet has not keys with provided keyset id.', {
+ throw new AppError(Err.NOTFOUND_ERROR, 'Mint has no keys with provided keyset id.', {
mintUrl,
keysetId: options.keysetId
})
@@ -253,7 +253,7 @@ export const WalletStoreModel = types
// if not we find active keyset with lowest fees and related keys
const activeKeyset: MintKeyset = self.getOptimalKeyset(mintInstance, unit) // throws
- log.trace('[WalletStore.getWallet]', {activeKeyset, mintUrl})
+ log.trace('[WalletStore.getWallet] Optimal keyset for this unit', {activeKeyset, unit, mintUrl})
const activeKeys = mintInstance.keys!.find((k: MintKeys) => k.id === activeKeyset.id)
@@ -271,7 +271,7 @@ export const WalletStoreModel = types
const seedWallet: CashuWallet | undefined = self.seedWallets.find(
w => w.mint.mintUrl === mintUrl &&
- w.keys.id === walletKeys.id
+ w.keysetId === walletKeys.id
)
if (seedWallet) {
@@ -283,10 +283,13 @@ export const WalletStoreModel = types
seed = yield self.getSeed()
const newSeedWallet = new CashuWallet(cashuMint, {
- keys: walletKeys,
- mnemonicOrSeed: seed
+ unit,
+ keys: mintInstance.keys,
+ keysets: mintInstance.keysets,
+ bip39seed: seed
})
+ newSeedWallet.keysetId = walletKeys.id
self.seedWallets.push(newSeedWallet)
log.trace('[WalletStore.getWallet]', 'Returning NEW cashuWallet instance with seed', {mintUrl})
@@ -296,7 +299,7 @@ export const WalletStoreModel = types
const wallet: CashuWallet | undefined = self.wallets.find(
w => w.mint.mintUrl === mintUrl &&
- w.keys.id === walletKeys.id
+ w.keysetId === walletKeys.id
)
if (wallet) {
@@ -305,10 +308,13 @@ export const WalletStoreModel = types
}
const newWallet = new CashuWallet(cashuMint, {
- keys: walletKeys,
- mnemonicOrSeed: undefined
+ unit,
+ keys: mintInstance.keys,
+ keysets: mintInstance.keysets,
+ bip39seed: undefined
})
+ newWallet.keysetId = walletKeys.id
self.wallets.push(newWallet)
log.trace('[WalletStore.getWallet]', 'Returning NEW cashuWallet instance', {mintUrl})
@@ -347,10 +353,9 @@ export const WalletStoreModel = types
receive: flow(function* receive(
mintUrl: string,
unit: MintUnit,
- decodedToken: TokenV3,
- swapFeeReserve: number,
+ decodedToken: Token,
options: {
- preference: AmountPreference[],
+ outputAmounts: OutputAmounts,
counter: number
}) {
@@ -362,17 +367,16 @@ export const WalletStoreModel = types
withSeed: true,
})
- const amountToReceive: number = CashuUtils.getTokenAmounts(decodedToken).totalAmount
+ const amountToReceive: number = CashuUtils.getProofsAmount(decodedToken.proofs)
+
+ // log.trace('[WalletStore.receive]', {decodedToken, keysetId: cashuWallet.keysetId, outputAmounts: options.outputAmounts, counter: options.counter})
const proofs = yield cashuWallet.receive(
- decodedToken,
- swapFeeReserve,
+ decodedToken,
{
- keysetId: cashuWallet.keys.id,
- preference: options.preference,
+ keysetId: cashuWallet.keysetId,
+ outputAmounts: options.outputAmounts,
counter: options.counter,
- pubkey: undefined,
- privkey: undefined
})
const receivedAmount: number = CashuUtils.getProofsAmount(proofs as Proof[])
@@ -388,13 +392,12 @@ export const WalletStoreModel = types
}
}),
send: flow(function* send(mintUrl: string,
- amountToSend: number,
- swapFeeReserve: number,
+ amountToSend: number,
unit: MintUnit,
proofsToSendFrom: Proof[],
options: {
- preference: AmountPreference[],
- counter: number
+ outputAmounts: OutputAmounts,
+ counter: number,
} ) {
try {
const cashuWallet = yield self.getWallet(
@@ -406,25 +409,23 @@ export const WalletStoreModel = types
log.debug('[WalletStore.send] counter', options.counter)
- const {returnChange, send} = yield cashuWallet.send(
- amountToSend,
- swapFeeReserve,
+ const {keep, send} = yield cashuWallet.swap(
+ amountToSend,
proofsToSendFrom,
{
- keysetId: cashuWallet.keys.id,
- preference: options.preference,
+ keysetId: cashuWallet.keysetId,
+ outputAmounts: options.outputAmounts,
counter: options.counter,
- pubkey: undefined,
- privkey: undefined
+ includeFees: false // fee reserve needs to be already in proofsToSendFrom
}
)
- log.trace(`[WalletStore.send] ${returnChange.length} returnedProofs`)
+ log.trace(`[WalletStore.send] ${keep.length} returnedProofs`)
log.trace(`[WalletStore.send] ${send.length} proofsToSend`)
// do some basic validations that proof amounts from mints match
const totalAmountToSendFrom: number = CashuUtils.getProofsAmount(proofsToSendFrom)
- const returnedAmount: number = CashuUtils.getProofsAmount(returnChange)
+ const returnedAmount: number = CashuUtils.getProofsAmount(keep)
const sendAmount: number = CashuUtils.getProofsAmount(send)
if (sendAmount !== amountToSend) {
@@ -437,8 +438,8 @@ export const WalletStoreModel = types
const swapFeePaid = totalAmountToSendFrom - amountToSend - returnedAmount
return {
- returnedProofs: returnChange as ProofV3[],
- proofsToSend: send as ProofV3[],
+ returnedProofs: keep as CashuProof[],
+ proofsToSend: send as CashuProof[],
swapFeePaid
}
} catch (e: any) {
@@ -455,23 +456,20 @@ export const WalletStoreModel = types
)
}
}),
- getSpentOrPendingProofsFromMint: flow(function* getSpentOrPendingProofsFromMint(
+ getProofsStatesFromMint: flow(function* getProofsStatesFromMint(
mintUrl: string,
unit: MintUnit,
proofs: Proof[]
) {
try {
- log.trace('[WalletStore.getSpentOrPendingProofsFromMint] start', {mintUrl, unit})
+ log.trace('[WalletStore.getProofsStatesFromMint] start', {mintUrl, unit})
const cashuWallet = yield self.getWallet(mintUrl, unit, {withSeed: false})
- const spentPendingProofs = yield cashuWallet.checkProofsSpent(proofs) // seems to work for all units
+ const proofsByState: {[CheckStateEnum: string]: Proof[]} = yield cashuWallet.checkProofsStates(proofs)
- log.trace('[WalletStore.getSpentOrPendingProofsFromMint]', {mintUrl, spentPendingProofs})
+ log.trace('[WalletStore.getProofsStatesFromMint]', {mintUrl, proofsByState})
- return spentPendingProofs as {
- spent: ProofV3[]
- pending: ProofV3[]
- }
+ return proofsByState
} catch (e: any) {
let message = 'Could not get response from the mint.'
@@ -481,7 +479,7 @@ export const WalletStoreModel = types
message,
{
message: e.message,
- caller: 'Wallet.getSpentOrPendingProofsFromMint',
+ caller: 'WalletStore.getProofsStatesFromMint',
mintUrl
}
)
@@ -565,23 +563,22 @@ export const WalletStoreModel = types
unit: MintUnit,
mintQuote: string,
options: {
- preference: AmountPreference[],
+ outputAmounts: OutputAmounts,
counter: number
}
) {
try {
const cashuWallet: CashuWallet = yield self.getWallet(mintUrl, unit, {withSeed: true}) // with seed
- const {proofs} = yield cashuWallet.mintTokens(
+ const proofs = yield cashuWallet.mintProofs(
amount,
mintQuote,
{
- keysetId: cashuWallet.keys.id,
- preference: options.preference,
- counter: options.counter,
- pubkey: undefined
+ keysetId: cashuWallet.keysetId,
+ outputAmounts: options.outputAmounts,
+ counter: options.counter,
}
- ) as Promise<{proofs: ProofV3[]}>
+ )
log.info('[mintProofs]', {proofs})
@@ -637,7 +634,7 @@ export const WalletStoreModel = types
mintUrl: string,
unit: MintUnit,
lightningMeltQuote: MeltQuoteResponse, // invoice is stored by mint by quote
- proofsToPayFrom: ProofV3[], // proofAmount >= amount + fee_reserve
+ proofsToPayFrom: CashuProof[], // proofAmount >= amount + fee_reserve
options: {
counter: number
}
@@ -645,12 +642,11 @@ export const WalletStoreModel = types
try {
const cashuWallet: CashuWallet = yield self.getWallet(mintUrl, unit, {withSeed: true}) // with seed
- const meltResponse: MeltTokensResponse =
- yield cashuWallet.meltTokens(
+ const meltResponse: MeltProofsResponse = yield cashuWallet.meltProofs(
lightningMeltQuote,
proofsToPayFrom,
{
- keysetId: cashuWallet.keys.id,
+ keysetId: cashuWallet.keysetId,
counter: options.counter
}
)
@@ -689,7 +685,7 @@ export const WalletStoreModel = types
const seedWallet = new CashuWallet(cashuMint, {
unit: 'sat', // just use default unit as we restore by keyset
- mnemonicOrSeed: seed
+ bip39seed: seed
})
const count = Math.abs(indexTo - indexFrom)
diff --git a/src/navigation/TabsNavigator.tsx b/src/navigation/TabsNavigator.tsx
index 73976803..4c986824 100644
--- a/src/navigation/TabsNavigator.tsx
+++ b/src/navigation/TabsNavigator.tsx
@@ -9,9 +9,7 @@ import { Icon, Text } from "../components"
import { translate } from "../i18n"
import {
WalletScreen,
- ReceiveOptionsScreen,
ReceiveScreen,
- SendOptionsScreen,
SendScreen,
ScanScreen,
LightningPayScreen,
@@ -129,14 +127,12 @@ export function TabsNavigator() {
export type WalletStackParamList = {
- Wallet: {scannedMintUrl? : string}
- ReceiveOptions: {unit: MintUnit} // to be removed
+ Wallet: {scannedMintUrl? : string}
TokenReceive: {
unit: MintUnit
mintUrl?: string,
}
- Receive: {unit: MintUnit, encodedToken? : string}
- SendOptions: {unit: MintUnit}
+ Receive: {unit: MintUnit, encodedToken? : string}
Send: {
unit: MintUnit,
paymentOption?: SendOption,
@@ -189,11 +185,9 @@ const WalletNavigator = function WalletNavigator() {
headerShown: false,
}}
>
-
-
+
-
-
+
diff --git a/src/screens/ContactDetailScreen.tsx b/src/screens/ContactDetailScreen.tsx
index e5ccb1b1..5daa11a6 100644
--- a/src/screens/ContactDetailScreen.tsx
+++ b/src/screens/ContactDetailScreen.tsx
@@ -12,8 +12,8 @@ import { ContactType } from '../models/Contact'
import { NostrClient, log } from '../services'
import { getImageSource } from '../utils/utils'
import { verticalScale } from '@gocodingnow/rn-size-matters'
-import { ReceiveOption } from './ReceiveOptionsScreen'
-import { SendOption } from './SendOptionsScreen'
+import { ReceiveOption } from './ReceiveScreen'
+import { SendOption } from './SendScreen'
import { IncomingDataType, IncomingParser } from '../services/incomingParser'
import { translate } from '../i18n'
diff --git a/src/screens/Contacts/ContactListItem.tsx b/src/screens/Contacts/ContactListItem.tsx
index 6a6fe670..9c4e9814 100644
--- a/src/screens/Contacts/ContactListItem.tsx
+++ b/src/screens/Contacts/ContactListItem.tsx
@@ -1,11 +1,10 @@
import { formatDistance } from 'date-fns'
import { observer } from "mobx-react-lite"
import React from "react"
-import { Image, ImageStyle, ScrollView, TextStyle, View, ViewStyle } from "react-native"
-import { Button, Icon, ListItem, Screen, Text } from "../../components"
-import { Contact, ContactType } from "../../models/Contact"
-import { NostrClient } from "../../services"
-import { colors, spacing, typography, useThemeColor } from "../../theme"
+import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native"
+import { ListItem } from "../../components"
+import { Contact } from "../../models/Contact"
+import { spacing } from "../../theme"
import { getImageSource } from '../../utils/utils'
diff --git a/src/screens/Contacts/OwnName.tsx b/src/screens/Contacts/OwnName.tsx
index 0ce36471..fac8c108 100644
--- a/src/screens/Contacts/OwnName.tsx
+++ b/src/screens/Contacts/OwnName.tsx
@@ -11,7 +11,7 @@ import { TransactionStatus } from '../../models/Transaction'
import { poller, stopPolling } from '../../utils/poller'
import { ResultModalInfo } from '../Wallet/ResultModalInfo'
import { MINIBITS_NIP05_DOMAIN } from '@env'
-import { SendOption } from '../SendOptionsScreen'
+import { SendOption } from '../SendScreen'
import { translate } from '../../i18n'
import { CurrencyAmount } from '../Wallet/CurrencyAmount'
import { CurrencyCode } from '../../services/wallet/currency'
diff --git a/src/screens/Contacts/PrivateContacts.tsx b/src/screens/Contacts/PrivateContacts.tsx
index d5525852..81634fde 100644
--- a/src/screens/Contacts/PrivateContacts.tsx
+++ b/src/screens/Contacts/PrivateContacts.tsx
@@ -13,8 +13,8 @@ import { log } from '../../services/logService'
import { ContactListItem } from './ContactListItem'
import { Contact, ContactType } from '../../models/Contact'
import { StackNavigationProp } from '@react-navigation/stack'
-import { ReceiveOption } from '../ReceiveOptionsScreen'
-import { SendOption } from '../SendOptionsScreen'
+import { ReceiveOption } from '../ReceiveScreen'
+import { SendOption } from '../SendScreen'
import { infoMessage, warningMessage } from '../../utils/utils'
import { IncomingDataType, IncomingParser } from '../../services/incomingParser'
import { translate } from '../../i18n'
@@ -422,8 +422,7 @@ const $newContainer: TextStyle = {
const $contactInput: TextStyle = {
flex: 1,
// borderRadius: 0,
- // borderBottomRightRadius: spacing.extraSmall,
- // borderTopLeftRadius: spacing.extraSmall,
+ borderRadius: spacing.extraSmall,
fontSize: verticalScale(16),
padding: spacing.small,
alignSelf: 'stretch',
@@ -433,6 +432,7 @@ const $contactInput: TextStyle = {
const $contactDomain: TextStyle = {
marginRight: spacing.small,
+ marginLeft: -spacing.small,
borderTopRightRadius: spacing.extraSmall,
borderBottomRightRadius: spacing.extraSmall,
padding: spacing.extraSmall,
diff --git a/src/screens/Contacts/PublicContacts.tsx b/src/screens/Contacts/PublicContacts.tsx
index b59d13f5..e898b7f6 100644
--- a/src/screens/Contacts/PublicContacts.tsx
+++ b/src/screens/Contacts/PublicContacts.tsx
@@ -13,8 +13,8 @@ import { log } from '../../services/logService'
import { Contact, ContactType } from '../../models/Contact'
import { StackNavigationProp } from '@react-navigation/stack'
import { ContactsStackParamList } from '../../navigation'
-import { SendOption } from '../SendOptionsScreen'
-import { ReceiveOption } from '../ReceiveOptionsScreen'
+import { SendOption } from '../SendScreen'
+import { ReceiveOption } from '../ReceiveScreen'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { IncomingDataType, IncomingParser } from '../../services/incomingParser'
import { translate } from '../../i18n'
diff --git a/src/screens/ContactsScreen.tsx b/src/screens/ContactsScreen.tsx
index eae145a3..cdb5aef4 100644
--- a/src/screens/ContactsScreen.tsx
+++ b/src/screens/ContactsScreen.tsx
@@ -10,8 +10,8 @@ import { PrivateContacts } from './Contacts/PrivateContacts'
import { PublicContacts } from './Contacts/PublicContacts'
import { log } from '../services/logService'
import { getImageSource } from '../utils/utils'
-import { ReceiveOption } from './ReceiveOptionsScreen'
-import { SendOption } from './SendOptionsScreen'
+import { ReceiveOption } from './ReceiveScreen'
+import { SendOption } from './SendScreen'
import { verticalScale } from '@gocodingnow/rn-size-matters'
diff --git a/src/screens/ExportBackupScreen.tsx b/src/screens/ExportBackupScreen.tsx
index a8872c9b..f8769e44 100644
--- a/src/screens/ExportBackupScreen.tsx
+++ b/src/screens/ExportBackupScreen.tsx
@@ -28,7 +28,7 @@ import AppError from '../utils/AppError'
import { Proof } from '../models/Proof'
import { useStores } from '../models'
import EventEmitter from '../utils/eventEmitter'
-import { CashuUtils, ProofV3, TokenV3 } from '../services/cashu/cashuUtils'
+import { CashuProof, CashuUtils } from '../services/cashu/cashuUtils'
import Clipboard from '@react-native-clipboard/clipboard'
import { translate } from '../i18n'
import { ProofsStoreSnapshot } from '../models/ProofsStore'
@@ -39,6 +39,7 @@ import { Database, TransactionTaskResult, WalletTask, WalletTaskResult } from '.
import { Transaction, TransactionStatus } from '../models/Transaction'
import { ResultModalInfo } from './Wallet/ResultModalInfo'
import { verticalScale } from '@gocodingnow/rn-size-matters'
+import { Token, getDecodedToken, getEncodedToken } from '@cashu/cashu-ts'
interface ExportBackupScreenProps extends SettingsStackScreenProps<'ExportBackup'> {}
@@ -117,9 +118,9 @@ export const ExportBackupScreen: FC =
// now we batch receive the pending encoded token
// this forces the proofs swap with the mint for standard denomination amounts
const encodedTokenToReceive: string = result.encodedTokenToSend
- const tokenToReceive = CashuUtils.decodeToken(encodedTokenToReceive)
- const {totalAmount: tokenAmount} = CashuUtils.getTokenAmounts(tokenToReceive)
- const proofsCount = tokenToReceive.token[0].proofs.length
+ const tokenToReceive = getDecodedToken(encodedTokenToReceive)
+ const tokenAmount = CashuUtils.getProofsAmount(tokenToReceive.proofs)
+ const proofsCount = tokenToReceive.proofs.length
setTotalSentProofsCount(prev => prev + proofsCount)
setIsReceiveBatchSentToQueue(true)
@@ -366,11 +367,11 @@ export const ExportBackupScreen: FC =
for (const keysetId in groupedByKeyset) {
const proofsByKeysetId = groupedByKeyset[keysetId]
- const proofsToExport: ProofV3[] = []
+ const proofsToExport: CashuProof[] = []
for (const p of proofsByKeysetId) {
// clean private params
- const proofToExport: ProofV3 = {
+ const proofToExport: CashuProof = {
id: p.id,
amount: p.amount,
secret: p.secret,
@@ -380,19 +381,15 @@ export const ExportBackupScreen: FC =
proofsToExport.push(proofToExport)
}
- const tokenByKeysetId: TokenV3 = {
- token: [
- {
- mint,
- proofs: proofsToExport
- }
- ],
+ const tokenByKeysetId: Token = {
+ mint,
+ proofs: proofsToExport,
unit: proofsByKeysetId[0].unit
}
log.trace('[copyEncodedTokens]', {tokenByKeysetId})
- const encodedByMint = CashuUtils.encodeToken(tokenByKeysetId)
+ const encodedByMint = getEncodedToken(tokenByKeysetId)
encodedTokens.push(encodedByMint)
}
}
@@ -501,7 +498,7 @@ export const ExportBackupScreen: FC =
continue
}
- const amount = CashuUtils.getProofsAmount(proofsToImport)
+ const amount = sumProofs(proofsToImport)
const unit = proofsByKeysetId[0].unit
log.trace('[doLocalRecovery] to be recovered', {mint, keysetId, unit, amount})
diff --git a/src/screens/ImportBackupScreen.tsx b/src/screens/ImportBackupScreen.tsx
index 96cc0ae4..04559047 100644
--- a/src/screens/ImportBackupScreen.tsx
+++ b/src/screens/ImportBackupScreen.tsx
@@ -25,9 +25,9 @@ import { Database, KeyChain, log, MinibitsClient, NostrClient } from '../service
import Clipboard from '@react-native-clipboard/clipboard'
import { rootStoreInstance, useStores } from '../models'
import {MnemonicInput} from './Recovery/MnemonicInput'
-import { TransactionData, TransactionStatus } from '../models/Transaction'
+import { TransactionStatus } from '../models/Transaction'
import { ResultModalInfo } from './Wallet/ResultModalInfo'
-import { deriveSeedFromMnemonic } from '@cashu/cashu-ts'
+import {deriveSeedFromMnemonic} from '@cashu/crypto/modules/client/NUT09'
import { MINIBITS_MINT_URL, MINIBITS_NIP05_DOMAIN } from '@env'
import { delay } from '../utils/utils'
import { applySnapshot} from 'mobx-state-tree'
diff --git a/src/screens/LightningPayScreen.tsx b/src/screens/LightningPayScreen.tsx
index 7db01c3f..e336d54b 100644
--- a/src/screens/LightningPayScreen.tsx
+++ b/src/screens/LightningPayScreen.tsx
@@ -10,13 +10,12 @@ import {colors, spacing, useThemeColor} from '../theme'
import {log} from '../services/logService'
import { IncomingDataType, IncomingParser } from '../services/incomingParser'
import AppError, { Err } from '../utils/AppError'
-import { Button, Card, ErrorModal, Header, Icon, InfoModal, ListItem, ScanIcon, Screen, Text } from '../components'
-import { LnurlUtils } from '../services/lnurl/lnurlUtils'
+import { Button, Card, ErrorModal, Icon, InfoModal, ListItem, ScanIcon, Screen, Text } from '../components'
import { infoMessage } from '../utils/utils'
import Clipboard from '@react-native-clipboard/clipboard'
import { SvgXml } from 'react-native-svg'
-import { SendOption } from './SendOptionsScreen'
-import { CurrencyCode, MintUnit } from '../services/wallet/currency'
+import { SendOption } from './SendScreen'
+import { MintUnit } from '../services/wallet/currency'
import { useStores } from '../models'
import { Mint } from '../models/Mint'
import { MintHeader } from './Mints/MintHeader'
diff --git a/src/screens/MintInfoScreen.tsx b/src/screens/MintInfoScreen.tsx
index 5554538e..223fc2a8 100644
--- a/src/screens/MintInfoScreen.tsx
+++ b/src/screens/MintInfoScreen.tsx
@@ -1,5 +1,5 @@
import React, { FC, useEffect, useMemo, useState } from 'react'
-import { GetInfoResponse, NUT15Entry, NUT17Entry, SwapMethod } from '@cashu/cashu-ts'
+import { GetInfoResponse, SwapMethod } from '@cashu/cashu-ts'
import { isObj } from '@cashu/cashu-ts/src/utils'
import Clipboard from '@react-native-clipboard/clipboard'
import { observer } from 'mobx-react-lite'
@@ -21,7 +21,6 @@ import {
Screen,
Text,
} from '../components'
-import { AvatarHeader } from '../components/AvatarHeader'
import { CollapsibleText } from '../components/CollapsibleText'
import { translate } from '../i18n'
import { useStores } from '../models'
@@ -387,11 +386,11 @@ function NutsCard(props: {info: GetInfoResponse}) {
// detailed nuts are separated from simple ones if we want to show more info abt them in the future
for (const [nut, info] of Object.entries(props.info.nuts)) {
- if (nut === '15' && (info as NUT15Entry[]).length > 0) {
+ if (nut === '15' && info) {
// see https://github.com/cashubtc/nuts/blob/main/15.md - multipath payments
// in the future, it might be nice to show for which currencies are multipath payments supported
// for example by extending NutItem
- nutsSimple.push(['15', (info as NUT15Entry[])[0]?.mpp ?? false])
+ nutsSimple.push(['15', (info)[0]?.mpp ?? false])
continue;
}
// bug: nutshell 0.15.3 returns NUT17Entry[], instead of { supported: NUT17Entry[] }
diff --git a/src/screens/MintsScreen.tsx b/src/screens/MintsScreen.tsx
index bdc3e2df..d5f495b9 100644
--- a/src/screens/MintsScreen.tsx
+++ b/src/screens/MintsScreen.tsx
@@ -5,7 +5,7 @@ import Clipboard from '@react-native-clipboard/clipboard'
import {
MINIBITS_MINT_URL
} from '@env'
-import {spacing, typography, useThemeColor} from '../theme'
+import {colors, spacing, typography, useThemeColor} from '../theme'
import {SettingsStackScreenProps} from '../navigation'
import {
Button,
@@ -279,6 +279,7 @@ export const MintsScreen: FC> = observer(
const iconColor = useThemeColor('textDim')
const inputBg = useThemeColor('background')
const headerTitle = useThemeColor('headerTitle')
+ const buttonBorder = useThemeColor('card')
return (
@@ -432,7 +433,9 @@ export const MintsScreen: FC> = observer(
tx='common.paste'
style={{
borderRadius: 0,
- marginLeft: 1,
+ marginLeft: -spacing.small,
+ borderLeftWidth: 1,
+ borderLeftColor: buttonBorder
}}
onPress={pasteMintUrl}
/>
@@ -532,32 +535,13 @@ const $card: ViewStyle = {
// paddingTop: 0,
}
-const $cardHeading: TextStyle = {
- fontFamily: typography.primary?.medium,
- fontSize: 20,
-}
-
-const $cardContent: TextStyle = {
- fontSize: 14,
-}
-
-const $bottomContainer: ViewStyle = {
- flex: 1,
- justifyContent: 'flex-end',
- marginBottom: spacing.large,
- alignSelf: 'stretch',
-}
-
const $bottomModal: ViewStyle = {
alignItems: 'center',
}
-
const $mintInput: TextStyle = {
flex: 1,
- borderTopLeftRadius: spacing.extraSmall,
- borderBottomLeftRadius: spacing.extraSmall,
- // fontSize: 16,
+ borderRadius: spacing.extraSmall,
padding: spacing.extraSmall,
alignSelf: 'stretch',
// textAlignVertical: 'top',
diff --git a/src/screens/MnemonicScreen.tsx b/src/screens/MnemonicScreen.tsx
index 64c1ffed..86f38e81 100644
--- a/src/screens/MnemonicScreen.tsx
+++ b/src/screens/MnemonicScreen.tsx
@@ -107,7 +107,7 @@ export const MnemonicScreen: FC> = observer
const headerTitle = useThemeColor('headerTitle')
return (
-
+
diff --git a/src/screens/NwcScreen.tsx b/src/screens/NwcScreen.tsx
index 282f1096..e012ca9c 100644
--- a/src/screens/NwcScreen.tsx
+++ b/src/screens/NwcScreen.tsx
@@ -1,6 +1,5 @@
import {observer} from 'mobx-react-lite'
import { Observer } from 'mobx-react-lite'
-import Clipboard from '@react-native-clipboard/clipboard'
import React, {FC, useEffect, useRef, useState} from 'react'
import {FlatList, TextInput, TextStyle, View, ViewStyle} from 'react-native'
import {colors, spacing, useThemeColor} from '../theme'
@@ -14,7 +13,6 @@ import { verticalScale } from '@gocodingnow/rn-size-matters'
import { NwcConnection } from '../models/NwcStore'
import { QRCodeBlock } from './Wallet/QRCode'
import { CollapsibleText } from '../components/CollapsibleText'
-import { isSameDay } from 'date-fns/isSameDay'
interface NwcScreenProps extends SettingsStackScreenProps<'Nwc'> {}
diff --git a/src/screens/OwnKeysScreen.tsx b/src/screens/OwnKeysScreen.tsx
index ecf9ebf6..443f7f43 100644
--- a/src/screens/OwnKeysScreen.tsx
+++ b/src/screens/OwnKeysScreen.tsx
@@ -2,6 +2,7 @@ import {observer} from 'mobx-react-lite'
import React, {FC, useRef, useState} from 'react'
import {Image, LayoutAnimation, Platform, TextInput, TextStyle, UIManager, View, ViewStyle} from 'react-native'
import {getPublicKey} from 'nostr-tools'
+import { hexToBytes } from '@noble/hashes/utils'
import {colors, spacing, typography, useThemeColor} from '../theme'
import {ContactsStackScreenProps} from '../navigation'
import {Icon, ListItem, Screen, Text, Card, BottomModal, Button, InfoModal, ErrorModal, Loading} from '../components'
@@ -169,7 +170,7 @@ export const OwnKeysScreen: FC = observer(function OwnKeysSc
}
// validate that nsec matches profile pubkey
const privateKey = NostrClient.getHexkey(ownNsec)
- const publicKey = getPublicKey(privateKey)
+ const publicKey = getPublicKey(hexToBytes(privateKey))
if(publicKey !== ownProfile.pubkey) {
throw new AppError(Err.VALIDATION_ERROR, translate("nsecPrivatePublicKeyMismatchError"), {publicKey})
@@ -397,7 +398,7 @@ export const OwnKeysScreen: FC = observer(function OwnKeysSc
isVisible={isProfileChangeCompleted ? true : false}
ContentComponent={
-
+
> = observer(
- function ReceiveOptionsScreen({route, navigation}) {
- useHeader({
- leftIcon: 'faArrowLeft',
- onLeftPress: () => navigation.goBack(),
- })
-
-
- const isInternetReachable = useIsInternetReachable()
-
- const [info, setInfo] = useState('')
- const [error, setError] = useState()
-
- const gotoContacts = function () {
- navigation.navigate('ContactsNavigator', {
- screen: 'Contacts',
- params: {
- paymentOption: ReceiveOption.SEND_PAYMENT_REQUEST
- }
- })
- }
-
-
- const gotoTopup = function () {
- navigation.navigate('Topup', { paymentOption: ReceiveOption.SHOW_INVOICE })
- }
-
-
- const onScan = async function () {
- navigation.navigate('Scan')
- }
-
-
- const handleError = function (e: AppError): void {
- log.error(e.name, e.message)
- setError(e)
- }
-
- const headerBg = useThemeColor('header')
- const iconColor = useThemeColor('textDim')
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- }
- // leftIcon='faQrcode'
- // leftIconColor={colors.palette.success200}
- // leftIconInverse={true}
- style={$item}
- topSeparator={true}
- onPress={onScan}
- />
- >
- }
- />
-
- {info && }
- {error && }
-
- )
- },
-)
-
-const $screen: ViewStyle = {
- flex: 1,
-}
-
-const $headerContainer: TextStyle = {
- alignItems: 'center',
- padding: spacing.medium,
- height: spacing.screenHeight * 0.20,
-}
-
-const $contentContainer: TextStyle = {
- // flex: 1,
- padding: spacing.extraSmall,
- // alignItems: 'center',
-}
-
-const $optionsCard: ViewStyle = {
- marginTop: -spacing.extraLarge * 2,
- marginBottom: spacing.small,
- //paddingTop: 0,
-}
-
-
-const $item: ViewStyle = {
- paddingHorizontal: spacing.small,
- paddingLeft: 0,
-}
-
-
diff --git a/src/screens/ReceiveScreen.tsx b/src/screens/ReceiveScreen.tsx
index 48365c70..e227e480 100644
--- a/src/screens/ReceiveScreen.tsx
+++ b/src/screens/ReceiveScreen.tsx
@@ -24,24 +24,33 @@ import {log} from '../services/logService'
import AppError, { Err } from '../utils/AppError'
import EventEmitter from '../utils/eventEmitter'
-import {CashuUtils, TokenV3} from '../services/cashu/cashuUtils'
+import {CashuUtils, CashuProof} from '../services/cashu/cashuUtils'
import {ResultModalInfo} from './Wallet/ResultModalInfo'
import {MintListItem} from './Mints/MintListItem'
import useIsInternetReachable from '../utils/useIsInternetReachable'
import { verticalScale } from '@gocodingnow/rn-size-matters'
-import { CurrencyCode, MintUnit, formatCurrency, getCurrency } from "../services/wallet/currency"
+import { CurrencyCode, MintUnit, getCurrency } from "../services/wallet/currency"
import { MintHeader } from './Mints/MintHeader'
import { round, toNumber } from '../utils/number'
import numbro from 'numbro'
import { TranItem } from './TranDetailScreen'
import { translate } from '../i18n'
+import { Token, getDecodedToken } from '@cashu/cashu-ts'
+
+export enum ReceiveOption {
+ // CREATE_AND_SEND_PAYMENT_REQUEST = 'CREATE_AND_SEND_PAYMENT_REQUEST',
+ SEND_PAYMENT_REQUEST = 'SEND_PAYMENT_REQUEST',
+ PASTE_OR_SCAN_TOKEN = 'PASTE_OR_SCAN_TOKEN',
+ SHOW_INVOICE = 'SHOW_INVOICE',
+ LNURL_WITHDRAW = 'LNURL_WITHDRAW'
+}
export const ReceiveScreen: FC> = observer(
function ReceiveScreen({route, navigation}) {
const isInternetReachable = useIsInternetReachable()
const {mintsStore, walletStore} = useStores()
- const [token, setToken] = useState()
+ const [token, setToken] = useState()
const [encodedToken, setEncodedToken] = useState()
const [amountToReceive, setAmountToReceive] = useState('0')
const [unit, setUnit] = useState('sat')
@@ -165,11 +174,11 @@ export const ReceiveScreen: FC> = observer(
try {
navigation.setParams({encodedToken: undefined})
- const decoded = CashuUtils.decodeToken(encoded)
- const tokenAmounts = CashuUtils.getTokenAmounts(decoded)
+ const decoded = getDecodedToken(encoded)
+ const tokenAmount = CashuUtils.getProofsAmount(decoded.proofs)
log.trace('decoded token', {decoded})
- log.trace('tokenAmounts', {tokenAmounts})
+ log.trace('tokenAmount', {tokenAmount})
if(!decoded.unit) {
setInfo(translate("decodedMissingCurrencyUnit", { unit: CurrencyCode.SAT }))
@@ -179,7 +188,7 @@ export const ReceiveScreen: FC> = observer(
const currency = getCurrency(decoded.unit as MintUnit)
setToken(decoded)
- setAmountToReceive(numbro(tokenAmounts.totalAmount / currency.precision).format({thousandSeparated: true, mantissa: currency.mantissa}))
+ setAmountToReceive(numbro(tokenAmount / currency.precision).format({thousandSeparated: true, mantissa: currency.mantissa}))
setUnit(decoded.unit as MintUnit)
if (decoded.memo && decoded.memo.length > 0) {
@@ -197,12 +206,12 @@ export const ReceiveScreen: FC> = observer(
setIsReceiveTaskSentToQueue(true)
const amountToReceiveInt = round(toNumber(amountToReceive) * getCurrency(unit).precision, 0)
- const proofsCount = token!.token.flatMap(entry => entry.proofs).length
+ const proofsCount = token!.proofs.length
if(proofsCount > MAX_SWAP_INPUT_SIZE) {
WalletTask.receiveBatch(
- token as TokenV3,
+ token as Token,
amountToReceiveInt,
memo,
encodedToken as string,
@@ -211,7 +220,7 @@ export const ReceiveScreen: FC> = observer(
} else {
WalletTask.receive(
- token as TokenV3,
+ token as Token,
amountToReceiveInt,
memo,
encodedToken as string,
@@ -234,7 +243,7 @@ export const ReceiveScreen: FC> = observer(
)
const mintInstance = mintsStore.findByUrl(mint)
- const counter = mintInstance!.getProofsCounterByKeysetId!(walletInstance.keys.id)
+ const counter = mintInstance!.getProofsCounterByKeysetId!(walletInstance.keysetId)
counter!.increaseProofsCounter(20)
// retry receive
@@ -254,7 +263,7 @@ export const ReceiveScreen: FC> = observer(
const amountToReceiveInt = round(toNumber(amountToReceive) * getCurrency(unit).precision, 0)
WalletTask.receiveOfflinePrepare(
- token as TokenV3,
+ token as Token,
amountToReceiveInt,
memo,
encodedToken as string,
diff --git a/src/screens/ScanScreen.tsx b/src/screens/ScanScreen.tsx
index 8292a075..18af2737 100644
--- a/src/screens/ScanScreen.tsx
+++ b/src/screens/ScanScreen.tsx
@@ -6,17 +6,15 @@ import {
ViewStyle,
View,
TextStyle,
- TextInput,
} from 'react-native'
import {WalletStackScreenProps} from '../navigation'
import {Camera, CameraType} from 'react-native-camera-kit'
import { URDecoder } from '@gandlaf21/bc-ur'
import {spacing, typography, useThemeColor} from '../theme'
-import {useHeader} from '../utils/useHeader'
import {log} from '../services/logService'
import { IncomingDataType, IncomingParser } from '../services/incomingParser'
import AppError, { Err } from '../utils/AppError'
-import { BottomModal, Button, ErrorModal, Header, Icon, Screen, Text } from '../components'
+import { Button, ErrorModal, Header, Icon, Screen } from '../components'
import { LnurlUtils } from '../services/lnurl/lnurlUtils'
import { infoMessage } from '../utils/utils'
import Clipboard from '@react-native-clipboard/clipboard'
diff --git a/src/screens/SeedRecoveryScreen.tsx b/src/screens/SeedRecoveryScreen.tsx
index dca278c6..32d4ac03 100644
--- a/src/screens/SeedRecoveryScreen.tsx
+++ b/src/screens/SeedRecoveryScreen.tsx
@@ -31,7 +31,7 @@ import { CashuUtils } from '../services/cashu/cashuUtils'
import { Proof } from '../models/Proof'
import { Transaction, TransactionData, TransactionRecord, TransactionStatus, TransactionType } from '../models/Transaction'
import { ResultModalInfo } from './Wallet/ResultModalInfo'
-import { deriveSeedFromMnemonic } from '@cashu/cashu-ts'
+import {deriveSeedFromMnemonic} from '@cashu/crypto/modules/client/NUT09'
import { MINIBITS_MINT_URL, MINIBITS_NIP05_DOMAIN } from '@env'
import { delay } from '../utils/utils'
import { getSnapshot, isStateTreeNode } from 'mobx-state-tree'
@@ -39,7 +39,7 @@ import { scale } from '@gocodingnow/rn-size-matters'
import { WalletUtils } from '../services/wallet/utils'
import { WalletScreen } from './WalletScreen'
import { MintUnit, formatCurrency, getCurrency } from '../services/wallet/currency'
-import { isObj } from '@cashu/cashu-ts/src/utils'
+import { isObj, sumProofs } from '@cashu/cashu-ts/src/utils'
import { WalletProfileRecord } from '../models/WalletProfileStore'
import { translate } from '../i18n'
@@ -271,7 +271,7 @@ export const SeedRecoveryScreen: FC> = obser
setStatusMessage(translate("recovery.spentProofsAmount", { amount: spent.length }))
- const spentAmount = CashuUtils.getProofsAmount(spent as Proof[])
+ const spentAmount = sumProofs(spent as Proof[])
alreadySpentAmount += spentAmount
const unspent = proofs.filter((proof: Proof) => !spent.includes(proof))
diff --git a/src/screens/SendOptionsScreen.tsx b/src/screens/SendOptionsScreen.tsx
deleted file mode 100644
index cbd9882b..00000000
--- a/src/screens/SendOptionsScreen.tsx
+++ /dev/null
@@ -1,153 +0,0 @@
-import {observer} from 'mobx-react-lite'
-import React, {FC, useState, useCallback, useEffect} from 'react'
-import {Alert, TextStyle, View, ViewStyle} from 'react-native'
-import {spacing, useThemeColor, colors} from '../theme'
-import {WalletStackScreenProps} from '../navigation'
-import {
- Button,
- Icon,
- Card,
- Screen,
- ListItem,
- Text,
-} from '../components'
-import {useHeader} from '../utils/useHeader'
-import {log} from '../services/logService'
-import AppError from '../utils/AppError'
-
-export enum SendOption {
- SEND_TOKEN = 'SEND_TOKEN',
- PASTE_OR_SCAN_INVOICE = 'PASTE_OR_SCAN_INVOICE',
- SHOW_TOKEN = 'SHOW_TOKEN',
- PAY_PAYMENT_REQUEST = 'PAY_PAYMENT_REQUEST',
- LNURL_PAY = 'LNURL_PAY',
- LNURL_ADDRESS = 'LNURL_ADDRESS',
- DONATION = 'DONATION',
-}
-
-export const SendOptionsScreen: FC> = observer(
- function SendOptionsScreen({route, navigation}) {
- useHeader({
- leftIcon: 'faArrowLeft',
- onLeftPress: () => navigation.goBack(),
- })
-
- const [error, setError] = useState()
-
- const gotoContacts = function () {
- navigation.navigate('ContactsNavigator', {
- screen: 'Contacts',
- params: {paymentOption: SendOption.SEND_TOKEN}})
- }
-
-
- const gotoSend = function () {
- navigation.navigate('Send', {
- paymentOption: SendOption.SHOW_TOKEN}
- )
- }
-
-
- const gotoLightningPay = async function () {
- navigation.navigate('LightningPay')
- }
-
-
- const handleError = function (e: AppError): void {
- log.error(e.name, e.message)
- setError(e)
- }
-
- const headerBg = useThemeColor('header')
- const subtitleColor = useThemeColor('textDim')
-
- return (
-
-
-
-
-
-
-
-
- >
- }
- />
-
-
- >
- }
-
- />
-
-
- )
- },
-)
-
-const $screen: ViewStyle = {
- flex: 1,
-}
-
-const $headerContainer: TextStyle = {
- alignItems: 'center',
- padding: spacing.medium,
- height: spacing.screenHeight * 0.20,
-}
-
-const $contentContainer: TextStyle = {
- // flex: 1,
- padding: spacing.extraSmall,
- // alignItems: 'center',
-}
-
-const $ecashCard: ViewStyle = {
- marginTop: -spacing.extraLarge * 2,
- marginBottom: spacing.small,
- // paddingTop: 0,
-}
-
-const $lightningCard: ViewStyle = {
- marginVertical: spacing.small,
- // paddingTop: 0,
- }
-
-const $item: ViewStyle = {
- paddingHorizontal: spacing.small,
- paddingLeft: 0,
-}
diff --git a/src/screens/SendScreen.tsx b/src/screens/SendScreen.tsx
index 3e0ae5d0..99ac0c0d 100644
--- a/src/screens/SendScreen.tsx
+++ b/src/screens/SendScreen.tsx
@@ -53,7 +53,6 @@ import useIsInternetReachable from '../utils/useIsInternetReachable'
import { Proof } from '../models/Proof'
import { Contact, ContactType } from '../models/Contact'
import { getImageSource, infoMessage } from '../utils/utils'
-import { SendOption } from './SendOptionsScreen'
import { verticalScale } from '@gocodingnow/rn-size-matters'
import { MintUnit, formatCurrency, getCurrency } from "../services/wallet/currency"
import { MintHeader } from './Mints/MintHeader'
@@ -64,6 +63,15 @@ import numbro from 'numbro'
import { TranItem } from './TranDetailScreen'
import { MemoInputCard } from '../components/MemoInputCard'
+export enum SendOption {
+ SEND_TOKEN = 'SEND_TOKEN',
+ PASTE_OR_SCAN_INVOICE = 'PASTE_OR_SCAN_INVOICE',
+ SHOW_TOKEN = 'SHOW_TOKEN',
+ PAY_PAYMENT_REQUEST = 'PAY_PAYMENT_REQUEST',
+ LNURL_PAY = 'LNURL_PAY',
+ LNURL_ADDRESS = 'LNURL_ADDRESS',
+ DONATION = 'DONATION',
+}
if (Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental) {
@@ -449,8 +457,8 @@ export const SendScreen: FC> = observer(
{withSeed: true}
)
const mintInstance = mintsStore.findByUrl(mintBalanceToSendFrom?.mintUrl as string)
- const counter = mintInstance!.getProofsCounterByKeysetId!(walletInstance.keys.id)
- counter!.increaseProofsCounter(50)
+ const counter = mintInstance!.getProofsCounterByKeysetId!(walletInstance.keysetId)
+ counter!.increaseProofsCounter(20)
// retry send
onMintBalanceConfirm()
@@ -698,7 +706,7 @@ export const SendScreen: FC> = observer(
!previousState)
- const increaseProofsCounter = async function (tokenToRetry: TokenV3) {
+ const increaseProofsCounter = async function (tokenToRetry: Token) {
const {mint} = transaction
const walletInstance = await walletStore.getWallet(
mint,
@@ -612,7 +613,7 @@ const ReceiveInfoBlock = function (props: {
)
const mintInstance = mintsStore.findByUrl(mint)
- const counter = mintInstance!.getProofsCounterByKeysetId!(walletInstance.keys.id)
+ const counter = mintInstance!.getProofsCounterByKeysetId!(walletInstance.keysetId)
counter!.increaseProofsCounter(20)
}
@@ -624,8 +625,8 @@ const ReceiveInfoBlock = function (props: {
setIsLoading(true)
try {
- const tokenToRetry: TokenV3 = CashuUtils.decodeToken(transaction.inputToken)
- const amountToReceive = CashuUtils.getTokenAmounts(tokenToRetry).totalAmount
+ const tokenToRetry = getDecodedToken(transaction.inputToken)
+ const amountToReceive = CashuUtils.getProofsAmount(tokenToRetry.proofs)
const memo = tokenToRetry.memo || ''
if(isCounterIncreaseNeeded) {
diff --git a/src/screens/Transactions/TransactionListItem.tsx b/src/screens/Transactions/TransactionListItem.tsx
index 50227143..89e000b4 100644
--- a/src/screens/Transactions/TransactionListItem.tsx
+++ b/src/screens/Transactions/TransactionListItem.tsx
@@ -210,7 +210,7 @@ export const TransactionListItem = observer(function (
amountStyle={{color: txReceiveColor}}
/>
)}
- {[TransactionStatus.ERROR, TransactionStatus.BLOCKED, TransactionStatus.PREPARED_OFFLINE].includes(tx.status) && (
+ {[TransactionStatus.ERROR, TransactionStatus.BLOCKED, TransactionStatus.PREPARED_OFFLINE, TransactionStatus.EXPIRED].includes(tx.status) && (
()
- const [encodedV4Token, setEncodedV4Token] = useState()
- const [decodedV3Token, setDecodedV3Token] = useState()
+ const [qrError, setQrError] = useState()
+ const [encodedV3Token, setEncodedV3Token] = useState()
+ const [decodedToken, setDecodedToken] = useState()
const [keysetFormat, setKeysetFormat] = useState<'hex' | 'base64' | undefined>()
const [isLoadingQRCode, setIsLoadingQRCode] = useState(false)
const [isQRCodeError, setIsQRCodeError] = useState(false)
@@ -37,20 +38,20 @@ export const QRCodeBlock = function (props: {
useEffect(() => {
const detectKeysetFormat = () => {
- if(type === 'EncodedV3Token') {
- const decoded = CashuUtils.decodeToken(qrCodeData) as TokenV3
- setDecodedV3Token(decoded)
+ if(type === 'EncodedV4Token') {
+ const decoded = getDecodedToken(qrCodeData)
+ setDecodedToken(decoded)
- if(decoded.token[0].proofs[0].id.startsWith('00')) {
- setKeysetFormat('hex')
+ if(decoded.proofs[0].id.startsWith('00')) {
+ setKeysetFormat('hex')
+ } else {
try {
- // make v4 default one
- const encodedV4 = CashuUtils.encodeToken(decoded, 4)
- setEncodedV4Token(encodedV4)
+ // make v3 legacy format
+ const encodedV3 = getEncodedToken(decoded, {version: 3})
+ setEncodedV3Token(encodedV3)
} catch (e: any) {
handleQrError(e)
}
- } else {
setKeysetFormat('base64')
}
}
@@ -122,19 +123,19 @@ export const QRCodeBlock = function (props: {
const switchTokenEncoding = function () {
try {
- if(encodedV4Token) {
- setEncodedV4Token(undefined)
- } else if(type === 'EncodedV3Token') {
- log.trace('[v3]', qrCodeData)
+ if(encodedV3Token) {
+ setEncodedV3Token(undefined)
+ } else if(type === 'EncodedV4Token') {
+ log.trace('[v4]', qrCodeData)
- if(!decodedV3Token) {
+ if(!decodedToken) {
return false
}
- const encodedV4 = CashuUtils.encodeToken(decodedV3Token, 4)
+ const encodedV3 = getEncodedToken(decodedToken, {version: 3})
- log.trace('[v4]', encodedV4)
- setEncodedV4Token(encodedV4)
+ log.trace('[v3]', encodedV3)
+ setEncodedV3Token(encodedV3)
}
} catch (e: any) {
handleQrError(e)
@@ -163,7 +164,7 @@ export const QRCodeBlock = function (props: {
const onCopy = function () {
try {
- Clipboard.setString(encodedV4Token || qrCodeData as string)
+ Clipboard.setString(encodedV3Token || qrCodeData as string)
} catch (e: any) {
handleQrError(e)
}
@@ -205,7 +206,7 @@ export const QRCodeBlock = function (props: {
/>
) : (
)}
@@ -240,10 +241,10 @@ export const QRCodeBlock = function (props: {
paddingVertical: verticalScale(spacing.tiny)
}}
/>
- {type === 'EncodedV3Token' && keysetFormat === 'hex' && !isAnimating && (
+ {type === 'EncodedV4Token' && keysetFormat === 'hex' && !isAnimating && (