LoginSignup
8
2

More than 5 years have passed since last update.

Truffle: Contract.call()が返すのはPromiseなのでハマった

Last updated at Posted at 2018-01-02

はじめに

Truffleを使い始めたばかりでコントラクトをつくってる最中にハマりましたのでメモ。

結論

Contract.call()が返すのは<object Promise>です。truffle console上では文字列が返ってきてるように見えてるけど、Promiseです。

truffle version
Truffle v4.0.4 (core: 4.0.4)
Solidity v0.4.18 (solc-js)
json_string = JSON.stringify({"greet": "Hello World!", "value": 999})
'{"greet":"Hello World!","value":999}'
contract = SimpleJsonStorage.at(SimpleJsonStorage.address)
contract.setJsonString.sendTransaction(json_string, {from: web3.eth.accounts[0]})

正しい
contract.json.call().then(v=>{ const json = JSON.parse(v); console.log(json.greet); })
Hello World!
undefined

間違い
v = contract.json.call()
'{"greet":"Hello World!","value":999}'
JSON.parse(v)
SyntaxError: Unexpected token o in JSON at position 1
    at JSON.parse (<anonymous>)
    at evalmachine.<anonymous>:1:6
    at ContextifyScript.Script.runInContext (vm.js:53:29)
    at Object.runInContext (vm.js:108:6)
    at Console.interpret (/Users/user/.nodebrew/node/v8.0.0/lib/node_modules/truffle/build/cli.bundled.js:202629:17)
    at ReplManager.interpret (/Users/user/.nodebrew/node/v8.0.0/lib/node_modules/truffle/build/cli.bundled.js:203345:18)
    at bound (domain.js:301:14)
    at REPLServer.runBound [as eval] (domain.js:314:12)
    at REPLServer.onLine (repl.js:433:10)
    at emitOne (events.js:115:13)

はまった顛末

Introduction to Smart Contracts A Simple Smart Contract を参考に以下のようなコントラクトを作ってみた。

SimpleJsonStorage.sol
pragma solidity ^0.4.18;

contract SimpleJsonStorage {
  string public json;

  function sendJsonString(string _json) {
    bytes memory temp = bytes(_json);
    require(temp.length > 0);
    json = _json;
  }

}

コンパイルしてデプロイして、

json_string = JSON.stringify({"greet": "Hello World!", "value": 999})
contract = SimpleJsonStorage.at(SimpleJsonStorage.address)
contract.sendJsonString.sendTransaction(json_string, {from: web3.eth.accounts[0]})
'0x4923c16608454e4bc58c87d26cb9646e1ec9dd7dff561cf9a256ebdfd17c0388'

v = contract.json.call()
'{"greet":"Hello World!","value":999}'
JSON.parse(v)
SyntaxError: Unexpected token o in JSON at position 1
    at JSON.parse (<anonymous>)
    at evalmachine.<anonymous>:1:6
    at ContextifyScript.Script.runInContext (vm.js:53:29)
    at Object.runInContext (vm.js:108:6)
    at Console.interpret (/Users/user/.nodebrew/node/v8.0.0/lib/node_modules/truffle/build/cli.bundled.js:202629:17)
    at ReplManager.interpret (/Users/user/.nodebrew/node/v8.0.0/lib/node_modules/truffle/build/cli.bundled.js:203345:18)
    at bound (domain.js:301:14)
    at REPLServer.runBound [as eval] (domain.js:314:12)
    at REPLServer.onLine (repl.js:433:10)
    at emitOne (events.js:115:13)

...え?ってなった。

調べたこと

そもそも

v = contract.json.call()
'{"greet":"Hello World!","value":999}'

って感じであたかも文字列が返ってきてるかのようにtruffle consoleが出すので紛らわしい。
資料あさってもそれっぽいのヒットしないし、以下のようにして突き止めた。

typeof v
'object'

ん? object? Stringじゃねえの?
なんのObjectかわからない場合は、toString()でなんかわかることもある。

v.toString()
'[object Promise]'

Promiseかよ!

contract.json.call().then(v=>{ const json = JSON.parse(v); console.log(json.greet); })
Hello World!
undefined

できたよ。。

まとめ

詳しく見てないんだけど、たぶんTruffleはweb3jsをラップしてるんじゃないかと思うのでこのあたりがヒントになったのかもしれない。あとで考えてみれば。

コンソールは親切にコールバックの結果を表示してくれるんだろう。親切なんだけど覚えておかないとまたハマりそうw

8
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2