굳헬로의 스팀 프로그램 일기!! 다섯번째 #5 스팀엔진 블록을 뒤져서 원하는 정보를 찾아보자!! 스팀엔진 마켓 거래 내역을 뽑아내는 예제

in sct •  last year  (Edited)

steem.jpg

안녕하세요. 굳헬로 @goodhello 입니다.

주말 잘 보내셨나요??

이제까지 파이썬 프로그램을 이용하여 steemengine 파이썬 api 설치하고 이를 이용한 몇가지 예제들을 살펴보았는데요.

steemengine.api.get_latest_block_info() 를 이용하여 제일 최근의 블록 정보를 가지고 올 수 있었고

steemengine.api.get_block_info()를 통해 원하는 블록의 정보를 가져올 수 있었습니다.

그리고 steemengine.api.find() 혹은 steemengine.api.findOne() 를 통해서는 토큰의 정보를 가져올수 있었구요

steemengine.api.get_history() 를 통해서는 특정 계정의 토큰 내역등을 살펴볼 수 있었습니다.

이러한 기능들을 바탕으로 오늘은 재미있는 예제를 하나 살펴보도록 하겠습니다.


steemengine 에 대하여 공부하다보니 예전에 재미난 일이 있었더라구요.

누군가 스팀엔진에 짝퉁 비트코인 BTC를 만들어서 팔았는데... 재미로 그랬다는데.... 그걸 산 사람들이 있고...

그게 문제가 되서 BTC 를 모두 소각하고 그걸 샀던 사람들에게 환불을 해주려고 하는데... 누가 샀는지 그걸 다 모른다는게 문제 였던 거죠.

scammer alert!! 666 - @fake.toshi - selling fake BTC coins !!!111

위의 글에서 확인할 수 있습니다.

그리고 그 방법을 @holger80 님께서 올렸더군요.

Scan all steem-engine blocks for specific data

제목 그대로 모든 스팀엔진 블록을 스캔해서 원하는 자료를 찾는것입니다.

오늘은 그 소스를 살펴보도록 하겠습니다.

import time
import logging
import json
from steemengine.api import Api
from beem.block import Block
log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)


if __name__ == "__main__":
    api = Api()
    latest_block = api.get_latest_block_info()

    scan_token = ['BTC']
    print("Scanning all blocks from 0 to %d..." % latest_block['blockNumber'])
    steemp_payments = []
    
    for block_num in range(latest_block['blockNumber']):
        block = api.get_block_info(block_num)
        if block_num % 1000 == 0:
            print("%.2f %%" % (block["blockNumber"]/latest_block['blockNumber'] * 100))
        for trx in block["transactions"]:
            
            if trx["contract"] not in ['market']:
                continue
            if trx["action"] not in ['buy', 'sell']:
                continue

            
            logs = json.loads(trx["logs"])
            sender = trx["sender"]
            payload = json.loads(trx["payload"])
            contract = trx["contract"]
            action = trx["action"]            
            
            if action == "sell":
                if "events" not in logs:
                    continue
                elif len(logs["events"]) == 1:
                    continue
                else:
                    token_found = False
                    for transfer in logs["events"]:
                        if transfer["data"]["symbol"] in scan_token:
                            token_found = True
                    if token_found:
                        steem_block = Block(block["refSteemBlockNumber"])
                        print("%d (%s) - %s:" % (block["blockNumber"], steem_block.json()["timestamp"], trx['transactionId']))
                        print("%s sold %s %s for %s" % (trx["sender"], payload["quantity"], payload["symbol"], payload["price"]))
                        for transfer in logs["events"]:
                            print("    - %s transfers %s %s to %s" % (transfer["data"]["from"], transfer["data"]["quantity"], transfer["data"]["symbol"], transfer["data"]["to"]))                    
                                
            elif action == "buy":
                if "events" not in logs:
                    continue
                elif len(logs["events"]) == 1:
                    continue
                else:
                    token_found = False
                    for transfer in logs["events"]:
                        if transfer["data"]["symbol"] in scan_token:
                            token_found = True
                    if token_found:
                        steem_block = Block(block["refSteemBlockNumber"])
                        print("%d (%s) - %s" % (block["blockNumber"], steem_block.json()["timestamp"], trx['transactionId']))
                        print("%s bought %s %s for %s" % (trx["sender"], payload["quantity"], payload["symbol"], payload["price"]))
                        for transfer in logs["events"]:
                            print("    - %s transfers %s %s to %s" % (transfer["data"]["from"], transfer["data"]["quantity"], transfer["data"]["symbol"], transfer["data"]["to"]))

소스가 조금 길죠.

조금씩 조금씩 떼어내서 필요한 부분을 살펴보도록 하겠습니다.

api = Api()
latest_block = api.get_latest_block_info()

