diff options
| author | Adam Soltys <[email protected]> | 2021-06-29 10:28:58 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2021-07-07 12:42:19 -0700 |
| commit | 0fb703b85d99c888d1df971e7c3562f7918e0ff8 (patch) | |
| tree | 2f167df25b172c3b7166952444e39e7f582e93c4 | |
| parent | 9bf4080d67d6342624c8f1fb543acab00191f730 (diff) | |
| download | coinos-server-0fb703b85d99c888d1df971e7c3562f7918e0ff8.tar.gz coinos-server-0fb703b85d99c888d1df971e7c3562f7918e0ff8.zip | |
add webhooks to invoices
| -rw-r--r-- | db/index.js | 50 | ||||
| l--------- | db/knexfile.js | 1 | ||||
| -rw-r--r-- | db/migrations/20210612181508_init_referrals.js | 19 | ||||
| -rw-r--r-- | db/migrations/20210612192804_init_waiting_list.js.js | 17 | ||||
| -rw-r--r-- | db/migrations/20210625232223_add_invoice_id_to_payments.js | 10 | ||||
| -rw-r--r-- | db/migrations/20210628221727_add_webhook_to_invoices.js | 11 | ||||
| -rw-r--r-- | db/migrations/user_adjustments.js | 53 | ||||
| -rw-r--r-- | db/models/invoices.js | 9 | ||||
| -rw-r--r-- | db/models/payments.js | 9 | ||||
| -rw-r--r-- | docker-compose.yml | 2 | ||||
| -rw-r--r-- | index.js | 7 | ||||
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | routes/bitcoin/receive.js | 33 | ||||
| -rw-r--r-- | routes/invoices.js | 2 | ||||
| -rw-r--r-- | routes/payments.js | 8 | ||||
| -rw-r--r-- | yarn.lock | 5 |
16 files changed, 113 insertions, 125 deletions
diff --git a/db/index.js b/db/index.js index 4c327d35..c1d316cc 100644 --- a/db/index.js +++ b/db/index.js @@ -1,28 +1,30 @@ const Sequelize = require("sequelize"); -const debug = require('debug')('debug'); +const debug = require("debug")("debug"); -const dbOptions = require('./../config/knexfile.js')[process.env.NODE_ENV || "development"] +const dbOptions = require("./../config/knexfile.js")[ + process.env.NODE_ENV || "development" +]; -db = new Sequelize(dbOptions.connection.database, dbOptions.connection.user, dbOptions.connection.password, { - host: dbOptions.connection.host, - dialect: "mariadb", - logging: false, - dialectOptions: { "multipleStatements": true, "timezone": "Etc/GMT+7" } -}); +db = new Sequelize( + dbOptions.connection.database, + dbOptions.connection.user, + dbOptions.connection.password, + { + host: dbOptions.connection.host, + dialect: "mariadb", + logging: false, + dialectOptions: { multipleStatements: true, timezone: "Etc/GMT+7" } + } +); -db.authenticate() -.then (response => { - console.log('DB Connection established'); -}) -.catch (err => { - console.debug('Error connecting to database: ' + err.message); - console.log(dbOptions.connection.database + '.' + dbOptions.connection.user); -}) +db.authenticate().catch(err => { + console.debug("Error connecting to database: " + err.message); + console.log(dbOptions.connection.database + "." + dbOptions.connection.user); +}); -console.log("DB: " + JSON.stringify(dbOptions)) -debug('knex dbOptions: ' + JSON.stringify(dbOptions)) +debug("knex dbOptions: " + JSON.stringify(dbOptions)); -knex = require('knex')(dbOptions) +knex = require("knex")(dbOptions); require("./models/accounts.js"); require("./models/codes.js"); @@ -62,7 +64,7 @@ require("./normalized/waiting_list.js"); // require("./normalized/orders.js"); // require("./normalized/invoices.js"); -const { User, Account, Payment, Invoice, Key, Order, Referral} = db; +const { User, Account, Payment, Invoice, Key, Order, Referral } = db; // move relationships to specfic models User.hasMany(Account, { @@ -125,6 +127,11 @@ Payment.belongsTo(User, { foreignKey: "user_id" }); +Payment.belongsTo(Invoice, { + as: "invoice", + foreignKey: "invoice_id" +}); + Order.belongsTo(User, { as: "user", foreignKey: "user_id" @@ -158,6 +165,5 @@ Referral.belongsTo(User, { foreignKey: "user_id" }); -debug('added model relationships') +debug("added model relationships"); db.Order = Order; - diff --git a/db/knexfile.js b/db/knexfile.js new file mode 120000 index 00000000..10bb1d03 --- /dev/null +++ b/db/knexfile.js @@ -0,0 +1 @@ +../config/knexfile.js
\ No newline at end of file diff --git a/db/migrations/20210612181508_init_referrals.js b/db/migrations/20210612181508_init_referrals.js deleted file mode 100644 index 260a2c8f..00000000 --- a/db/migrations/20210612181508_init_referrals.js +++ /dev/null @@ -1,19 +0,0 @@ - -exports.up = function(knex) { - return knex.schema.createTable('referrals', function(t) { - t.increments('id').unsigned().primary(); - - t.string('token').notNull(); - t.string('expiry').nullable(); - t.enum('status', ['pending', 'active', 'expired', 'cancelled')).notNull().defaultTo('pending'); - t.int('sponsor_id').notNull(); - t.foreign('sponsor_id').references('users.user_id') - t.int('user_id').nullable(); - t.foreign('user_id').references('users.user_id') - - t.timestamps(); -}; - -exports.down = function(knex) { - return knex.schema.dropTable('referrals'); -}; diff --git a/db/migrations/20210612192804_init_waiting_list.js.js b/db/migrations/20210612192804_init_waiting_list.js.js deleted file mode 100644 index 5322cf6d..00000000 --- a/db/migrations/20210612192804_init_waiting_list.js.js +++ /dev/null @@ -1,17 +0,0 @@ - -exports.up = function(knex) { - return knex.schema.createTable('waiting_list', function(t) { - t.increments('id').unsigned().primary(); - - t.string('email').nullable(); - t.string('sms').nullable(); - t.enum('status', ['pending', 'contacted', 'registered', 'cancelled')).notNull().defaultTo('pending'); - t.int('user_id').notNull(); - t.foreign('user_id').references('users.user_id'); - - t.timestamps(); -}; - -exports.down = function(knex) { - return knex.schema.dropTable('waiting_list'); -}; diff --git a/db/migrations/20210625232223_add_invoice_id_to_payments.js b/db/migrations/20210625232223_add_invoice_id_to_payments.js new file mode 100644 index 00000000..46e2a82e --- /dev/null +++ b/db/migrations/20210625232223_add_invoice_id_to_payments.js @@ -0,0 +1,10 @@ +exports.up = async knex => + knex.schema.table("payments", function(table) { + table.integer("invoice_id"); + table.foreign("invoice_id").references("invoices.id"); + }); + +exports.down = async knex => + knex.schema.table("payments", function(table) { + table.dropColumn("invoice_id"); + }); diff --git a/db/migrations/20210628221727_add_webhook_to_invoices.js b/db/migrations/20210628221727_add_webhook_to_invoices.js new file mode 100644 index 00000000..073b8d01 --- /dev/null +++ b/db/migrations/20210628221727_add_webhook_to_invoices.js @@ -0,0 +1,11 @@ +exports.up = async function(knex) { + return knex.schema.table("invoices", function(table) { + table.text("webhook"); + }); +}; + +exports.down = async function(knex) { + return knex.schema.table("invoices", function(table) { + table.dropColumn("webhook"); + }); +}; diff --git a/db/migrations/user_adjustments.js b/db/migrations/user_adjustments.js deleted file mode 100644 index b4273848..00000000 --- a/db/migrations/user_adjustments.js +++ /dev/null @@ -1,53 +0,0 @@ - -exports.up = function(knex) { - return Promise.all([ - - // move security fields to separate t (potentially different access permissions) - - knex.schema.createTable('user_security', function (t) { - t.increments('id').unsigned().primary(); - t.int('user_id').notNull(); - t.foreign('user_id').references('users.user_id'); - - t.boolean('twofa').notNull().defaultTo(false); - t.string('pin').notNull(); - t.string('otp_secret').nullable(); - t.string('seed').nullable(); - }, - - knex.raw("INSERT INTO user_security (user_id, twofa, pin, otp_secret, seed) SELECT users.id, twofa, pin, otpsecret, seed FROM users"), - - // move user-customizeable fields to separate t (potentially different access permissions) - - knex.schema.createTable('user_preferences', function (t) { - t.increments('id').unsigned().primary(); - t.int('user_id').notNull(); - t.foreign('user_id').references('users.user_id'); - - t.enum('default_unit', ['SAT', 'BTC', 'CAD']).notNull().defaultTo('SAT'); - t.enum('default_currency', ['CAD', 'USD']).notNull().defaultTo('CAD'); - t.enum('default_fiat', ['CAD', 'USD']).notNull().defaultTo('CAD'); - t.set('show_currencies', ['CAD', 'USD']).notNull().defaultTo('CAD'); - } - - knex.raw("INSERT INTO user_preferences (user_id, default_unit, default_currency, default_fiat, show_currencies) SELECT users.id, unit, currency, fiat, currencies FROM users"), - - // remove deprecated fields - - knex.schema.table('users', function (t) { - t.string('uuid'); - t.enum('access', ['Anonymous', 'Member', 'Admin']).defaultTo('Anonymous'); - - t.dropColumn('account_id'); - t.dropColumn('unit'); - t.dropColumn('fiat'); - t.dropColumn('currency'); - t.dropColumn('currencies'); - }, - ]) - -}; - -exports.down = function(knex) { - -}; diff --git a/db/models/invoices.js b/db/models/invoices.js index e2c499f4..a51ee3f9 100644 --- a/db/models/invoices.js +++ b/db/models/invoices.js @@ -145,6 +145,15 @@ const attributes = { comment: null, field: "amount" }, + webhook: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: null, + primaryKey: false, + autoIncrement: false, + comment: null, + field: "webhook" + }, tip: { type: DataTypes.DOUBLE, allowNull: true, diff --git a/db/models/payments.js b/db/models/payments.js index 94050a0b..c315a5a0 100644 --- a/db/models/payments.js +++ b/db/models/payments.js @@ -19,6 +19,15 @@ const attributes = { comment: null, field: "account_id" }, + invoice_id: { + type: DataTypes.INTEGER(11), + allowNull: true, + defaultValue: null, + primaryKey: false, + autoIncrement: false, + comment: null, + field: "invoice_id" + }, user_id: { type: DataTypes.INTEGER(11), allowNull: true, diff --git a/docker-compose.yml b/docker-compose.yml index 3fe0f546..8e3f4ef8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -79,7 +79,7 @@ services: - ${LIQUID_ELECTRS_RPC_PORT}:60401 - ${LIQUID_ELECTRS_PORT}:3002 volumes: - - ./liquidregtest/liquid-config/:/config + - ./liquid/:/config restart: unless-stopped esplora-liquid: image: vulpemventures/esplora:latest @@ -58,7 +58,6 @@ require("./db"); require("./lib/utils"); require("./lib/sockets"); require("./lib/passport"); - require("./lib/register"); require("./lib/send"); @@ -69,24 +68,20 @@ require("./routes/users"); // Exclude plugins for minimalist version if (process.env.SCOPE !== 'MIN') { - if (config.bitcoin) networks.push("bitcoin"); if (config.liquid) networks.push("liquid"); if (config.lna) networks.push("lightning"); require("./lib/rates"); require("./lib/notifications"); + if (config.imap) require("./lib/mail"); - if (config.lnurl) require("./routes/lnurl"); if (config.mailgun) require("./routes/funding"); - require("./routes/funding"); require("./routes/invoices"); require("./routes/payments"); - require("./routes/swaps"); - } // Scope based Route Handling diff --git a/package.json b/package.json index 8babd585..1474238a 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "multer": "^1.4.2", "mysql": "^2.18.1", "mysql2": "^2.2.5", + "node-fetch": "^2.6.1", "nodemon": "^2.0.7", "otplib": "^12.0.1", "passport": "0.4.0", @@ -54,6 +55,7 @@ "sqlite3": "^5.0.2", "uuid": "^3.3.2", "web-push": "^3.4.4", + "wretch": "^1.7.4", "ws": "^7.1.2", "zeromq": "^5.1.0" }, diff --git a/routes/bitcoin/receive.js b/routes/bitcoin/receive.js index 6bf38a9e..ba522aeb 100644 --- a/routes/bitcoin/receive.js +++ b/routes/bitcoin/receive.js @@ -2,6 +2,9 @@ const reverse = require("buffer-reverse"); const zmq = require("zeromq"); const { Op } = require("sequelize"); const { fromBase58 } = require("bip32"); +const wretch = require("wretch"); +const fetch = require("node-fetch"); +wretch().polyfills({ fetch }); const bitcoin = require("bitcoinjs-lib"); @@ -84,7 +87,6 @@ zmqRawTx.on("message", async (topic, message, sequence) => { for (let i = 0; i < tx.ins.length; i++) { let { hash, index } = tx.ins[i]; hash = reverse(hash).toString("hex"); - console.log(hash); let hex = await bc.getRawTransaction(hash); let inputTx = bitcoin.Transaction.fromHex(hex); totalInputs += inputTx.outs[index].value; @@ -104,7 +106,8 @@ zmqRawTx.on("message", async (topic, message, sequence) => { tip, confirmed, address, - network: "bitcoin" + network: "bitcoin", + invoice_id: invoice.id }); payment = payment.get({ plain: true }); payment.account = account.get({ plain: true }); @@ -154,13 +157,24 @@ setInterval(async () => { { model: db.User, as: "user" + }, + { + model: db.Invoice, + as: "invoice" } ], lock: transaction.LOCK.UPDATE, transaction }); - + if (p.invoice && p.invoice.webhook) { + l.info("calling webhook", p.invoice.webhook); + console.log(await wretch() + .url(p.invoice.webhook) + .post({ oh: "yeah" }) + .json()); + } + if (p && p.address) address = p.address; if (p && p.user) user = p.user; @@ -194,7 +208,12 @@ setInterval(async () => { let c = convert[address]; if (address && c) { - l.info("bitcoin detected to conversion address", address, c.address, user.username); + l.info( + "bitcoin detected to conversion address", + address, + c.address, + user.username + ); user.account = account; await sendLiquid({ @@ -206,6 +225,10 @@ setInterval(async () => { } } } catch (e) { - l.error("problem processing queued bitcoin transaction", e.message, e.stack); + l.error( + "problem processing queued bitcoin transaction", + e.message, + e.stack + ); } }, 1000); diff --git a/routes/invoices.js b/routes/invoices.js index f7682bfe..c188811e 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -55,7 +55,7 @@ app.post( invoice.amount, invoice.tip, invoice.currency, - `${invoice.text.substr(0, 8)}..${invoice.text.substr(-6)}`, + invoice.text && `${invoice.text.substr(0, 8)}..${invoice.text.substr(-6)}`, ); if (!invoice.tip) invoice.tip = 0; diff --git a/routes/payments.js b/routes/payments.js index a52ad395..41dfce26 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -17,6 +17,7 @@ ah(async () => { l.warn("couldn't read exceptions file", e.message); } + try { ( await db.Invoice.findAll({ include: { @@ -28,6 +29,9 @@ ah(async () => { if (address && user) addresses[address] = user.username; if (unconfidential && user) addresses[unconfidential] = user.username; }); + } catch(e) { + console.log(e); + } try { const accounts = await db.Account.findAll({ @@ -51,6 +55,7 @@ ah(async () => { }) ).map((p) => p.hash); + setInterval(async () => { const unconfirmed = ( await db.Payment.findAll({ @@ -129,6 +134,7 @@ ah(async () => { } }, 50); } + /* if (config.liquid) { lq = new BitcoinCore(config.liquid); @@ -151,7 +157,6 @@ ah(async () => { }, 50); } - app.get( "/payments", auth, @@ -194,4 +199,5 @@ ah(async () => { } }) ); +*/ })(); @@ -4566,6 +4566,11 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +wretch@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/wretch/-/wretch-1.7.4.tgz#d71fc16ed01a8fd549df6cd06f205c6d13e2cf73" + integrity sha512-gBET7PgqgJ89GPBHujw0+arM/8YtWPqG6od8dRMTumvr3xvSlONpp2ANYqbpSL+cSoe6g97quZTgwM0jNn6riA== + write-file-atomic@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" |
