モザイクガチャ　（nemlog版）の仕組みについて

NEMというブロックチ-ェンを使ったblogサービスであるnemlogサービスで公開している　”モザイクガチャ”　の仕組みについて説明します
モザイクというのはNEM上で作成することができるトークンです
モザイクについてはぜひこちらのページを御覧ください
https://www.cryptostream.jp/nem-namespace-mosaic-3551/
NEMのネームスペースとモザイクって何なのか？（トレストさん著）

仕様

サービス利用者　　モザイクガチャを使ってモザイクを配りたいひと

サービス提供者　　モザイクガチャを提供する側

サービス利用者はイベント用にアドレスを作ってそこにモザイクを送付してもらう
ガチャアドレスとする

動作条件   Raspbian　を　ラズパイ３B+で動かしています
　　　　　　python3.7でプログラムを実行　
　　　　　　定期的にcronで繰り返し

ラズパイを使う理由
　　　　　　低コストで導入でき低コストで運用できる
　　　　　　将来的に複数動かしても負担はそれほどない
　　　　　　sshでCUIで動くのが好き

 

サービス提供はガチャアドレスのトランザクションをチェックしてモザイクを送ってくれたアドレスに自動で用意されてあるモザイク、あるいはモザイクのセットを送り返す
　
現在はNIS１でのサービス提供
カタパルトがでればnem2-cliをpython3から呼び出して引数を与えて使う予定
(これはまだプログラムできていない)

NIS1のプログラムの概要を描いてみたいと思います
python3ですが抜粋してるのでimportとか飛ばしてます
さらにインデントもきっちりできてないです


#パターン１　
（投げnemを受けるアドレスとモザイクを返送するのは同じアドレス）

#outgoingからtenplastidを作成する

        node  = random.choice(("http://alice2.nem.ninja:7890",\
       "http://alice3.nem.ninja:7890","http://alice4.nem.ninja:7890",\
       "http://alice5.nem.ninja:7890","http://alice6.nem.ninja:7890",\
       "http://alice7.nem.ninja:7890"));

        api = '/account/transfers/outgoing'
        parameter = 'address=投げ返すアドレス'
        url = str(node + api + '?' + parameter)
        ro = requests.get(url).json()
        
        for n in  range(0,1):
        	print(n)
		print('id:{}'.format(dataout[n]['meta']['id']))
                templastid = ('{}'.format(dataout[0]['meta']['id']))
		print(templastid)


#indomingから送られてきたトランザクションの履歴をみる

##node = 上と同じようにランダムで選ぶ

        api = '/account/transfers/incoming'
        parameter = 'address=投げ返すアドレス' 

        url = str(node + api + '?' + parameter )
        ri = requests.get(url).json()


#そのままtemplastidのデータ保持で次の処理へ
idによる振り分け 前回のIDより小さい場合は次へ
１回では２５件の検査になるので足りなけれなdata2[0]を引数にしてincomingを取る（未対応）
#
        max = len(ri)
        for n in range(0,max):
             time.sleep(3)
             print(n)
             print('id:{}'.format(data2[n]['meta']['id']))
             if '{}'.format(data2[n]['meta']['id']) > templastid:
                  print('there is new data!')
                  print('id:{}'.format(data2[n]['meta']['id']) + /
                  '  p-key:{}'.format(data2[n]['transaction']['signer']))

#p-keyからアドレスを引く　
       node  = random.choice(("http://alice2.nem.ninja:7890",\
       "http://alice3.nem.ninja:7890","http://alice4.nem.ninja:7890",\
       "http://alice5.nem.ninja:7890","http://alice6.nem.ninja:7890",\
       "http://alice7.nem.ninja:7890"));
                  api = '/account/get/from-public-key?'
                  pkey = ('{}'.format(data2[n]['transaction']['signer']))
		　url = str(node + api + 'publicKey=' + pkey)
                  q = requests.get(url).json()
                  print('address: {}'.format(q['account']['address']))
		　adddata = ("{}".format(q['account']['address']))

#トランザクション用のデータを作成するルーチン（関数）を呼んで終了
			mkdata-fromjson  
     
これでガチャをしているアドレスにモザイクを送ってもらってモザイクを送り返す説明は終了です


#パターン２　
          
投げNEMはモザイクを配りたい人が作成して秘密鍵など保守してるアドレスA
モザイクはガチャ専用アドレスBに送ってもらってそこから返送
ガチャ返送アドレスBの管理は私がしています（秘密鍵を持っている）
##私はアドレスAに関しては何の権限も持っていません
この前提で作ったプログラムです

