feat: configurable fee rates via VITE_CASH_IN_FEE and VITE_CASH_OUT_FEE
Accepts percentage (5.55) or decimal (0.0555) — auto-detected by whether the value is >= 1. Defaults to 3.33% cash-in, 7.77% cash-out. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cc109b2958
commit
2a2faf41ef
4 changed files with 31 additions and 3 deletions
|
|
@ -30,6 +30,12 @@ import { initializeHal, type HalInstance } from './hal-service.js'
|
||||||
const __filename = fileURLToPath(import.meta.url)
|
const __filename = fileURLToPath(import.meta.url)
|
||||||
const __dirname = path.dirname(__filename)
|
const __dirname = path.dirname(__filename)
|
||||||
|
|
||||||
|
/** Parse fee value: accepts percentage (5.55 → 0.0555) or decimal (0.0555 → 0.0555) */
|
||||||
|
function parseFee(val: string): number {
|
||||||
|
const n = parseFloat(val)
|
||||||
|
return n >= 1 ? n / 100 : n
|
||||||
|
}
|
||||||
|
|
||||||
// Load .env file manually (Electron main process doesn't have Vite's env loading)
|
// Load .env file manually (Electron main process doesn't have Vite's env loading)
|
||||||
function loadEnvFile() {
|
function loadEnvFile() {
|
||||||
const envPath = path.join(__dirname, '..', '.env')
|
const envPath = path.join(__dirname, '..', '.env')
|
||||||
|
|
@ -190,6 +196,10 @@ ipcMain.handle('get-config', () => {
|
||||||
|
|
||||||
// Maintenance mode — show "out of service" screen
|
// Maintenance mode — show "out of service" screen
|
||||||
maintenanceMode: process.env.VITE_MAINTENANCE_MODE === 'true',
|
maintenanceMode: process.env.VITE_MAINTENANCE_MODE === 'true',
|
||||||
|
|
||||||
|
// Fee rates — accepts percentage (5.55) or decimal (0.0555), auto-detected
|
||||||
|
cashInFeeRate: parseFee(process.env.VITE_CASH_IN_FEE || '0.0333'),
|
||||||
|
cashOutFeeRate: parseFee(process.env.VITE_CASH_OUT_FEE || '0.0777'),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,8 @@ export const useAtmStore = defineStore('atm', () => {
|
||||||
const allowMockFallback = ref(true) // default true for browser dev
|
const allowMockFallback = ref(true) // default true for browser dev
|
||||||
const initError = ref<string | null>(null) // fatal error → maintenance screen
|
const initError = ref<string | null>(null) // fatal error → maintenance screen
|
||||||
const fiatCode = ref('USD')
|
const fiatCode = ref('USD')
|
||||||
|
const cashInFeeRate = ref(0.0333)
|
||||||
|
const cashOutFeeRate = ref(0.0777)
|
||||||
const machineModel = ref('atm')
|
const machineModel = ref('atm')
|
||||||
const useLiveServices = ref(false)
|
const useLiveServices = ref(false)
|
||||||
const connectionStatus = ref<'disconnected' | 'connecting' | 'connected' | 'error'>(
|
const connectionStatus = ref<'disconnected' | 'connecting' | 'connected' | 'error'>(
|
||||||
|
|
@ -359,7 +361,11 @@ export const useAtmStore = defineStore('atm', () => {
|
||||||
// Actions
|
// Actions
|
||||||
function initialize(services: ATMServices = mockServices) {
|
function initialize(services: ATMServices = mockServices) {
|
||||||
atmServicesRef = services
|
atmServicesRef = services
|
||||||
const machine = createATMMachine(services, { currency: fiatCode.value })
|
const machine = createATMMachine(services, {
|
||||||
|
currency: fiatCode.value,
|
||||||
|
cashInFeeRate: cashInFeeRate.value,
|
||||||
|
cashOutFeeRate: cashOutFeeRate.value,
|
||||||
|
})
|
||||||
actor.value = createActor(machine)
|
actor.value = createActor(machine)
|
||||||
|
|
||||||
// Track previous state to detect transitions into 'complete'
|
// Track previous state to detect transitions into 'complete'
|
||||||
|
|
@ -925,6 +931,9 @@ export const useAtmStore = defineStore('atm', () => {
|
||||||
machineModel.value = model
|
machineModel.value = model
|
||||||
const runtimeFiatCode = runtimeConfig.fiatCode || 'USD'
|
const runtimeFiatCode = runtimeConfig.fiatCode || 'USD'
|
||||||
fiatCode.value = runtimeFiatCode
|
fiatCode.value = runtimeFiatCode
|
||||||
|
if (runtimeConfig.cashInFeeRate !== undefined) cashInFeeRate.value = runtimeConfig.cashInFeeRate
|
||||||
|
if (runtimeConfig.cashOutFeeRate !== undefined)
|
||||||
|
cashOutFeeRate.value = runtimeConfig.cashOutFeeRate
|
||||||
|
|
||||||
// Build device config from runtime values
|
// Build device config from runtime values
|
||||||
const { getDeviceConfig, toHalConfig, MACHINE_PRESETS } = await import('@/config')
|
const { getDeviceConfig, toHalConfig, MACHINE_PRESETS } = await import('@/config')
|
||||||
|
|
|
||||||
2
apps/machine/src/types/electron.d.ts
vendored
2
apps/machine/src/types/electron.d.ts
vendored
|
|
@ -16,6 +16,8 @@ export interface RuntimeConfig {
|
||||||
allowMockFallback: boolean
|
allowMockFallback: boolean
|
||||||
operatorPubkeys: string
|
operatorPubkeys: string
|
||||||
maintenanceMode: boolean
|
maintenanceMode: boolean
|
||||||
|
cashInFeeRate: number
|
||||||
|
cashOutFeeRate: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AtmSecrets {
|
export interface AtmSecrets {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import {
|
||||||
*/
|
*/
|
||||||
export function createATMMachine(
|
export function createATMMachine(
|
||||||
services: Partial<ATMServices> = {},
|
services: Partial<ATMServices> = {},
|
||||||
options?: { currency?: string }
|
options?: { currency?: string; cashInFeeRate?: number; cashOutFeeRate?: number }
|
||||||
) {
|
) {
|
||||||
return setup({
|
return setup({
|
||||||
types: {
|
types: {
|
||||||
|
|
@ -401,7 +401,14 @@ export function createATMMachine(
|
||||||
}).createMachine({
|
}).createMachine({
|
||||||
id: 'atm',
|
id: 'atm',
|
||||||
initial: 'idle',
|
initial: 'idle',
|
||||||
context: { ...initialContext, ...(options?.currency ? { currency: options.currency } : {}) },
|
context: {
|
||||||
|
...initialContext,
|
||||||
|
...(options?.currency ? { currency: options.currency } : {}),
|
||||||
|
...(options?.cashInFeeRate !== undefined ? { cashInFeePercent: options.cashInFeeRate } : {}),
|
||||||
|
...(options?.cashOutFeeRate !== undefined
|
||||||
|
? { cashOutFeePercent: options.cashOutFeeRate }
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
states: {
|
states: {
|
||||||
idle: {
|
idle: {
|
||||||
entry: 'resetContext',
|
entry: 'resetContext',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue