forked from mertimus/nft-sales-bot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsales_bot.js
134 lines (120 loc) · 4.89 KB
/
sales_bot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const solanaWeb3 = require('@solana/web3.js');
const { Connection, programs } = require('@metaplex/js');
const axios = require('axios');
if (!process.env.PROJECT_ADDRESS || !process.env.DISCORD_URL) {
console.log("please set your environment variables!");
return;
}
const projectPubKey = new solanaWeb3.PublicKey(process.env.PROJECT_ADDRESS);
const url = solanaWeb3.clusterApiUrl('mainnet-beta');
const solanaConnection = new solanaWeb3.Connection(url, 'confirmed');
const metaplexConnection = new Connection('mainnet-beta');
const { metadata: { Metadata } } = programs;
const pollingInterval = 2000; // ms
const marketplaceMap = {
"MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8": "Magic Eden",
"HZaWndaNWHFDd9Dhk5pqUUtsmoBCqzb1MLu3NAh1VX6B": "Alpha Art",
"617jbWo616ggkDxvW1Le8pV38XLbVSyWY8ae6QUmGBAU": "Solsea",
"CJsLwbP1iu5DuUikHEJnLfANgKy6stB2uFgvBBHoyxwz": "Solanart",
"A7p8451ktDCHq5yYaHczeLMYsjRsAkzc3hCXcSrwYHU7": "Digital Eyes",
"AmK5g2XcyptVLCFESBCJqoSfwV3znGoVYQnqEnaAZKWn": "Exchange Art",
};
const runSalesBot = async () => {
console.log("starting sales bot...");
let signatures;
let lastKnownSignature;
const options = {};
while (true) {
try {
signatures = await solanaConnection.getSignaturesForAddress(projectPubKey, options);
if (!signatures.length) {
console.log("polling...")
await timer(pollingInterval);
continue;
}
} catch (err) {
console.log("error fetching signatures: ", err);
continue;
}
for (let i = signatures.length - 1; i >= 0; i--) {
try {
let { signature } = signatures[i];
const txn = await solanaConnection.getTransaction(signature);
if (txn.meta && txn.meta.err != null) { continue; }
const dateString = new Date(txn.blockTime * 1000).toLocaleString();
const price = Math.abs((txn.meta.preBalances[0] - txn.meta.postBalances[0])) / solanaWeb3.LAMPORTS_PER_SOL;
const accounts = txn.transaction.message.accountKeys;
const marketplaceAccount = accounts[accounts.length - 1].toString();
if (marketplaceMap[marketplaceAccount]) {
const metadata = await getMetadata(txn.meta.postTokenBalances[0].mint);
if (!metadata) {
console.log("couldn't get metadata");
continue;
}
printSalesInfo(dateString, price, signature, metadata.name, marketplaceMap[marketplaceAccount], metadata.image);
await postSaleToDiscord(metadata.name, price, dateString, signature, metadata.image)
} else {
console.log("not a supported marketplace sale");
}
} catch (err) {
console.log("error while going through signatures: ", err);
continue;
}
}
lastKnownSignature = signatures[0].signature;
if (lastKnownSignature) {
options.until = lastKnownSignature;
}
}
}
runSalesBot();
const printSalesInfo = (date, price, signature, title, marketplace, imageURL) => {
console.log("-------------------------------------------")
console.log(`Sale at ${date} ---> ${price} SOL`)
console.log("Signature: ", signature)
console.log("Name: ", title)
console.log("Image: ", imageURL)
console.log("Marketplace: ", marketplace)
}
const timer = ms => new Promise(res => setTimeout(res, ms))
const getMetadata = async (tokenPubKey) => {
try {
const addr = await Metadata.getPDA(tokenPubKey)
const resp = await Metadata.load(metaplexConnection, addr);
const { data } = await axios.get(resp.data.data.uri);
return data;
} catch (error) {
console.log("error fetching metadata: ", error)
}
}
const postSaleToDiscord = (title, price, date, signature, imageURL) => {
axios.post(process.env.DISCORD_URL,
{
"embeds": [
{
"title": `SALE`,
"description": `${title}`,
"fields": [
{
"name": "Price",
"value": `${price} SOL`,
"inline": true
},
{
"name": "Date",
"value": `${date}`,
"inline": true
},
{
"name": "Explorer",
"value": `https://explorer.solana.com/tx/${signature}`
}
],
"image": {
"url": `${imageURL}`,
}
}
]
}
)
}