実践ブロックチェーンゲーム/Blockchain Game in Practice

3383368c2bd31bbc7cc9c6043e335e09?s=47 Ryo Manzoku
December 17, 2018

実践ブロックチェーンゲーム/Blockchain Game in Practice

2018-12-17 blockchain.tokyo #15
https://blockchain-tokyo.connpass.com/event/110424/

3383368c2bd31bbc7cc9c6043e335e09?s=128

Ryo Manzoku

December 17, 2018
Tweet

Transcript

  1. 1.
  2. 3.

    ࣗݾ঺հ Name: Ryo Manzoku @rmanzoku Work: double jump.tokyo inc Job:

    Blockchain Engineer Sidework: 
 SRE / Cloud Infrastructure Language:
 Golang / Python
  3. 5.

    My Crypto Heroes֓ཁ My Crypto HeroesɺMCHɺϚΠΫϦ 2018-11-30 ਖ਼ࣜαʔϏε։࢝ EthereumΛར༻ͨ͠ϒϩοΫνΣʔϯήʔϜ ϫʔΧʔϓϨΠεϝϯτܕRPG

    Ξηοτ(ERC721)͸Ethereum mainnet ʹͯ؅ཧ ήʔϜϩδοΫ͸ΦϑνΣʔϯαʔόʹ࣮ͯߦ PCͰ΋εϚϗͰ΋ɺWallet͕ͳͯ͘΋༡΂Δ
  4. 17.
  5. 18.
  6. 25.

    Assetൃߦ্ݶ mapping(uint16 => uint16) private extensionTypeToSupplyLimit; function setSupplyLimit(uint16 _extensionType, uint16

    _supplyLimit) external onlyMinter { require(_supplyLimit != 0); require(extensionTypeToSupplyLimit[_extensionType] == 0 || _supplyLimit < extensionTypeToSupplyLimit[_extensionType], "_supplyLimit is bigger”); extensionTypeToSupplyLimit[_extensionType] = _supplyLimit; } function mintExtensionAsset(address _owner, uint256 _tokenId) public onlyMinter { uint16 _extensionType = uint16(_tokenId / EXTENSION_TYPE_OFFSET); uint16 _extensionTypeIndex = uint16(_tokenId % EXTENSION_TYPE_OFFSET) - 1; require(_extensionTypeIndex < extensionTypeToSupplyLimit[_extensionType], "supply over"); _mint(_owner, _tokenId); }
  7. 31.

    $ abigen --abi token.abi -pkg main -type Token -out token.go

    package main import ( "fmt" “log" “token” "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" ) func main() { // Create an IPC based RPC connection to a remote node conn, err := ethclient.Dial("/home/karalabe/.ethereum/testnet/geth.ipc") if err != nil { log.Fatalf("Failed to connect to the Ethereum client: %v", err) } // Instantiate the contract and display its name token, err := NewToken(common.HexToAddress("0x21e6fc92f93c8a1bb41e2be64b4e1f88a54d3576"), conn) if err != nil { log.Fatalf("Failed to instantiate a Token contract: %v", err) } name, err := token.Name(nil) if err != nil { log.Fatalf("Failed to retrieve token name: %v", err) } fmt.Println("Token name:", name) }
  8. 33.

    op, _ := crawler.GetCommandOptions() c, err := crawler.NewCrawler(op) c.FilterOpts.End, err

    = c.SafeBlockNum(3) contract, err := gum_gateway.NewGumGateway(c.Contract()) iter, err := contract.FilterSold(c.FilterOpts, nil, nil) grpcClient := gateway.NewGatewayServiceClient(c.GRPC) for iter.Next() { e := iter.Event if e.Raw.Removed { fmt.Printf("level:info\tmsg:%s removed block\n", e.Raw.TxHash.String()) continue } input := &gateway.PurchaseInfo{ EthPurchaser: e.User.String(), EthAffiliator: e.Referrer.String(), EthAmountGwei: crawler.ToGwei(e.Value).Uint64(), TxHash: e.Raw.TxHash.String(), } if !op.DryRun { _, err := grpcClient.GumSale(context.Background(), input) if err != nil { if strings.HasPrefix(err.Error(), "rpc error: code = Unknown desc = Error 1062: Duplicate entry") { fmt.Printf("level:debug\tmsg:%s already affected\n", e.Raw.TxHash.String()) continue } return err } } fmt.Printf("level:info\tmsg:%s is affected \n", e.Raw.TxHash.String()) }
  9. 39.

    ࣌ؒ༨ͬͨΒ஻Δωλ ࣮ࡍʹMainnetͰ΍Δͱ৭ʑπϥΠ OperatorRoleͷඞཁੑ CS໨ઢͰͷGas gRPC-webΛ࢖ͬͨSPAΞϓϦέʔγϣϯ ecrecover࢖ͬͨϩάΠϯػೳ Loom SDKΫϥελߏங Loom Go

    Plugin։ൃ αʔόʔϨε୹ॖURL੡଄ػ IPFS΁ͷը૾౤ߘػೳ ERC721 Metadataʹ͍ͭͯ ϒϩοΫνΣʔϯήʔϜΤίγεςϜʹ͍ͭͯͷ࢛ํࢁ࿩ ೔ຊʹ͓͚ΔNon Fungible Token αΠυνΣʔϯɺϦΞϧӡ༻ݶք