print("Scanning all blocks from 0 to %d..." % latest_block['blockNumber'])

가장 먼저 살펴 볼 부분은 최근의 블록 정보를 가져오는 api.get_latest_block_info() 입니다.

최근의 블록 정보를 latest_block에 담겠다는 말입니다.

최근의 블록 넘버는 latest_block['blockNumber'] 를 통해 확인할 수 있습니다.

이 부분은 한마디로 0부터 최근의 블록까지 모두 스캔하겠다고 화면에 출력해 주는 구문입니다.

Scanning all blocks from 0 to 792957...

이 부분은 실제 이렇게 출력된답니다.

0부터 현재 블록인 792957까지 모든 블록을 스캔하겠다는것을 알려주네요.

for block_num in range(latest_block['blockNumber']):
        block = api.get_block_info(block_num)
        if block_num % 1000 == 0:
            print("%.2f %%" % (block["blockNumber"]/latest_block['blockNumber'] * 100))

다음으로 나오는 for 문은 작업을 반복할때 사용하는 명령어인데 첫블록부터 최신의 블록까지 하나 하나 작업을 하겠다는 구문입니다.

그리고 앞전에 배운 블록 정보를 가져올 수 있는 steemengine.api.get_block_info() 구문이 사용해 for 문이 반복되는동안 첫번째 블록부터 최신의 블록까지 하나씩 블록의 정보를 block 저장해서 사용하겠다는 말입니다.

그리고 그 아래 if 문은 조건문으로 작업의 진행율을 보여주기 위해 추가된 구문입니다.

간단히 설명하자면 1000개의 블록을 작업 할때마다 현재 진행율을 출력해 줍니다.

이런식으로 출력되는데, 실제로 블록을 하나씩 하나씩 검사하는 작업에 시간이 많이 걸리더라구요. 대략 0.1% 진행하는데 3-4분은 더 걸린것 같네요.

이렇게 긴 작업을 하는데 진행율을 표시해 주지 않으면, 화면에 아무것도 안나오면 이상한 생각(뻗었는지, 죽었는지)이 들지도 모르니 이렇게 작업중이라고 알려주는건 좋은 생각 같습니다.

 for trx in block["transactions"]:
     if trx["contract"] not in ['market']:
            continue
    if trx["action"] not in ['buy', 'sell']:
            continue

    logs = json.loads(trx["logs"])
    sender = trx["sender"]
    payload = json.loads(trx["payload"])
    contract = trx["contract"]
    action = trx["action"]           

다음으로 다시 또 for 반복문과 if 조건문이 등장하였네요.

이 부분은 트랜젝션을 하나 하나 검사하여 contract 정보가 market이고, action 정보가 buy 혹은 sell 인것만 찾겠다는 구문입니다.

BTC의 거래 정보를 찾는 코드이기에 마켓에서 BTC를 사고 파는 정보외에는 다 필요가 없는거겠지요.

그래서 필요한 정보( contract 정보가 market이고, action 정보가 buy 혹은 sell)를 찾게 되면, sender, payload, contract, action 정보를 저장합니다.

if action == "sell":
    if "events" not in logs:
        continue
    elif len(logs["events"]) == 1:
        continue
    else:
        token_found = False
        for transfer in logs["events"]:
            if transfer["data"]["symbol"] in scan_token:
                token_found = True
            if token_found:
                steem_block = Block(block["refSteemBlockNumber"])
                print("%d (%s) - %s:" % (block["blockNumber"], steem_block.json()["timestamp"], trx['transactionId']))
                print("%s sold %s %s for %s" % (trx["sender"], payload["quantity"], payload["symbol"], payload["price"]))
                for transfer in logs["events"]:
                    print("    - %s transfers %s %s to %s" % (transfer["data"]["from"], transfer["data"]["quantity"], transfer["data"]["symbol"], transfer["data"]["to"])) 

elif action == "buy":
    if "events" not in logs:
        continue
    elif len(logs["events"]) == 1:
        continue
    else:
        token_found = False
        for transfer in logs["events"]:
            if transfer["data"]["symbol"] in scan_token:
                token_found = True
            if token_found:
                steem_block = Block(block["refSteemBlockNumber"])
                print("%d (%s) - %s" % (block["blockNumber"], steem_block.json()["timestamp"], trx['transactionId']))
                print("%s bought %s %s for %s" % (trx["sender"], payload["quantity"], payload["symbol"], payload["price"]))
                for transfer in logs["events"]:
                    print("    - %s transfers %s %s to %s" % (transfer["data"]["from"], transfer["data"]["quantity"], transfer["data"]["symbol"], transfer["data"]["to"]))

그래서 이제 뽑아온 action 정보가 sell 이냐 'buy' 냐에 따라 그 때 일어났던 처리 결과를 출력해 줍니다.

