Skip to content

Commit

Permalink
Merge pull request #79 from MAGICGrants/funding-required-endpoint
Browse files Browse the repository at this point in the history
Funding required endpoint
  • Loading branch information
Keeqler authored Sep 20, 2024
2 parents efed201 + 853a1f1 commit 0db2c11
Show file tree
Hide file tree
Showing 14 changed files with 480 additions and 79 deletions.
10 changes: 5 additions & 5 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ services:
expose:
- '49392'
environment:
BTCPAY_POSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=btcpayserver;Database=btcpayserver${NBITCOIN_NETWORK:-regtest}
BTCPAY_EXPLORERPOSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=btcpayserver;MaxPoolSize=80;Database=nbxplorer${NBITCOIN_NETWORK:-regtest}
BTCPAY_NETWORK: ${NBITCOIN_NETWORK:-regtest}
BTCPAY_POSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=btcpayserver;Database=btcpayserver${NBITCOIN_NETWORK:-mainnet}
BTCPAY_EXPLORERPOSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=btcpayserver;MaxPoolSize=80;Database=nbxplorer${NBITCOIN_NETWORK:-mainnet}
BTCPAY_NETWORK: ${NBITCOIN_NETWORK:-mainnet}
BTCPAY_BIND: 0.0.0.0:49392
BTCPAY_ROOTPATH: ${BTCPAY_ROOTPATH:-/}
BTCPAY_SSHCONNECTION: '[email protected]'
Expand Down Expand Up @@ -57,11 +57,11 @@ services:
expose:
- '32838'
environment:
NBXPLORER_NETWORK: ${NBITCOIN_NETWORK:-regtest}
NBXPLORER_NETWORK: ${NBITCOIN_NETWORK:-mainnet}
NBXPLORER_BIND: 0.0.0.0:32838
NBXPLORER_TRIMEVENTS: 10000
NBXPLORER_SIGNALFILESDIR: /datadir
NBXPLORER_POSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=nbxplorer;MaxPoolSize=20;Database=nbxplorer${NBITCOIN_NETWORK:-regtest}
NBXPLORER_POSTGRES: User ID=postgres;Host=postgres;Port=5432;Application Name=nbxplorer;MaxPoolSize=20;Database=nbxplorer${NBITCOIN_NETWORK:-mainnet}
NBXPLORER_AUTOMIGRATE: 1
NBXPLORER_NOMIGRATEEVTS: 1
NBXPLORER_DELETEAFTERMIGRATION: 1
Expand Down
1 change: 1 addition & 0 deletions docs/monero/projects/eth_xmr_atomic_swaps.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ fund: monero
title: 'ETH<>XMR Atomic Swap Continued Development'
summary: 'A trustless way to exchange Monero and Ethereum.'
nym: 'noot'
date: '2022-09-01'
coverImage: '/img/project/Ethereum_logo.png'
website: 'https://github.com/AthanorLabs/atomic-swap'
personalWebsite: 'https://github.com/noot'
Expand Down
1 change: 1 addition & 0 deletions docs/monero/projects/ring_signature_ai.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ fund: monero
title: 'Ring Signature Resiliency to AI Analysis'
summary: "A test of machine learning attacks on Monero's untraceability."
nym: 'ACK-J'
date: '2022-03-01'
coverImage: '/img/project/ring_sig.png'
website: 'https://magicgrants.org/Monero-Tracing-Research/'
personalWebsite: 'https://github.com/ACK-J'
Expand Down
86 changes: 43 additions & 43 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 58 additions & 18 deletions pages/api/btcpay/webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@ import getRawBody from 'raw-body'
import crypto from 'crypto'
import dayjs from 'dayjs'

import { DonationMetadata } from '../../../server/types'
import {
BtcPayGetRatesRes,
BtcPayGetPaymentMethodsRes,
DonationMetadata,
} from '../../../server/types'
import { btcpayApi as _btcpayApi, btcpayApi, prisma } from '../../../server/services'
import { env } from '../../../env.mjs'
import axios from 'axios'

export const config = {
api: {
bodyParser: false,
},
}

type BtcpayBody = {
type BtcpayBody = Record<string, any> & {
deliveryId: string
webhookId: string
originalDeliveryId: string
Expand All @@ -25,12 +30,6 @@ type BtcpayBody = {
metadata: DonationMetadata
}

type BtcpayPaymentMethodsResponse = {
rate: string
amount: string
cryptoCode: string
}[]

async function handleBtcpayWebhook(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'POST') {
res.setHeader('Allow', ['POST'])
Expand Down Expand Up @@ -59,30 +58,71 @@ async function handleBtcpayWebhook(req: NextApiRequest, res: NextApiResponse) {
return
}

if (body.type === 'InvoiceSettled') {
const { data: paymentMethods } = await btcpayApi.get<BtcpayPaymentMethodsResponse>(
`/invoices/${body.invoiceId}/payment-methods`
if (body.type === 'InvoicePaymentSettled') {
// Handle payments to funding required API invoices ONLY
if (body.metadata.staticGeneratedForApi === 'false') {
return res.status(200).json({ success: true })
}

const cryptoCode = body.paymentMethod === 'BTC-OnChain' ? 'BTC' : 'XMR'

const { data: rates } = await btcpayApi.get<BtcPayGetRatesRes>(
`/rates?currencyPair=${cryptoCode}_USD`
)

const cryptoAmount = Number(paymentMethods[0].amount)
const fiatAmount = Number(paymentMethods[0].amount) * Number(paymentMethods[0].rate)
const cryptoRate = Number(rates[0].rate)
const cryptoAmount = Number(body.payment.value)

await prisma.donation.create({
data: {
userId: body.metadata.userId,
userId: null,
btcPayInvoiceId: body.invoiceId,
projectName: body.metadata.projectName,
projectSlug: body.metadata.projectSlug,
fundSlug: body.metadata.fundSlug,
cryptoCode: paymentMethods[0].cryptoCode,
cryptoCode,
cryptoAmount,
fiatAmount: Number(fiatAmount.toFixed(2)),
membershipExpiresAt:
body.metadata.isMembership === 'true' ? dayjs().add(1, 'year').toDate() : null,
fiatAmount: Number((cryptoAmount * cryptoRate).toFixed(2)),
},
})
}

if (body.type === 'InvoiceSettled') {
// If this is a funding required API invoice, let InvoiceReceivedPayment handle it instead
if (body.metadata.staticGeneratedForApi === 'true') {
return res.status(200).json({ success: true })
}

const { data: paymentMethods } = await btcpayApi.get<BtcPayGetPaymentMethodsRes>(
`/invoices/${body.invoiceId}/payment-methods`
)

await Promise.all(
paymentMethods.map(async (paymentMethod) => {
const cryptoAmount = Number(paymentMethod.amount)

if (!cryptoAmount) return

const fiatAmount = Number(paymentMethod.amount) * Number(paymentMethod.rate)

await prisma.donation.create({
data: {
userId: body.metadata.userId,
btcPayInvoiceId: body.invoiceId,
projectName: body.metadata.projectName,
projectSlug: body.metadata.projectSlug,
fundSlug: body.metadata.fundSlug,
cryptoCode: paymentMethod.cryptoCode,
cryptoAmount,
fiatAmount: Number(fiatAmount.toFixed(2)),
membershipExpiresAt:
body.metadata.isMembership === 'true' ? dayjs().add(1, 'year').toDate() : null,
},
})
})
)
}

res.status(200).json({ success: true })
}

Expand Down
Loading

0 comments on commit 0db2c11

Please sign in to comment.