Skip to content

Commit

Permalink
feat: add hooks for spend/receive ecash (#103)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlwn123 authored Dec 6, 2024
1 parent a3b69ff commit e98a1b8
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/strong-poets-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fedimint/react': patch
---

Added useSpendEcash and useReceiveEcash hooks
2 changes: 2 additions & 0 deletions packages/react/lib/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ export { useOpenWallet } from './useOpenWallet'
export { useFedimintWallet } from './useFedimintWallet'
export { useReceiveLightning } from './useReceiveLightning'
export { useSendLightning } from './useSendLightning'
export { useSpendEcash } from './useSpendEcash'
export { useReceiveEcash } from './useReceiveEcash'
45 changes: 45 additions & 0 deletions packages/react/lib/hooks/useReceiveEcash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useCallback, useEffect, useState } from 'react'
import { useFedimintWallet, useOpenWallet } from '.'

export const useReceiveEcash = () => {
const wallet = useFedimintWallet()
const { walletStatus } = useOpenWallet()

const [operationId, setOperationId] = useState<string>()
const [notes, setNotes] = useState<string>()
const [state, setState] = useState<any>()

useEffect(() => {
if (!operationId) return

const unsubscribe = wallet.mint.subscribeReissueExternalNotes(
operationId,
(_state) => (_state ? setState(_state) : setState(undefined)),
(error) => {
console.error('ECASH SPEND STATE ERROR', error)
},
)

return () => {
unsubscribe()
}
}, [operationId])

const redeemEcash = useCallback(
async (notes: string) => {
if (walletStatus !== 'open') throw new Error('Wallet is not open')
const response = await wallet.mint.redeemEcash(notes)
console.error('REEDEEEM', response)
// setOperationId(response.operation_id)
// setNotes(response.notes)
return response
},
[wallet],
)

return {
redeemEcash,
notes,
state,
}
}
47 changes: 47 additions & 0 deletions packages/react/lib/hooks/useSpendEcash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useCallback, useEffect, useState } from 'react'
import { useFedimintWallet, useOpenWallet } from '.'

export const useSpendEcash = () => {
const wallet = useFedimintWallet()
const { walletStatus } = useOpenWallet()

const [operationId, setOperationId] = useState<string>()
const [notes, setNotes] = useState<string>()
const [state, setState] = useState<any>()

useEffect(() => {
if (!operationId) return

const unsubscribe = wallet.mint.subscribeSpendNotes(
operationId,
(_state) => (_state ? setState(_state) : setState(undefined)),
(error) => {
console.error('ECASH SPEND STATE ERROR', error)
},
)

return () => {
unsubscribe()
}
}, [operationId])

const spendEcash = useCallback(
async (amountSats: number, reclaimAfter?: number) => {
if (walletStatus !== 'open') throw new Error('Wallet is not open')
const response = await wallet.mint.spendNotes(
amountSats * 1000,
reclaimAfter,
)
setOperationId(response.operation_id)
setNotes(response.notes)
return response.notes
},
[wallet],
)

return {
spendEcash,
notes,
state,
}
}
86 changes: 86 additions & 0 deletions packages/react/src/components/HooksDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import {
useReceiveLightning,
useOpenWallet,
useSendLightning,
useSpendEcash,
useReceiveEcash,
} from '../../lib'

const TEST_FEDERATION_INVITE =
'fed11qgqzc2nhwden5te0vejkg6tdd9h8gepwvejkg6tdd9h8garhduhx6at5d9h8jmn9wshxxmmd9uqqzgxg6s3evnr6m9zdxr6hxkdkukexpcs3mn7mj3g5pc5dfh63l4tj6g9zk4er'

function HooksDemo() {
const [bolt11Input, setBolt11Input] = useState<string>()
const [ecashAmount, setEcashAmount] = useState<number>()
const [ecashInput, setEcashInput] = useState<string>()

// Balance
const balance = useBalance()
Expand All @@ -27,6 +31,12 @@ function HooksDemo() {
const { payInvoice, payment, paymentStatus, paymentError } =
useSendLightning()

// SendEcash
const { spendEcash, notes, state: ecashState } = useSpendEcash()

// ReceiveEcash
const { redeemEcash } = useReceiveEcash()

return (
<>
<div className="card">
Expand Down Expand Up @@ -130,6 +140,82 @@ function HooksDemo() {
<p>{paymentError}</p>
</div>
</div>
<div className="section">
<b>useSpendEcash()</b>
<div className="row">
<b>amount sats</b>
<input
type="number"
value={ecashAmount}
onChange={(e) => setEcashAmount(parseInt(e.target.value))}
/>
</div>
<div className="row">
<b>spendEcash(amount)</b>
<button
disabled={!isOpen || ecashAmount === 0}
onClick={() => ecashAmount && spendEcash(ecashAmount)}
>
Spend Ecash
</button>
</div>
<div className="row">
<b>ecashStatus</b>
<p>
{typeof ecashState === 'string'
? ecashState
: typeof ecashState === 'object'
? Object.keys(ecashState)[0]
: 'no ecash status'}
</p>
</div>
<div className="row">
<b>ecashNote</b>
<p>{notes}</p>
</div>
{/* <div className="row">
<b>error</b>
<p>{paymentError}</p>
</div> */}
</div>
<div className="section">
<b>useReceiveEcash()</b>
<div className="row">
<b>Ecash string</b>
<input
type="string"
value={ecashInput}
onChange={(e) => setEcashInput(e.target.value)}
/>
</div>
<div className="row">
<b>redeemEcash(notes)</b>
<button
disabled={!isOpen || !ecashInput}
onClick={() => ecashInput && redeemEcash(ecashInput)}
>
Redeem Ecash
</button>
</div>
<div className="row">
<b>ecashStatus</b>
<p>
{typeof ecashState === 'string'
? ecashState
: typeof ecashState === 'object'
? Object.keys(ecashState)[0]
: 'no ecash status'}
</p>
</div>
<div className="row">
<b>ecashNote</b>
<p>{notes}</p>
</div>
{/* <div className="row">
<b>error</b>
<p>{paymentError}</p>
</div> */}
</div>
</div>
</>
)
Expand Down

0 comments on commit e98a1b8

Please sign in to comment.