Skip to content

Commit 7de23f6

Browse files
committed
Add cashu wallet
* cashu wallet def exports new property 'components' to render balance and buttons for deposit and withdraw * new context CashuContext is included in pages/_app.js * CashuContext includes hooks to read/write proofs and show balance
1 parent c40ef5a commit 7de23f6

File tree

19 files changed

+533
-34
lines changed

19 files changed

+533
-34
lines changed

components/use-indexeddb.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect, useCallback, useRef } from 'react'
1+
import { useState, useEffect, useCallback, useRef, useMemo } from 'react'
22

33
export function getDbName (userId, name) {
44
return `app:storage:${userId ?? ''}${name ? `:${name}` : ''}`
@@ -294,7 +294,7 @@ function useIndexedDB ({ dbName, storeName, options = DEFAULT_OPTIONS, indices =
294294
})
295295
}, [queueOperation, storeName])
296296

297-
return { add, get, getAll, set, remove, clear, getByIndex, getAllByIndex, getPage, error, notSupported }
297+
return useMemo(() => ({ add, get, getAll, set, remove, clear, getByIndex, getAllByIndex, getPage, error, notSupported }), [add, get, getAll, set, remove, clear, getByIndex, getAllByIndex, getPage, error, notSupported])
298298
}
299299

300300
export default useIndexedDB

docker-compose.yml

+30-1
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,34 @@ services:
821821
CONNECT: "localhost:${LNBITS_WEB_PORT}"
822822
TORDIR: "/app/.tor"
823823
cpu_shares: "${CPU_SHARES_LOW}"
824+
cashu:
825+
image: cashubtc/nutshell:0.16.4
826+
container_name: cashu
827+
profiles:
828+
- wallets
829+
restart: unless-stopped
830+
ports:
831+
- "3338:3338"
832+
depends_on:
833+
lnd:
834+
condition: service_healthy
835+
restart: true
836+
environment:
837+
- MINT_LISTEN_HOST=0.0.0.0
838+
- MINT_LISTEN_PORT=3338
839+
- MINT_INFO_NAME="SN Cashu Test Mint"
840+
- MINT_PRIVATE_KEY=TEST_PRIVATE_KEY
841+
- MINT_BACKEND_BOLT11_SAT=LndRPCWallet
842+
- MINT_LND_RPC_ENDPOINT=lnd:10009
843+
- MINT_LND_RPC_CERT=/app/.lnd/tls.cert
844+
- MINT_LND_RPC_MACAROON=/app/.lnd/data/chain/bitcoin/regtest/admin.macaroon
845+
command: ["poetry", "run", "mint"]
846+
volumes:
847+
- lnd:/app/.lnd
848+
- cashu:/app/.cashu
849+
labels:
850+
CONNECT: "localhost:3338"
851+
cpu_shares: "${CPU_SHARES_LOW}"
824852
volumes:
825853
db:
826854
os:
@@ -833,4 +861,5 @@ volumes:
833861
nwc_send:
834862
nwc_recv:
835863
tordata:
836-
eclair:
864+
eclair:
865+
cashu:

lib/validate.js

+4
Original file line numberDiff line numberDiff line change
@@ -515,3 +515,7 @@ export const deviceSyncSchema = object().shape({
515515
return true
516516
})
517517
})
518+
519+
export const mintQuoteSchema = object({
520+
amount: intValidator.required('required').positive('must be positive')
521+
})

package-lock.json

+163-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@apollo/server": "^4.11.0",
1818
"@as-integrations/next": "^3.1.0",
1919
"@auth/prisma-adapter": "^2.7.0",
20+
"@cashu/cashu-ts": "^2.1.0",
2021
"@graphql-tools/schema": "^10.0.6",
2122
"@lightninglabs/lnc-web": "^0.3.2-alpha",
2223
"@noble/curves": "^1.6.0",

pages/_app.js

+23-20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { HasNewNotesProvider } from '@/components/use-has-new-notes'
2323
import { WebLnProvider } from '@/wallets/webln/client'
2424
import { AccountProvider } from '@/components/account'
2525
import { WalletsProvider } from '@/wallets/index'
26+
import { CashuProvider } from '@/wallets/cashu/client'
2627

