EOS.IO Programming Notes: How to create the HelloWorld contractsteemCreated with Sketch.

in #eos6 years ago (edited)

$ My EOS.IO programming notes for 2/27/2018

by: Gunnar Pope

Please upvote @powderskier on Steemit to support!

Or Donate!

BTC: 35fLcnnsUFDRp4fW3d7GLBTdEtyGR8SY7g

LTC: MC85Gqxaj5sBxKSui54VbKTypUie4Rrng

Ok, let's get started

$ cd ~/eos/build/programs/eos-walletd && ./eos-walletd

Open a new terminal, using Command+t. In the new terminal, open the public testnet

~$ cd eos/build/programs/eosc/
eosc$ ./eosc wallet open -n gptestnet
Opened: gptestnet
eosc$ ./eosc wallet list
Wallets:
[
  "gptestnet"
]
eosc$ eosc wallet unlock -n gptestnet
password: Unlocked: gptestnet
eosc$ eosc wallet list
Wallets:
[
  "gptestnet *"
]
eosc$ ./eosc -H testnet1.eos.io -p 80 get account powderskier
{
  "account_name": "powderskier",
  "eos_balance": "100.0000 EOS",
  "staked_balance": "0.0001 EOS",
  "unstaking_balance": "0.0000 EOS",
  "last_unstaking_time": "1969-12-31T23:59:59",
  "permissions": [{
      "perm_name": "active",
      "parent": "owner",
      "required_auth": {
        "threshold": 1,
        "keys": [{
            "key": "EOS7gUMtWH1TEW31v8rXCe6zYajqUo46qH22CQN6PX4nzMzJZkUhS",
            "weight": 1
          }
        ],
        "accounts": []
      }
    },{
      "perm_name": "owner",
      "parent": "",
      "required_auth": {
        "threshold": 1,
        "keys": [{
            "key": "EOS7gUMtWH1TEW31v8rXCe6zYajqUo46qH22CQN6PX4nzMzJZkUhS",
            "weight": 1
          }
        ],
        "accounts": []
      }
    }
  ]
}

Ok, we're in. Now let's learn how to make our own contract from scratch. Jump
into the contracts folder and use eoscpp to generate the template for a
new hello world contract (that is artificially intelligent :).

$ cd ~/eos/contracts
contracts$ ls
CMakeLists.txt      dice            identity        musl            skeleton        test.system     tic_tac_toe
asserter        eosio.system        infinite        noop            social          test_api
bancor          eosiolib        libc++          proxy           stltest         test_api_db
currency        exchange        multi_index_test    simpledb        storage         test_api_mem

Create a new contract named helloworld

contracts$ eoscpp -n helloworld
created helloworld from skeleton
contracts$ ls
CMakeLists.txt      dice            helloworld      multi_index_test    simpledb        storage         test_api_mem
asserter        eosio.system        identity        musl            skeleton        test.system     tic_tac_toe
bancor          eosiolib        infinite        noop            social          test_api
currency        exchange        libc++          proxy           stltest         test_api_db
contracts$ cd helloworld/
helloworld$ ls
helloworld.abi  helloworld.cpp  helloworld.hpp

So we now have .abi .cpp and .hpp templates for a simple helloworld app. (Thanks
eosio dev team!). Let's make our own print statement and try to upload this in
it's simplest state before building complexity on top of it. I always write programs
as a series of mini-test cases that start simple and build up in complexity. That
way, you always have a working example for your troubleshooting and not dozens
of returned errors.

Open the vim text editor. (Read about vim usage if unfamiliar).

helloworld$ vim helloworld.cpp

/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#include <helloworld.hpp>

/**
 *  The init() and apply() methods must have C calling convention so that the blockchain can lookup and
 *  call these methods.
 */
extern "C" {

    /**
     *  This method is called once when the contract is published or updated.
     */
    void init()  {
       eosio::print( "Init World!\n" );
    }

    /// The apply method implements the dispatch of events to this contract
    void apply( uint64_t code, uint64_t action ) {
       eosio::print( "Hello World: ", eosio::name(code), "->", eosio::name(action), "\n" );
    }

} // extern "C"

Type :wq to save changes and exit the vim editor.

Now, we must compile the .cpp file into a .wasm before uploading the contract
to the blockchain.

helloworld$ ls
helloworld.abi  helloworld.cpp  helloworld.hpp

helloworld$ eoscpp -o helloworld.wast helloworld.cpp
/usr/local/wasm/bin/clang -emit-llvm -O3 --std=c++14 --target=wasm32 -ffreestanding -nostdlib -fno-threadsafe-statics -fno-rtti -fno-exceptions -I /Users/winter/eos/build/install/include -I . -c helloworld.cpp -o /var/folders/8x/n9my8ww91_q304d3s0hdmdrh0000gq/T/tmp.eS0IfkMs/built/helloworld.cpp

helloworld$ ls
helloworld.abi  helloworld.cpp  helloworld.hpp  helloworld.wast

Cool! We have a helloworld.wast file that we can now set in the eos blockchain.

helloworld$ ./eosc -H testnet1.eos.io -p 80 set contract powderskier helloworld.wast
-bash: ./eosc: No such file or directory
helloworld$ eosc -H testnet1.eos.io -p 80 set contract powderskier helloworld.wast
-bash: ./eosc: No such file or directory

Looks like the terminal cannot find where the ./eosc script is located. Let's try to add that to our path and try again.

