mirror of
https://github.com/minibits-cash/minibits_wallet.git
synced 2026-10-05 19:28:26 +00:00
POC for v4 token encoding and decoding
This commit is contained in:
+2
-1
@@ -19,7 +19,8 @@
|
||||
"postinstall": "patch-package --exclude 'nothing'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cashu/cashu-ts": "minibits-cash/cashu-ts#1.0.0-minibits.3",
|
||||
"@cashu/cashu-ts": "minibits-cash/cashu-ts#1.0.0-minibits.4",
|
||||
"@exodus/borc": "^2.1.1",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||
|
||||
@@ -123,7 +123,7 @@ interface CardProps extends TouchableOpacityProps {
|
||||
*
|
||||
* - [Documentation and Examples](https://github.com/infinitered/ignite/blob/master/docs/Components-Card.md)
|
||||
*/
|
||||
export function Card(props: CardProps) {
|
||||
export const Card = function (props: CardProps) {
|
||||
|
||||
const backgroundColor = useThemeColor('card')
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { verticalScale } from "@gocodingnow/rn-size-matters"
|
||||
import React, { ReactElement } from "react"
|
||||
import { ReactElement } from "react"
|
||||
import { ColorValue, useColorScheme } from "react-native"
|
||||
import {
|
||||
StyleProp,
|
||||
@@ -122,7 +122,7 @@ interface ListItemActionProps {
|
||||
*
|
||||
* - [Documentation and Examples](https://github.com/infinitered/ignite/blob/master/docs/Components-ListItem.md)
|
||||
*/
|
||||
export function ListItem(props: ListItemProps) {
|
||||
export const ListItem = function (props: ListItemProps) {
|
||||
const colorScheme = useColorScheme()
|
||||
|
||||
const {
|
||||
|
||||
@@ -304,7 +304,7 @@
|
||||
"profileToRecoverDesc": "This is the wallet address linked to your seed. If you press Complete, your wallet profile will reset to above seed and address.",
|
||||
"pushNotifications": "Push notifications",
|
||||
"qr": {
|
||||
"fail": "Could not display QR code, copy or share the Ecash token instead."
|
||||
"fail": "Could not display QR code, try new v4 token format or use option to send token to contact."
|
||||
},
|
||||
"receiverMemo": "Memo for the receiver",
|
||||
"receiveScreen": {
|
||||
|
||||
@@ -335,6 +335,7 @@ export const OwnName = observer(function (props: {navigation: any, pubkey: strin
|
||||
<QRCodeBlock
|
||||
qrCodeData={donationInvoice.payment_request}
|
||||
title='Lightning invoice to pay'
|
||||
type='Bolt11Invoice'
|
||||
size={270}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import React, {FC, useState, useEffect, useRef, useMemo} from 'react'
|
||||
import React, {FC, useState, useEffect} from 'react'
|
||||
import {
|
||||
TextStyle,
|
||||
ViewStyle,
|
||||
@@ -30,13 +30,10 @@ import AppError from '../utils/AppError'
|
||||
import {BackupProof, Proof} from '../models/Proof'
|
||||
import { useStores } from '../models'
|
||||
import { CashuUtils } from '../services/cashu/cashuUtils'
|
||||
import JSONTree from 'react-native-json-tree'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import { getEncodedToken } from '@cashu/cashu-ts'
|
||||
import { Transaction, TransactionData, TransactionRecord, TransactionStatus, TransactionType } from '../models/Transaction'
|
||||
import { WalletUtils } from '../services/wallet/utils'
|
||||
import { MintUnit, MintUnits, getCurrency } from '../services/wallet/currency'
|
||||
import { ScrollView } from 'react-native-gesture-handler'
|
||||
import { MintUnits, getCurrency } from '../services/wallet/currency'
|
||||
import { CurrencyAmount } from './Wallet/CurrencyAmount'
|
||||
import { translate } from '../i18n'
|
||||
|
||||
@@ -172,7 +169,7 @@ export const LocalRecoveryScreen: FC<LocalRecoveryScreenProps> =
|
||||
|
||||
log.trace(tokenByMint)
|
||||
|
||||
const encodedByMint = getEncodedToken(tokenByMint)
|
||||
const encodedByMint = CashuUtils.encodeToken(tokenByMint)
|
||||
encodedTokens.push(encodedByMint)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ export const OutgoingRequests = observer(function (props: {
|
||||
<QRCodeBlock
|
||||
qrCodeData={selectedRequest?.encodedInvoice as string}
|
||||
title="Scan and pay to topup"
|
||||
type='Bolt11Invoice'
|
||||
size={270}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -636,8 +636,9 @@ export const SendScreen: FC<WalletStackScreenProps<'Send'>> = observer(
|
||||
{transactionStatus === TransactionStatus.PENDING && encodedTokenToSend && paymentOption && (
|
||||
<>
|
||||
<QRCodeBlock
|
||||
qrCodeData={encodedTokenToSend as string}
|
||||
title='Ecash token to send'
|
||||
qrCodeData={encodedTokenToSend as string}
|
||||
title='Ecash token to send'
|
||||
type='EncodedV3Token'
|
||||
/>
|
||||
<TokenOptionsBlock
|
||||
toggleNostrDMModal={toggleNostrDMModal}
|
||||
|
||||
@@ -22,7 +22,6 @@ import { Mint } from '../models/Mint'
|
||||
import { MintHeader } from './Mints/MintHeader'
|
||||
import { moderateVerticalScale } from '@gocodingnow/rn-size-matters'
|
||||
import { translate } from '../i18n'
|
||||
import { validCashuAToken } from '../services/cashu/cashuUtils'
|
||||
|
||||
|
||||
export const TokenReceiveScreen: FC<WalletStackScreenProps<'TokenReceive'>> = function TokenReceiveScreen(_props) {
|
||||
|
||||
@@ -752,7 +752,8 @@ export const TopupScreen: FC<WalletStackScreenProps<'Topup'>> = observer(
|
||||
<>
|
||||
<QRCodeBlock
|
||||
qrCodeData={invoiceToPay as string}
|
||||
title="Invoice to pay"
|
||||
title='Invoice to pay'
|
||||
type='Bolt11Invoice'
|
||||
size={270}
|
||||
/>
|
||||
<InvoiceOptionsBlock
|
||||
|
||||
@@ -1284,6 +1284,7 @@ const TopupInfoBlock = function (props: {
|
||||
<QRCodeBlock
|
||||
qrCodeData={paymentRequest.encodedInvoice}
|
||||
title={translate("tranDetailScreen.invoice")}
|
||||
type='Bolt11Invoice'
|
||||
size={spacing.screenWidth * 0.8}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -7,16 +7,20 @@ import { moderateVerticalScale } from "@gocodingnow/rn-size-matters"
|
||||
import { colors, spacing } from "../../theme"
|
||||
import { useState } from "react"
|
||||
import { translate } from "../../i18n"
|
||||
import { CashuUtils } from "../../services/cashu/cashuUtils"
|
||||
import { log } from "../../services"
|
||||
|
||||
export const QRCodeBlock = function (props: {
|
||||
qrCodeData: string
|
||||
qrCodeData: string
|
||||
title: string
|
||||
type: 'EncodedV3Token' | 'EncodedV4Token' | 'Bolt11Invoice' | 'URL'
|
||||
size?: number
|
||||
}
|
||||
) {
|
||||
|
||||
const {qrCodeData, title, size} = props
|
||||
const [qrError, setQrError] = useState<Error | undefined>()
|
||||
const {qrCodeData, title, type, size} = props
|
||||
const [qrError, setQrError] = useState<Error | undefined>()
|
||||
const [encodedV4Token, setEncodedV4Token] = useState<string | undefined>()
|
||||
|
||||
const handleQrError = function (error: Error) {
|
||||
setQrError(error)
|
||||
@@ -40,6 +44,26 @@ export const QRCodeBlock = function (props: {
|
||||
setQrError(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const switchTokenEncoding = function () {
|
||||
try {
|
||||
if(encodedV4Token) {
|
||||
setEncodedV4Token(undefined)
|
||||
} else if(type === 'EncodedV3Token') {
|
||||
log.trace('[v3]', qrCodeData)
|
||||
|
||||
const decoded = CashuUtils.decodeToken(qrCodeData)
|
||||
const encodedV4 = CashuUtils.encodeToken(decoded, 4)
|
||||
|
||||
log.trace('[v4]', encodedV4)
|
||||
|
||||
setEncodedV4Token(encodedV4)
|
||||
}
|
||||
} catch (e: any) {
|
||||
setQrError(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const onCopy = function () {
|
||||
@@ -54,7 +78,7 @@ export const QRCodeBlock = function (props: {
|
||||
<Card
|
||||
heading={title}
|
||||
headingStyle={{textAlign: 'center', color: colors.light.text, marginBottom: spacing.extraSmall}}
|
||||
style={{backgroundColor: 'white', paddingBottom: 0}}
|
||||
style={{backgroundColor: 'white', paddingBottom: spacing.small}}
|
||||
ContentComponent={qrError ? (
|
||||
<ListItem
|
||||
text={translate("qr.fail")}
|
||||
@@ -67,11 +91,11 @@ export const QRCodeBlock = function (props: {
|
||||
) : (
|
||||
<View style={$qrCodeContainer}>
|
||||
<QRCode
|
||||
size={size || spacing.screenWidth - spacing.large * 2} value={qrCodeData}
|
||||
size={size || spacing.screenWidth - spacing.large * 2} value={encodedV4Token || qrCodeData}
|
||||
onError={(error: any) => handleQrError(error)}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
)}
|
||||
FooterComponent={
|
||||
<View style={$buttonContainer}>
|
||||
<Button
|
||||
@@ -99,8 +123,23 @@ export const QRCodeBlock = function (props: {
|
||||
paddingVertical: moderateVerticalScale(spacing.tiny),
|
||||
marginRight: spacing.small
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
/>
|
||||
{type === 'EncodedV3Token' && (
|
||||
<Button
|
||||
preset="tertiary"
|
||||
text={`Show ${encodedV4Token ? 'v3' : 'v4'} format`}
|
||||
onPress={switchTokenEncoding}
|
||||
LeftAccessory={() => <Icon icon='faMoneyBill1' size={spacing.small} color={colors.light.text} />}
|
||||
textStyle={{color: colors.light.text, fontSize: 14}}
|
||||
style={{
|
||||
minWidth: 60,
|
||||
minHeight: moderateVerticalScale(40),
|
||||
paddingVertical: moderateVerticalScale(spacing.tiny),
|
||||
marginRight: spacing.small
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import {Mint} from '../../models/Mint'
|
||||
import {
|
||||
AmountPreference,
|
||||
getDecodedToken,
|
||||
getDecodedToken,
|
||||
getEncodedToken,
|
||||
} from '@cashu/cashu-ts'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
import cbor from '@exodus/borc'
|
||||
import type {Token as V3Token, TokenEntry as V3TokenEntry, Proof as V3Proof} from '@cashu/cashu-ts'
|
||||
import AppError, {Err} from '../../utils/AppError'
|
||||
import {Token} from '../../models/Token'
|
||||
import {TokenEntry} from '../../models/TokenEntry'
|
||||
import {} from '@cashu/cashu-ts'
|
||||
import {Proof} from '../../models/Proof'
|
||||
import { log } from '../logService'
|
||||
// import { encodeCBOR } from '@cashu/cashu-ts/src/cbor'
|
||||
import { encodeBase64ToJson, encodeBase64toUint8, encodeUint8toBase64 } from '@cashu/cashu-ts/src/base64'
|
||||
import { bytesToHex, hexToBytes } from '@noble/curves/abstract/utils';
|
||||
|
||||
const findEncodedCashuToken = function (content: string) {
|
||||
const words = content.split(/\s+|\n+/) // Split text into words
|
||||
const maybeToken = words.find(word => CASHU_TOKEN_PREFIXES.some(pref => word.includes(pref)))
|
||||
return maybeToken || null
|
||||
}
|
||||
|
||||
const CASHU_URI_PREFIXES = [
|
||||
'https://wallet.nutstash.app/#',
|
||||
@@ -28,8 +27,13 @@ const CASHU_TOKEN_PREFIXES = [
|
||||
'cashuB'
|
||||
]
|
||||
|
||||
const findEncodedCashuToken = function (content: string) {
|
||||
const words = content.split(/\s+|\n+/) // Split text into words
|
||||
const maybeToken = words.find(word => CASHU_TOKEN_PREFIXES.some(pref => word.includes(pref)))
|
||||
return maybeToken || null
|
||||
}
|
||||
|
||||
export function validCashuAToken(text: string) {
|
||||
const isValidCashuToken = function (text: string) {
|
||||
for (const prefix of CASHU_URI_PREFIXES) {
|
||||
if (text && text.startsWith(prefix)) {
|
||||
text = text.slice(prefix.length)
|
||||
@@ -44,19 +48,19 @@ const extractEncodedCashuToken = function (maybeToken: string): string {
|
||||
log.trace('[extractEncodedCashuToken] Extract token from', {maybeToken})
|
||||
|
||||
let encodedToken: string | undefined = undefined
|
||||
let decoded: Token | undefined = undefined
|
||||
let decoded: V3Token | undefined = undefined
|
||||
|
||||
if (maybeToken && CASHU_TOKEN_PREFIXES.some(pref => maybeToken.startsWith(pref))) {
|
||||
decoded = decodeToken(maybeToken) // throws
|
||||
return maybeToken
|
||||
}
|
||||
|
||||
for (const prefix of CASHU_URI_PREFIXES) {
|
||||
if (maybeToken && maybeToken.startsWith(prefix)) {
|
||||
encodedToken = maybeToken.slice(prefix.length)
|
||||
break // necessary
|
||||
}
|
||||
}
|
||||
for (const prefix of CASHU_URI_PREFIXES) {
|
||||
if (maybeToken && maybeToken.startsWith(prefix)) {
|
||||
encodedToken = maybeToken.slice(prefix.length)
|
||||
break // necessary
|
||||
}
|
||||
}
|
||||
|
||||
log.trace('[extractEncodedCashuToken] Token without prefix', {encodedToken})
|
||||
|
||||
@@ -71,22 +75,162 @@ const extractEncodedCashuToken = function (maybeToken: string): string {
|
||||
|
||||
|
||||
|
||||
const decodeToken = function (encoded: string): Token {
|
||||
/* const decodeToken = function (encoded: string): V3Token {
|
||||
try {
|
||||
const decoded = getDecodedToken(encoded)
|
||||
return decoded as Token
|
||||
return decoded as V3Token
|
||||
} catch (e: any) {
|
||||
throw new AppError(
|
||||
Err.VALIDATION_ERROR,
|
||||
`Provided ecash token is invalid.`,
|
||||
encoded,
|
||||
{message: e.message, encoded},
|
||||
)
|
||||
}
|
||||
} */
|
||||
|
||||
interface V4Proof {
|
||||
a: number;
|
||||
s: string;
|
||||
c: Uint8Array;
|
||||
d?: {
|
||||
e: Uint8Array,
|
||||
s: Uint8Array,
|
||||
r: Uint8Array
|
||||
},
|
||||
w?: string
|
||||
}
|
||||
|
||||
interface V4TokenEntry {
|
||||
i: Uint8Array;
|
||||
p: V4Proof[];
|
||||
}
|
||||
|
||||
interface V4Token {
|
||||
m: string;
|
||||
u: string;
|
||||
d?: string;
|
||||
t: V4TokenEntry[]
|
||||
}
|
||||
|
||||
function mapToV4TokenEntries(tokenEntries: V3TokenEntry[]): V4TokenEntry[] {
|
||||
const v4TokenEntries: V4TokenEntry[] = [];
|
||||
|
||||
tokenEntries.forEach(entry => {
|
||||
const idMap: { [id: string]: V4Proof[] } = {};
|
||||
|
||||
entry.proofs.forEach(proof => {
|
||||
if (!idMap[proof.id]) {
|
||||
idMap[proof.id] = [];
|
||||
}
|
||||
idMap[proof.id].push({
|
||||
a: proof.amount,
|
||||
s: proof.secret,
|
||||
c: hexToBytes(proof.C)
|
||||
});
|
||||
});
|
||||
|
||||
for (const id in idMap) {
|
||||
v4TokenEntries.push({
|
||||
i: hexToBytes(id),
|
||||
p: idMap[id]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return v4TokenEntries
|
||||
}
|
||||
|
||||
function base64urlFromBase64(str: string) {
|
||||
return str.replace(/\+/g, '-').replace(/\//g, '_').split('=')[0];
|
||||
// .replace(/=/g, '.');
|
||||
}
|
||||
|
||||
function base64urlToBase64(str: string) {
|
||||
return str.replace(/-/g, '+').replace(/_/g, '/').split('=')[0];
|
||||
// .replace(/./g, '=');
|
||||
}
|
||||
|
||||
|
||||
const encodeToken = function (token: V3Token, version: 3 | 4 = 3): string {
|
||||
try {
|
||||
if(version === 3) {
|
||||
return getEncodedToken(token)
|
||||
} else if(version === 4) {
|
||||
const v4tokenEntries = mapToV4TokenEntries(token.token)
|
||||
|
||||
const v4Token: V4Token = {
|
||||
m: token.token[0].mint as string,
|
||||
u: token.unit as string,
|
||||
d: token.memo as string,
|
||||
t: v4tokenEntries
|
||||
}
|
||||
|
||||
log.trace('[encodeToken]', {v4Token})
|
||||
|
||||
const encodedCbor = cbor.encode(v4Token)
|
||||
return 'cashuB' + base64urlFromBase64(encodeUint8toBase64(encodedCbor))
|
||||
} else {
|
||||
throw new Error('Invalid version.')
|
||||
}
|
||||
} catch (e: any) {
|
||||
throw new AppError(
|
||||
Err.VALIDATION_ERROR,
|
||||
`Error encoding token to version {${version}} format.`,
|
||||
{message: e.message},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to decode cashu tokens into object
|
||||
* @param token an encoded cashu token (cashuAey...)
|
||||
* @returns cashu token object
|
||||
*/
|
||||
function decodeToken(token: string) {
|
||||
// remove prefixes
|
||||
const uriPrefixes = [...CASHU_URI_PREFIXES, 'cashu'];
|
||||
uriPrefixes.forEach((prefix) => {
|
||||
if (!token.startsWith(prefix)) {
|
||||
return;
|
||||
}
|
||||
token = token.slice(prefix.length);
|
||||
});
|
||||
return handleTokens(token);
|
||||
}
|
||||
|
||||
const getTokenAmounts = function (token: Token) {
|
||||
/**
|
||||
* @param token
|
||||
* @returns
|
||||
*/
|
||||
function handleTokens(token: string): V3Token {
|
||||
const version = token.slice(0, 1);
|
||||
const encodedToken = token.slice(1);
|
||||
if (version === 'A') {
|
||||
return encodeBase64ToJson<V3Token>(encodedToken);
|
||||
} else if (version === 'B') {
|
||||
const uInt8Token = encodeBase64toUint8(base64urlToBase64(encodedToken));
|
||||
const tokenData = cbor.decodeFirst(uInt8Token) as V4Token
|
||||
const mergedTokenEntry: V3TokenEntry = { mint: tokenData.m, proofs: [] };
|
||||
tokenData.t.forEach((tokenEntry) =>
|
||||
tokenEntry.p.forEach((p) => {
|
||||
mergedTokenEntry.proofs.push({
|
||||
secret: p.s,
|
||||
C: bytesToHex(p.c),
|
||||
amount: p.a,
|
||||
id: bytesToHex(tokenEntry.i)
|
||||
});
|
||||
})
|
||||
);
|
||||
return { token: [mergedTokenEntry], memo: tokenData.d || '', unit: tokenData.u };
|
||||
} else {
|
||||
throw new Error('Token version is not supported');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const getTokenAmounts = function (token: V3Token) {
|
||||
const mintAmounts: {[k: string]: number} = {}
|
||||
let totalAmount = 0
|
||||
|
||||
@@ -118,7 +262,7 @@ const getTokenAmounts = function (token: Token) {
|
||||
}
|
||||
|
||||
|
||||
const getTokenEntryAmount = function (tokenEntry: TokenEntry) {
|
||||
const getTokenEntryAmount = function (tokenEntry: V3TokenEntry) {
|
||||
try {
|
||||
return getProofsAmount(tokenEntry.proofs)
|
||||
} catch (e: any) {
|
||||
@@ -131,7 +275,7 @@ const getTokenEntryAmount = function (tokenEntry: TokenEntry) {
|
||||
}
|
||||
|
||||
|
||||
const getProofsAmount = function (proofs: Array<Proof>): number {
|
||||
const getProofsAmount = function (proofs: Array<V3Proof>): number {
|
||||
let totalAmount = 0
|
||||
|
||||
for (const proof of proofs) {
|
||||
@@ -148,14 +292,14 @@ const getAmountPreferencesCount = function (amountPreferences: AmountPreference[
|
||||
}
|
||||
|
||||
|
||||
const getMintsFromToken = function (token: Token): string[] {
|
||||
const getMintsFromToken = function (token: V3Token): string[] {
|
||||
const mints = token.token.map(item => item.mint)
|
||||
return Array.from(new Set(mints)) // make sure the mints are not duplicated
|
||||
}
|
||||
|
||||
|
||||
const getProofsFromTokenEntries = (tokenEntries: TokenEntry[]) => {
|
||||
const proofs: Proof[] = []
|
||||
const getProofsFromTokenEntries = (tokenEntries: V3TokenEntry[]) => {
|
||||
const proofs: V3Proof[] = []
|
||||
|
||||
for (const entry of tokenEntries) {
|
||||
proofs.push(...entry.proofs)
|
||||
@@ -221,25 +365,6 @@ const getProofsToSend = function (requestedAmount: number, proofs: Proof[]): Pro
|
||||
return findMinExcess(requestedAmount, proofs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns a subset of tokens, so that not all tokens are sent to mint for smaller amounts.
|
||||
* @param amount
|
||||
* @param tokens
|
||||
* @returns
|
||||
*/
|
||||
/* const getProofsToSend = function (amount: number, proofs: Array<Proof>) {
|
||||
let proofsAmount = 0
|
||||
const proofSubset = proofs.filter(proof => {
|
||||
if (proofsAmount < amount) {
|
||||
proofsAmount += proof.amount
|
||||
return true
|
||||
}
|
||||
})
|
||||
return proofSubset
|
||||
} */
|
||||
|
||||
|
||||
/**
|
||||
* removes a set of tokens from another set of tokens, and returns the remaining.
|
||||
* @param proofs
|
||||
@@ -306,7 +431,9 @@ const getMintFromProof = function (
|
||||
export const CashuUtils = {
|
||||
findEncodedCashuToken,
|
||||
extractEncodedCashuToken,
|
||||
decodeToken,
|
||||
isValidCashuToken,
|
||||
decodeToken,
|
||||
encodeToken,
|
||||
getTokenAmounts,
|
||||
getTokenEntryAmount,
|
||||
getProofsAmount,
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
type Token as CashuToken,
|
||||
type Proof as CashuProof
|
||||
} from '@cashu/cashu-ts'
|
||||
import { getDefaultAmountPreference, getEncodedToken } from '@cashu/cashu-ts/src/utils'
|
||||
import { getDefaultAmountPreference } from '@cashu/cashu-ts/src/utils'
|
||||
import { TransactionTaskResult } from '../walletService'
|
||||
import { WalletUtils } from './utils'
|
||||
import { MintUnit, formatCurrency, getCurrency } from './currency'
|
||||
@@ -163,7 +163,7 @@ export const receiveTask = async function (
|
||||
proofs: receivedProofs,
|
||||
}
|
||||
|
||||
const updatedToken = getEncodedToken({
|
||||
const updatedToken = CashuUtils.encodeToken({
|
||||
token: [tokenEntryToSend],
|
||||
unit,
|
||||
memo,
|
||||
@@ -491,7 +491,7 @@ export const receiveOfflineCompleteTask = async function (
|
||||
proofs: receivedProofs,
|
||||
}
|
||||
|
||||
const updatedToken = getEncodedToken({
|
||||
const updatedToken = CashuUtils.encodeToken({
|
||||
token: [tokenEntryToSend],
|
||||
unit,
|
||||
})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import {getEncodedToken} from '@cashu/cashu-ts'
|
||||
import {log} from '../logService'
|
||||
import {MintClient} from '../cashuMintClient'
|
||||
import {
|
||||
@@ -108,7 +107,7 @@ export const sendTask = async function (
|
||||
memo = 'Sent from Minibits'
|
||||
}
|
||||
|
||||
const encodedTokenToSend = getEncodedToken({
|
||||
const encodedTokenToSend = CashuUtils.encodeToken({
|
||||
token: [tokenEntryToSend as CashuTokenEntry],
|
||||
unit,
|
||||
memo,
|
||||
|
||||
@@ -1202,9 +1202,9 @@
|
||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@cashu/cashu-ts@minibits-cash/cashu-ts#1.0.0-minibits.2":
|
||||
version "1.0.0-minibits"
|
||||
resolved "https://codeload.github.com/minibits-cash/cashu-ts/tar.gz/03b26c1db3a72d3d8e975a72f63b0ed06dc1be34"
|
||||
"@cashu/cashu-ts@minibits-cash/cashu-ts#1.0.0-minibits.4":
|
||||
version "1.0.0-minibits.4"
|
||||
resolved "https://codeload.github.com/minibits-cash/cashu-ts/tar.gz/c8932a044126e143a5460c14a3a47c196e26baa2"
|
||||
dependencies:
|
||||
"@cashu/crypto" "^0.2.6"
|
||||
"@noble/curves" "^1.3.0"
|
||||
@@ -1271,6 +1271,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.55.0.tgz#b721d52060f369aa259cf97392403cb9ce892ec6"
|
||||
integrity sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==
|
||||
|
||||
"@exodus/borc@^2.1.1":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@exodus/borc/-/borc-2.1.1.tgz#42f38d3b96bcf53a93c72e9739192b876a8058fa"
|
||||
integrity sha512-rOFa4apJXK67mdUU8RI25umOIXUEpt+gwqPKsNCg/OwTYhi2b1tzX6H+g8dXahHzG7gwOImoDQmw8Vxho+us5A==
|
||||
dependencies:
|
||||
bignumber.js "^8.0.1"
|
||||
ieee754 "^1.1.8"
|
||||
iso-url "~0.4.4"
|
||||
|
||||
"@fortawesome/fontawesome-common-types@6.5.2":
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz#eaf2f5699f73cef198454ebc0c414e3688898179"
|
||||
@@ -3048,6 +3057,11 @@ bignumber.js@*, "bignumber.js@^8 || ^9":
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c"
|
||||
integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==
|
||||
|
||||
bignumber.js@^8.0.1:
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.1.1.tgz#4b072ae5aea9c20f6730e4e5d529df1271c4d885"
|
||||
integrity sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ==
|
||||
|
||||
bl@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
|
||||
@@ -4957,7 +4971,7 @@ iconv-lite@^0.4.24:
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
ieee754@^1.1.13, ieee754@^1.2.1:
|
||||
ieee754@^1.1.13, ieee754@^1.1.8, ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
@@ -5321,6 +5335,11 @@ isexe@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||
|
||||
iso-url@~0.4.4:
|
||||
version "0.4.7"
|
||||
resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-0.4.7.tgz#de7e48120dae46921079fe78f325ac9e9217a385"
|
||||
integrity sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==
|
||||
|
||||
isobject@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
|
||||
|
||||
Reference in New Issue
Block a user