├── .gitignore ├── LICENSE ├── README.md ├── assets ├── coinflip.mp3 ├── components │ └── ground.js ├── icon-140.png ├── icon-192.png ├── noun_1493927_cc.png └── shaders │ └── skyGradient.js ├── contracts ├── Migrations.sol ├── SimpleToken.sol └── StandardToken.sol ├── css ├── index.css └── mobile.css ├── index-2.html ├── index.html ├── js ├── app.js ├── compat.js ├── truffle-contract.min.js └── web3.min.js ├── make-it-rain.html ├── migrations ├── 1_initial_migration.js └── 2_deploy_token.js ├── package-lock.json ├── ss ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png └── 6.png ├── truffle-config.js └── truffle.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Truffle Builds 2 | build/ 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (http://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | 42 | # Typescript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Paul Gadi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hello Crypto 2 | 3 | 4 | The "Hello World" of blockchain and cryptogames! (ノ ˘_˘)ノ 。゜。゚ 5 | 6 | Live demo here: 7 | 8 | ## Quickstart 9 | 10 | To just run the project, install [Node and npm](https://nodejs.org/en/), and then run lite-server: 11 | 12 | ``` 13 | npm install -g lite-server 14 | lite-server 15 | 16 | ``` 17 | ## Creating It From Scratch 18 | If we want to learn how the pieces come together, it helps to go through the process of creating the Hello Crypto app ourselves. 19 | 20 | We can break it down into 3 parts: 21 | 22 | * (1) interacting with the Ethereum blockchain in your app, 23 | * (2) creating our own ERC20 token, and 24 | * (3) deploying it on the blockchain. 25 | 26 | ---- 27 | 28 | ### Interacting with the Ethereum Blockchain in Your App 29 | 30 | #### 1. Install Metamask 31 | 32 | If you haven't yet, install the [Metamask Extension](https://metamask.io/) on your browser. 33 | 34 | In order to interact with the blockchain, we will need a wallet address from which to call transactions from. Currently the easiest way to create one is by using Metamask. And since we're making a web app, Metamask also conveniently provides us helper functions that we'll be using later. 35 | 36 | #### 2. Create a new project directory and copy starter files 37 | 38 | Create a new directory, and then copy the following files from the Hello Crypto project onto that directory: 39 | 40 | ``` 41 | index-2.html 42 | js/web3.min.js 43 | js/truffle-contract.min.js 44 | ``` 45 | 46 | Rename index-2.html to index.html: 47 | 48 | ``` 49 | mv index-2.html index.html 50 | ``` 51 | 52 | The javascript libraries we copied over are [web3.js, the Ethereum Javascript API](https://github.com/ethereum/web3.js) and [truffle-contract](https://github.com/trufflesuite/truffle-contract), a library to help us call Blockchain contracts. 53 | 54 | #### 3. Use lite-server to run the app 55 | 56 | Install lite-server and run the app: 57 | 58 | ``` 59 | npm install -g lite-server 60 | lite-server 61 | ``` 62 | 63 | The browser should automatically start the web app from index.html and you should see a screen similar to the one below: 64 | 65 | ![Alt text](ss/1.png?raw=true "First Run") 66 | 67 | The app uses our wallet account in Metamask and the web3.js library to interact with the blockchain-- it queries the account's ETH balance, and uses Javascript to display them on the page. If your wallet has ETH it should show the current amount here. 68 | 69 | **Note:** The SIM Balance error is expected, it appears since we don't have that custom token's smart contract deployed on the blockchain. We will fix that in the next section. 70 | 71 | ---- 72 | 73 | ### Creating Our Own ERC20 Token 74 | 75 | Creating a custom ERC20 Token is usually the first use case for those learning how to deploy smart contracts. We'll see how to do this using a simple workflow, and then integrate the ERC20 Token it with our web app. 76 | 77 | #### 1. Set up Truffle then truffle init 78 | 79 | [Truffle](http://truffleframework.com/) is the easiest Ethereum development framework to learn, and is a good fit for us since we've already started using Node and NPM for our web app. Install it via the terminal: 80 | 81 | ``` 82 | npm install -g truffle 83 | ``` 84 | And then initialize our project by typing: 85 | 86 | ``` 87 | truffle init 88 | ``` 89 | 90 | Once done you'll see a bunch of new files and directories created in our project directory. These are Truffle's deployment scripts and config files. 91 | 92 | #### 2. Install OpenZeppelin 93 | 94 | We will be using the example token smart contract from [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity). This is a good starting point as they're peer-reviewed smart contracts that follow standards defined by the community. We can use them by simply downloading them also from npm: 95 | 96 | ``` 97 | npm install @openzeppelin/contracts 98 | ``` 99 | 100 | You should see a node_modules/@openzeppelin folder once the command completes. 101 | 102 | #### 3. Open StandardToken.sol 103 | 104 | This is almost a copy of `@openzeppelin/contracts/token/ERC20/ERC20.sol` which implements the IERC20.sol contract interface but instead of having private member variables we will leave them as public. 105 | 106 | #### 4. Open SimpleToken.sol 107 | 108 | This is our own ERC-20 custom token which inherits from StandardToken. 109 | 110 | ![Alt text](ss/2.png?raw=true "Change Import") 111 | 112 | #### 4. Add Deployment Script 113 | 114 | We then need to add a deployment script to the migrations folder so that truffle can deploy our SimpleToken to a blockchain. Create a **2_deploy_token.js** file in the migrations directory, and add the following lines: 115 | 116 | ``` 117 | var SimpleToken = artifacts.require("SimpleToken"); 118 | 119 | module.exports = function(deployer) { 120 | deployer.deploy(SimpleToken); 121 | }; 122 | ``` 123 | 124 | ![Alt text](ss/3.png?raw=true "Deployment Script") 125 | 126 | #### 5. Create local blockchain with truffle develop 127 | 128 | We now setup a local test blockchain by using Truffle, which can be done simply by typing: 129 | 130 | ``` 131 | truffle develop 132 | ``` 133 | ![Alt text](ss/4.png?raw=true "Truffle Develop") 134 | 135 | Once successful we should see the same screen, with us entering the truffle develop console. 136 | 137 | #### 6. Deploy the smart contract via truffle migrate 138 | 139 | Now that we have a local test blockchain, we can try deploying the SimpleToken contract that we copied from OpenZeppelin. We can do this from within the truffle develop console by typing in: 140 | 141 | ``` 142 | migrate 143 | ``` 144 | 145 | This will compile our smart contracts into JSON under the build folder, and also deploy the smart contracts unto the local blockchain. A successful run would look similar to the screen below. 146 | 147 | ![Alt text](ss/5.png?raw=true "Truffle Migrate") 148 | 149 | Congratulations, you have just deployed an ERC20 Token onto a blockchain! (It's on a local development blockchain for now, we'll see how to deploy to live blockchains in the next section) 150 | 151 | #### 7. Connect to the local blockchain from Metamask 152 | 153 | Now that we've deployed our contract on a local blockchain, let's see it in action on our web app. Go back to our running web app on the browser (if you closed it, open a new tab and start **lite-server** again). 154 | 155 | In Metamask, change the network that we're connecting to by clicking the dropdown on the upper left of the extension's page. Select **Custom RPC**, and input the default host used by truffle develop: **http://localhost:9545/** 156 | 157 | You should see the error we had previously is now gone, as our web app is now successfully querying the custom token balance from the local blockchain. 158 | 159 | ![Alt text](ss/6.png?raw=true "Local Blockchain") 160 | 161 | **Note:** Truffle uses the first account in Truffle develop as the contract creator. In the screenshot above, we imported that account in Metamask using its private key. As the OpenZeppelin SimpleToken sets the contract creator as the holder of all the initial supply of our custom token, we see that the Truffle Account's Sim balance contains exactly that. 162 | 163 | ## IN PROGRESS 164 | 165 | 166 | (optional) interact with contract on truffle console 167 | 168 | Send ETH 169 | 170 | web3.eth.accounts 171 | 172 | contract creator is web3.eth.accounts[0] 173 | 174 | recipientAccount = web3.eth.accounts[1] 175 | 176 | web3.eth.getBalance 0 and 1 177 | 178 | web3.eth.sendTransaction({from:Account1, to:Account2, value: 10000}) 179 | 180 | 181 | Send SIM 182 | 183 | contractInstance = SimpleToken.deployed().then(i => contractInstance = i) 184 | 185 | contractInstance.totalSupply 186 | 187 | contractInstance.balanceOf(web3.eth.accounts[0]) 188 | 189 | contractInstance.balanceOf(recipientAccount) 190 | 191 | What is Big Number? 192 | 193 | contractInstance.transfer(recipientAddress, 5000) 194 | 195 | check new balance 196 | 197 | 198 | (optional) Setup web3 javascript console 199 | 200 | Perform previous ETH transfer operations 201 | 202 | web3.eth 203 | 204 | add truffle-contract.min.js 205 | 206 | load simpleToken json 207 | 208 | return balance 209 | 210 | Add make-it-rain.html 211 | 212 | 213 | III. Deploy on the Blockchain 214 | 215 | To interact with the blockchain, we’ll need to have our own wallet account. We’ve been using Truffle develop accounts, but now we should use our own by creating one 216 | 217 | Install Metamask, remember mnemonic 218 | 219 | Get some ETH from faucet inside metamask 220 | 221 | setup HDWallet provider, then connect to ropsten 222 | migrate 223 | 224 | Change make-it-rain settings to call ropsten on testnet instead 225 | 226 | Change settings to use ETH instead 227 | 228 | Show deployed website -------------------------------------------------------------------------------- /assets/coinflip.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/assets/coinflip.mp3 -------------------------------------------------------------------------------- /assets/components/ground.js: -------------------------------------------------------------------------------- 1 | /* global AFRAME, THREE */ 2 | 3 | /** 4 | * Loads and setup ground model. 5 | */ 6 | AFRAME.registerComponent('ground', { 7 | init: function () { 8 | var objectLoader; 9 | var object3D = this.el.object3D; 10 | var MODEL_URL = 'https://cdn.aframe.io/link-traversal/models/ground.json'; 11 | if (this.objectLoader) { return; } 12 | objectLoader = this.objectLoader = new THREE.ObjectLoader(); 13 | objectLoader.crossOrigin = ''; 14 | objectLoader.load(MODEL_URL, function (obj) { 15 | obj.children.forEach(function (value) { 16 | value.receiveShadow = true; 17 | value.material.flatShading = THREE.FlatShading; 18 | }); 19 | object3D.add(obj); 20 | }); 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /assets/icon-140.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/assets/icon-140.png -------------------------------------------------------------------------------- /assets/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/assets/icon-192.png -------------------------------------------------------------------------------- /assets/noun_1493927_cc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/assets/noun_1493927_cc.png -------------------------------------------------------------------------------- /assets/shaders/skyGradient.js: -------------------------------------------------------------------------------- 1 | /* global AFRAME */ 2 | AFRAME.registerShader('skyGradient', { 3 | schema: { 4 | colorTop: { type: 'color', default: 'black', is: 'uniform' }, 5 | colorBottom: { type: 'color', default: 'red', is: 'uniform' } 6 | }, 7 | 8 | vertexShader: [ 9 | 'varying vec3 vWorldPosition;', 10 | 11 | 'void main() {', 12 | 13 | 'vec4 worldPosition = modelMatrix * vec4( position, 1.0 );', 14 | 'vWorldPosition = worldPosition.xyz;', 15 | 16 | 'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', 17 | 18 | '}' 19 | 20 | ].join('\n'), 21 | 22 | fragmentShader: [ 23 | 'uniform vec3 colorTop;', 24 | 'uniform vec3 colorBottom;', 25 | 26 | 'varying vec3 vWorldPosition;', 27 | 28 | 'void main()', 29 | 30 | '{', 31 | 'vec3 pointOnSphere = normalize(vWorldPosition.xyz);', 32 | 'float f = 1.0;', 33 | 'if(pointOnSphere.y > - 0.2){', 34 | 35 | 'f = sin(pointOnSphere.y * 2.0);', 36 | 37 | '}', 38 | 'gl_FragColor = vec4(mix(colorBottom,colorTop, f ), 1.0);', 39 | 40 | '}' 41 | ].join('\n') 42 | }); 43 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <0.6.0; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | constructor() public { 8 | owner = msg.sender; 9 | } 10 | 11 | modifier restricted() { 12 | if (msg.sender == owner) _; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/SimpleToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <0.6.0; 2 | 3 | import './StandardToken.sol'; 4 | 5 | /** 6 | * @title SimpleToken 7 | * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator. 8 | * Note they can later distribute these tokens as they wish using `transfer` and other 9 | * `StandardToken` functions. 10 | */ 11 | contract SimpleToken is StandardToken { 12 | using SafeMath for uint256; 13 | 14 | string public constant name = "SimpleToken"; // solium-disable-line uppercase 15 | string public constant symbol = "SIM"; // solium-disable-line uppercase 16 | uint8 public constant decimals = 18; // solium-disable-line uppercase 17 | 18 | uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals)); 19 | 20 | constructor() public { 21 | _totalSupply = INITIAL_SUPPLY; 22 | _balances[msg.sender] = INITIAL_SUPPLY; 23 | transfer(msg.sender, INITIAL_SUPPLY); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/StandardToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <0.6.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import "@openzeppelin/contracts/math/SafeMath.sol"; 5 | 6 | /** 7 | * @title StandardToken 8 | * @dev Implements the IERC20 interface. Copied from @openzeppelin/contracts/token/ERC20/IERC20.sol. 9 | */ 10 | contract StandardToken is IERC20 { 11 | using SafeMath for uint256; 12 | 13 | mapping (address => uint256) _balances; 14 | mapping (address => mapping (address => uint256)) _allowances; 15 | uint256 _totalSupply; 16 | 17 | function totalSupply() public view returns (uint256) { 18 | return _totalSupply; 19 | } 20 | 21 | function balanceOf(address account) public view returns (uint256) { 22 | return _balances[account]; 23 | } 24 | 25 | function transfer(address recipient, uint256 amount) public returns (bool) { 26 | _transfer(msg.sender, recipient, amount); 27 | return true; 28 | } 29 | 30 | function allowance(address owner, address spender) public view returns (uint256) { 31 | return _allowances[owner][spender]; 32 | } 33 | 34 | function approve(address spender, uint256 value) public returns (bool) { 35 | _approve(msg.sender, spender, value); 36 | return true; 37 | } 38 | 39 | function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { 40 | _transfer(sender, recipient, amount); 41 | _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount)); 42 | return true; 43 | } 44 | 45 | function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { 46 | _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); 47 | return true; 48 | } 49 | 50 | function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { 51 | _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue)); 52 | return true; 53 | } 54 | 55 | function _transfer(address sender, address recipient, uint256 amount) internal { 56 | require(sender != address(0), "ERC20: transfer from the zero address"); 57 | require(recipient != address(0), "ERC20: transfer to the zero address"); 58 | 59 | _balances[sender] = _balances[sender].sub(amount); 60 | _balances[recipient] = _balances[recipient].add(amount); 61 | emit Transfer(sender, recipient, amount); 62 | } 63 | 64 | function _mint(address account, uint256 amount) internal { 65 | require(account != address(0), "ERC20: mint to the zero address"); 66 | 67 | _totalSupply = _totalSupply.add(amount); 68 | _balances[account] = _balances[account].add(amount); 69 | emit Transfer(address(0), account, amount); 70 | } 71 | 72 | function _burn(address account, uint256 value) internal { 73 | require(account != address(0), "ERC20: burn from the zero address"); 74 | 75 | _totalSupply = _totalSupply.sub(value); 76 | _balances[account] = _balances[account].sub(value); 77 | emit Transfer(account, address(0), value); 78 | } 79 | 80 | function _approve(address owner, address spender, uint256 value) internal { 81 | require(owner != address(0), "ERC20: approve from the zero address"); 82 | require(spender != address(0), "ERC20: approve to the zero address"); 83 | 84 | _allowances[owner][spender] = value; 85 | emit Approval(owner, spender, value); 86 | } 87 | 88 | function _burnFrom(address account, uint256 amount) internal { 89 | _burn(account, amount); 90 | _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount)); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /css/index.css: -------------------------------------------------------------------------------- 1 | .gutter pre{ 2 | color:#999; 3 | } 4 | pre .line{ 5 | min-height:19px; 6 | } 7 | pre{ 8 | color:#525252; 9 | } 10 | pre .function .keyword,pre .constant{ 11 | color:#0092db; 12 | } 13 | pre .keyword,pre .attr{ 14 | color:#e96900; 15 | } 16 | pre .number,pre .literal{ 17 | color:#ae81ff; 18 | } 19 | pre .tag,pre .tag .title,pre .change,pre .winutils,pre .flow,pre .lisp .title,pre .clojure .built_in,pre .nginx .title,pre .tex .special{ 20 | color:#2973b7; 21 | } 22 | pre .class .title{ 23 | color:#fff; 24 | } 25 | pre .symbol,pre .symbol .string,pre .value,pre .regexp{ 26 | color:#4b8; 27 | } 28 | pre .title{ 29 | color:#a6e22e; 30 | } 31 | pre .tag .value,pre .string,pre .subst,pre .haskell .type,pre .preprocessor,pre .ruby .class .parent,pre .built_in,pre .sql .aggregate,pre .django .template_tag,pre .django .variable,pre .smalltalk .class,pre .javadoc,pre .django .filter .argument,pre .smalltalk .localvars,pre .smalltalk .array,pre .attr_selector,pre .pseudo,pre .addition,pre .stream,pre .envvar,pre .apache .tag,pre .apache .cbracket,pre .tex .command,pre .prompt{ 32 | color:#4b8; 33 | } 34 | pre .comment,pre .java .annotation,pre .python .decorator,pre .template_comment,pre .pi,pre .doctype,pre .deletion,pre .shebang,pre .apache .sqbracket,pre .tex .formula{ 35 | color:#b3b3b3; 36 | } 37 | pre .coffeescript .javascript,pre .javascript .xml,pre .tex .formula,pre .xml .javascript,pre .xml .vbscript,pre .xml .css,pre .xml .cdata{ 38 | opacity:0.5; 39 | } 40 | *{ 41 | margin:0; 42 | padding:0; 43 | box-sizing:border-box; 44 | } 45 | html,body{ 46 | height:100%; 47 | } 48 | html{ 49 | font-size:14px; 50 | } 51 | body{ 52 | font:400 1.1rem/1.6 Fira Sans,Helvetica,Arial,sans-serif; 53 | color:#333; 54 | } 55 | iframe,img,button,input[type=button],.btn{ 56 | border:0; 57 | } 58 | .borderless-links a,a.borderless-links,a.borderless-link{ 59 | border:0; 60 | } 61 | .hidden-visually{ 62 | border:0; 63 | clip:rect(0 0 0 0); 64 | height:1px; 65 | margin:-1px; 66 | overflow:hidden; 67 | padding:0; 68 | position:absolute; 69 | width:1px; 70 | } 71 | strong{ 72 | font-weight:600; 73 | } 74 | code,pre{ 75 | font-family:Fira Mono,Consolas,Andale Mono,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace; 76 | } 77 | pre{ 78 | font-size:1rem; 79 | } 80 | [data-is-mobile="true"] pre{ 81 | font-size:0.8rem; 82 | } 83 | .font-loaded-mono code,.font-loaded-mono pre{ 84 | font-family:Fira Mono,Consolas,Andale Mono,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace; 85 | } 86 | p code,li code,dd code{ 87 | background:#f8f8f8; 88 | font-weight:600; 89 | padding:0 2px; 90 | margin:0 1px; 91 | } 92 | h2 code{ 93 | font-weight:600; 94 | padding:0 1px; 95 | } 96 | h3 code{ 97 | background:#f8f8f8; 98 | padding-left:2px; 99 | padding-right:2px; 100 | } 101 | [data-page-type="community"] li code{ 102 | font-weight:500; 103 | } 104 | p{ 105 | word-spacing:0.05em; 106 | } 107 | h1{ 108 | color:#305f83; 109 | } 110 | h2,h3,h4{ 111 | color:#2c3e50; 112 | font-weight:500; 113 | } 114 | h4{ 115 | font-weight:600; 116 | } 117 | .btn{ 118 | cursor:pointer; 119 | font:inherit; 120 | } 121 | .copy__wrap{ 122 | max-width:100%; 123 | } 124 | @media (min-width: 900px) { 125 | .copy__wrap{ 126 | max-width:700px; 127 | } 128 | } 129 | .sidebar__wrap,.copy__wrap{ 130 | padding:40px; 131 | } 132 | [data-page-type="blog"] .copy__wrap{ 133 | padding-top:20px; 134 | } 135 | .nav,.subnav{ 136 | list-style-type:none; 137 | } 138 | .copy a.btn{ 139 | font-size:0.9em; 140 | color:#fff; 141 | margin:0.2em 0; 142 | max-width:180px; 143 | text-align:center; 144 | padding:12px 24px; 145 | display:inline-block; 146 | vertical-align:middle; 147 | } 148 | .copy img{ 149 | max-width:100%; 150 | } 151 | .copy span.light{ 152 | color:#7f8c8d; 153 | } 154 | .copy span.info{ 155 | font-size:0.85em; 156 | display:inline-block; 157 | vertical-align:middle; 158 | width:280px; 159 | margin-left:20px; 160 | } 161 | .copy h2{ 162 | margin:1.5em 0 0.8em; 163 | padding-bottom:0.7em; 164 | border-bottom:1px solid #ddd; 165 | } 166 | .copy h3{ 167 | font-size:1.5rem; 168 | } 169 | .copy h3,.copy h4{ 170 | margin:2em 0 0.25em; 171 | position:relative; 172 | } 173 | .copy figure,.copy p,.copy ul,.copy ol,.copy table{ 174 | margin:15px 0; 175 | } 176 | .copy figure:last-child+.footer,.copy p:last-child+.footer,.copy ul:last-child+.footer,.copy ol:last-child+.footer,.copy table:last-child+.footer{ 177 | margin-bottom:0; 178 | } 179 | .copy p,.copy ul,.copy ol,.copy table{ 180 | line-height:1.6; 181 | } 182 | .copy ul,.copy ol{ 183 | padding-left:1.5em; 184 | } 185 | .copy blockquote{ 186 | background:#f8f8f8; 187 | margin:2em 0; 188 | padding:5px 5px 5px 20px; 189 | border-left:4px solid #ef2d5e; 190 | } 191 | .copy blockquote p{ 192 | font-weight:400; 193 | margin-left:0; 194 | } 195 | .copy iframe{ 196 | margin:1em 0; 197 | } 198 | .copy p+h2,.copy table+table{ 199 | margin-top:1.5em; 200 | } 201 | .copy .tip{ 202 | background-color:#f8f8f8; 203 | border-bottom-right-radius:2px; 204 | border-left:4px solid #ef2d5e; 205 | border-top-right-radius:2px; 206 | margin:2em 0; 207 | padding:1.5em 2em; 208 | position:relative; 209 | } 210 | .copy .tip:before{ 211 | position:absolute; 212 | top:14px; 213 | left:-12px; 214 | background-color:#ef2d5e; 215 | color:#fff; 216 | content:"!"; 217 | width:20px; 218 | height:20px; 219 | border-radius:100%; 220 | text-align:center; 221 | line-height:20px; 222 | font-weight:bold; 223 | font-size:14px; 224 | } 225 | .copy .tip.tip--dark{ 226 | background-color:rgba(0,0,0,0.5); 227 | border-left-color:rgba(239,45,94,0.5); 228 | } 229 | .copy .tip.tip--dark:before{ 230 | background-color:#ef2d5e; 231 | border:2px solid #000; 232 | color:#fff; 233 | left:-14px; 234 | } 235 | .copy .tip.tip--thin{ 236 | font-size:0.9rem; 237 | padding:1rem 2rem; 238 | } 239 | .copy .tip.tip--thin:before{ 240 | top:0.75rem; 241 | } 242 | .copy .tip p:first-child{ 243 | margin-top:0; 244 | } 245 | .copy .tip p:last-child{ 246 | margin-bottom:0; 247 | } 248 | .copy ul{ 249 | list-style:disc; 250 | margin-left:1em; 251 | padding-left:1em; 252 | } 253 | .copy ul ul{ 254 | margin-bottom:0; 255 | margin-top:0; 256 | } 257 | .copy ol{ 258 | list-style:decimal; 259 | margin-left:1em; 260 | padding-left:1em; 261 | } 262 | .copy ol ol{ 263 | list-style:circle; 264 | } 265 | .copy li+li,.copy ul ul li,.copy ol ol li{ 266 | margin-top:0.35rem; 267 | } 268 | .logo__wordmark{ 269 | background:url("../images/aframe-name-pink.svg") no-repeat; 270 | display:block; 271 | height:31px; 272 | margin-bottom:30px; 273 | text-indent:-9999px; 274 | } 275 | @media (min-width: 900px) { 276 | .logo__wordmark{ 277 | height:33px; 278 | } 279 | } 280 | .float-left{ 281 | float:left; 282 | } 283 | .float-right{ 284 | float:right; 285 | } 286 | .c:after{ 287 | clear:both; 288 | content:""; 289 | display:table; 290 | } 291 | @media screen and (max-width: 768px) { 292 | .sidebar__wrap,.copy__wrap{ 293 | padding:20px; 294 | } 295 | .logo__wordmark{ 296 | margin-bottom:20px; 297 | } 298 | } 299 | .sponsor{ 300 | vertical-align:middle; 301 | position:absolute; 302 | bottom:0; 303 | right:0; 304 | margin:0 20px 20px; 305 | height:30px; 306 | } 307 | .sponsor .message{ 308 | margin-right:7px; 309 | display:inline-block; 310 | height:30px; 311 | line-height:30px; 312 | vertical-align:top; 313 | font-weight:300; 314 | } 315 | a.mozilla-logo{ 316 | display:inline-block; 317 | opacity:0.8; 318 | background:url("../images/mozilla-logo.svg") no-repeat; 319 | height:24px; 320 | width:84px; 321 | border:none; 322 | margin-left:0.25ch; 323 | top:1px; 324 | transition:0.15s opacity ease-in-out; 325 | } 326 | a.mozilla-logo:hover{ 327 | opacity:1; 328 | } 329 | .github-emoji{ 330 | vertical-align:top; 331 | } 332 | code,pre,.example__viewsource,.sidebar .page-title,.menu-item a{ 333 | font-family:Fira Mono,Consolas,Andale Mono,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace; 334 | } 335 | .hidden{ 336 | display:!important; 337 | } 338 | em{ 339 | color:#7f8c8d; 340 | } 341 | html[data-is-home="true"]{ 342 | min-width:1000px; 343 | } 344 | html[data-is-home="true"] .sidebar .get-started{ 345 | display:none; 346 | } 347 | body{ 348 | color:#fff; 349 | } 350 | a{ 351 | border-bottom:1px solid rgba(255,255,255,0.25); 352 | color:rgba(255,255,255,0.5); 353 | text-decoration:none; 354 | } 355 | a:hover{ 356 | border-bottom-color:rgba(255,255,255,0.3); 357 | color:rgba(255,255,255,0.75); 358 | } 359 | a:active,a.click{ 360 | border-bottom-color:rgba(255,255,255,0.5); 361 | color:#fff; 362 | } 363 | ul{ 364 | list-style-type:none; 365 | } 366 | .logo__wordmark{ 367 | background:url("../images/aframe-name-white.svg") no-repeat; 368 | } 369 | .sidebar{ 370 | background:#ef2d5e; 371 | -webkit-overflow-scrolling:touch; 372 | -ms-overflow-style:none; 373 | width:270px; 374 | } 375 | .sidebar::-webkit-scrollbar{ 376 | width:0!important; 377 | } 378 | .sidebar .page-title{ 379 | font-size:20px; 380 | color:rgba(0,0,0,0.6); 381 | font-weight:100; 382 | letter-spacing:0.02em; 383 | } 384 | 385 | .sidebar .page-content{ 386 | font-size:12px; 387 | color:rgba(255,255,255,1); 388 | font-weight:100; 389 | letter-spacing:0.02em; 390 | padding:5px 0px; 391 | padding-bottom: 40px; 392 | } 393 | 394 | .sidebar .wallet-info{ 395 | font-size:12px; 396 | color:rgba(255,255,255,1); 397 | font-weight:100; 398 | letter-spacing:0.02em; 399 | padding:5px 0px; 400 | display:none; 401 | } 402 | 403 | .sidebar .metamask-prompt{ 404 | font-size:12px; 405 | color:rgba(255,255,255,1); 406 | font-weight:100; 407 | letter-spacing:0.02em; 408 | padding:5px 0px; 409 | display:none; 410 | } 411 | 412 | 413 | .sidebar .getting-started-info{ 414 | font-size:12px; 415 | color:rgba(255,255,255,1); 416 | font-weight:100; 417 | letter-spacing:0.02em; 418 | padding:5px 0px; 419 | } 420 | 421 | 422 | 423 | .sidebar .page-subtitle{ 424 | font-size:12px; 425 | color:rgba(0,0,0,0.6); 426 | font-weight:100; 427 | letter-spacing:0.02em; 428 | } 429 | 430 | 431 | .main{ 432 | background:#ef2d5e; 433 | display:-webkit-box; 434 | display:-ms-flexbox; 435 | display:flex; 436 | height:100%; 437 | } 438 | .sidebar,.content{ 439 | position:relative; 440 | } 441 | .sidebar{ 442 | max-width:400px; 443 | overflow-x:hidden; 444 | } 445 | .sidebar__wrap{ 446 | height:100vh; 447 | position:relative; 448 | overflow-y:auto; 449 | } 450 | .content{ 451 | -webkit-box-flex:1; 452 | -ms-flex:1; 453 | flex:1; 454 | overflow-y:auto; 455 | display:-webkit-box; 456 | display:-ms-flexbox; 457 | display:flex; 458 | -webkit-box-orient:vertical; 459 | -webkit-box-direction:normal; 460 | -ms-flex-direction:column; 461 | flex-direction:column; 462 | } 463 | .example__controls{ 464 | position:absolute; 465 | text-transform:uppercase; 466 | top:5px; 467 | right:5px; 468 | z-index:2; 469 | font-size:12px; 470 | line-height:1.5; 471 | } 472 | .example__controls a{ 473 | background:rgba(0,0,0,0.35); 474 | color:#fff; 475 | display:inline-block; 476 | padding:5px 10px; 477 | } 478 | .example__controls a:active,.example__controls a:hover{ 479 | background-color:#ef2d5e; 480 | } 481 | .aframe-animation .example__controls{ 482 | display:none; 483 | } 484 | [data-is-mobile="true"] .example__controls{ 485 | display:none; 486 | } 487 | .page__title{ 488 | line-height:1.3; 489 | font-size:36px; 490 | font-weight:600; 491 | } 492 | .subnav-link{ 493 | font-size:16px; 494 | font-weight:300; 495 | margin-left:-3px; 496 | padding:2px 4px 2px 3px; 497 | display:block; 498 | transition:0.05s color ease; 499 | color:#fff; 500 | width:100%; 501 | } 502 | .subnav-link:hover{ 503 | background-color:rgba(0,0,0,0.05); 504 | color:#fff; 505 | } 506 | .subnav-link:active,.subnav-link.click{ 507 | background-color:rgba(0,0,0,0.5); 508 | } 509 | .subnav-link.current,.subnav-link.current:hover{ 510 | font-weight:500; 511 | color:#fff; 512 | } 513 | .example__iframe{ 514 | display:block; 515 | } 516 | .example-nav-link{ 517 | border:0; 518 | height:100%; 519 | font-size:2rem; 520 | font-weight:600; 521 | display:inline-block; 522 | padding:0.5rem 1rem; 523 | margin:-0.5rem -1rem; 524 | width:50%; 525 | } 526 | .example-nav-link span{ 527 | display:none; 528 | } 529 | .example-nav-next{ 530 | text-align:right; 531 | } 532 | .credits{ 533 | background:url("../images/mozvr-white.svg") 45% 60% no-repeat; 534 | background-size:80% 80%; 535 | position:absolute; 536 | bottom:0; 537 | right:0; 538 | height:50px; 539 | width:90px; 540 | margin:0px 20px 20px; 541 | } 542 | .credits:hover{ 543 | background-color:rgba(0,0,0,0.1); 544 | } 545 | .sponsor{ 546 | vertical-align:middle; 547 | position:absolute; 548 | bottom:0; 549 | right:0; 550 | margin:0 20px 20px; 551 | height:30px; 552 | } 553 | .sponsor .message{ 554 | margin-right:7px; 555 | display:inline-block; 556 | height:30px; 557 | line-height:30px; 558 | vertical-align:top; 559 | font-weight:300; 560 | } 561 | a.mozilla-logo{ 562 | display:inline-block; 563 | opacity:0.8; 564 | background:url("../images/mozilla-logo.svg") no-repeat; 565 | height:24px; 566 | width:88px; 567 | border:none; 568 | position:relative; 569 | top:1px; 570 | transition:0.15s opacity ease-in-out; 571 | } 572 | a.mozilla-logo:hover{ 573 | opacity:1; 574 | } 575 | .examples-subnav{ 576 | margin-top:0.5rem; 577 | } 578 | .btn-index{ 579 | color:#fff; 580 | } 581 | .content--examples,.content--body{ 582 | height:100%; 583 | } 584 | .content--examples .content--body{ 585 | background:#dadada; 586 | } 587 | span[itemprop]{ 588 | opacity:0.65; 589 | } 590 | .content--index{ 591 | -webkit-box-orient:horizontal; 592 | -webkit-box-direction:normal; 593 | -ms-flex-direction:row; 594 | flex-direction:row; 595 | } 596 | .content--index .slogan{ 597 | color:#fff; 598 | font-size:28px; 599 | font-weight:300; 600 | line-height:1.2; 601 | letter-spacing:-0.05rem; 602 | } 603 | .content--index .intro{ 604 | color:#fff; 605 | font-size:16.5px; 606 | font-weight:300; 607 | line-height:1.55; 608 | margin-top:10px; 609 | width:350px; 610 | } 611 | .content--index .disclaimer{ 612 | color:rgba(255,255,255,0.5); 613 | } 614 | .menu{ 615 | margin-bottom:38px; 616 | } 617 | .menu-item{ 618 | display:inline-block; 619 | } 620 | .menu-item a{ 621 | text-transform:uppercase; 622 | color:rgba(0,0,0,0.75); 623 | margin-right:20px; 624 | border:none; 625 | } 626 | .menu-item a:hover{ 627 | color:#000; 628 | background-color:rgba(0,0,0,0.02); 629 | border-bottom:1px solid rgba(0,0,0,0.5); 630 | } 631 | .get-started{ 632 | background-color:#fff; 633 | border:3px solid #fff; 634 | box-shadow: 635 | 0 0 0 1px #C63702 inset, 636 | 0 0 0 2px rgba(white, 0.15) inset, 637 | 0 8px 0 0 #AD3002, 638 | 0 8px 0 1px rgba(black, 0.4), 639 | 0 8px 8px 1px rgba(black, 0.5); 640 | color:#000; 641 | display:inline-block; 642 | font-size:12px; 643 | font-weight:300; 644 | letter-spacing:0.05rem; 645 | margin-top:20px; 646 | padding:8px 30px; 647 | text-align:center; 648 | text-transform:uppercase; 649 | transition:0.05s ease; 650 | } 651 | .get-started:hover{ 652 | background-color:#fff; 653 | color:#ef2d5e; 654 | } 655 | .get-started:active{ 656 | opacity:0.8; 657 | } 658 | .mobile-get-started{ 659 | margin:0 0 20px; 660 | } 661 | 662 | .mobile-put-back{ 663 | margin:0 0 20px; 664 | } 665 | 666 | 667 | @media screen and (max-width: 399px) { 668 | #logo{ 669 | max-width:40vw; 670 | } 671 | } 672 | @media screen and (min-width: 480px) { 673 | .example__controls{ 674 | top:20px; 675 | right:20px; 676 | } 677 | } 678 | @media screen and (min-width: 768px) { 679 | .example__controls{ 680 | top:30px; 681 | right:30px; 682 | } 683 | } 684 | @media only screen and (max-device-width: 736px) and (orientation: landscape) { 685 | .sidebar{ 686 | display:none; 687 | } 688 | } 689 | [data-is-android="true"] [data-supports-android="false"],[data-is-ios="true"] [data-supports-ios="false"]{ 690 | display:none!important; 691 | } 692 | .home-content{ 693 | display:-webkit-box; 694 | display:-ms-flexbox; 695 | display:flex; 696 | } 697 | .home-center{ 698 | background-color:#353449; 699 | -webkit-box-flex:2; 700 | -ms-flex:2; 701 | flex:2; 702 | height:100vh; 703 | width:100%; 704 | } 705 | .content--index .copy__wrap{ 706 | -webkit-box-flex:1; 707 | -ms-flex:1; 708 | flex:1; 709 | min-width:440px; 710 | } 711 | .home-feature-links{ 712 | display:none; 713 | font-size:16px; 714 | font-weight:300; 715 | margin-bottom:25px; 716 | } 717 | .home-feature-links li{ 718 | margin-left:-3px; 719 | padding:2px 4px 2px 3px; 720 | text-transform:uppercase; 721 | } 722 | .home-feature-links li:hover{ 723 | background-color:rgba(0,0,0,0.05); 724 | } 725 | .home-feature-links a{ 726 | border:0; 727 | color:#fff; 728 | display:block; 729 | } 730 | [data-is-mobile="false"] .home-feature-links{ 731 | display:block; 732 | } 733 | .example-tracked-controllers{ 734 | display:inline-block; 735 | height:18px; 736 | left:1px; 737 | position:relative; 738 | top:4px; 739 | width:20px; 740 | } 741 | .blog-list{ 742 | display:none; 743 | padding-top:100px; 744 | } 745 | @media (min-width: 900px) { 746 | .blog-list{ 747 | display:block; 748 | } 749 | } 750 | .blog-list .page-title a{ 751 | border-bottom:0; 752 | font-weight:300; 753 | font-size:15px; 754 | color:rgba(0,0,0,0.6); 755 | font-weight:100; 756 | letter-spacing:0.02em; 757 | } 758 | .blog-list .subnav-link{ 759 | width:210px; 760 | overflow:hidden; 761 | text-overflow:ellipsis; 762 | white-space:nowrap; 763 | } 764 | .example-nav{ 765 | margin-top:18px; 766 | } 767 | -------------------------------------------------------------------------------- /css/mobile.css: -------------------------------------------------------------------------------- 1 | @media screen and (max-width: 768px) { 2 | .mobile-get-started{ 3 | display:inline-block; 4 | position:absolute; 5 | padding:1.5vw 5vw; 6 | margin:0; 7 | right:20px; 8 | top:20px; 9 | } 10 | 11 | .mobile-put-back{ 12 | display:inline-block; 13 | position:absolute; 14 | padding:1.5vw 5vw; 15 | margin:0; 16 | left:20px; 17 | top:20px; 18 | } 19 | 20 | .main{ 21 | -webkit-box-orient:vertical; 22 | -webkit-box-direction:normal; 23 | -ms-flex-direction:column; 24 | flex-direction:column; 25 | -webkit-box-pack:justify; 26 | -ms-flex-pack:justify; 27 | justify-content:space-between; 28 | } 29 | .example__iframe{ 30 | height:100%; 31 | } 32 | .content--body{ 33 | position:absolute; 34 | bottom:0; 35 | left:0; 36 | top:0; 37 | right:0; 38 | } 39 | .sidebar__wrap,.copy__wrap{ 40 | padding:20px; 41 | } 42 | .sidebar,.sidebar__wrap{ 43 | height:150px; 44 | overflow-x:hidden; 45 | } 46 | .sidebar{ 47 | -webkit-box-ordinal-group:2; 48 | -ms-flex-order:1; 49 | order:1; 50 | padding:0; 51 | position:relative; 52 | max-width:100%; 53 | width:100%; 54 | } 55 | .sidebar .nav{ 56 | border:0; 57 | margin-bottom:0; 58 | padding:20px 0 0; 59 | } 60 | .example-nav{ 61 | position:absolute; 62 | height:80px; 63 | bottom:0; 64 | left:0; 65 | width:100%; 66 | } 67 | #logo{ 68 | display:block; 69 | height:35px; 70 | pointer-events:none; 71 | } 72 | .logo__wordmark{ 73 | background-position:0 50%; 74 | background-size:contain; 75 | margin-bottom:20px; 76 | width:100%; 77 | } 78 | .example-nav-link{ 79 | border:0; 80 | height:100%; 81 | font-size:2rem; 82 | font-weight:600; 83 | width:50%; 84 | margin:0; 85 | padding:0.5rem 16px; 86 | position:absolute; 87 | bottom:0; 88 | } 89 | 90 | .metamask-prompt 91 | { 92 | padding:0.5rem 2rem; 93 | position:absolute; 94 | top:75px; 95 | left:0; 96 | right:0; 97 | text-align:center; 98 | width:100%; 99 | } 100 | 101 | .wallet-info 102 | { 103 | display:none; 104 | } 105 | 106 | .getting-started-info 107 | { 108 | padding:0.5rem 2rem; 109 | position:absolute; 110 | top:100px; 111 | left:0; 112 | right:0; 113 | text-align:center; 114 | width:100%; 115 | } 116 | 117 | a{ 118 | border-bottom:1px solid rgba(255,255,255,0.25); 119 | color:rgba(255,255,255,0.8); 120 | text-decoration:none; 121 | } 122 | 123 | .page-title 124 | { 125 | display:none; 126 | } 127 | 128 | .page-content 129 | { 130 | display:none; 131 | } 132 | 133 | .example-nav-link span{ 134 | display:none; 135 | } 136 | .example-nav-prev{ 137 | left:0; 138 | } 139 | .example-nav-next{ 140 | right:0; 141 | } 142 | .subnav-item.current{ 143 | padding:0.5rem 2rem; 144 | position:absolute; 145 | top:75px; 146 | left:0; 147 | right:0; 148 | pointer-events:none; 149 | text-align:center; 150 | width:100%; 151 | } 152 | .subnav-item.current .subnav-link{ 153 | font-size:1.4rem; 154 | } 155 | .subnav-item:not(.current),.page-title{ 156 | display:none; 157 | } 158 | .examples-list{ 159 | border:0; 160 | padding:0; 161 | } 162 | .example-nav{ 163 | margin-top:0; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /index-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

web3 Provider

6 |

0x000000000

7 |

Account Key

8 |

0x000000000

9 |

Eth Balance

10 |

0

11 |

Sim Balance

12 |

0

13 | 14 | 15 | 16 | 17 | 18 | 19 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello Crypto! 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 69 |
70 |
71 | 72 | 73 | 74 |
75 |
76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | 2 | window.onload = function() 3 | { 4 | // vars 5 | this.buttonRaining = true; 6 | this.currentRainingEth = 0; 7 | this.rainObject = {}; 8 | this.counterObject = {}; 9 | this.counterBGObject = {}; 10 | this.walletInfo = {}; 11 | 12 | // uses Ethereum balance if true, otherwise gets SIM balance 13 | useEth = true; 14 | 15 | bindUI(); 16 | 17 | // if mobile, inform user to visit desktop and exit function 18 | if (settings.isMobile) { 19 | document.getElementById('metamask-prompt').textContent = 'Visit this page on your desktop browser for Metamask support.'; 20 | document.getElementById('metamask-prompt').style.display = 'block'; 21 | return; 22 | } 23 | 24 | // Get web3 provider 25 | if (typeof web3 !== 'undefined') { 26 | web3Provider = web3.currentProvider; 27 | this.walletInfo.provider=web3Provider.constructor.name; 28 | } else { 29 | // If no injected web3 instance is detected, fallback to the TestRPC 30 | web3Provider = new Web3.providers.HttpProvider('http://localhost:9545'); 31 | this.walletInfo.provider="HttpProvider"; 32 | } 33 | 34 | web3 = new Web3(web3Provider); 35 | 36 | // Get account ID 37 | this.walletInfo.accountID = web3.eth.accounts[0]; 38 | 39 | // Get token balances 40 | if (useEth) 41 | 42 | { 43 | web3.eth.getBalance(this.walletInfo.accountID, function(error, result){ 44 | if(!error) 45 | { 46 | walletInfo.ETHBalance = web3.fromWei(result, "ether").toFixed(2) + " ETH"; 47 | rainObject.data.maxDrops = web3.fromWei(result, "ether"); 48 | displayWallet(); 49 | } 50 | else 51 | console.error(error); 52 | }); 53 | } 54 | 55 | else // use custom SimpleToken SIM 56 | 57 | { 58 | 59 | var simpleTokenContract; 60 | var simpleTokenInstance; 61 | var errorMsg; 62 | 63 | // store the contract 64 | $.getJSON('build/contracts/SimpleToken.json', function(data) { 65 | 66 | // Get the necessary contract artifact file and instantiate it with truffle-contract 67 | var SimpleTokenArtifact = data; 68 | simpleTokenContract = TruffleContract(SimpleTokenArtifact); 69 | 70 | // Set the provider for our contract 71 | simpleTokenContract.setProvider(web3Provider); 72 | 73 | // invoke the contract to get the balance 74 | simpleTokenContract.deployed().then(function(instance) { 75 | simpleTokenContractInstance = instance; 76 | 77 | return simpleTokenContractInstance.balanceOf(this.walletInfo.accountID); 78 | }).then(function(result) { 79 | walletInfo.SIMBalance = result.toString(); 80 | displayWallet(); 81 | 82 | }).catch(function(err) { 83 | walletInfo.SIMBalanceError=err.toString(); 84 | }); 85 | }); 86 | 87 | } 88 | 89 | displayWallet(); 90 | 91 | } 92 | 93 | function bindUI() 94 | { 95 | document.getElementById('rainbutton').onclick = function() { 96 | makeItRain(); 97 | } 98 | 99 | var i = document.querySelector('iframe'); 100 | this.rainObject = i.contentWindow.document.body.querySelector('a-scene[rain]').components.rain; 101 | this.counterBGObject = i.contentWindow.document.body.querySelector('#counter-bg'); 102 | this.counterObject = i.contentWindow.document.body.querySelector('#counter'); 103 | } 104 | 105 | // need to access it from inside the iframe, so hacky! 106 | function makeItRain() 107 | { 108 | var rain = this.rainObject; 109 | 110 | rain.data.isRaining = this.buttonRaining; 111 | 112 | this.counterBGObject.setAttribute("visible", this.buttonRaining); 113 | 114 | if (!rain.data.isRaining) 115 | { 116 | document.getElementById('rainbutton').textContent = "(ノ ˘_˘)ノ 。゜。゚" 117 | } 118 | 119 | else { 120 | document.getElementById('rainbutton').textContent = "。.。. .。.ノ( º _ ºノ)" 121 | this.rainObject.data.currentDrop = 0; 122 | } 123 | 124 | // switch button started 125 | this.buttonRaining = !this.buttonRaining; 126 | 127 | } 128 | 129 | function displayWallet() 130 | { 131 | var walletInfo = this.walletInfo; 132 | 133 | /* 134 | document.getElementById('wallet-info').textContent=walletInfo.provider; 135 | document.getElementById('wallet-info').style.display = 'block'; 136 | */ 137 | 138 | var l = walletInfo.accountID.length; 139 | 140 | document.getElementById('key').textContent= "Wallet ID: " + 141 | walletInfo.accountID.slice(0, 8) + "......" + walletInfo.accountID.slice(l-8, l); 142 | document.getElementById('ethbal').textContent="Account Balance: " + walletInfo.ETHBalance; 143 | document.getElementById('simbal').textContent=walletInfo.SIMBalance; 144 | 145 | document.getElementById('key').style.display = 'block'; 146 | document.getElementById('ethbal').style.display = 'block'; 147 | document.getElementById('simbal').style.display = 'block'; 148 | 149 | } 150 | -------------------------------------------------------------------------------- /js/compat.js: -------------------------------------------------------------------------------- 1 | (function(){var html=document.documentElement;function isIOS(){return/iPad|iPhone|iPod/i.test(navigator.platform);} 2 | function isAndroid(){return/Android/i.test(navigator.userAgent);} 3 | function isMobile(){var check=false;(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))){check=true;} 4 | if(isIOS()){check=true;}})(navigator.userAgent||navigator.vendor||window.opera);return check;} 5 | function strToBool(str){return(str||'').trim().toLowerCase()==='true';} 6 | var settings=window.settings={};Object.keys(html.dataset).forEach(function(key){settings[key]=html.dataset[key];});settings.isMobile=isMobile();settings.isAndroid=isAndroid();settings.isIOS=isIOS();settings.isHome=strToBool(settings.isHome);settings.isSpa=strToBool(settings.isSpa);settings.siteBaseUrl=settings.siteBaseUrl;settings.siteRootPath=settings.siteRootPath;settings.siteHomeUrl=settings.siteHomeUrl;settings.libHomeUrl=settings.libHomeUrl;settings.libExamplesUrl=settings.libExamplesUrl;html.setAttribute('data-is-mobile',settings.isMobile);html.setAttribute('data-is-android',settings.isAndroid);html.setAttribute('data-is-ios',settings.isIOS);if(settings.isMobile&&settings.isHome){window.location.pathname='/examples/';return;} 7 | html.setAttribute('data-supports-touch','ontouchstart'in window);var supportsVR='getVRDisplays'in navigator;var supportsVRLegacy='getVRDevices'in navigator;html.setAttribute('data-supports-vr',supportsVR||supportsVRLegacy);html.setAttribute('data-supports-vr-legacy',supportsVRLegacy);html.setAttribute('data-supports-webvrplus','WEBVRPLUS'in window);})(); 8 | -------------------------------------------------------------------------------- /make-it-rain.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hello Crypto! 8 | 9 | 10 | 11 | 12 | 182 | 183 | 184 | 185 | 186 | 187 | 190 | 191 | 192 | 193 | 194 | 200 | 201 | 202 | 203 | 204 | 206 | 210 | 215 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /migrations/2_deploy_token.js: -------------------------------------------------------------------------------- 1 | var SimpleToken = artifacts.require("SimpleToken"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(SimpleToken); 5 | }; 6 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "@openzeppelin/contracts": { 6 | "version": "2.3.0", 7 | "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-2.3.0.tgz", 8 | "integrity": "sha512-lf8C3oULQAnsu3OTRP4tP5/ddfil6l65Lg3JQCwAIgc99vZ1jz5qeBoETGGGmczxt+bIyMI06WPP2apC74EZag==" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ss/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/ss/1.png -------------------------------------------------------------------------------- /ss/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/ss/2.png -------------------------------------------------------------------------------- /ss/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/ss/3.png -------------------------------------------------------------------------------- /ss/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/ss/4.png -------------------------------------------------------------------------------- /ss/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/ss/5.png -------------------------------------------------------------------------------- /ss/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alto-io/hello-crypto/16417b44801b963b9333272a76b166a33dd7a0a8/ss/6.png -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Use this file to configure your truffle project. It's seeded with some 3 | * common settings for different networks and features like migrations, 4 | * compilation and testing. Uncomment the ones you need or modify 5 | * them to suit your project as necessary. 6 | * 7 | * More information about configuration can be found at: 8 | * 9 | * truffleframework.com/docs/advanced/configuration 10 | * 11 | * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider) 12 | * to sign your transactions before they're sent to a remote public node. Infura accounts 13 | * are available for free at: infura.io/register. 14 | * 15 | * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate 16 | * public/private key pairs. If you're publishing your code to GitHub make sure you load this 17 | * phrase from a file you've .gitignored so it doesn't accidentally become public. 18 | * 19 | */ 20 | 21 | // const HDWalletProvider = require('truffle-hdwallet-provider'); 22 | // const infuraKey = "fj4jll3k....."; 23 | // 24 | // const fs = require('fs'); 25 | // const mnemonic = fs.readFileSync(".secret").toString().trim(); 26 | 27 | module.exports = { 28 | /** 29 | * Networks define how you connect to your ethereum client and let you set the 30 | * defaults web3 uses to send transactions. If you don't specify one truffle 31 | * will spin up a development blockchain for you on port 9545 when you 32 | * run `develop` or `test`. You can ask a truffle command to use a specific 33 | * network from the command line, e.g 34 | * 35 | * $ truffle test --network 36 | */ 37 | 38 | networks: { 39 | // Useful for testing. The `development` name is special - truffle uses it by default 40 | // if it's defined here and no other network is specified at the command line. 41 | // You should run a client (like ganache-cli, geth or parity) in a separate terminal 42 | // tab if you use this network and you must also set the `host`, `port` and `network_id` 43 | // options below to some value. 44 | // 45 | // development: { 46 | // host: "127.0.0.1", // Localhost (default: none) 47 | // port: 8545, // Standard Ethereum port (default: none) 48 | // network_id: "*", // Any network (default: none) 49 | // }, 50 | 51 | // Another network with more advanced options... 52 | // advanced: { 53 | // port: 8777, // Custom port 54 | // network_id: 1342, // Custom network 55 | // gas: 8500000, // Gas sent with each transaction (default: ~6700000) 56 | // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) 57 | // from:
, // Account to send txs from (default: accounts[0]) 58 | // websockets: true // Enable EventEmitter interface for web3 (default: false) 59 | // }, 60 | 61 | // Useful for deploying to a public network. 62 | // NB: It's important to wrap the provider as a function. 63 | // ropsten: { 64 | // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), 65 | // network_id: 3, // Ropsten's id 66 | // gas: 5500000, // Ropsten has a lower block limit than mainnet 67 | // confirmations: 2, // # of confs to wait between deployments. (default: 0) 68 | // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 69 | // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) 70 | // }, 71 | 72 | // Useful for private networks 73 | // private: { 74 | // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), 75 | // network_id: 2111, // This network is yours, in the cloud. 76 | // production: true // Treats this network as if it was a public net. (default: false) 77 | // } 78 | }, 79 | 80 | // Set default mocha options here, use special reporters etc. 81 | mocha: { 82 | // timeout: 100000 83 | }, 84 | 85 | // Configure your compilers 86 | compilers: { 87 | solc: { 88 | // version: "0.5.1", // Fetch exact version from solc-bin (default: truffle's version) 89 | // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) 90 | // settings: { // See the solidity docs for advice about optimization and evmVersion 91 | // optimizer: { 92 | // enabled: false, 93 | // runs: 200 94 | // }, 95 | // evmVersion: "byzantium" 96 | // } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | var HDWalletProvider = require("truffle-hdwallet-provider"); 2 | var mnemonic = "desert chest husband hedgehog kit galaxy opinion someone truly flag scorpion marble"; 3 | 4 | module.exports = { 5 | networks: { 6 | ropsten: { 7 | provider: function() { 8 | return new HDWalletProvider(mnemonic, "https://ropsten.infura.io/kHINF1xpjrbTrUgnr8Dk") 9 | }, 10 | network_id: 3, 11 | gas: 4600000 12 | } 13 | } 14 | }; 15 | --------------------------------------------------------------------------------