Open Market Dapp solution written in solidity smart contracts with web client.
This application is an Open Market that consists 3 roles;
- OWNER; Owns the smart contract and can add or remove Admin accounts;
- Admin; Admins are responsible to add, remove store owners.
- Store Owner;
- Store owners can create stores with labels up to 5
- Store owners put products into stores by using panel and list them to sell
- Customer; Customers can buy any product that is listed on front page. (Currently only supports buying procedure)
This application is just for self education. And there are (will be) many many mistakes or unfinished business. Currently i am continuening to discover Dapp environment. Also there is a TODO list that i keep.
We need npx
for running nodejs custom commands
yarn global add npx
Migrate this repository and install dependencies;
git clone https://github.com/alkimake/omarket.git
cd omarket
yarn
Make alterations in truffle-config.js
. Currently truffle-config.js
supports 2 network.
- Development: Ganache Network
- Ropsten: Via infura
For development, you need to install and run ganache-cli
to have a local test network. We add -i 5777
to make sure the ganache network id is proper.
$ yarn global add ganache-cli
$ ganache-cli -i 5777
Ganache CLI v6.4.5 (ganache-core: 2.5.7)
Available Accounts
==================
(0) 0xaeebc0685e3a6d7a08e2a9ff855a4916cd586f9d (~100 ETH)
(1) 0x4be3f7863ad7adda47b2657bffa8d76a3443a1a6 (~100 ETH)
(2) 0x3254d76535d87923b339e7059394cdcb42d754d2 (~100 ETH)
(3) 0x28ee0be50f9909f092ccf11c627ae22b3bed2dc3 (~100 ETH)
(4) 0x855fe8f0d6ca7636eae32345c46b5daf6a3dc955 (~100 ETH)
(5) 0x3065c52cb069858f1ed90cb7efd83e7dc07393c3 (~100 ETH)
(6) 0x43dd7a550cab201fa2e7b5ef3a2fb167c9d03c3f (~100 ETH)
(7) 0x2f3cfe1a5dc81ad7d44bf7a30fbad3da3c325062 (~100 ETH)
(8) 0xb4ebf2991a3fa7aa9124145259d9acda1d8d67a8 (~100 ETH)
(9) 0xbda63d4e7168a62a98426b16e055ed813c6f4f56 (~100 ETH)
Private Keys
==================
(0) 0xf103e25388fd1bb55c037f0aa74d9db429839be718ea99aa26736d47223ac743
(1) 0xc2f58f09d31650cd853c24c40d78e43e82117da32ea495b3c9c7c91baeaadf62
(2) 0x0f70f21672c592abc42b40d070fb429361a08916d71d49e8fdbef1925a86a4a8
(3) 0x1e7f3c8677ae7322c622f95357eed6350a9e1eaebf7ac9b888ae178ed0658fef
(4) 0x80b5e16b030a810624c629eab6aad6fc25106048e0fe136e014df970ccfbd22b
(5) 0xf0d4d510a2d4c115e25db8fc8a24bc07bfabe67354a9f8913cafcdc0c5faaea5
(6) 0xaea3c7f264d242b93d13b3c4b1122f6cd639bcf9aac2dabeba24d707ea264579
(7) 0x1fa7f80bd55d9c3503cea1657f15b90a62659b39c4aa7d9e3d3cf398867e69db
(8) 0xd3bf2b49ef54a7e2013aca5329a9302c4406887154465740b3b4c6087883c351
(9) 0x6569d60e6f08933b0524661d828ccfac8ced1a2e0efdcbb2b13bbc6391bb1de1
HD Wallet
==================
Mnemonic: ill cotton toilet bounce frost barely fee example famous final vague captain
Base HD Path: m/44'/60'/0'/0/{account_index}
Gas Price
==================
20000000000
Gas Limit
==================
6721975
Listening on 127.0.0.1:8545
Use the mnemonics to get accounts on metamask
Check your host and port settings for your ganache.
Change your infura api key and create .secret
file on root. So you can deploy the contracts to Ropsten network.
This smart contract is already deployed on ropsten
network and can be seen on Etherscan
https://ropsten.etherscan.io/tx/0xd375158a557af31a7282a3a3a524cd8e0680c015bcda2cc9261b2b5bbd146840
Build contracts;
yarn build:contracts
If you need to migrate your contract to the network you should use
yarn migrate:contracts
This command migrates the contracts into development
network (which is served on http://localhost:8545 Ganache Network)
INFO: The images for products are kept on ipfs by uploading and receiving infura
ipfs gateway. There is nothing to change on this.
INFO: The build version of this client can be found on IPFS Hash: QmbZdNJhrTHNZuWHHHiFT2At8Ttj15T7va77oU5MpiBrCd
Web client will work via ipfs gateways. eg. https://ipfs.io/ipfs/QmbZdNJhrTHNZuWHHHiFT2At8Ttj15T7va77oU5MpiBrCd
BUILD To build and serve the webclient on ipfs you can use following build command;
$ DEPLOYED_ADDRESS="<contract_address>" APPROVED_NETWORK_ID="<network_id>" npx parcel build index.html --public-url ./ --no-source-maps --target browser
$ ipfs add -r ./dist
Environment variables are
Name | Mandatory | Default |
---|---|---|
APPROVED_NETWORK_ID | x | 5777 |
DEPLOYED_ADDRESS | x |
If you migrate your contracts you don't need to put these env variables. Run directly yarn dev
Otherwise;
$ DEPLOYED_ADDRESS="0x..." APPROVED_NETWORK_ID="1" yarn dev
npx parcel index.html
Server running at http://localhost:1234
✨ Built in 20.94s.
Currently supports following Networks;
- 1: Main Net,
- 2: Deprecated Morden test network,
- 3: Ropsten test network,
- 4: Rinkeby test network,
- 42: Kovan test network,
- 4447: Truffle Develop Network,
- 5777: Ganache Blockchain,
- 666: Daniel Private Blockchain
Now you can browse http://localhost:1234
in your browser.
Upgrading the contract guide can be found at Upgrade doc. Currently Owned Proxy Pattern is used. Upgrade is possible with more methods and patterns such as upgradeable external storage pattern.
You need to run ganache
to run tests
$ yarn global add ganache-cli
$ ganache-cli
On another terminal you can run
yarn test:sol
sol
is for solidity. I haven't done anything to test web application client yet.
Sample output can be;
yarn run v1.16.0
$ truffle test
Compiling your contracts...
===========================
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/OMarket.sol
> Compiling ./contracts/Store.sol
> Compiling ./contracts/lib/strings.sol
> Compiling openzeppelin-solidity/contracts/access/Roles.sol
> Compiling openzeppelin-solidity/contracts/access/roles/PauserRole.sol
> Compiling openzeppelin-solidity/contracts/lifecycle/Pausable.sol
> Compiling openzeppelin-solidity/contracts/ownership/Ownable.sol
> compilation warnings encountered:
/home/ake/Projects/blockchain/s/omarket/contracts/Store.sol:2:1: Warning: Experimental features are turned on. Do not use experimental features on live deployments.
pragma experimental ABIEncoderV2;
^-------------------------------^
> Artifacts written to /tmp/test-119617-21412-17b1ykz.yr6
> Compiled successfully using:
- solc: 0.5.8+commit.23d335f2.Emscripten.clang
Contract: OMarket
Setup
✓ OWNER should be set to the deploying address
✓ PAUSED shoud be set to false (63ms)
✓ pause can not be called other than owner (92ms)
Admin
✓ getAdmins should include addmin address (149ms)
✓ user should get if user is admin (103ms)
addAdmin()
✓ only the owner should be able to add an admin (257ms)
✓ adding an admin should triggger an event (95ms)
✓ should revert when contract is in paused state (205ms)
removeAdmin()
✓ should not remove admin if the address is not in admin list (113ms)
✓ should remove admin properly (286ms)
✓ should remove admin in the middle (479ms)
StoreOwner
addStoreOwner()
✓ only the admin should be able to add a store owner (286ms)
✓ adding an storeOwner should triggger an event (127ms)
✓ should not add store owners when contract is paused (286ms)
has valid storeOwner
✓ getStoreOwners should include store owner address (71ms)
✓ readStoreOwner should return informations about store owner (77ms)
✓ should not add same store owner again (150ms)
✓ user should get if user is storeOwner (118ms)
✓ can toggle active status (228ms)
✓ toggle status should be reverted if the address is not store owner (168ms)
Stores
✓ should create new store from storeOwner (154ms)
✓ store list should revert (76ms)
when created a store
✓ store list for owner should contain first store (90ms)
✓ can not create more than 5 store (797ms)
Contract: Store
Setup
✓ OWNER should be set to the deploying address (145ms)
✓ Info (72ms)
Adding product
✓ only the owner should be able to add an product (224ms)
✓ adding an product should emit an product with the provided product details (71ms)
readProduct()
✓ providing the product Id should return the correct product details (142ms)
buyProducts()
✓ products should only be able to be purchased when they are available (219ms)
✓ products should only be able to be purchased when enough value is sent with the transaction (73ms)
✓ products should only be able to be purchased when there are enough products remaining (139ms)
✓ a LogBuyProducts() event with the correct details should be emitted when products are purchased (61ms)
Owner balance
✓ should have correct balance (128ms)
✓ should return correct balance (137ms)
35 passing (16s)
Done in 25.59s.
I have tried some of the ethereum patterns and techinuques to learn in depth. All examples are in their git branches.
- EthPM -> ethpm
- There is a
LibraryDemo.sol
file in thecontracts
folder which demonstrates ExampleCoin and zeppelins ethpm package withSafeMath
andERC20
token
- There is a
Anything welcome. Just pick something from TODO file. Or use your imagination.