2728
const PWAPrompt = dynamic(() => import('react-ios-pwa-prompt'), { ssr: false })
2829

@@ -117,26 +118,28 @@ export default function MyApp ({ Component, pageProps: { ...props } }) {
117118
<HasNewNotesProvider>
118119
<LoggerProvider>
119120
<WebLnProvider>
120-
<ServiceWorkerProvider>
121-
<AccountProvider>
122-
<PriceProvider price={price}>
123-
<LightningProvider>
124-
<ToastProvider>
125-
<ShowModalProvider>
126-
<BlockHeightProvider blockHeight={blockHeight}>
127-
<ChainFeeProvider chainFee={chainFee}>
128-
<ErrorBoundary>
129-
<Component ssrData={ssrData} {...otherProps} />
130-
{!router?.query?.disablePrompt && <PWAPrompt copyBody='This website has app functionality. Add it to your home screen to use it in fullscreen and receive notifications. In Safari:' promptOnVisit={2} />}
131-
</ErrorBoundary>
132-
</ChainFeeProvider>
133-
</BlockHeightProvider>
134-
</ShowModalProvider>
135-
</ToastProvider>
136-
</LightningProvider>
137-
</PriceProvider>
138-
</AccountProvider>
139-
</ServiceWorkerProvider>
121+
<CashuProvider>
122+
<ServiceWorkerProvider>
123+
<AccountProvider>
124+
<PriceProvider price={price}>
125+
<LightningProvider>
126+
<ToastProvider>
127+
<ShowModalProvider>
128+
<BlockHeightProvider blockHeight={blockHeight}>
129+
<ChainFeeProvider chainFee={chainFee}>
130+
<ErrorBoundary>
131+
<Component ssrData={ssrData} {...otherProps} />
132+
{!router?.query?.disablePrompt && <PWAPrompt copyBody='This website has app functionality. Add it to your home screen to use it in fullscreen and receive notifications. In Safari:' promptOnVisit={2} />}
133+
</ErrorBoundary>
134+
</ChainFeeProvider>
135+
</BlockHeightProvider>
136+
</ShowModalProvider>
137+
</ToastProvider>
138+
</LightningProvider>
139+
</PriceProvider>
140+
</AccountProvider>
141+
</ServiceWorkerProvider>
142+
</CashuProvider>
140143
</WebLnProvider>
141144
</LoggerProvider>
142145
</HasNewNotesProvider>

pages/wallets/[wallet].js

+16-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { canReceive, canSend, isConfigured } from '@/wallets/common'
1313
import { SSR } from '@/lib/constants'
1414
import WalletButtonBar from '@/components/wallet-buttonbar'
1515
import { useWalletConfigurator } from '@/wallets/config'
16-
import { useCallback, useMemo } from 'react'
16+
import { Fragment, useCallback, useMemo } from 'react'
1717
import { useMe } from '@/components/me'
1818
import validateWallet from '@/wallets/validate'
1919
import { ValidationError } from 'yup'
@@ -101,6 +101,7 @@ export default function WalletSettings () {
101101
>
102102
<SendWarningBanner walletDef={wallet.def} />
103103
{wallet && <WalletFields wallet={wallet} />}
104+
{wallet && <WalletComponents wallet={wallet} />}
104105
<CheckboxGroup name='enabled'>
105106
<Checkbox
106107
disabled={!isConfigured(wallet)}
@@ -185,3 +186,17 @@ function WalletFields ({ wallet }) {
185186
return null
186187
})
187188
}
189+
190+
function WalletComponents ({ wallet }) {
191+
if (!canSend({ def: wallet.def, config: wallet.config })) return null
192+
193+
return (
194+
<div className='d-flex align-items-center justify-content-end column-gap-3'>
195+
{
196+
wallet.def.components?.map((Component, i) => {
197+
return (<Fragment key={i}><Component wallet={wallet} /></Fragment>)
198+
})
199+
}
200+
</div>
201+
)
202+
}

0 commit comments

Comments
 (0)