helloworld$ echo "export PATH=$PATH:eos/build/install/bin" >> ~/.bash_rc
helloworld$ source ~/.bash_rc
helloworld$ eosc -H testnet1.eos.io -p 80 set contract powderskier helloworld.wast
-bash: ./eosc: No such file or directory
helloworld$ ./eosc -H testnet1.eos.io -p 80 set contract powderskier helloworld.wast
-bash: ./eosc: No such file or directory

That's weird. Thought that would work. Well, I know that I can run the script
directly within the /build/programs/eosc/ folder so let's navagate there
and try to upload the contract again.

helloworld$ cd ..
contracts$ cd ..      
eos$ cd build/programs/eosc/

eosc$ ./eosc -H testnet1.eos.io -p 80 set contract powderskier ../../../contracts/helloworld/helloworld.wast
Reading WAST...
Assembling WASM...
Publishing contract...
{
  "transaction_id": "bac597c2494fa72743b12db864bfb888d63922544802c6a29903da431a077d34",
  "processed": {
    "ref_block_num": 7288,
    "ref_block_prefix": 3994800132,
    "expiration": "2018-02-27T15:18:04",
    "scope": [
      "eos",
      "powderskier"
    ],
    "signatures": [
      "2041f4c33c15f87fd4ae1dd43343243664bc998dff2c19d3f576df58e92856a321198bf3b435c3d76aec6d1063f08fa24e9320842cbf4170cdf0b68ad4cd87f6cd"
    ],
    "messages": [{
        "code": "eos",
        "type": "setcode",
        "authorization": [{
            "account": "powderskier",
            "permission": "active"
          }
        ],
        "data": {
          "account": "powderskier",
          "vm_type": 0,
          "vm_version": 0,
          "code": "0061736d0100000001110460017f0060017e0060000060027e7e00021b0203656e76067072696e746e000103656e76067072696e7473000003030202030404017000000503010001071903066d656d6f7279020004696e69740002056170706c7900030a20020600411010010b17004120100120001000413010012001100041c00010010b0b3f050041040b04504000000041100b0d496e697420576f726c64210a000041200b0e48656c6c6f20576f726c643a20000041300b032d3e000041c0000b020a000029046e616d6504067072696e746e0100067072696e7473010004696e697400056170706c790201300131",
          "code_abi": {
            "types": [],
            "structs": [],
            "actions": [],
            "tables": []
          }
        },
        "hex_data": "00ae72105f9538ad0000f1010061736d0100000001110460017f0060017e0060000060027e7e00021b0203656e76067072696e746e000103656e76067072696e7473000003030202030404017000000503010001071903066d656d6f7279020004696e69740002056170706c7900030a20020600411010010b17004120100120001000413010012001100041c00010010b0b3f050041040b04504000000041100b0d496e697420576f726c64210a000041200b0e48656c6c6f20576f726c643a20000041300b032d3e000041c0000b020a000029046e616d6504067072696e746e0100067072696e7473010004696e697400056170706c79020130013100000000"
      }
    ],
    "output": [{
        "notify": [],
        "deferred_trxs": []
      }
    ]
  }
}

Ok, looks like it got uploaded. Let's see if we generate the "Hello world" output.

eosc$ eosc push message powderskier hello '"abcd"' --scope powderskier
1885144ms            main.cpp:1128                 operator()           ] Converting argument to binary...
{
  "transaction_id": "ffd0af11f8f8087efc8b2ff7557e730e33eca32a688c5ee850967af3c214a021",
  "processed": {
    "ref_block_num": 7703,
    "ref_block_prefix": 3694985328,
    "expiration": "2018-02-27T15:31:54",
    "scope": [
      "powderskier"
    ],
    "signatures": [],
    "messages": [{
        "code": "powderskier",
        "type": "hello",
        "authorization": [],
        "data": ""
      }
    ],
    "output": [{
        "notify": [],
        "deferred_trxs": []
      }
    ]
  }
}

I don't know if that worked...
Maybe the 'hello' phrase is the message passed to the contract? Let's pass a new
message using the same function.

eosc$ eosc push message powderskier helloworlddoesthiswork? '"abcd"' --scope powderskier
2277295ms            main.cpp:1128                 operator()           ] Converting argument to binary...
2277561ms            main.cpp:1195                 main                 ] Failed with error: Assert Exception (10)
status_code == 200: Error code 500
: {"code":500,"message":"Internal Service Error","details":"10 assert_exception: Assert Exception\nlen <= 13: \n    {}\n      native.hpp:111 set\n\n    {\"str\":\"helloworlddoesthiswork?\"}\n      native.hpp:115 set"}

Nope, that didn't work. Maybe the "abcd" data is the message payload. Let's
change that and see if that modifies the "data": "" field.

eosc$ eosc push message powderskier hello '"datapayload"' --scope powderskier
2741187ms            main.cpp:1128                 operator()           ] Converting argument to binary...
{
  "transaction_id": "2fe23c69d6c30cdfd0a6bb5ef5a2da24ec070c44a1d1b141bb9a6ff72a0c3d60",
  "processed": {
    "ref_block_num": 8131,
    "ref_block_prefix": 1071053060,
    "expiration": "2018-02-27T15:46:10",
    "scope": [
      "powderskier"
    ],
    "signatures": [],
    "messages": [{
        "code": "powderskier",
        "type": "hello",
        "authorization": [],
        "data": ""
      }
    ],
    "output": [{
        "notify": [],
        "deferred_trxs": []
      }
    ]
  }
}

I'm not sure if this function is working because I don't see my "Hello World: " output. I'll try more tomorrow to figure out how to control the input->output messaging better.

I hope this helps!

-@powderskier

Coin Marketplace

STEEM 0.20
TRX 0.14
JST 0.030
BTC 66543.69
ETH 3327.31
USDT 1.00
SBD 2.71