Mango Notifi Integration (#2)
* Add notifiAlertId * Put back mango account checks * Conditionally validating alert based on alertProvider * Import notifi-node * Hook up to notifi-node SDK * Update Notifi SDK The new SDK has a different parameter name: healthValue rather than value. We should no longer delete the alert from server side. * Bump up to latest SDK * Comment out debugging logging Co-authored-by: juni-notifi <hyungjoon.kim@notifi.network>
This commit is contained in:
parent
b96df3bada
commit
fd182e1ae1
|
@ -32,6 +32,7 @@
|
|||
"dependencies": {
|
||||
"@blockworks-foundation/mango-client": "^3.2.9",
|
||||
"@koa/cors": "^3.1.0",
|
||||
"@notifi-network/notifi-node": "^0.8.0",
|
||||
"@solana/web3.js": "^1.2.6",
|
||||
"dotenv": "^8.2.0",
|
||||
"email-validator": "^2.0.4",
|
||||
|
|
|
@ -14,4 +14,6 @@ export default {
|
|||
mailJetKey: process.env.MAILJET_KEY || "",
|
||||
mailJetSecret: process.env.MAILJET_SECRET || "",
|
||||
updatePassword: process.env.UPDATE_PASSWORD,
|
||||
notifiSid: process.env.NOTIFI_SID || "",
|
||||
notifiSecret: process.env.NOTIFI_SECRET || ""
|
||||
}
|
||||
|
|
13
src/index.ts
13
src/index.ts
|
@ -20,6 +20,7 @@ import {
|
|||
validateEmail,
|
||||
sendAlert,
|
||||
validateUpdatePassword,
|
||||
validateNotifiAlertId,
|
||||
} from "./utils"
|
||||
import config from "./environment"
|
||||
|
||||
|
@ -63,7 +64,13 @@ router.post("/alerts", async (ctx, next) => {
|
|||
try {
|
||||
const alert: any = ctx.request.body
|
||||
await validateMangoAccount(client, alert)
|
||||
validateEmail(alert.email)
|
||||
if (alert.alertProvider === 'mail') {
|
||||
validateEmail(alert.email)
|
||||
} else if (alert.alertProvider === 'notifi') {
|
||||
validateNotifiAlertId(alert.notifiAlertId)
|
||||
} else {
|
||||
throw new UserError("Invalid alertProvider")
|
||||
}
|
||||
ctx.body = { status: "success" }
|
||||
alert.open = true
|
||||
alert.timestamp = Date.now()
|
||||
|
@ -115,6 +122,7 @@ router.get("/alerts/:mangoAccountPk", async (ctx, next) => {
|
|||
open: 1,
|
||||
timestamp: 1,
|
||||
triggeredTimestamp: 1,
|
||||
notifiAlertId: 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
@ -245,6 +253,7 @@ const handleAlert = async (alert: any, db: any) => {
|
|||
mangoAccountPk,
|
||||
mangoGroup.dexProgramId
|
||||
)
|
||||
const walletPublicKey = mangoAccount.owner.toBase58();
|
||||
const health = await mangoAccount.getHealthRatio(
|
||||
mangoGroup,
|
||||
mangoCache,
|
||||
|
@ -255,7 +264,7 @@ const handleAlert = async (alert: any, db: any) => {
|
|||
message +=
|
||||
"Deposit more collateral or reduce your liabilities to improve your account health. \n"
|
||||
message += `View your account: https://trade.mango.markets/account?pubkey=${alert.mangoAccountPk}`
|
||||
const alertSent = await sendAlert(alert, message)
|
||||
const alertSent = await sendAlert(alert, message, Number(health), walletPublicKey)
|
||||
if (alertSent) {
|
||||
db.collection("alerts").deleteOne({ _id: alert._id })
|
||||
}
|
||||
|
|
70
src/utils.ts
70
src/utils.ts
|
@ -3,13 +3,25 @@ import * as EmailValidator from "email-validator"
|
|||
|
||||
import { MangoClient } from "@blockworks-foundation/mango-client"
|
||||
import { PublicKey } from "@solana/web3.js"
|
||||
import {
|
||||
NotifiClient,
|
||||
NotifiEnvironment,
|
||||
createAxiosInstance,
|
||||
} from '@notifi-network/notifi-node';
|
||||
import axios from 'axios';
|
||||
|
||||
import { UserError } from "./errors"
|
||||
|
||||
import config from "./environment"
|
||||
import { randomUUID } from "crypto"
|
||||
|
||||
const mailjetTransport = require("nodemailer-mailjet-transport")
|
||||
|
||||
// Initialize Notifi client
|
||||
const env: NotifiEnvironment = 'Development';
|
||||
const axiosInstance = createAxiosInstance(axios, env);
|
||||
const notifiClient = new NotifiClient(axiosInstance);
|
||||
|
||||
export const validateMangoAccount = (client: MangoClient, alert: any) => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
try {
|
||||
|
@ -52,6 +64,13 @@ export const validateEmail = (email: string) => {
|
|||
return
|
||||
}
|
||||
|
||||
export const validateNotifiAlertId = (notifiAlertId: string) => {
|
||||
if (!notifiAlertId) {
|
||||
throw new UserError("Invalid notifiAlertId")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const sendEmail = async (email: string, message: string) => {
|
||||
const transport = nodemailer.createTransport(
|
||||
mailjetTransport({
|
||||
|
@ -70,16 +89,59 @@ const sendEmail = async (email: string, message: string) => {
|
|||
|
||||
try {
|
||||
await transport.sendMail(mailOptions)
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
transport.sendMail(mailOptions)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export const sendAlert = async (alert: any, message: string) => {
|
||||
const sendNotifiAlert = async (alertId: string, health: number, walletPublicKey: string ) => {
|
||||
const sid = config.notifiSid
|
||||
const secret = config.notifiSecret
|
||||
if (!sid || !secret) {
|
||||
throw new UserError("Missing sid/secret pair")
|
||||
}
|
||||
|
||||
try {
|
||||
// login with sid/secret to get jwt
|
||||
const { token: jwt, expiry } = await notifiClient.logIn({ sid, secret })
|
||||
// console.log(`login successfully, received jwt expire at ${expiry}`)
|
||||
if (jwt) {
|
||||
// trigger notifi to send notification
|
||||
const key = randomUUID()
|
||||
await notifiClient.sendSimpleHealthThreshold(jwt, {
|
||||
key,
|
||||
walletPublicKey,
|
||||
walletBlockchain: "SOLANA",
|
||||
healthValue: health,
|
||||
})
|
||||
// console.log(`sending alert with key: ${key}, walletPublicKey: ${walletPublicKey}, value: ${health}`);
|
||||
return true
|
||||
} else {
|
||||
throw new UserError("Invalid jwt, please login")
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
export const sendAlert = async (alert: any, message: string, health: number, walletPublicKey: string) => {
|
||||
if (alert.alertProvider == "mail") {
|
||||
const email = alert.email
|
||||
sendEmail(email, message)
|
||||
const emailSent = await sendEmail(email, message)
|
||||
return emailSent
|
||||
} else if (alert.alertProvider == "notifi") {
|
||||
try {
|
||||
const alertSent = await sendNotifiAlert(alert.notifiAlertId, health, walletPublicKey)
|
||||
return alertSent;
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -65,6 +65,18 @@
|
|||
dependencies:
|
||||
vary "^1.1.2"
|
||||
|
||||
"@notifi-network/notifi-axios-utils@^0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@notifi-network/notifi-axios-utils/-/notifi-axios-utils-0.8.0.tgz#83ac4a649ee9facbd32a8d121748bb5c827f9c4f"
|
||||
integrity sha512-q+RDUZ2gRkLl0gfKy6pVQrZHe9fGwLa+zH1Fy+dm3U6SCyAZX8cjqiLpFLYVJE89nguMMc28tnp3T5K39+wBlQ==
|
||||
|
||||
"@notifi-network/notifi-node@^0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@notifi-network/notifi-node/-/notifi-node-0.8.0.tgz#0c91b5f3ac27c41e4b54ddd5eed8a9118e54a2e6"
|
||||
integrity sha512-bgleeL1M6RMm0GQFKhXETH6fbtDOJ7poqBX/VPg2ZTG7hThhYcxlFnYhQ33/qnG2FsMmYq1YjOlCV5Ens6o1XA==
|
||||
dependencies:
|
||||
"@notifi-network/notifi-axios-utils" "^0.8.0"
|
||||
|
||||
"@project-serum/anchor@^0.11.1":
|
||||
version "0.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.11.1.tgz#155bff2c70652eafdcfd5559c81a83bb19cec9ff"
|
||||
|
|
Loading…
Reference in New Issue