feat(state-machine): fetch balance with exchange rate on cash-in
Add getRateAndBalance actor that fetches exchange rate and available balance in parallel during cash-in flow. Add generateLnurlWithdraw service type for LNURL-withdraw support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1e891765de
commit
c199431b8e
2 changed files with 19 additions and 2 deletions
|
|
@ -68,6 +68,17 @@ export function createATMMachine(services: Partial<ATMServices> = {}) {
|
||||||
}
|
}
|
||||||
return services.getExchangeRate(input)
|
return services.getExchangeRate(input)
|
||||||
}),
|
}),
|
||||||
|
// Fetch both exchange rate and available balance in parallel for cash-in
|
||||||
|
getRateAndBalance: fromPromise(async ({ input }: { input: string }) => {
|
||||||
|
if (!services.getExchangeRate) {
|
||||||
|
throw new Error('getExchangeRate service not provided')
|
||||||
|
}
|
||||||
|
const [exchangeRate, availableBalance] = await Promise.all([
|
||||||
|
services.getExchangeRate(input),
|
||||||
|
services.getAvailableBalance ? services.getAvailableBalance() : Promise.resolve(0),
|
||||||
|
])
|
||||||
|
return { exchangeRate, availableBalance }
|
||||||
|
}),
|
||||||
generateNoffer: fromPromise(async () => {
|
generateNoffer: fromPromise(async () => {
|
||||||
if (!services.generateNoffer) {
|
if (!services.generateNoffer) {
|
||||||
throw new Error('generateNoffer service not provided')
|
throw new Error('generateNoffer service not provided')
|
||||||
|
|
@ -363,12 +374,13 @@ export function createATMMachine(services: Partial<ATMServices> = {}) {
|
||||||
states: {
|
states: {
|
||||||
fetchingRate: {
|
fetchingRate: {
|
||||||
invoke: {
|
invoke: {
|
||||||
src: 'getExchangeRate',
|
src: 'getRateAndBalance',
|
||||||
input: ({ context }) => context.currency,
|
input: ({ context }) => context.currency,
|
||||||
onDone: {
|
onDone: {
|
||||||
target: 'insertingBills',
|
target: 'insertingBills',
|
||||||
actions: assign({
|
actions: assign({
|
||||||
exchangeRate: ({ event }) => event.output,
|
exchangeRate: ({ event }) => event.output.exchangeRate,
|
||||||
|
availableBalance: ({ event }) => event.output.availableBalance,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
onError: {
|
onError: {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ export interface ATMContext {
|
||||||
exchangeRate: number
|
exchangeRate: number
|
||||||
/** Fee percentage (0.02 = 2%) */
|
/** Fee percentage (0.02 = 2%) */
|
||||||
feePercent: number
|
feePercent: number
|
||||||
|
/** ATM's available balance in sats (for limiting cash-in transactions) */
|
||||||
|
availableBalance: number
|
||||||
|
|
||||||
// Payment
|
// Payment
|
||||||
/** BOLT11 invoice for payment */
|
/** BOLT11 invoice for payment */
|
||||||
|
|
@ -128,6 +130,7 @@ export const initialContext: ATMContext = {
|
||||||
currency: 'USD',
|
currency: 'USD',
|
||||||
exchangeRate: 0,
|
exchangeRate: 0,
|
||||||
feePercent: 0.02,
|
feePercent: 0.02,
|
||||||
|
availableBalance: 0,
|
||||||
invoice: null,
|
invoice: null,
|
||||||
clinkOffer: null,
|
clinkOffer: null,
|
||||||
nofferString: null,
|
nofferString: null,
|
||||||
|
|
@ -167,6 +170,8 @@ export interface ATMServices {
|
||||||
dispenseCash: (amounts: { denomination: number; count: number }[]) => Promise<void>
|
dispenseCash: (amounts: { denomination: number; count: number }[]) => Promise<void>
|
||||||
/** Get current exchange rate */
|
/** Get current exchange rate */
|
||||||
getExchangeRate: (currency: string) => Promise<number>
|
getExchangeRate: (currency: string) => Promise<number>
|
||||||
|
/** Get ATM's available balance in sats (for limiting cash-in transactions) */
|
||||||
|
getAvailableBalance: () => Promise<number>
|
||||||
/** Generate noffer string for cash-out (static payment code) */
|
/** Generate noffer string for cash-out (static payment code) */
|
||||||
generateNoffer: () => Promise<string>
|
generateNoffer: () => Promise<string>
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue