时间:2023-06-21 17:30:02 | 来源:网站运营
时间:2023-06-21 17:30:02 来源:网站运营
基于EOS生态的一元夺宝游戏开发:docker pull eosio/eosdocker run --name eosio / --publish 7777:7777 / --publish 127.0.0.1:5555:5555 / --volume /root/contracts:/root/contracts / --detach / eosio/eos / /bin/bash -c / "keosd --http-server-address=0.0.0.0:5555 & exec nodeos -e -p eosio --plugin eosio::producer_plugin --plugin eosio::history_plugin --plugin eosio::chain_api_plugin --plugin eosio::history_plugin --plugin eosio::history_api_plugin --plugin eosio::http_plugin -d /mnt/dev/data --config-dir /mnt/dev/config --http-server-address=0.0.0.0:7777 --access-control-allow-origin=* --contracts-console --http-validate-host=false --filter-on='*'"
智能合约编译环境(EOSIO-CPP)class duobao: public eosio::contract{public: duobao(account_name self) :contract(self), bets(_self, _self), winners(_self, _self) { } using contract::contract; static constexpr int64_t unit_count = 10; static constexpr int64_t min_count = 1 * unit_count; static constexpr int64_t max_count = 20 * unit_count; static constexpr float win_ratio = 0.9; uint64_t random_generate(uint64_t range) { checksum256 result; auto mixedBlock = tapos_block_prefix() * tapos_block_num(); const char *mixedChar = reinterpret_cast<const char *>(&mixedBlock); sha256( (char *)mixedChar, sizeof(mixedChar), &result); const char *p64 = reinterpret_cast<const char *>(&result); int64_t sum = 0; for(int i = 0; i<6; i++) { sum += (int64_t)p64[i]; } return (abs(sum) % (range)); } void buy(account_name from, account_name to, asset quantity, string memo) { if ((from == _self) || (to != _self)) { return; } eosio_assert(quantity.symbol == CORE_SYMBOL, "Must by paid by EOS"); eosio_assert(quantity.amount % min_count == 0, "Bet Must Be divided by 1 EOS"); eosio_assert(quantity.amount >= min_count, "Bet Must be greater than 1 EOS"); auto new_offer_itr = bets.emplace(_self, [&](auto& betting){ betting.id = bets.available_primary_key(); betting.bet = quantity; betting.owner = from; betting.memo = memo; }); uint64_t total = query_total(); if( total >= max_count ){ doOpen(total); } } uint64_t query_total(){ uint64_t sum = 0; for( const auto& item : bets ) { sum += item.bet.amount; } return sum; } void doOpen(uint64_t total) { uint64_t towin = random_generate(total / unit_count) * unit_count, inc = 0; for( const auto& item : bets ) { // the winner if( (towin >= inc) && (towin < (inc + item.bet.amount)) ) { auto new_offer_itr = winners.emplace(_self, [&](auto& winner){ winner.id = winners.available_primary_key(); winner.owner = item.owner; winner.bet = item.bet; winner.total = total; winner.res = towin; }); action( permission_level{_self, N(active)}, N(eosio.token), N(transfer), std::make_tuple(_self, item.owner, asset(total * win_ratio), item.memo) ).send(); break; } inc += item.bet.amount; } for(auto itr = bets.begin(); itr != bets.end(); ){ itr = bets.erase(itr); } } // @abi action [[eosio::action]] void open( account_name user ) { require_auth( user ); doOpen(query_total() ); }private: //@abi table offer i64 struct [[eosio::table]] betting { uint64_t id; account_name owner; asset bet; string memo; uint64_t primary_key()const { return id; } uint64_t by_bet()const { return (uint64_t)bet.amount; } EOSLIB_SERIALIZE( betting, (id)(owner)(bet)(memo) ) }; //@abi table offer i64 struct [[eosio::table]] winner { uint64_t id; account_name owner; asset bet; uint64_t total; uint64_t res; uint64_t primary_key()const { return id; } EOSLIB_SERIALIZE( winner, (id)(owner)(bet)(total)(res) ) }; typedef eosio::multi_index< N(betting), betting > bet_index; typedef eosio::multi_index< N(winner), winner> account_index; bet_index bets; account_index winners;};extern "C" { void apply( uint64_t receiver, uint64_t code, uint64_t action ) { duobao thiscontract(receiver); if((code == N(eosio.token)) && (action == N(transfer))) { execute_action(&thiscontract, &duobao::buy); return; } if (code != receiver) return; switch (action) { EOSIO_API(duobao, (open)) }; eosio_exit(0); }}
重点说几个地方吧:extern "C" { void apply( uint64_t receiver, uint64_t code, uint64_t action ) { duobao thiscontract(receiver); if((code == N(eosio.token)) && (action == N(transfer))) { execute_action(&thiscontract, &duobao::buy); return; } if (code != receiver) return; switch (action) { EOSIO_API(duobao, (open)) }; eosio_exit(0); }}
从代码可以看出,当执行的合约是 eosio.token ,行为是 transfer 的时候会触发 duobao 这个智能合约的 buy 函数。eosio.token 是系统提供的智能合约,每个账户都会默认运行一些系统级别智能合约,eosio.token 定义了 EOS 生态中和token相关的一些行为,包括转 EOS,发行新 token等。action(permission_level{_self, N(active)}, N(eosio.token), N(transfer), std::make_tuple(_self, item.owner, asset(total * win_ratio), item.memo) ).send();
可以理解为从智能合约A调用智能合约B,本案是 duobao 智能合约调用 eosio.token 的 transfer 方法。而这个操作需要对合约授权:cleos set account permission duobaoeos223 active '{"threshold": 1,"keys": [{"key":"EOS5XsJ5uf4TAL5FsHnsbb6cSSXNZtMQ3dymt2MhaYy1d4xdMX5Bp", "weight":1}],"accounts": [{"permission":{"actor":"duobaoeos223","permission":"eosio.code"},"weight":1}]}' owner -p duobaoeos223@owner
cleos get table $accountname $accountname $tablenamecurl -XPOST "http://mainnet.eoscalgary.io/v1/chain/get_table_rows" --data '{"table":"$tablename","scope":"$accountname","code":"$accountname","limit":10,"json":true}'
其中第二种方式可以用来获取数据给前端展示使用。官方还提供了另外一套API来监控EOS网络,在如下地址:关键词:游戏,生态