diff --git a/.gitignore b/.gitignore index 663e560..9489b5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ node_modules/ .env docker-compose.override.yml -build/ wallet/ diff --git a/Dockerfile b/Dockerfile index baee0c2..06ebe39 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,5 +4,4 @@ WORKDIR /usr/local/src COPY package*.json ./ RUN npm ci --omit=dev COPY . . -RUN npm run build ENTRYPOINT ["npm", "run", "--"] diff --git a/main.js b/main.js new file mode 100644 index 0000000..4c0cc43 --- /dev/null +++ b/main.js @@ -0,0 +1,96 @@ +import dotenv from 'dotenv' +import express, { Express, Request, Response } from 'express' +import Wallet from 'monero-wallet-rpc-js' +(async () => { + + 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 + let wallet; try { + 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, + restoreHeight: process.env.WALLET_RESTORE_HEIGHT, + }) + } catch (err) { + console.error(`Failed to open wallet: ${err}`) + } + + // 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, + }) + } catch (err) { + console.error(`Failed to set auto_refresh to ${process.env.WALLET_REFRESH_SEC}: ${err}`) + } + + try { + console.log(`Wallet height: ${await wallet.getHeight()}`) + } catch (err) { + console.error(`Failed to get blockchain height: ${err}`) + } + + // 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) => + res.send( + String((await wallet.getBalance({ + account_index: WALLET_ACCOUNT_INDEX, + })).balance * 0.000000000001) + ) + ) + + // New payment + app.post('/payment', async (req, res) => { + res.redirect(`/payment/${(await wallet.createAddress({ + account_index: WALLET_ACCOUNT_INDEX, + label: req.body.label, + })).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) + }) + +})() diff --git a/package-lock.json b/package-lock.json index f48181f..54a19d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,18 @@ { "name": "pago", - "version": "1.0.0", + "version": "1.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pago", - "version": "1.0.0", + "version": "1.1.1", "license": "MIT", "dependencies": { "dotenv": "^16.4.5", "express": "^4.19.2", - "monero-wallet-rpc-js": "^1.2.5", + "monero-wallet-rpc-js": "^1.2.9", "socket.io": "^4.7.5" - }, - "devDependencies": { - "typescript": "^5.4.5" } }, "node_modules/@socket.io/component-emitter": { @@ -628,9 +625,9 @@ } }, "node_modules/monero-wallet-rpc-js": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/monero-wallet-rpc-js/-/monero-wallet-rpc-js-1.2.5.tgz", - "integrity": "sha512-AM7VUZIPURhVKUbeaSIagCtDY+7uNx+1++GO9TCylWxh2pbjIwhvJmkXGLBIDJ7mOiR4vhLFa3Ns/q9x/oerFQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/monero-wallet-rpc-js/-/monero-wallet-rpc-js-1.2.9.tgz", + "integrity": "sha512-NU+2d21beM300MjOiq76eUrma2SugAZqz0CHIg4vuMTdxgZhBy15p5Akz5NBeWBtuEVBQ8CB2yZLIeC22Wy6jg==", "dependencies": { "axios": "^1.6.8" } @@ -974,19 +971,6 @@ "node": ">= 0.6" } }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", diff --git a/package.json b/package.json index 6a92b37..c3e9191 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,10 @@ { "name": "pago", - "version": "1.1.0", + "version": "1.1.1", "description": "Lightweight monero payment gateway", "main": "index.js", "scripts": { - "build": "tsc", - "start": "node --no-experimental-fetch './build/main.js'" + "start": "node main.js" }, "repository": { "type": "git", @@ -19,10 +18,7 @@ "dependencies": { "dotenv": "^16.4.5", "express": "^4.19.2", - "monero-wallet-rpc-js": "^1.2.5", + "monero-wallet-rpc-js": "^1.2.9", "socket.io": "^4.7.5" - }, - "devDependencies": { - "typescript": "^5.4.5" } } diff --git a/sample.env b/sample.env index ed3d87a..dba8962 100644 --- a/sample.env +++ b/sample.env @@ -18,23 +18,22 @@ WALLET_FILENAME='pago' # Wallet password (Change this!) WALLET_PASSWORD='6vzyEYNW0uGPuIx' # Main wallet address (Change this!) -WALLET_ADDRESS='55bcxMRhBWea6xxsot8moF1rdPprjJR2x4mfnNnTGgBJFgXa4gWXmWAYdUBKiRcJxy9AUAGJEg28DejvWdJU2VgUDrUvCHG' +WALLET_ADDRESS='49YQ71oTRA4Vm5t3nfJH3R9CSf99ofbcf8TJPdNvv7rZZSCLvas7vo1W8knBjWcKf7aQiefSgWb4wH6TXurEcD8JUnJxfsZ' # Viewkey used for the wallet (Change this!) -WALLET_VIEWKEY='03d463f03ae547b11dfdf194a07ff82c14a3c6a3de559bd89c9a5e8dc5e9ae02' +WALLET_VIEWKEY='a23474fe2d3ef001b7f0d311d7bb10eb149bbf9c0e206f7f31cc91ab58781809' # Set this to the blockheight of first transaction -WALLET_RESTORE_HEIGHT=573936 +WALLET_RESTORE_HEIGHT=3133069 # Which wallet account to use for payments WALLET_ACCOUNT_INDEX=1 # Wallet RPC WALLET_RPC_URI='http://pago_wallet:18082' # Interval to rescan for transactions WALLET_REFRESH_SEC=1 -# Interval to save wallet -# Disable autosave with 0 +# Interval to save wallet (disable with 0) WALLET_REFRESH_SEC=10 -# Public remote node -# Find one on https://monero.fail/ +# Public remote node (pick one from https://monero.fail/) MONERO_DAEMON_HOST='xmr.gf4.pw:443' +# Same as above, different format MONERO_DAEMON_URI='https://xmr.gf4.pw' -# Local monero daemon (activate in docker-compose.override.yml) +# Local node (activate in docker-compose.override.yml) #MONERO_DAEMON_URI='http://monerod' diff --git a/src/main.ts b/src/main.ts deleted file mode 100644 index 04f26e4..0000000 --- a/src/main.ts +++ /dev/null @@ -1,68 +0,0 @@ -import dotenv from 'dotenv' -import express, { Express, Request, Response } from 'express' -import Wallet from 'monero-wallet-rpc-js' -(async () => { - - dotenv.config() - - // Load monero wallet - let wallet; try { - 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, - restoreHeight: process.env.WALLET_RESTORE_HEIGHT, - }) - } catch (err) { - console.error(`Failed to open wallet: ${err}`) - } - - // Set auto save - if (Number(process.env.WALLET_AUTOSAVE_SEC) > 0) - setInterval( - wallet.store(), - Number(process.env.WALLET_AUTOSAVE_SEC) - ) - - // Set auto refresh - try { - await wallet.rpc('auto_refresh', { - enable: true, - period: Number(process.env.WALLET_REFRESH_SEC), - }) - } catch (err) { - console.error(`Failed to set auto_refresh to ${process.env.WALLET_REFRESH_SEC}: ${err}`) - } - - try { - console.log(`Wallet height: ${await wallet.getHeight()}`) - } catch (err) { - console.error(`Failed to get blockchain height: ${err}`) - } - - // Server - const app: Express = express() - app.use(express.json()) - app.listen(80) - - - // Healthchecks - app.get('/wallet/height', async (req: Request, res: Response) => - res.send((await wallet.getHeight()).toString()) - ) - app.get('/wallet/balance', async (req: Request, res: Response) => - res.send( - ((await wallet.getBalance()).balance * 0.000000000001) - .toString() - ) - ) - - // New payment - //app.post('/payment', async (req: Request, res: Response) => { - // console.log(`New payment created: "${req.body.label}"`) - // return res.sendStatus(200) - //}) - -})() diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index cc995ad..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "outDir": "./build", - "allowJs": true, - "target": "es6", - "module": "NodeNext", - "moduleResolution": "NodeNext" - }, - "include": ["./src/**/*"] -}