#outgoingからtemplastidを作成する
        node  = random.choice(("http://alice2.nem.ninja:7890",\
       "http://alice3.nem.ninja:7890","http://alice4.nem.ninja:7890",\
       "http://alice5.nem.ninja:7890","http://alice6.nem.ninja:7890",\
       "http://alice7.nem.ninja:7890")); 
        api = '/account/transfers/outgoing'
        parameter = 'address=モザイクを預かって送り返すためのアドレスB'
        url = str(node + api + '?' + parameter)
        ro = requests.get(url).json()

        for n in  range(0,1):
        	print(n)
		print('id:{}'.format(dataout[n]['meta']['id']))
                templastid = ('{}'.format(dataout[0]['meta']['id']))
		print(templastid)



#indomingからトランザクションの履歴をみる
        node  = random.choice(("http://alice2.nem.ninja:7890",\
       "http://alice3.nem.ninja:7890","http://alice4.nem.ninja:7890",\
       "http://alice5.nem.ninja:7890","http://alice6.nem.ninja:7890",\
       "http://alice7.nem.ninja:7890"));
        api = '/account/transfers/incoming'
        parameter = 'address=モザイクを投票してもらうアドレスA' 

        url = str(node + api + '?' + parameter )
        ri = requests.get(url).json()


#そのままtemplastidのデータ保持で次の工程へ
あとはパターン１と同じ処理になります

#パターン１と２で違うところ
モザイク配りたい人にモザイク返送サービスを提供
まったく別のアドレスでサービスの提供をします




#パターン3
##追加機能
同じネームスペースにmosaicが６つあります
上記のようにもざいくを投げる場合毎回同じではおもしろくないしガチャになっていません
そのため所持しているモザイクのうちどれかを投げるにはポストするデータのモザイクを記載してる部分を乱数でかき分けてやりますそのためのルーチンです

#普通の記載
```
 "mosaics":[
            {
                "mosaicId":{
                    "namespaceId": "kishuu",
                    "name": "mikan"   
                },
                "quantity": 10
            }


```
#乱数で置き換える場合
```
mosaicr = random.choice(("ume","mikon","jidori","55mangoku","kishuuinu","odori"))
print(mosaicr)


param=.
      .
      .


"mosaics":[
            {
                "mosaicId":{
                    "namespaceId": "kishuu",
                    "name": mosaicr   
                },
                "quantity": 10
            }

```
#おまけ　
モザイクの状況を知りたい場合　知りたいアドレスを入れて実行してみてください

この結果を加工すると、いろいろモザイクを持っている状態で相手に対するアクションを変えることができます

```
import json
import requests

node  = random.choice(("http://alice2.nem.ninja:7890",\
"http://alice3.nem.ninja:7890","http://alice4.nem.ninja:7890",\
"http://alice5.nem.ninja:7890","http://alice6.nem.ninja:7890",\
"http://alice7.nem.ninja:7890"));
api = '/account/mosaic/owned'
parameter = 'address=知りたいアドレス' 
url = str(node + api + '?' + parameter )

print(url)
r = requests.get(url).json()
print(json.dumps(r,indent=4))

p = r['data']

print(json.dumps(p,indent=4)) 

max = len(p)

print('max =',max)

for n in range(0,max):
        mosaic_data = 'mosaicid:{}'.format(p[n]['mosaicId']['namespaceId'])
        mosaic_name = 'mosaicid:{}'.format(p[n]['mosaicId']['name'])
        number = 'number:{}'.format(p[n]['quantity'])
        print('no.',n)
        print('mosaic_data',mosaic_data)
        print('mosaic_name',mosaic_name)
        print('number',number)

```
参考URL
https://i-yusuke.com/entry/nem-nis-api-document-japanese/#3111


#イベントをやってみて感じた問題点

もともとはずっとパターン１で自分のnemlog記事に自動返信していました。

問題点１　nemlogで自動返送すると投げnemできない
　　　　　投げるとその時点でoutgoingにデータが入るのでそれまで投げてくれていても
　　　　　投げたことになってしまう。

　　　　　それほど投げられる頻度はなかったので返送から投げられる前（朝早く）などに
　　　　　投げると大丈夫
　　　　　他人にはおすすめできるシステムではないですね

問題点２　パターン２で提供したつもりが動かす時にバタバタしていてパターン１で判定してました
　　　　　パターン２にしてからは問題なく動いてます
　　　　　幾つかメンテ用のチェックポイントを作ったけどもう少しメンテしやすくしないと

問題点３　自分はたくさん投げるつもりですが、モザイクが少数の場合、最新のものから順に
　　　　　投げるので、先に投げたのにもらえなかったという場合が出てきそう
　　　　　これはある程度モザイクの数を確保しておいて個別対応が必要かも
　　　　　古い順に投げるロジックを考えたほうがいいかも
　　　　　今回のイベントではピークで１時間３つぐらいだったので逆転は起きませんでした

以上読みにくい文章、プログラムですみません。
とりあえずNIS1のincomingとoutgoingを組み合わせるだけでも面白いことができるかも
最後まで読んでいただいてありがとうございます。

最後まで読んでいただいてありがとうございました。
https://nemlog.nem.social/blog/34210