원래 코드에서는 scan_token = ['BTC'] BTC 토큰을 스캔하는 코드였는데, 하도 한참전에 일어났던 일이라 작업결과를 확인하는데 너무 오래 걸리더라구요.

그래서 제가 이코드를 scan_token = ['SCT'] 이렇게 수정하여 SCT 거래 내역을 찾앙오도록 만들고 그 결과를 출력해 보았습니다.

그리고 처음 블록부터 검색하면 너무 오래 걸리기에 최신의 블록부터 역순으로 검색을 해보았네요.

그 결과 최근 블록에서 다음 2개의 거래 내역을 찾을수 있었습니다.

스팀엔진의 SCT 거래 내역입니다.

스팀엔진상에는 언제 얼마에 얼마만큼의 거래가 있었는지 보여주지만, 블록을 뒤져보면 누가 누구에게 팔았는지 다 확인이 가능해 지는군요.

이 코드를 활용하면 스팀엔진상에서 토큰들 거래 내역을 다 뽑아낼수 있겠네요.


오늘의 예제 유용하셨나요??

딱히 필요는 없지만, 공부하기에 정말 유용했던 예제 였던것 같습니다.

앞으로 더욱 재미있어질 것 같네요.

그럼 다음 시간에는 또 다른 재미난 예제로 돌아 올테니, 궁금한 점 있으면 질문도 해주시구요. 복습도 해보시길 바래요~

행복한 하루 되세요.


굳헬로의 스팀 프로그램 일기!! 시리즈

#1 굳헬로의 스팀 프로그램 일기!! 대망의 시작 #1 Python 프로그램 설치 && steemengine 파이썬 api 설치 && 간단한 steemengine 예제

#2 굳헬로의 스팀 프로그램 일기!! 그 두번째 #2 비주얼 스튜디오 코드 프로그램 설치 && 비주얼 스튜디오 코드를 사용하여 파이썬 다루기 && 간단한 steemengine 예제

#3 굳헬로의 스팀 프로그램 일기!! 세번째 #3 스팀엔진 토큰의 정보를 가져오는 findOne() && 누군가의 토큰 사용 내역을 가져오는 get_history() && JSON 데이터 출력

#4 굳헬로의 스팀 프로그램 일기!! 네번째 #4 steemengine Token 클래스 && Token.get_holder() && Token.get_market_info() && Token.get_buy_book() && Token.get_sell_book()

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

gfriend96님이 goodhello님을 멘션하셨습니당. 아래 링크를 누르시면 연결되용~ ^^
gfriend96님의 [Steemmonsters] Tounament STEEM prize Rank - 2019.07.22 11:00 KST(GMT+9)

...le="text-align:right">170 goodhello/td> 21 <td style="text-al...

굿굿!! 스팀엔진에 기록되어 있는 모든 정보를 볼 수 있겠군요.

네~ 그런데.. 전부 열람하려니... 시간이 엄청 걸리더라는.. 다른 방법을 생각하고 있어요.

그래서 원사마님은 블록체인 정보를 하드에 저장한다고 하네요

Posted using Partiko Android

네.. 어제 대화했었어요.

전 디비에 다 넣으려고 하다가 원사마님과 얘기 했더니 파일로 저장하신다고 하시더라구요...

전 디비가 편해서 디비를 이용해볼까 합니다.

Thank you for your continued support towards JJM. For each 1000 JJM you are holding, you can get an additional 1% of upvote. 10,000JJM would give you a 11% daily voting from the 700K SP virus707 account.

열심히 하셔서 빨리 숙제 해결하시길...

ㅎㅎㅎ 숙제부터 해야겠군요~

오~~ 요즘 부쩍 굳헬로님이 다르게 보입니다!!!! ㅋㅋ 매일보던 뽀로로 매트를 못보니 괜시리 아쉽군요..

ㅎㅎㅎㅎㅎ 알코올 일기도 쓰고 싶은데... 2가지를 하려니 쉽지 않네요..

하나만 열심히 하려구요.

그래도 알코올은 매일 매일 만나고 있답니다~

Hi @goodhello!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your UA account score is currently 3.940 which ranks you at #4278 across all Steem accounts.
Your rank has improved 9 places in the last three days (old rank 4287).

In our last Algorithmic Curation Round, consisting of 149 contributions, your post is ranked at #48.

Evaluation of your UA score:
  • You're on the right track, try to gather more followers.
  • The readers like your work!
  • Good user engagement!

Feel free to join our @steem-ua Discord server

union.sct님이 goodhello님을 멘션하셨습니당. 아래 링크를 누르시면 연결되용~ ^^
union.sct님의 [공지] R토큰 에어드랍 배분을 위한 임대량 확인 요청

...ediatrics, buchheim, isi3.sct, naha, matildah2, happyberrysboy, chocolate1st, tradingideas, goodhello hyokhyok, lovelyyeon.sct