From 8aefd41378cedfa332553f5369989b90142e12a2 Mon Sep 17 00:00:00 2001 From: Michael Bumann Date: Sun, 28 Nov 2021 13:06:01 -0600 Subject: [PATCH] Implement invoice generation and verification --- functions/graphql/resolvers.js | 55 +++- functions/graphql/typeDefs.js | 3 + package-lock.json | 273 ++++++++++++++++++ package.json | 2 + .../migration.sql | 1 + prisma/schema.prisma | 21 +- prisma/seed.js | 1 + 7 files changed, 344 insertions(+), 12 deletions(-) rename prisma/migrations/{20211128171210_init => 20211128173513_init}/migration.sql (97%) diff --git a/functions/graphql/resolvers.js b/functions/graphql/resolvers.js index 8cddfcd..cfb69a8 100644 --- a/functions/graphql/resolvers.js +++ b/functions/graphql/resolvers.js @@ -1,3 +1,34 @@ +const { parsePaymentRequest } = require('invoices'); +const axios = require('axios'); +const { createHash } = require('crypto'); + +function hexToUint8Array (hexString) { + const match = hexString.match(/.{1,2}/g); + if (match) { + return new Uint8Array(match.map((byte) => parseInt(byte, 16))); + } +} + +// TODO validate responses +function getPaymetRequest(lightning_address, amount_in_sat) { + const [name, domain] = lightning_address.split("@"); + const lnurl = `https://${domain}/.well-known/lnurlp/${name}`; + return axios.get(lnurl) + .then((response) => { + console.log(response.data); + const callbackUrl = response.data.callback; + const amount = amount_in_sat * 1000; // msats + return axios.get(callbackUrl, { params: { amount }} ) + .then(prResponse => { + console.log(prResponse.data); + return prResponse.data.pr; + }); + }) + .catch(function (error) { + console.error(error); + }) +} + module.exports = { Query: { allCategories: async (_source, args, context) => { @@ -17,13 +48,33 @@ module.exports = { Mutation: { vote: async (_source, args, context) => { const project = await context.prisma.project.findUnique({where: { id: args.project_id }}); - console.log(project) + const pr = await getPaymetRequest(project.lightning_address, args.amount_in_sat); + const invoice = parsePaymentRequest({ request: pr }); return context.prisma.vote.create({ data: { project_id: project.id, amount_in_sat: args.amount_in_sat, + payment_request: pr, + payment_hash: invoice.id, } }); }, + confirmVote: async (_source, args, context) => { + const paymentHash = createHash('sha256').update(hexToUint8Array(args.preimage)).digest('hex'); + // look for a vote for the payment request and the calculated payment hash + const vote = await context.prisma.vote.findFirst({where: { payment_request: args.payment_request, payment_hash: paymentHash}}); + // if we find a vote it means the preimage is correct and we update the vote and mark it as paid + if (vote) { + return context.prisma.vote.update({ + where: { id: vote.id }, + data: { + paid: true, + preimage: args.preimage, + } + }); + } else { + throw new Error("Invalid preimage"); + } + } }, -}; +}; \ No newline at end of file diff --git a/functions/graphql/typeDefs.js b/functions/graphql/typeDefs.js index 6d23fc6..e15ae35 100644 --- a/functions/graphql/typeDefs.js +++ b/functions/graphql/typeDefs.js @@ -7,6 +7,7 @@ module.exports = gql` thumbnail_image: String! title: String! website: String! + lightning_address: String! votes_count: Int! category: Category! } @@ -21,6 +22,7 @@ module.exports = gql` project: Project! amount_in_sat: Int! payment_request: String! + payment_hash: String! paid: Boolean! } @@ -31,5 +33,6 @@ module.exports = gql` } type Mutation { vote (project_id: Int!, amount_in_sat: Int!): Vote! + confirmVote (payment_request: String!, preimage: String!): Vote! } `; diff --git a/package-lock.json b/package-lock.json index cb72fcd..85e9a85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,10 @@ "@types/react-dom": "^17.0.10", "apollo-server": "^3.5.0", "apollo-server-lambda": "^3.5.0", + "axios": "^0.24.0", "framer-motion": "^5.3.0", "graphql": "^16.0.1", + "invoices": "^2.0.2", "lodash.throttle": "^4.1.1", "prisma": "3.5.0", "react": "^17.0.2", @@ -8863,6 +8865,14 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "dependencies": { + "follow-redirects": "^1.14.4" + } + }, "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -9590,6 +9600,14 @@ "node": ">=0.10.0" } }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/base/node_modules/define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", @@ -9631,6 +9649,11 @@ "integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg=", "dev": true }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" + }, "node_modules/better-opn": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", @@ -9691,6 +9714,31 @@ "file-uri-to-path": "1.0.0" } }, + "node_modules/bip174": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.0.1.tgz", + "integrity": "sha512-i3X26uKJOkDTAalYAp0Er+qGMDhrbbh2o93/xiPyAN2s25KrClSpe3VXo/7mNJoqA5qfko8rLS2l3RWZgYmjKQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bitcoinjs-lib": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.0.0.tgz", + "integrity": "sha512-KYx81rVE4LDbZcHfE375NCX4CDeZuz7HECZm/KAmqKMY2jpD3ZcUnI7Fm+QX5EMF/xmtzzfrNL/BNxo8o0iOQg==", + "dependencies": { + "bech32": "^2.0.0", + "bip174": "^2.0.1", + "bs58check": "^2.1.2", + "create-hash": "^1.1.0", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2", + "wif": "^2.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -9742,6 +9790,22 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/bolt07": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/bolt07/-/bolt07-1.7.4.tgz", + "integrity": "sha512-y82Na9vEBY+rqjJhjYMFAch70nWvbL5OiEPFqNf7cGTtQfG7g/Vui2KnemrX1mxEw2SgccF+Rn1NSRm9HFtu3w==", + "dependencies": { + "bn.js": "5.2.0" + } + }, + "node_modules/bolt09": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.2.0.tgz", + "integrity": "sha512-s6QWo7qqu6fKGLISGMSG+vFxIRzeUT3KQHDiHpvhflyI3TQD6zdaMu4fEpP7PoyMFJt2Ve26SBvvRP3MM7V0bw==", + "engines": { + "node": ">=10.4.0" + } + }, "node_modules/bonjour": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", @@ -10024,6 +10088,24 @@ "url": "https://opencollective.com/browserslist" } }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -16640,6 +16722,22 @@ "loose-envify": "^1.0.0" } }, + "node_modules/invoices": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/invoices/-/invoices-2.0.2.tgz", + "integrity": "sha512-d1PX0ivZUw5u5kqIZ4bEajzTmKMe6EHXry4ZypsKT6SuvG4bTmn3sdCz867EhuMNZY2/Yj3/R1LXqCVTtsDPmA==", + "dependencies": { + "bech32": "2.0.0", + "bitcoinjs-lib": "6.0.0", + "bn.js": "5.2.0", + "bolt07": "1.7.4", + "bolt09": "0.2.0", + "secp256k1": "4.0.2" + }, + "engines": { + "node": ">=10.4.0" + } + }, "node_modules/ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -43785,6 +43883,11 @@ "tslib": "^2.0.3" } }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, "node_modules/node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", @@ -43844,6 +43947,16 @@ "node": ">= 6.0.0" } }, + "node_modules/node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -48825,6 +48938,20 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -51197,6 +51324,11 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typeforce": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + }, "node_modules/typescript": { "version": "4.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", @@ -51816,6 +51948,14 @@ "node": ">=12" } }, + "node_modules/varuint-bitcoin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", + "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", + "dependencies": { + "safe-buffer": "^5.1.1" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -53460,6 +53600,14 @@ "node": ">=8" } }, + "node_modules/wif": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", + "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", + "dependencies": { + "bs58check": "<3.0.0" + } + }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -60314,6 +60462,14 @@ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.3.5.tgz", "integrity": "sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==" }, + "axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "requires": { + "follow-redirects": "^1.14.4" + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -60920,6 +61076,14 @@ } } }, + "base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -60936,6 +61100,11 @@ "integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg=", "dev": true }, + "bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" + }, "better-opn": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", @@ -60981,6 +61150,25 @@ "file-uri-to-path": "1.0.0" } }, + "bip174": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.0.1.tgz", + "integrity": "sha512-i3X26uKJOkDTAalYAp0Er+qGMDhrbbh2o93/xiPyAN2s25KrClSpe3VXo/7mNJoqA5qfko8rLS2l3RWZgYmjKQ==" + }, + "bitcoinjs-lib": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.0.0.tgz", + "integrity": "sha512-KYx81rVE4LDbZcHfE375NCX4CDeZuz7HECZm/KAmqKMY2jpD3ZcUnI7Fm+QX5EMF/xmtzzfrNL/BNxo8o0iOQg==", + "requires": { + "bech32": "^2.0.0", + "bip174": "^2.0.1", + "bs58check": "^2.1.2", + "create-hash": "^1.1.0", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2", + "wif": "^2.0.1" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -61028,6 +61216,19 @@ } } }, + "bolt07": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/bolt07/-/bolt07-1.7.4.tgz", + "integrity": "sha512-y82Na9vEBY+rqjJhjYMFAch70nWvbL5OiEPFqNf7cGTtQfG7g/Vui2KnemrX1mxEw2SgccF+Rn1NSRm9HFtu3w==", + "requires": { + "bn.js": "5.2.0" + } + }, + "bolt09": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.2.0.tgz", + "integrity": "sha512-s6QWo7qqu6fKGLISGMSG+vFxIRzeUT3KQHDiHpvhflyI3TQD6zdaMu4fEpP7PoyMFJt2Ve26SBvvRP3MM7V0bw==" + }, "bonjour": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", @@ -61257,6 +61458,24 @@ "picocolors": "^1.0.0" } }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, "bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -66382,6 +66601,19 @@ "loose-envify": "^1.0.0" } }, + "invoices": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/invoices/-/invoices-2.0.2.tgz", + "integrity": "sha512-d1PX0ivZUw5u5kqIZ4bEajzTmKMe6EHXry4ZypsKT6SuvG4bTmn3sdCz867EhuMNZY2/Yj3/R1LXqCVTtsDPmA==", + "requires": { + "bech32": "2.0.0", + "bitcoinjs-lib": "6.0.0", + "bn.js": "5.2.0", + "bolt07": "1.7.4", + "bolt09": "0.2.0", + "secp256k1": "4.0.2" + } + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -87276,6 +87508,11 @@ "tslib": "^2.0.3" } }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, "node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", @@ -87328,6 +87565,11 @@ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" }, + "node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==" + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -91234,6 +91476,16 @@ "ajv-keywords": "^3.5.2" } }, + "secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -93125,6 +93377,11 @@ "is-typedarray": "^1.0.0" } }, + "typeforce": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + }, "typescript": { "version": "4.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", @@ -93579,6 +93836,14 @@ "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==" }, + "varuint-bitcoin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", + "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -94882,6 +95147,14 @@ "string-width": "^4.0.0" } }, + "wif": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", + "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", + "requires": { + "bs58check": "<3.0.0" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/package.json b/package.json index 5caa02b..130411a 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,10 @@ "@types/react-dom": "^17.0.10", "apollo-server": "^3.5.0", "apollo-server-lambda": "^3.5.0", + "axios": "^0.24.0", "framer-motion": "^5.3.0", "graphql": "^16.0.1", + "invoices": "^2.0.2", "lodash.throttle": "^4.1.1", "prisma": "3.5.0", "react": "^17.0.2", diff --git a/prisma/migrations/20211128171210_init/migration.sql b/prisma/migrations/20211128173513_init/migration.sql similarity index 97% rename from prisma/migrations/20211128171210_init/migration.sql rename to prisma/migrations/20211128173513_init/migration.sql index dc37055..9812f94 100644 --- a/prisma/migrations/20211128171210_init/migration.sql +++ b/prisma/migrations/20211128173513_init/migration.sql @@ -16,6 +16,7 @@ CREATE TABLE "Project" ( "cover_image" TEXT, "category_id" INTEGER NOT NULL, "votes_count" INTEGER NOT NULL DEFAULT 0, + "lightning_address" TEXT, CONSTRAINT "Project_pkey" PRIMARY KEY ("id") ); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7448aed..ffce0ec 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -14,16 +14,17 @@ model Category { } model Project { - id Int @id @default(autoincrement()) - title String - description String - website String - thumbnail_image String? - cover_image String? - category Category @relation(fields: [category_id], references: [id]) - category_id Int - votes_count Int @default(0) - Vote Vote[] + id Int @id @default(autoincrement()) + title String + description String + website String + thumbnail_image String? + cover_image String? + lightning_address String? + category Category @relation(fields: [category_id], references: [id]) + category_id Int + votes_count Int @default(0) + Vote Vote[] } model Vote { diff --git a/prisma/seed.js b/prisma/seed.js index b8f95e5..e58b735 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -14,6 +14,7 @@ async function main() { description: "HQ on a VULCANO lake", website: "https://github.com/peakshift", category_id: category.id, + lightning_address: "johns@getalby.com", } }); }