Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update #40

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 10 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
# EOSIO Quickstart Web IDE for decentralized applications ![EOSIO Alpha](https://img.shields.io/badge/EOSIO-Alpha-blue.svg)

[![Software License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](./LICENSE)

EOSIO Quickstart Web IDE lets developers start building full-stack EOSIO applications in a matter of minutes.

Powered by Gitpod.io and Docker, it provides developers with a personal single-node EOSIO blockchain for development and testing purposes without a need of going through advanced local environment setup. It also includes an example application with a smart contract and web frontend, connected to the blockchain. Developers can also use EOSIO tools like cleos and eosio.cdt straight out of the box. This project requires zero installation on the user's machine. All code is stored and managed on the developer's personal GitHub account, with the changes saved automatically.

We built this project with ease of use and simplicity in mind. It can be used by new developers trying out or learning EOSIO, as well as advanced developers and teams. It is especially useful in the environments where users don't have full control over the systems they work on (universities, banks, government organizations, etc.) or when they have lower-than-required computer specs to run EOSIO locally.

We hope you will find this project useful and welcome feedback on future improvements.
# EOSIO Quickstart Web IDE for decentralized applications !

# Setup

1. Fork this repo to your personal GitHub account so that you can save your work into your personal Github account.

2. Point your browser to the following URL https://gitpod.io/#https://github.com/your-github-account/eosio-web-ide to start the IDE. You will be automatically prompted to create a Gitpod account (all types of Gitpod accounts (including free) will work). You can also choose to provide multiple developers push access to your personal github fork of this repo to collaborate with them (one developer working on the smart contract (C++) while the other working on the front-end decentralized application (EOSJS), etc.). Each such developer sharing access to the forked repo will get their own copy of the EOSIO blockchain components to enable independent development.
Point your browser to the following URL https://gitpod.io/#https://github.com/your-github-account/eosio-web-ide to start the IDE. You will be automatically prompted to create a Gitpod account (all types of Gitpod accounts (including free) will work). You can also choose to provide multiple developers push access to your personal github fork of this repo to collaborate with them (one developer working on the smart contract (C++) while the other working on the front-end decentralized application (EOSJS), etc.). Each such developer sharing access to the forked repo will get their own copy of the EOSIO blockchain components to enable independent development.

You can test drive the system by accessing the IDE at https://gitpod.io/#https://github.com/EOSIO/eosio-web-ide (however you will not be able to save your work into the EOSIO/eosio-web-ide Github repository)

Expand All @@ -31,40 +18,37 @@ To open a terminal, use the Terminal drop-down menu in the IDE user interface.
The source code for the sample smartcontract is at `contract/talk.cpp` within the IDE. To compile the contract, run this in a terminal:

```
eosio-cpp contract/talk.cpp
eosio-cpp contract/integral.cpp

```

This will produce `talk.abi` and `talk.wasm`.
This will produce `integral.abi` and `integral.wasm`.

## Installing the contract

Run this in a terminal:

```
cleos create account eosio talk EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
cleos set code talk talk.wasm
cleos set abi talk talk.abi
cleos create account eosio integral EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
cleos set code integral integral.wasm
cleos set abi integral integral.abi

```

## Creating users and using the contract

Run this in a terminal:
```
cleos create account eosio bob EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
cleos create account eosio jane EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
cleos push action talk post '[1000, 0, bob, "This is a new post"]' -p bob
cleos push action talk post '[2000, 0, jane, "This is my first post"]' -p jane
cleos push action talk post '[1001, 2000, bob, "Replying to your post"]' -p bob
cleos create account eosio alice EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
cleos push action integral create '[ "integral", "1000000000.0000 INTA"]' -p integral@active

```

## Listing the messages

Run this in a terminal:
```
cleos get table talk '' message
cleos get currency stats integral INTA

```

Expand All @@ -77,68 +61,4 @@ gp preview $(gp url 8000)

```

## Building and running the unit test

The source code for the unit test is at the `tests` directory within the IDE. To build the tests, run this in the terminal:

```
./build-tests

```

This will produce the `tester` binary, which can be run from the terminal to start the actual unit test:

```
./tester

```

The unit test creates the `talk_tests` test suite and verifies that the following statements are executed without error:

1. Create user account `talk`.
2. Load the `talk` smart contract in the `talk` account sandbox.
2. Create user accounts `john` and `jane`.
3. Test the `post` action by performing the following:
1. Push the `post` action from `talk` to `john` with message "`post 1`" identified as `1` and addressed to message `0` (sent by noone).
This posts the message `1` from `john` to noone in the chat.
2. Push the `post` action from `talk` to `jane` with message "`post 2`" identified as `2` and addressed to message `0` (sent by noone).
This posts the message `2` from `jane` to noone in the chat.
3. Push the `post` action from `talk` to `john` with message "`post 3: reply`" identified as `3` and addressed to message `2` (sent by `jane`).
This posts the reply message `3` from `john` to `jane` in the chat.
4. Test failure of the `post` action if message is addressed to a non-existant message id.

## Resetting the chain

To remove the existing chain and create another:

* Switch to the terminal running `nodeos`
* Press `ctrl+c` to stop it
* Run the following

```
rm -rf ~/eosio/chain
nodeos --config-dir ~/eosio/chain/config --data-dir ~/eosio/chain/data -e -p eosio --plugin eosio::chain_api_plugin --contracts-console

```

Note: if the web app is currently open, then it will cause errors like the following. You may ignore them:

```
FC Exception encountered while processing chain.get_table_rows
```

## Contributing

[Contributing Guide](./CONTRIBUTING.md)

[Code of Conduct](./CONTRIBUTING.md#conduct)

## License

[MIT](./LICENSE)

## Important

See [LICENSE](LICENSE) for copyright and license terms.

All repositories and other materials are provided subject to the terms of this [IMPORTANT](important.md) notice and you must familiarize yourself with its terms. The notice contains important information, limitations and restrictions relating to our software, publications, trademarks, third-party resources, and forward-looking statements. By accessing any of our repositories and other materials, you accept and agree to the terms of the notice.
207 changes: 207 additions & 0 deletions contract/integral.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
#include<eosio/eosio.hpp>
#include<eosio/asset.hpp>
#include<string>

using namespace eosio;
using std::string;

class [[eosio::contract]] integral : public contract {
public:
using contract::contract;

[[eosio::action]]
void create( const name& issuer, const asset& maximum_supply){
/*
@param issuer - the business account that creates the token,
@param maximum_supply - the maximum supply set for the token created.
*/
require_auth(get_self());

auto sym = maximum_supply.symbol;
check( sym.is_valid(), "invalid symbol name" );
check( maximum_supply.is_valid(), "invalid supply");
check( maximum_supply.amount > 0, "max-supply must be positive");

stats statstable( get_self(), sym.code().raw() );
auto existing = statstable.find( sym.code().raw() );
check( existing == statstable.end(), "token with symbol already exists" );

statstable.emplace( get_self(), [&]( auto& s ) {
s.supply.symbol = maximum_supply.symbol;
s.max_supply = maximum_supply;
s.issuer = issuer;
});
}

[[eosio::action]]
void issue( const name& to, const asset& quantity, const string& memo ){
/*
@param to - the account to issue tokens to, it must be the same as the issuer,
@param quntity - the amount of tokens to be issued,
@memo - the memo string that accompanies the token issue transaction.
*/
auto sym = quantity.symbol;
check( sym.is_valid(), "invalid symbol name" );
check( memo.size() <= 256, "memo has more than 256 bytes" );

stats statstable( get_self(), sym.code().raw() );
auto existing = statstable.find( sym.code().raw() );
check( existing != statstable.end(), "token with symbol does not exist, create token before issue" );
const auto& st = *existing;
check( to == st.issuer, "tokens can only be issued to issuer account" );

require_auth( st.issuer );
check( quantity.is_valid(), "invalid quantity" );
check( quantity.amount > 0, "must issue positive quantity" );

check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );
check( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply");

statstable.modify( st, same_payer, [&]( auto& s ) {
s.supply += quantity;
});

add_balance( st.issuer, quantity, st.issuer );
}

[[eosio::action]]
void retire( const asset& quantity, const string& memo ){
/*
@param quantity - the quantity of tokens to retire,
@param memo - the memo string to accompany the transaction.
*/
auto sym = quantity.symbol;
check( sym.is_valid(), "invalid symbol name" );
check( memo.size() <= 256, "memo has more than 256 bytes" );

stats statstable( get_self(), sym.code().raw() );
auto existing = statstable.find( sym.code().raw() );
check( existing != statstable.end(), "token with symbol does not exist" );
const auto& st = *existing;

require_auth( st.issuer );
check( quantity.is_valid(), "invalid quantity" );
check( quantity.amount > 0, "must retire positive quantity" );

check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );

statstable.modify( st, same_payer, [&]( auto& s ) {
s.supply -= quantity;
});

sub_balance( st.issuer, quantity );
}

[[eosio::action]]
void transfer( const name& from, const name& to, const asset& quantity, const string& memo ){
/*
@param owner - the account to transfer integral,
@param from - the integral to transferr from,
@param to - the integral to be transferred,
@param memo - the memo string to accompany the transaction.
*/
check( from != to, "cannot transfer to self" );
require_auth( from );
check( is_account( to ), "to account does not exist");
auto sym = quantity.symbol.code();
stats statstable( get_self(), sym.raw() );
const auto& st = statstable.get( sym.raw() );

require_recipient( from );
require_recipient( to );

check( quantity.is_valid(), "invalid quantity" );
check( quantity.amount > 0, "must transfer positive quantity" );
check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );
check( memo.size() <= 256, "memo has more than 256 bytes" );

auto payer = has_auth( to ) ? to : from;

sub_balance( from, quantity );
add_balance( to, quantity, payer );
}

[[eosio::action]]
void open( const name& owner, const symbol& symbol, const name& ram_payer ){
require_auth( ram_payer );

check( is_account( owner ), "owner account does not exist" );

auto sym_code_raw = symbol.code().raw();
stats statstable( get_self(), sym_code_raw );
const auto& st = statstable.get( sym_code_raw, "symbol does not exist" );
check( st.supply.symbol == symbol, "symbol precision mismatch" );

accounts acnts( get_self(), owner.value );
auto it = acnts.find( sym_code_raw );
if( it == acnts.end() ) {
acnts.emplace( ram_payer, [&]( auto& a ){
a.balance = asset{0, symbol};
});
}
}

[[eosio::action]]
void close( const name& owner, const symbol& symbol ){
require_auth( owner );
accounts acnts( get_self(), owner.value );
auto it = acnts.find( symbol.code().raw() );
check( it != acnts.end(), "Balance row already deleted or never existed. Action won't have any effect." );
check( it->balance.amount == 0, "Cannot close because the balance is not zero." );
acnts.erase( it );
}

static asset get_supply( const name& token_contract_account, const symbol_code& sym_code ){
stats statstable( token_contract_account, sym_code.raw() );
const auto& st = statstable.get( sym_code.raw() );
return st.supply;
}

static asset get_balance( const name& token_contract_account, const name& owner, const symbol_code& sym_code ){
accounts accountstable( token_contract_account, owner.value );
const auto& ac = accountstable.get( sym_code.raw() );
return ac.balance;
}

private:
struct [[eosio::table]] account {
asset balance;

uint64_t primary_key()const { return balance.symbol.code().raw(); }
};

struct [[eosio::table]] currency_stats {
asset supply;
asset max_supply;
name issuer;

uint64_t primary_key()const { return supply.symbol.code().raw(); }
};

typedef eosio::multi_index< "accounts"_n, account > accounts;
typedef eosio::multi_index< "stat"_n, currency_stats > stats;

void sub_balance( const name& owner, const asset& value ){
accounts from_acnts( get_self(), owner.value );

const auto& from = from_acnts.get( value.symbol.code().raw(), "no balance object found" );
check( from.balance.amount >= value.amount, "overdrawn balance" );

from_acnts.modify( from, owner, [&]( auto& a ) {
a.balance -= value;
});
}
void add_balance( const name& owner, const asset& value, const name& ram_payer ){
accounts to_acnts( get_self(), owner.value );
auto to = to_acnts.find( value.symbol.code().raw() );
if( to == to_acnts.end() ) {
to_acnts.emplace( ram_payer, [&]( auto& a ){
a.balance = value;
});
} else {
to_acnts.modify( to, same_payer, [&]( auto& a ) {
a.balance += value;
});
}
}
};
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
"antd": "^4.13.1"
}
}
2 changes: 1 addition & 1 deletion webapp/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</head>

<body>
<div id="example"></div>
<div id="tab"></div>
<script src="./node_modules/react/umd/react.development.js">

</script>
Expand Down
Loading