Skip to content

Commit

Permalink
tut part 2: expose to Telegram
Browse files Browse the repository at this point in the history
  • Loading branch information
Ash Beech committed Sep 14, 2021
1 parent bdd8d64 commit 55e63df
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 32 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"framer-motion": "^4.1.17",
"js-sha3": "^0.5.7",
"moralis": "^0.0.36",
"node-telegram-bot-api": "^0.54.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-final-form": "^6.5.3",
Expand Down
107 changes: 91 additions & 16 deletions src/Cloud/CloudFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,57 @@
// * add address to watch list
// * alert on change of address state

// todo: implement various conditions to apply to wathced addresses
// todo: cross-chain compatible.
// todo: all hardcoded variables and settings are exposed to frontend UI
// todo: user accounts login/logout/etc

// ---

const sendTelegramAlert = async (request) => {
// Telegram creds
const telegram_bot_id = "xxx"; // <-- ENTER TELEGRAM BOT ID
const chat_id = "-xxx"; // <-- ENTER TELEGRAM CHAT ID

// alert message
let message = "https://etherscan.io/tx/" + request.get("hash");

// Moralis httpRequest to Telegram API
Moralis.Cloud.httpRequest({
url: "https://api.telegram.org/bot" + telegram_bot_id + "/sendMessage",
method: "POST",
crossDomain: true,
headers: {
"Content-Type": "application/json",
"cache-control": "no-cache",
},
params: "chat_id=" + chat_id + "&text=" + message,
}).then(
function (httpResponse) {
logger.info(httpResponse.text);
},
function (httpResponse) {
logger.info("Request failed with response code " + httpResponse.status);
}
);
};

// full description of how to set this up with Moralis x SendGrid here:
// https://youtu.be/SY30AUb8144
// docs here: https://docs.moralis.io/moralis-server/tools/sending-email

const sendEmailAlert = async (request) => {
let _link = "https://etherscan.io/tx/" + request.get("hash");

Moralis.Cloud.sendEmail({
to: "xxx", // <-- ENTER EMAIL ADDRESS HERE
templateId: "d-xxx", // <-- ENTER SENDGRID TEMPLATE ID HERE
dynamic_template_data: {
link: _link,
},
});
};

Moralis.Cloud.define("watchAddress", async (request) => {
const logger = Moralis.Cloud.getLogger();

Expand All @@ -27,11 +78,27 @@ Moralis.Cloud.define("watchAddress", async (request) => {

// add address to watch list
// sync all txs in realtime to WatchedEthAddress class
Moralis.Cloud.run("watchEthAddress", {
await Moralis.Cloud.run("watchEthAddress", {
address,
sync_historical: false,
});

// method of alerting
const alert_method = "telegram"; // temporarily static for demo telegram/email/twitter/etc
// check address has saved
const query = new Moralis.Query("WatchedEthAddress");
// get row of saved address
query.equalTo("address", address);
const row_object = await query.first();
// set alert method for that row
row_object.set("alertMethod", alert_method);
// save it
try {
await row_object.save();
} catch (err) {
logger.info(err);
}

// every time the 'to_address' of tx is on our watch list, fire alert
Moralis.Cloud.afterSave("EthTransactions", async function (request) {
// check address is in watch list
Expand All @@ -40,28 +107,36 @@ Moralis.Cloud.define("watchAddress", async (request) => {
const query = new Moralis.Query("WatchedEthAddress");
// temporary demo alert condition: address of tx == to_address
query.equalTo("address", to_address);
const results = await query.find();
// results = tx data
const tx_data = await query.first();

// results exist, fire alert with link to block explorer
if (results) {
if (tx_data) {
// temporary demo alert readout
/*
logger.info("----------------");
logger.info("https://etherscan.io/tx/" + request.object.get("hash"));
logger.info("--🚨ALERT 🚨--");
}
*/

// declare alert method from
let _alert_method = tx_data.get("alertMethod");
// pass instructions to allocated alert functions as request.object

// todo: dispatch alerts via Telegram/Twitter/Native Push
// e.g. send alert: via email
/* Moralis.Cloud.sendEmail({
to: request.user.get("email"),
templateId: "300ebeac203c4d8d9678163c78fc67e6",
dynamic_template_data: {
name: data.to_address
}
});
*/
// todo: check if conditions regarding address are met
// todo: cross-chain, same code.
//if telegram selected
if (_alert_method == "telegram") {
sendTelegramAlert(request.object);
}
//if email selected
if (_alert_method == "email") {
//sendEmailAlert(request.object);
}
//if Twitter selected
if (_alert_method == "twitter") {
//todo: expose to twitter API
//sendTwitterAlert(request.object);
}
}
});

return true;
Expand Down
39 changes: 23 additions & 16 deletions src/Forms/WatchAddress.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ const serverUrl = process.env.REACT_APP_MORALIS_SERVER_URL;
Moralis.initialize(appId);
Moralis.serverURL = serverUrl;

/**
* Build form and handle input
*
* @method onSubmit
* @return <Form/>
*/
/**
* Build form and handle input
*
* @method onSubmit
* @return <Form/>
*/

export const WatchAddress = () => {

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// handle form submission
Expand All @@ -37,10 +36,14 @@ export const WatchAddress = () => {
// run cloud function to watch, sync and alert
const watch = await Moralis.Cloud.run("watchAddress", params);
// user feedback
if(watch){
window.alert(JSON.stringify(address + " added to watch list. πŸ‹πŸ‘€", 0, 2));
if (watch) {
window.alert(
JSON.stringify(address + " added to watch list. πŸ‹πŸ‘€", 0, 2)
);
} else {
window.alert(JSON.stringify("🚫 You're already watching this address. 🚫", 0, 2));
window.alert(
JSON.stringify("🚫 You're already watching this address. 🚫", 0, 2)
);
}
};

Expand All @@ -64,14 +67,18 @@ export const WatchAddress = () => {
boxShadow="1px 1px 3px rgba(0,0,0,0.3)"
onSubmit={handleSubmit}
>
{
// input field
}
<InputControl name="address" label="Enter Address" colorScheme="green"/>
<ButtonGroup spacing={4}>
{
// submit button
// input field
}
<InputControl
name="address"
label="Enter Address"
colorScheme="green"
/>
<ButtonGroup spacing={4}>
{
// submit button
}
<Button
isLoading={submitting}
loadingText="Submitting"
Expand Down

0 comments on commit 55e63df

Please sign in to comment.