SCT ๋ฆฌ์น๋ฆฌ์คํธ
https://coin-on.com/rich
์ด๋ป๊ฒ ๋ง๋ค์๋ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํ๋ ํฌ์คํ ์ ๋๋ค.
์ฐ๋ฆฌ ๊ฐ๋ฐ์๋ค์ด ๋ง์ฝ Facebook API ๋ Twitter API ๋ฅผ ์ด์ฉํด์ ๋ญ ๋ง๋ค๋ ค๋ฉด ์ฝ์ต๋๋ค. Documentation ๋ ์๋ ์๋ผ์๊ณ ๋งํ๋๋ฉด ๊ตฌ๊ธ๋ง์ผ๋ก stackoverflow.com ์ ๋ต๋ณ์ ์ฐพ์๋ณด๋ฉด ๋ค ๋์ต๋๋ค.
๊ทธ๋ฐ์์ผ๋ก ๋ธ๋ก์ฒด์ธ ๊ด๋ จ ๊ฐ๋ฐ์
๊ณ์ ์์ ๋ญ ํด๋ณด๋ ค๊ณ ํ๋ฉด ๋ถ์กฑํ ๊ฐ๋ฐ๋ฌธ์์ ๊ฑฐ์ ์๋ค์ํผ ํ stackoverflow ๊ฒ์๊ฒฐ๊ณผ ๋๋ฌธ์ ๋๊ฐํด์ง๋๋ฐ์.
๋ธ๋ก์ฒด์ธ ๊ฐ๋ฐํ์๊ฒ ์์ด์ 3rd party ๊ฐ๋ฐ์๋ค์ ์ํ ๊ฐ๋ฐ๋ฌธ์ ์์ฑ์ด๋ ์ฐ์ ์์๊ฐ ํ์ฐธ ํ์์๊ณ ๋ค๋ฅธ ์ค์ํ ํ ์ผ์ด ๋ง๊ธฐ๋๋ฌธ์ ์ด๋ฐ๋ฅ์ ์ด์ฉ์์๋ ํ์ค์
๋๋ค.
์คํ์์ง์ธก์์ ์ ๊ณตํ๋ ๊ฐ๋ฐ์ ๋ฌธ์์ API ์คํ๊ฐ์๊ฒ ์๋์ง, ์ด๋์๋์ง, ์ผ๋งํผ ์ ๋ผ์๋์ง ์ง๊ธ ์ด ๊ธ์ ์ฐ๋ ์๊ฐ์๋ ์ ๋ชจ๋ฅด๊ฒ ์ผ๋
์ผ๋จ https://steem-engine.com/?p=balances&a=morning ์ฌ๊ธฐ ์ง๊ฐ์ ๊ฐ๋ณด๋ฉด ๋ฆฌ์น๋ฆฌ์คํธ๋ฅผ ๋ง๋๋๋ฐ ํ์ํ ๋ฐ์ดํฐ๊ฐ ์ ๋์์ฃผ๊ณ ์์ด์
account ๋ฅผ ์ ๋ ฅํ๋ฉด stake ์ balance ๊ฐ ๋์์ค๋ค
์ฌ๊ธฐ์ ์ฌ์ฉ๋ API call ์ ๋๊ฐ์ด ๊ฐ์ ธ๋ค ์ฐ๋ฉด ๋๊ฒ ์ฃ
ํฌ๋กฌ์์ F12 ๋๋ฌ์ Developer Tools ๋ค์ด๊ฐ์ Network ํญ, XHR ๋ก ํํฐ๋ง ํด๋๊ณ F5 ์๋ก๊ณ ์นจ.
์ํ๋๊ฑธ ์ฐพ์์ต๋๋ค. JSON Response ์์ balance ์ stake ๊ฐ ๋์ค๋๊ตฐ์
์ต์ํ ์ธ์ด Node.js์ ๊ฐ๋จํ ๋ฐ์ดํฐ๋ฒ ์ด์ค NeDB ๋ฅผ ์ด์ฉํด์ ์ต๋ํ ๋นจ๋ฆฌ ๊ฒฐ๊ณผ๋ฌผ์ ๋ด๋๊ธฐ๋ก ํ๊ณ ๋ง๋ค์์ต๋๋ค.
๋ ๋ถ๋ถ์ผ๋ก ๋๋ฉ๋๋ค.
์ฒซ๋ฒ์งธ๋ ์์์ ์ฐพ์๋ธ API ๋ฅผ ๋์์์ด ํธ์ถํด์ ์ต์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ๋ค๊ฐ DB์๋ค๊ฐ ์ ์ฅ์ํค๋ ์ฝ๋.
๋๋ฒ์งธ๋ ์์์ ์ ์ฅ๋ DB๋ฅผ ์ฝ์ด๋ค๊ฐ ์นํ์ด์ง์ ๋ฟ๋ ค์ฃผ๋ ์ฝ๋.
(๋๋ฒ์งธ ๊ฑฐ๋ ์๋ ํ๋ฒํ๋ฏ๋ก ์ค๋ช
์ ์๋ตํฉ๋๋ค.)
ํด๋น request ์ ์ค๋ฅธํด๋ฆญํด์ cURL ํฌ๋งท์ผ๋ก ๋ณต์ฌํด์ ํ ์คํธ ์๋ํฐ์ ๋ถ์ฌ๋ฃ๊ณ
curl 'https://api.steem-engine.com/rpc/contracts'
-H 'Access-Control-Allow-Origin: *'
-H 'Accept: application/json, text/plain, */*'
-H 'Referer: https://steem-engine.com/?p=balances&a=morning'
-H 'Origin: https://steem-engine.com'
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
-H 'Content-Type: application/json'
--data-binary '{"jsonrpc":"2.0","id":12,"method":"find","params":{"contract":"tokens","table":"balances","query":{"account":"morning"},"limit":1000,"offset":0,"indexes":""}}'
--compressed
๊ทธ๋๋ก request (https://www.npmjs.com/package/request) ์ด์ฉํด์ ์ธ ์ ์๋๋ก ํด๋ณด๋ฉด ์๋์ฒ๋ผ ์์ฑํ๋ ๊ฐ์๊ฒฐ๊ณผ๊ฐ ๋์ต๋๋ค.
const options = {
method: 'POST',
url: 'https://api.steem-engine.com/rpc/contracts',
headers: {
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json, text/plain, */*',
'Referer': 'https://steem-engine.com/?p=balances&a=morning',
'Origin': 'https://steem-engine.com',
'User-Agent': 'request',
'Content-Type': 'application/json'
},
gzip: true,
json: true,
body: {
"jsonrpc":"2.0",
"id":10,
"method":"find",
"params":{
"contract":"tokens",
"table":"balances",
"query":{"account":"์คํ์์ด๋"},
"limit":1000,
"offset":0,
"indexes":""
}
}
};
request(options, function(err, res, body) {
console.log(body);
}
์ console.log(body) ์์ ํ์ธํ ๊ฒฐ๊ณผ๋ฅผ DB์ ์ ์ฅํ๋ ์ฝ๋
const Datastore = require('nedb');
const db = new Datastore({ filename: 'richlist.db', autoload: true, timestampData: true});
// ...
if (body.result.length > 0) {
var i = body.result.length;
while(i--) {
var b = body.result[i];
if (b.symbol == symbol) {
var doc = {
'account': account,
'balance': parseFloat(b.balance),
'stake': parseFloat(b.stake),
'stakeBalance': parseFloat(b.balance) + parseFloat(b.stake),
'delegatedStake': parseFloat(b.delegatedStake),
'receivedStake': parseFloat(b.receivedStake),
'pendingUnstake': parseFloat(b.pendingUnstake)
};
db.count({'account': account}, function (err, count) {
if (count) {
db.update({'account': account}, doc, {}, function(err, num) {
console.log('updated', num, doc);
});
} else {
db.insert(doc, function(err, newDoc) {
console.log('inserted', newDoc);
});
}
});
}
}
}
์์ ์ฝ๋๋ฅผ
const grabBalance = function(symbol, account, done) {
}
์ด๋ฐ ํจ์ ์์ ๋ฃ์ด๋๊ณ ๋ฐ๋ณต์ ์ผ๋ก ํธ์ถํฉ๋๋ค.
const async = require('async');
// ...
var accountPool = [{'account': 'morning'}, {'account': 'ned'}];
const start = function() {
async.eachSeries(accountPool, function(acc, callback) {
grabBalance('SCT', acc.account, function() {
setTimeout(function() {
callback();
}, 100); // ํน์ ๋ชจ๋ฅผ rate limit ๋ฌธ์ ๋ฅผ ํผํ๊ธฐ ์ํด ์ฝ๊ฐ์ ์๊ฐ์ฐจ๋ฅผ ๋ก๋๋ค.
});
}, function(err) {
setTimeout(function() {
start();
}, 60000); // accountPool ์ ๋ค ๋๋ฆฌ๊ณ ๋๋ฉด ์ข ์ฌ์๋ค๊ฐ ๋๋ฆฝ๋๋ค.
});
}
start();
์ด๋ฐ์์ผ๋ก ํ๋ฉด DB์ ์ ์์ด๊ฒ ์ฃ ?
DB์์ ๊ธ์ด๋ค๊ฐ ๋ฟ๋ ค์ฃผ๋ฉด ๋ฆฌ์น๋ฆฌ์คํธ ์์ฑ.
grabBalance ํ๋ผ๋ฏธํฐ๊ฐ์ 'SCT' ๋ง๊ณ ๋ค๋ฅธ๊ฑธ๋ก ํ๋ฉด ๋ค๋ฅธ ์คํ์์งํ ํฐ์๋ ์์ฉ ๊ฐ๋ฅ.