pago/main.js

134 lines
3.8 KiB
JavaScript

const dotenv = require('dotenv')
const express = require('express')
const Wallet = require('monero-wallet-rpc-js')
;(async () => {
const deAtomize = (atomic) => Number(atomic) * 0.000000000001
dotenv.config()
const WALLET_ACCOUNT_INDEX = Number(process.env.WALLET_ACCOUNT_INDEX)
const WALLET_AUTOSAVE_SEC = Number(process.env.WALLET_AUTOSAVE_SEC)
const WALLET_REFRESH_SEC = Number(process.env.WALLET_REFRESH_SEC)
// Load monero wallet
const wallet = await new Wallet({
url: process.env.WALLET_RPC_URI,
filename: process.env.WALLET_FILENAME,
password: process.env.WALLET_PASSWORD,
address: process.env.WALLET_ADDRESS,
viewkey: process.env.WALLET_VIEWKEY,
restore_height: process.env.WALLET_RESTORE_HEIGHT,
})
// Set auto save
if (WALLET_AUTOSAVE_SEC > 0)
setInterval(wallet.store(), WALLET_AUTOSAVE_SEC)
// Set auto refresh
try {
await wallet.rpc('auto_refresh', {
enable:true, period:WALLET_REFRESH_SEC,
})
console.log(`Auto-refreshing wallet every ${process.env.WALLET_REFRESH_SEC} seconds. `)
} catch (err) {
console.error(`Failed to set auto_refresh to ${process.env.WALLET_REFRESH_SEC}: ${err}`)
}
// Confirm sync
try {
console.log(`Wallet synced to block ${await wallet.getHeight()}.`)
} catch (err) {
console.error(`Failed to get blockchain height: ${err}`)
}
// Check accounts, create account if needed
// TODO: Validate that the admin didn't set WALLET_ACCOUNT_INDEX too high
const getAccount = async (i) => {
try {
accounts = (await wallet.getAccounts()).subaddress_accounts
} catch (err) {
console.error(`Failed to get account listing from rpc: ${err}`)
}
account = accounts.find(a => a.account_index == i)
if (account===undefined) {
console.log(`There is no account #${i}. Creating account...`)
try {
const newAccount = await wallet.createAccount()
console.log(`Created account #${newAccount.account_index}.`)
} catch (err) {
console.error(`Failed to create new account: ${err}`)
}
return getAccount(i)
} else {
console.log(`Account #${i} exists with a balance of ${deAtomize(account.balance)} XMR.`)
return account
}
}; getAccount(WALLET_ACCOUNT_INDEX)
// Server
const app = express()
app.use(express.json())
app.listen(80)
// Healthchecks
app.get('/wallet/height', async (req, res) =>
res.send((await wallet.getHeight()).toString())
)
app.get('/wallet/balance', async (req, res) => {
let result; try {
result = await wallet.getBalance({
account_index: WALLET_ACCOUNT_INDEX,
})
} catch (err) {
console.error(`Failed to get balance: ${err}`)
return res.sendStatus(500)
}
return res.send(`${deAtomize(result.balance)} XMR`)
})
// New payment
app.post('/payment', async (req, res) => {
let result; try {
result = await wallet.createAddress({
account_index: 1,
label: req.body.label,
})
} catch (err) {
console.error(`Failed to create address "${req.body.label}": ${err}`)
return res.sendStatus(500)
}
console.log(`Created new payment at subaddress #${result.address_index}`)
return res.redirect(`/payment/${result.address}`)
})
// Check payment
app.get('/payment/:addr', async (req, res) => {
let subaddr_index; try {
subaddr_index = (await wallet.getAddressIndex({
address: req.params.addr
})).index.minor
} catch (err) {
console.error(`Failed to get index of subaddress: ${err}`)
return res.status(500).sendText('Failed to determine subaddress index!')
}
let transfers; try {
transfers = Object.values(await wallet.getTransfers({
in: true,
pending: true,
failed: true,
pool: true,
account_index: WALLET_ACCOUNT_INDEX,
subaddr_indices: [subaddr_index],
})).flat()
} catch (err) {
console.error(`Failed to get transactions for subaddress: ${err}`)
return res.status(500).sendText('Failed to get transactions!')
}
return res.json(transfers)
})
})()