Workshop para desenvolvedores apresentando smart-contracts na plataforma Ethereum
47 |
48 |
49 |
50 |
51 |
Player2
52 |
Account address:
53 |
Seed:
54 |
55 |
Balance
56 |
57 |
58 |
Total Pokemons
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
Vender Pokémon
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
Mercado Ativo
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/app/javascripts/txutils.js:
--------------------------------------------------------------------------------
1 | var Transaction = require('ethereumjs-tx');
2 | var coder = require('web3/lib/solidity/coder');
3 | var rlp = require('rlp');
4 | var CryptoJS = require('crypto-js');
5 |
6 | function add0x (input) {
7 | if (typeof(input) !== 'string') {
8 | return input;
9 | }
10 | else if (input.length < 2 || input.slice(0,2) !== '0x') {
11 | return '0x' + input;
12 | }
13 | else {
14 | return input;
15 | }
16 | }
17 |
18 | function _encodeFunctionTxData (functionName, types, args) {
19 |
20 | var fullName = functionName + '(' + types.join() + ')';
21 | var signature = CryptoJS.SHA3(fullName, { outputLength: 256 }).toString(CryptoJS.enc.Hex).slice(0, 8);
22 | var dataHex = signature + coder.encodeParams(types, args);
23 |
24 | return dataHex;
25 | }
26 |
27 | function _getTypesFromAbi (abi, functionName) {
28 |
29 | function matchesFunctionName(json) {
30 | return (json.name === functionName && json.type === 'function');
31 | }
32 |
33 | function getTypes(json) {
34 | return json.type;
35 | }
36 |
37 | var funcJson = abi.filter(matchesFunctionName)[0];
38 |
39 | return (funcJson.inputs).map(getTypes);
40 | }
41 |
42 | function functionTx (abi, functionName, args, txObject) {
43 | // txObject contains gasPrice, gasLimit, nonce, to, value
44 |
45 | var types = _getTypesFromAbi(abi, functionName);
46 | var txData = _encodeFunctionTxData(functionName, types, args);
47 |
48 | var txObjectCopy = {};
49 | txObjectCopy.to = add0x(txObject.to);
50 | txObjectCopy.gasPrice = add0x(txObject.gasPrice);
51 | txObjectCopy.gasLimit = add0x(txObject.gasLimit);
52 | txObjectCopy.nonce = add0x(txObject.nonce);
53 | txObjectCopy.data = add0x(txData);
54 | txObjectCopy.value = add0x(txObject.value);
55 |
56 | return (new Transaction(txObjectCopy)).serialize().toString('hex');
57 | }
58 |
59 | function createdContractAddress (fromAddress, nonce) {
60 | var rlpEncodedHex = rlp.encode([new Buffer(fromAddress, 'hex'), nonce]).toString('hex');
61 | var rlpEncodedWordArray = CryptoJS.enc.Hex.parse(rlpEncodedHex);
62 | var hash = CryptoJS.SHA3(rlpEncodedWordArray, {outputLength: 256}).toString(CryptoJS.enc.Hex);
63 |
64 | return hash.slice(24);
65 | }
66 |
67 | function createContractTx (fromAddress, txObject) {
68 | // txObject contains gasPrice, gasLimit, value, data, nonce
69 |
70 | var txObjectCopy = {};
71 | txObjectCopy.to = add0x(txObject.to);
72 | txObjectCopy.gasPrice = add0x(txObject.gasPrice);
73 | txObjectCopy.gasLimit = add0x(txObject.gasLimit);
74 | txObjectCopy.nonce = add0x(txObject.nonce);
75 | txObjectCopy.data = add0x(txObject.data);
76 | txObjectCopy.value = add0x(txObject.value);
77 |
78 | var contractAddress = createdContractAddress(fromAddress, txObject.nonce);
79 | var tx = new Transaction(txObjectCopy);
80 |
81 | return {tx: tx.serialize().toString('hex'), addr: contractAddress};
82 | }
83 |
84 | function valueTx (txObject) {
85 | // txObject contains gasPrice, gasLimit, value, nonce
86 |
87 | var txObjectCopy = {};
88 | txObjectCopy.to = add0x(txObject.to);
89 | txObjectCopy.gasPrice = add0x(txObject.gasPrice);
90 | txObjectCopy.gasLimit = add0x(txObject.gasLimit);
91 | txObjectCopy.nonce = add0x(txObject.nonce);
92 | txObjectCopy.value = add0x(txObject.value);
93 |
94 | var tx = new Transaction(txObjectCopy);
95 |
96 | return tx.serialize().toString('hex');
97 | }
98 |
99 | module.exports = {
100 | _encodeFunctionTxData: _encodeFunctionTxData,
101 | _getTypesFromAbi: _getTypesFromAbi,
102 | functionTx: functionTx,
103 | createdContractAddress: createdContractAddress,
104 | createContractTx: createContractTx,
105 | valueTx: valueTx
106 | };
107 |
--------------------------------------------------------------------------------
/contracts/PokeCoin.sol:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2016 Edilson Osorio Junior - OriginalMy.com
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | pragma solidity ^0.4.2;
24 | contract tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData); }
25 |
26 | contract accessControlled {
27 | address public owner;
28 | address public pokeMarketAddress;
29 |
30 | function owned() {
31 | owner = msg.sender;
32 | }
33 |
34 | modifier onlyOwner {
35 | if (msg.sender != owner) throw;
36 | /* o caracter "_" é substituído pelo corpo da funcao onde o modifier é utilizado */
37 | _;
38 | }
39 |
40 | function transferOwnership(address newOwner) onlyOwner {
41 | owner = newOwner;
42 | }
43 |
44 | function updatePokeMarketAddress(address marketAddress) onlyOwner {
45 | pokeMarketAddress = marketAddress;
46 | }
47 |
48 | }
49 |
50 | contract PokeCoin is accessControlled{
51 | /* Variaveis publicas */
52 | string public standard = 'Pokecoin 0.1';
53 | string public name = 'Pokecoin';
54 | string public symbol = "pkc";
55 | uint256 public totalSupply;
56 |
57 | /* Cria array com os balancos */
58 | mapping (address => uint256) public balanceOf;
59 |
60 | /* Gera um evento publico padrao, que ira notificar os clientes */
61 | event Transfer(address indexed from, address indexed to, uint256 value);
62 |
63 | /* Inicializa o contrato com o numero inicial de tokens */
64 | function PokeCoin( uint256 initialSupply, address account1Demo, address account2Demo) {
65 | owner = msg.sender;
66 |
67 | /* Envia as pokecoins para o criador */
68 | balanceOf[msg.sender] = initialSupply;
69 | /* Ajusta o totalsupply */
70 | totalSupply = initialSupply;
71 |
72 | /* Se incluiu os enderecos demo, então divide as pokecoins entre eles */
73 | if (account1Demo != 0 && account2Demo != 0){
74 | transfer(account1Demo, totalSupply/2);
75 | transfer(account2Demo, totalSupply/2);
76 | }
77 | }
78 |
79 | /* Transferencia de pokecoins (necessario para Mist fazer a transferencia) */
80 | function transfer(address _to, uint256 _value) onlyOwner {
81 | if (balanceOf[msg.sender] < _value) throw; // Verifica se o remetente possui pokecoins suficientes
82 | if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Checa se nao houve ataque
83 | balanceOf[msg.sender] -= _value; // Subtrai as pokecoins do remetente
84 | balanceOf[_to] += _value; // Adiciona pokecoins para o destinatario
85 | Transfer(msg.sender, _to, _value); // Notifica os clientes que estiverem nonitorando
86 | }
87 |
88 | /* Emite novas pokecoins para o owner distribuí-las */
89 | function issueNew(uint256 newSupply) onlyOwner{
90 | balanceOf[msg.sender] += newSupply;
91 | totalSupply += newSupply;
92 | }
93 |
94 | /* Exclui pokecoins do endereço do owner */
95 | function vanishCoins(uint256 qtdCoinsToDelete) onlyOwner{
96 | if (balanceOf[msg.sender] < qtdCoinsToDelete) throw; // Verifica se o owner possui pokecoins suficientes para exclusao
97 | balanceOf[msg.sender] -= qtdCoinsToDelete;
98 | totalSupply -= qtdCoinsToDelete;
99 | }
100 |
101 | /* Funcao para os contratos poderem transferir pokecoins */
102 | function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
103 | if (msg.sender != owner && msg.sender != pokeMarketAddress) throw; // Somente da acesso ao owner e ao mercado pokemon para executar essa funcao
104 |
105 | if (balanceOf[_from] < _value) throw; // Verifica se o remetente possui pokecoins suficientes
106 | if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Checa se nao houve ataque
107 | balanceOf[_from] -= _value; // Subtrai as pokecoins do remetente
108 | balanceOf[_to] += _value; // Adiciona pokecoins para o destinatario
109 | Transfer(_from, _to, _value); // Notifica os clientes que estiverem nonitorando
110 | return true;
111 | }
112 |
113 | /* Uma funcao sem nome '()' eh chamada todas as vezes que forem enviados ethers para ela */
114 | function () {
115 | throw; // Nao permite o recebimento de ether
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/app/javascripts/encryption.js:
--------------------------------------------------------------------------------
1 | var util = require("ethereumjs-util");
2 | var nacl = require('tweetnacl');
3 |
4 | function nacl_encodeHex(msgUInt8Arr) {
5 | var msgBase64 = nacl.util.encodeBase64(msgUInt8Arr);
6 | return (new Buffer(msgBase64, 'base64')).toString('hex');
7 | }
8 |
9 | function nacl_decodeHex(msgHex) {
10 | var msgBase64 = (new Buffer(msgHex, 'hex')).toString('base64');
11 | return nacl.util.decodeBase64(msgBase64);
12 | }
13 |
14 | function _asymEncryptRaw (keystore, pwDerivedKey, msgUint8Array, myPubKey, theirPubKey, hdPathString) {
15 |
16 | if (hdPathString === undefined) {
17 | hdPathString = keystore.defaultHdPathString;
18 | }
19 |
20 | if (keystore.ksData[hdPathString].info.purpose !== 'asymEncrypt') {
21 | throw new Error('encryption._asymEncryptRaw: Function not defined when purpose is not "asymEncrypt"');
22 | }
23 |
24 | if (keystore.ksData[hdPathString].encPrivKeys[myPubKey] === undefined) {
25 | throw new Error('encryption._asymEncryptRaw: public key not found in KeyStore');
26 | }
27 |
28 | var privKey = keystore.exportPrivateKey(myPubKey, pwDerivedKey, hdPathString);
29 | var privKeyUInt8Array = nacl_decodeHex(privKey);
30 | var pubKeyUInt8Array = nacl_decodeHex(theirPubKey);
31 | var nonce = nacl.randomBytes(nacl.box.nonceLength);
32 | var encryptedMessage = nacl.box(msgUint8Array, nonce, pubKeyUInt8Array, privKeyUInt8Array);
33 |
34 | var output = {
35 | alg: 'curve25519-xsalsa20-poly1305',
36 | nonce: nacl.util.encodeBase64(nonce),
37 | ciphertext: nacl.util.encodeBase64(encryptedMessage)
38 | };
39 |
40 | return output;
41 | }
42 |
43 | function _asymDecryptRaw (keystore, pwDerivedKey, encMsg, theirPubKey, myPubKey, hdPathString) {
44 |
45 | if (hdPathString === undefined) {
46 | hdPathString = keystore.defaultHdPathString;
47 | }
48 |
49 | if (keystore.ksData[hdPathString].info.purpose !== 'asymEncrypt') {
50 | throw new Error('encryption._asymDecryptRaw: Function not defined when purpose is not "asymEncrypt"');
51 | }
52 |
53 | if (keystore.ksData[hdPathString].encPrivKeys[myPubKey] === undefined) {
54 | throw new Error('encryption._asymDecryptRaw: public key not found in KeyStore');
55 | }
56 |
57 | var privKey = keystore.exportPrivateKey(myPubKey, pwDerivedKey, hdPathString);
58 | var privKeyUInt8Array = nacl_decodeHex(privKey);
59 | var pubKeyUInt8Array = nacl_decodeHex(theirPubKey);
60 |
61 | var nonce = nacl.util.decodeBase64(encMsg.nonce);
62 | var ciphertext = nacl.util.decodeBase64(encMsg.ciphertext);
63 | var cleartext = nacl.box.open(ciphertext, nonce, pubKeyUInt8Array, privKeyUInt8Array);
64 |
65 | return cleartext;
66 |
67 | }
68 |
69 | var asymEncryptString = function (keystore, pwDerivedKey, msg, myPubKey, theirPubKey, hdPathString) {
70 |
71 | var messageUInt8Array = nacl.util.decodeUTF8(msg);
72 |
73 | return _asymEncryptRaw(keystore, pwDerivedKey, messageUInt8Array, myPubKey, theirPubKey, hdPathString);
74 |
75 | }
76 |
77 | var asymDecryptString = function (keystore, pwDerivedKey, encMsg, theirPubKey, myPubKey, hdPathString) {
78 |
79 | var cleartext = _asymDecryptRaw(keystore, pwDerivedKey, encMsg, theirPubKey, myPubKey, hdPathString);
80 |
81 | if (cleartext === false) {
82 | return false;
83 | }
84 | else {
85 | return nacl.util.encodeUTF8(cleartext);
86 | }
87 |
88 | }
89 |
90 | var multiEncryptString = function (keystore, pwDerivedKey, msg, myPubKey, theirPubKeyArray, hdPathString) {
91 |
92 | var messageUInt8Array = nacl.util.decodeUTF8(msg);
93 | var symEncryptionKey = nacl.randomBytes(nacl.secretbox.keyLength);
94 | var symNonce = nacl.randomBytes(nacl.secretbox.nonceLength);
95 |
96 | var symEncMessage = nacl.secretbox(messageUInt8Array, symNonce, symEncryptionKey);
97 |
98 | if (theirPubKeyArray.length < 1) {
99 | throw new Error('Found no pubkeys to encrypt to.');
100 | }
101 |
102 | var encryptedSymKey = {};
103 | encryptedSymKey = []
104 | for (var i=0; i/support/UTC--2015-08-09T04-06-35.465758600Z--6a5b342ec71def8aac337b82969d9ddd811023c9 private_net/keystore
30 | ```
31 |
32 | 3. Start the blockchain with a new genesis
33 | ```
34 | geth --datadir ./private_net init /support/private_genesis.json
35 | ```
36 |
37 | 4. Start the node
38 | ```
39 | geth --fast --cache 512 -ipcpath ~/Library/Ethereum/geth.ipc --networkid 1234 --datadir ./private_net --unlock 0 --rpc --rpccorsdomain="*" --rpcaddr "0.0.0.0"
40 | ```
41 | 5. Unlock the account[0] with the password 'abcd'
42 |
43 | 6. On a new terminal, attach to the geth console
44 | ```
45 | geth attach
46 | miner.start(1)
47 | ```
48 |
49 | ## Setup using Ethereum Wallet (for using Truffle, jump to the next section)
50 |
51 | 1. Open file `accounts-for-testing.txt`
52 |
53 | 2. Load `contracts/pokecoin.sol` in Ethereum Wallet (contracts > Deploy new contract) and use the demo account addresses from Player1 and Player2 to launch the contract. (2000000 gas)
54 |
55 | 3. Load `contracts/pokecentral.sol` in Ethereum Wallet and use the demo account addresses from Player1 and Player2 to launch the contract. (6000000 gas)
56 |
57 | 4. Write the `Pokecoin` and `PokeCentral` addresses on a notepad.
58 |
59 | 5. Load `contracts/pokemarket.sol` no Ethereum Wallet and use `PokeCoinAddress` and `PokeCentralAddress` to launch the contract. (6000000 gas)
60 |
61 | 6. Write the `Pokemarket` address on a notepad.
62 |
63 | 7. You must update `PokeMarketAddress` in the contracts `PokeCoin` e `PokeCentral` to enable access.
64 |
65 | 8. Update the variables `PokeCoinAddress`, `PokeCentralAddress` e `PokeMarketAddress` in `javascripts/mercadopokemon.js`
66 |
67 | 9. Load `app/player1.html` and `app/player2.html` in separate windows on Chrome browser.
68 |
69 |
70 | ## Setup truffle
71 | 1. Go to the truffle-mercado-pokemon dir and open the Truffle console on a new terminal
72 | ```
73 | truffle console
74 | ```
75 |
76 | 2. Run the migrate to load contracts to blockchain
77 | ```
78 | migrate --reset
79 | ```
80 |
81 | 3. Update vars PokeCoinAddress, PokeCentralAddress and PokeMarketAddress in mercadopokemon.js
82 |
83 | ## Using Mercado Pokemon
84 |
85 | Open player1.html and player2.html each one in a new window in Chrome
86 |
87 | ## Examples using Truffle console
88 |
89 | 1. Transfer pokecoins to the players 1 and 2 using the console:
90 | ```
91 | pokecoin.transfer(account1Demo, 5000, {from:web3.eth.accounts[0],gas:2000000});
92 | pokecoin.transfer(account2Demo, 5000, {from:web3.eth.accounts[0],gas:2000000});
93 | ```
94 |
95 | 5.1 Verify is the transfers were suceeded
96 | ```
97 | pokecoin.balanceOf(account1Demo) // 5000
98 | pokecoin.balanceOf(account2Demo) // 5000
99 | ```
100 |
101 |
102 | 2. Create the next four valid pokemons:
103 | ```
104 | pokecentral.newPokemon(3,500,40, {from:web3.eth.accounts[0],gas:2000000});
105 | pokecentral.newPokemon(1,535,70, {from:web3.eth.accounts[0],gas:2000000});
106 | pokecentral.newPokemon(4,546,80, {from:web3.eth.accounts[0],gas:2000000});
107 | pokecentral.newPokemon(2,557,90, {from:web3.eth.accounts[0],gas:2000000});
108 | ```
109 |
110 | 2.1 Verify pokemon total
111 | ```
112 | pokecentral.totalPokemonSupply() // 4
113 | ```
114 |
115 | 2.2 Verify the pokemon owner (wait until mining)
116 | ```
117 | pokecentral.pokemons(0);
118 | pokecentral.pokemons(1);
119 | pokecentral.pokemons(2);
120 | pokecentral.pokemons(3);
121 | pokecentral.pokemons(4);
122 | ```
123 |
124 | 3. Transfer the pokemons to player1 and player2
125 | ```
126 | pokecentral.transferPokemon(web3.eth.accounts[0], account1Demo, 1,{from:web3.eth.accounts[0],gas:2000000});
127 | pokecentral.transferPokemon(web3.eth.accounts[0], account1Demo, 4,{from:web3.eth.accounts[0],gas:2000000});
128 | pokecentral.transferPokemon(web3.eth.accounts[0], account2Demo, 2,{from:web3.eth.accounts[0],gas:2000000});
129 | pokecentral.transferPokemon(web3.eth.accounts[0], account2Demo, 3,{from:web3.eth.accounts[0],gas:2000000});
130 | ```
131 |
132 | 3.1 Verify the pokemon owner, as in 2.2
133 |
134 | 4. Update the PokeMarketAddress in dapps PokeCoin e PokeCentral
135 | ```
136 | pokecoin.updatePokeMarketAddress(pokemarket.address, {from:web3.eth.accounts[0],gas:2000000});
137 | pokecentral.updatePokeMarketAddress(pokemarket.address, {from:web3.eth.accounts[0],gas:2000000});
138 | ```
139 |
140 | 4.1 Verify the addresses
141 | ```
142 | pokecoin.pokeMarketAddress();
143 | pokecentral.pokeMarketAddress();
144 | ```
145 |
146 | 5. Put the pokemon 1 from account1Demo for selling by 2000 pkc:
147 | ```
148 | pokemarket.newSale(account1Demo, 1, 2000, {from:web3.eth.accounts[0],gas:2000000});
149 | ```
150 |
151 | 6. Verify the number of active sells:
152 | ```
153 | pokemarket.totalActiveSales();
154 | ```
155 |
156 | 7. Verify the active sell 1 data:
157 | ```
158 | pokemarket.pokeSales(0);
159 | ```
160 |
161 | 8. Verify if the pokemon 1 is active for selling:
162 | ```
163 | pokemarket.pokeSelling(1);
164 | ```
165 |
166 | 9. Buy the pokemon 1, with the player 2
167 | ```
168 | pokemarket.buyPokemon(account2Demo, 1, {from:web3.eth.accounts[0],gas:2000000});
169 | ```
170 |
171 | 10. Verify if the pokemon owner was changed to account2Demo address
172 | ```
173 | pokecentral.pokemons(1);
174 | ```
175 |
176 | 11. Verify the pokecoins total for each player
177 | ```
178 | pokecoin.balanceOf(account1Demo);
179 | pokecoin.balanceOf(account2Demo);
180 | ```
181 |
182 | ## How it works:
183 |
184 | Once the contracts were loaded, we created the PokeCoins and Pokemons, and distributed them between Player1 and Player2 accounts.
185 | Through the html files you can put Pokemons for sale and make the purchase.
186 |
187 | ## Obs:
188 | It is necessary that the account [0] is unlocked and has funds. To do this, type: personal.unlockAccount(eth.accounts[0]) on the console.
189 |
190 | If pokecoins are transferred to an account, you can trade them directly in the secondary market, but that wallet must have funds for paying the rsk gas transaction.
191 |
--------------------------------------------------------------------------------
/app/javascripts/hooked-web3-provider.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | "use strict";
4 |
5 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
6 |
7 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
8 |
9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
10 |
11 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
12 |
13 | var factory = function factory(web3) {
14 | var HookedWeb3Provider = (function (_web3$providers$HttpProvider) {
15 | _inherits(HookedWeb3Provider, _web3$providers$HttpProvider);
16 |
17 | function HookedWeb3Provider(_ref) {
18 | var host = _ref.host;
19 | var transaction_signer = _ref.transaction_signer;
20 |
21 | _classCallCheck(this, HookedWeb3Provider);
22 |
23 | _get(Object.getPrototypeOf(HookedWeb3Provider.prototype), "constructor", this).call(this, host);
24 | this.transaction_signer = transaction_signer;
25 |
26 | // Cache of the most up to date transaction counts (nonces) for each address
27 | // encountered by the web3 provider that's managed by the transaction signer.
28 | this.global_nonces = {};
29 | }
30 |
31 | // We can't support *all* synchronous methods because we have to call out to
32 | // a transaction signer. So removing the ability to serve any.
33 |
34 | _createClass(HookedWeb3Provider, [{
35 | key: "send",
36 | value: function send(payload, callback) {
37 | var _this = this;
38 |
39 | var requests = payload;
40 | if (!(requests instanceof Array)) {
41 | requests = [requests];
42 | }
43 |
44 | var _iteratorNormalCompletion = true;
45 | var _didIteratorError = false;
46 | var _iteratorError = undefined;
47 |
48 | try {
49 | for (var _iterator = requests[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
50 | var request = _step.value;
51 |
52 | if (request.method == "eth_sendTransaction") {
53 | throw new Error("HookedWeb3Provider does not support synchronous transactions. Please provide a callback.");
54 | }
55 | }
56 | } catch (err) {
57 | _didIteratorError = true;
58 | _iteratorError = err;
59 | } finally {
60 | try {
61 | if (!_iteratorNormalCompletion && _iterator["return"]) {
62 | _iterator["return"]();
63 | }
64 | } finally {
65 | if (_didIteratorError) {
66 | throw _iteratorError;
67 | }
68 | }
69 | }
70 |
71 | var finishedWithRewrite = function finishedWithRewrite() {
72 | return _get(Object.getPrototypeOf(HookedWeb3Provider.prototype), "send", _this).call(_this, payload, callback);
73 | };
74 |
75 | return this.rewritePayloads(0, requests, {}, finishedWithRewrite);
76 | }
77 |
78 | // Catch the requests at the sendAsync level, rewriting all sendTransaction
79 | // methods to sendRawTransaction, calling out to the transaction_signer to
80 | // get the data for sendRawTransaction.
81 | }, {
82 | key: "sendAsync",
83 | value: function sendAsync(payload, callback) {
84 | var _this2 = this;
85 |
86 | var finishedWithRewrite = function finishedWithRewrite() {
87 | _get(Object.getPrototypeOf(HookedWeb3Provider.prototype), "sendAsync", _this2).call(_this2, payload, callback);
88 | };
89 |
90 | var requests = payload;
91 |
92 | if (!(payload instanceof Array)) {
93 | requests = [payload];
94 | }
95 |
96 | this.rewritePayloads(0, requests, {}, finishedWithRewrite);
97 | }
98 |
99 | // Rewrite all eth_sendTransaction payloads in the requests array.
100 | // This takes care of batch requests, and updates the nonces accordingly.
101 | }, {
102 | key: "rewritePayloads",
103 | value: function rewritePayloads(index, requests, session_nonces, finished) {
104 | var _this3 = this;
105 |
106 | if (index >= requests.length) {
107 | return finished();
108 | }
109 |
110 | var payload = requests[index];
111 |
112 | // Function to remove code duplication for going to the next payload
113 | var next = function next(err) {
114 | if (err != null) {
115 | return finished(err);
116 | }
117 | return _this3.rewritePayloads(index + 1, requests, session_nonces, finished);
118 | };
119 |
120 | // If this isn't a transaction we can modify, ignore it.
121 | if (payload.method != "eth_sendTransaction") {
122 | return next();
123 | }
124 |
125 | var tx_params = payload.params[0];
126 | var sender = tx_params.from;
127 |
128 | this.transaction_signer.hasAddress(sender, function (err, has_address) {
129 | if (err != null || has_address == false) {
130 | return next(err);
131 | }
132 |
133 | // Get the nonce, requesting from web3 if we haven't already requested it in this session.
134 | // Remember: "session_nonces" is the nonces we know about for this batch of rewriting (this "session").
135 | // Having this cache makes it so we only need to call getTransactionCount once per batch.
136 | // "global_nonces" is nonces across the life of this provider.
137 | var getNonce = function getNonce(done) {
138 | // If a nonce is specified in our nonce list, use that nonce.
139 | var nonce = session_nonces[sender];
140 | if (nonce != null) {
141 | done(null, nonce);
142 | } else {
143 | // Include pending transactions, so the nonce is set accordingly.
144 | // Note: "pending" doesn't seem to take effect for some Ethereum clients (geth),
145 | // hence the need for global_nonces.
146 | // We call directly to our own sendAsync method, because the web3 provider
147 | // is not guaranteed to be set.
148 | _this3.sendAsync({
149 | jsonrpc: '2.0',
150 | method: 'eth_getTransactionCount',
151 | params: [sender, "pending"],
152 | id: new Date().getTime()
153 | }, function (err, result) {
154 | if (err != null) {
155 | done(err);
156 | } else {
157 | var new_nonce = result.result;
158 | done(null, web3.toDecimal(new_nonce));
159 | }
160 | });
161 | }
162 | };
163 |
164 | // Get the nonce, requesting from web3 if we need to.
165 | // We then store the nonce and update it so we don't have to
166 | // to request from web3 again.
167 | getNonce(function (err, nonce) {
168 | if (err != null) {
169 | return finished(err);
170 | }
171 |
172 | // Set the expected nonce, and update our caches of nonces.
173 | // Note that if our session nonce is lower than what we have cached
174 | // across all transactions (and not just this batch) use our cached
175 | // version instead, even if
176 | var final_nonce = Math.max(nonce, _this3.global_nonces[sender] || 0);
177 |
178 | // Update the transaction parameters.
179 | tx_params.nonce = web3.toHex(final_nonce);
180 |
181 | // Update caches.
182 | session_nonces[sender] = final_nonce + 1;
183 | _this3.global_nonces[sender] = final_nonce + 1;
184 |
185 | // If our transaction signer does represent the address,
186 | // sign the transaction ourself and rewrite the payload.
187 | _this3.transaction_signer.signTransaction(tx_params, function (err, raw_tx) {
188 | if (err != null) {
189 | return next(err);
190 | }
191 |
192 | payload.method = "eth_sendRawTransaction";
193 | payload.params = [raw_tx];
194 | return next();
195 | });
196 | });
197 | });
198 | }
199 | }]);
200 |
201 | return HookedWeb3Provider;
202 | })(web3.providers.HttpProvider);
203 |
204 | return HookedWeb3Provider;
205 | };
206 |
207 | if (typeof module !== 'undefined') {
208 | module.exports = factory(require("web3"));
209 | } else {
210 | var web3 = new Web3();
211 | window.HookedWeb3Provider = factory(web3);
212 | }
213 |
--------------------------------------------------------------------------------
/contracts/PokeMarket.sol:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2016 Edilson Osorio Junior - OriginalMy.com
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | /* Prototipagem dos contratos que serao chamados a partir deste */
24 | pragma solidity ^0.4.2;
25 | contract pokeCoinContract { mapping (address => uint256) public balanceOf; function transferFrom(address _from, address _to, uint256 _value){ } }
26 | contract pokeCentralContract { mapping (uint256 => address) public pokemonToMaster; function transferPokemon(address _from, address _to, uint256 _pokemonID) { } }
27 |
28 | contract accessControlled {
29 | address public owner;
30 |
31 | function owned() {
32 | owner = msg.sender;
33 | }
34 |
35 | modifier onlyOwner {
36 | if (msg.sender != owner) throw;
37 | /* o caracter "_" é substituído pelo corpo da funcao onde o modifier é utilizado */
38 | _;
39 | }
40 |
41 | function transferOwnership(address newOwner) onlyOwner {
42 | owner = newOwner;
43 | }
44 |
45 |
46 | }
47 |
48 | contract PokeMarket is accessControlled {
49 | pokeCoinContract public pokeCoin;
50 | pokeCentralContract public pokeCentral;
51 |
52 | uint public totalPokemonSales;
53 | uint public totalActiveSales;
54 |
55 | PokeSale[] public pokeSales;
56 |
57 | mapping (uint => bool) public pokeSelling;
58 | mapping (address => uint[]) public pokeMasterSelling;
59 | mapping (uint => uint) public pokeSaleIndex;
60 |
61 | struct PokeSale{
62 | address pokeSeller;
63 | address pokeBuyer;
64 | uint pokeID;
65 | uint pokePrice;
66 | bool pokeSold;
67 | bool pokeSellActive;
68 | }
69 |
70 | event NewSale(address pokeSellerAddress, uint pokemonID, uint pokemonSalePrice);
71 | event StopSale(address pokeSellerAddress, uint pokemonID);
72 | event PokeTrade(address pokeBuyerAddress, address pokeSellerAddress, uint pokemonID );
73 |
74 | /* Inicializa o mercado pokemon apontando os endereços da PokeCoin e da PokeCentral */
75 | function PokeMarket(pokeCoinContract pokeCoinAddress, pokeCentralContract pokeCentralAddress) {
76 | owner = msg.sender;
77 | pokeCoin = pokeCoinContract(pokeCoinAddress);
78 | pokeCentral = pokeCentralContract(pokeCentralAddress);
79 | }
80 |
81 |
82 | /* Inicia uma nova venda */
83 | function newSale(address pokeSellerAddress, uint pokemonID, uint pokemonSalePrice) onlyOwner returns (bool success){
84 | if (pokeSellerAddress != pokeCentral.pokemonToMaster(pokemonID)) throw; // Verifica se o vendedor possui o pokemon colocado a venda
85 | if (pokeSelling[pokemonID]) throw; // Verifica se ja ha venda ativa para este pokemon
86 |
87 | uint pokeSalesID = pokeSales.length++;
88 | PokeSale p = pokeSales[pokeSalesID];
89 | if (p.pokeSellActive) throw;
90 | p.pokeSeller = pokeSellerAddress;
91 | p.pokeID = pokemonID;
92 | p.pokePrice = pokemonSalePrice;
93 | p.pokeSold = false;
94 | p.pokeSellActive = true;
95 |
96 | pokeSelling[pokemonID] = true;
97 | pokeSaleIndex[pokemonID] = pokeSalesID; // Em muitos casos é importante criar um indice para o pesquisar no struct
98 |
99 | //addPokemonToSellingList(pokeSellerAddress, pokemonID); // Adiciona esta venda na lista de vendas
100 |
101 | totalPokemonSales+=1;
102 | totalActiveSales+=1;
103 |
104 | NewSale(pokeSellerAddress, pokemonID, pokemonSalePrice); // Notifica os clientes que há uma nova venda
105 | return (true);
106 | }
107 |
108 | /* Cancela uma venda ativa */
109 | function stopSale(address pokeSellerAddress, uint pokemonID) onlyOwner {
110 | if (msg.sender != owner && msg.sender != pokeSellerAddress) throw; // Verifica se quem está solicitando o cancelamento da venda é o criador da mesma ou o owner
111 | if (pokeSellerAddress != pokeCentral.pokemonToMaster(pokemonID)) throw; // Verifica se o pokemon é do proprietario
112 | if (!pokeSelling[pokemonID]) throw; // Verifica se a venda esta ativa
113 |
114 | uint pokeSalesID = pokeSaleIndex[pokemonID];
115 | PokeSale p = pokeSales[pokeSalesID];
116 | if (!p.pokeSellActive) throw;
117 | p.pokeSellActive = false;
118 | pokeSelling[pokemonID] = false;
119 |
120 | delPokemonFromSellingList(pokeSellerAddress, pokemonID);
121 |
122 | totalActiveSales-=1;
123 |
124 | StopSale(pokeSellerAddress, pokemonID);
125 | }
126 |
127 | /* Compra um Pokemon */
128 | function buyPokemon(address pokeBuyerAddress, uint pokemonID) {
129 | if (pokeBuyerAddress == pokeCentral.pokemonToMaster(pokemonID)) throw; // Verifica se quem está comprando é o próprio vendedor
130 | if (!pokeSelling[pokemonID]) throw; // Verifica se o pokemon esta a venda
131 |
132 | uint pokeSalesID = pokeSaleIndex[pokemonID];
133 | PokeSale p = pokeSales[pokeSalesID];
134 | if (!p.pokeSellActive) throw; // Verifica se na struct o pokemon esta com venda ativa
135 | if (pokeCoin.balanceOf(pokeBuyerAddress) < p.pokePrice) throw; // Verifica se o comprador possui fundos suficientes para comprar o pokemon
136 |
137 | pokeCoin.transferFrom(pokeBuyerAddress, p.pokeSeller, p.pokePrice); // Chama a funcao transferFrom do contrato pokecoin
138 | pokeCentral.transferPokemon(p.pokeSeller, pokeBuyerAddress, pokemonID); // Chama a funcao transferPokemon do contrato pokecentral
139 | p.pokeBuyer = pokeBuyerAddress; // Ajusta o endereço do comprador
140 | p.pokeSold = true; // Marca o pokemon como vendido
141 |
142 | stopSale(pokeBuyerAddress,pokemonID); // Cancela a venda
143 |
144 | PokeTrade(pokeBuyerAddress, p.pokeSeller, pokemonID ); // Notifica os clientes que a venda ocorreu
145 |
146 | }
147 |
148 | /* Adiciona o pokemon para a lista de vendas */
149 | function addPokemonToSellingList(address pokeSellerAddress, uint pokemonID) onlyOwner internal {
150 | uint[] tempList = pokeMasterSelling[pokeSellerAddress]; // Carrega a lista de vendas para o vendedor
151 | tempList[tempList.length++] = pokemonID; // Adiciona um pokemon ao final da lista
152 |
153 | pokeMasterSelling[pokeSellerAddress] = cleanArray(tempList); // Substitui o mapping que possui a lista de vendas, reorganizando o array (retirando os zeros)
154 | }
155 |
156 |
157 | /* Exclui um pokemon da lista de vendas */
158 | function delPokemonFromSellingList(address pokeSellerAddress, uint pokemonID) onlyOwner internal {
159 | uint[] tempList = pokeMasterSelling[pokeSellerAddress]; // Carrega a lista de vendas para o vendedor
160 | uint count = tempList.length; // Conta o numero de itens da lista
161 |
162 | for (uint i=0; i 0 ){
182 | tempList[j] = pokeList[i]; // Ajusta a lista temporaria com os valores que nao sao zero
183 | j++;
184 | }
185 | }
186 | uint[] memory tempList2 = new uint[](j); // Cria uma segunda lista em memória, com tamanho do "j" que e a contagem dos itens do "for" anterior
187 | for (i=0; i< j; i++) tempList2[i] = tempList[i]; // Adiciona cada item do primeiro array para o segundo array. O excedente fica de fora
188 | return tempList2; // Retorna a segunda lista
189 | }
190 |
191 | /* Uma funcao sem nome '()' eh chamada todas as vezes que forem enviados ethers para ela */
192 | function (){
193 | throw; // Nao permite o recebimento de ether
194 | }
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/contracts/PokeCentral.sol:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2016 Edilson Osorio Junior - OriginalMy.com
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | pragma solidity ^0.4.2;
24 | contract accessControlled {
25 | address public owner;
26 | address public pokeMarketAddress;
27 |
28 | function accessControlled() {
29 | owner = msg.sender;
30 | }
31 |
32 | modifier onlyOwner {
33 | if (msg.sender != owner) throw;
34 | /* o caracter "_" é substituído pelo corpo da funcao onde o modifier é utilizado */
35 | _;
36 | }
37 |
38 | function transferOwnership(address newOwner) onlyOwner {
39 | owner = newOwner;
40 | }
41 |
42 | function updatePokeMarketAddress(address marketAddress) onlyOwner {
43 | pokeMarketAddress = marketAddress;
44 | }
45 |
46 | }
47 |
48 |
49 | contract PokeCentral is accessControlled {
50 |
51 | uint256 public totalPokemonSupply;
52 |
53 | Pokemon[] public pokemons;
54 | PokemonMaster[] public pokeMasters;
55 |
56 | mapping (uint256 => address) public pokemonToMaster;
57 | mapping (address => uint256) public pokeOwnerIndex;
58 | mapping (address => uint256) public totalPokemonsFromMaster;
59 | mapping (address => uint256[]) public balanceOf;
60 |
61 | struct Pokemon {
62 | uint pokeNumber;
63 | string pokeName;
64 | string pokeType;
65 | uint pokeCP;
66 | uint pokeHP;
67 | bytes32 pokemonHash;
68 | address pokeOwner;
69 | }
70 |
71 | struct PokemonMaster {
72 | address pokeMaster;
73 | uint[] pokemons;
74 | }
75 |
76 | /* Exemplo de array bidimensional para armazenar o nome do pokemon e seu tipo. O índice é seu número na Pokedex */
77 | string[][] public pokemonNameTypes = [["Pokemon 0", "invalid"], ["Bulbassauro", "Grass/Poison"], ["Charmander", "Fire"], ["Squirtle","Water"], ["Pikachu","Eletric"]]; // Este tipo não aceita bytes
78 |
79 | /* Gera um evento publico no blockchain e avisa os clientes que estao monitorando */
80 | event Transfer(address from, address to, uint256 value);
81 | event CreatePokemon(uint id, string name, uint cp, uint hp );
82 | event UpdatePokemon(uint id, string name, uint cp, uint hp );
83 | event UpdateMasterPokemons(address owner, uint total);
84 | event Log1(uint number);
85 | event Log2(string message);
86 |
87 | /* Inicializa o contrato */
88 | function PokeCentral(address account1Demo, address account2Demo) {
89 | owner = msg.sender;
90 |
91 | newPokemonMaster(owner); // Todos pokemons serao criados para este owner
92 |
93 | /*
94 | Há um problema com um array de indices, pois quando um item é excluído, é substituído por 0.
95 | Então vamos criar um pokemon fake no primeiro item e ajustar a quantidade para ignorá-lo
96 | */
97 | newPokemon(0,0,0); // Pokemon Índice 0
98 | totalPokemonSupply-=1; // Ajusta o total de pokemons porque o primeiro é fake
99 |
100 | /* Criacao de pokemons iniciais */
101 | //newPokemon(3,500,40);
102 | //newPokemon(1,535,70);
103 | //newPokemon(4,546,80);
104 | //newPokemon(2,557,90);
105 |
106 | /* Se as contas demo forem apresentadas no carregamento, então os pokemons criados serão distribuidos entre elas */
107 | //if (account1Demo != 0 && account2Demo != 0){
108 | //transferPokemon(msg.sender, account1Demo, 1);
109 | //transferPokemon(msg.sender, account1Demo, 4);
110 | //transferPokemon(msg.sender, account2Demo, 2);
111 | //transferPokemon(msg.sender, account2Demo, 3);
112 | //}
113 | }
114 |
115 | /* Criar novo Pokemon */
116 | function newPokemon(uint pokemonNumber, uint cp, uint hp ) onlyOwner returns (bool success) { // cp e hp podem ser fornecidos randomicamente por https://api.random.org/json-rpc/1/basic
117 | uint pokemonID = pokemons.length++;
118 | Pokemon p = pokemons[pokemonID];
119 | p.pokeNumber = pokemonNumber;
120 | p.pokeName = pokemonNameTypes[pokemonNumber][0];
121 | p.pokeType = pokemonNameTypes[pokemonNumber][1];
122 | p.pokeCP = cp;
123 | p.pokeHP = hp;
124 |
125 | p.pokemonHash = sha3(p.pokeNumber,p.pokeName,p.pokeType,p.pokeCP,p.pokeHP); // Hash de verificacao das infos do pokémon
126 | p.pokeOwner = owner;
127 | pokemonToMaster[pokemonID] = owner;
128 | addPokemonToMaster(owner, pokemonID);
129 |
130 | totalPokemonSupply += 1;
131 | CreatePokemon(pokemonID, p.pokeName, p.pokeCP, p.pokeHP);
132 | return true;
133 | }
134 |
135 | /* Alterar CP e HP de um Pokemon */
136 | function updatePokemon(uint _pokemonID, uint _cp, uint _hp ) onlyOwner returns (bool success) {
137 | Pokemon p = pokemons[_pokemonID];
138 | p.pokeCP = _cp;
139 | p.pokeHP = _hp;
140 |
141 | p.pokemonHash = sha3(p.pokeNumber,p.pokeName,p.pokeType,p.pokeCP,p.pokeHP);
142 |
143 | UpdatePokemon(_pokemonID, p.pokeName, p.pokeCP, p.pokeHP);
144 | return true;
145 |
146 | }
147 |
148 | /* Criar novo Mestre Pokemon */
149 | function newPokemonMaster(address pokemonMaster) onlyOwner returns (bool success) {
150 | uint ownerID = pokeMasters.length++;
151 | PokemonMaster o = pokeMasters[ownerID];
152 | o.pokeMaster = pokemonMaster;
153 | pokeOwnerIndex[pokemonMaster] = ownerID;
154 | return true;
155 | }
156 |
157 | /* Transferencia de Pokemons */
158 | function transferPokemon(address _from, address _to, uint256 _pokemonID) returns (uint pokemonID, address from, address to) {
159 | if (msg.sender != owner && msg.sender != pokeMarketAddress) throw;
160 | Pokemon p = pokemons[_pokemonID];
161 | if (p.pokeOwner != _from) throw;
162 | /* Se o Mestre Pokémon não existe ainda, crie-o */
163 | if (pokeOwnerIndex[_to] == 0 && _to != pokemonToMaster[0] ) newPokemonMaster(_to);
164 | p.pokeOwner = _to;
165 | pokemonToMaster[_pokemonID] = _to;
166 | delPokemonFromMaster(_from, _pokemonID);
167 | addPokemonToMaster(_to, _pokemonID);
168 | Transfer(_from, _to, _pokemonID);
169 | return (_pokemonID, _from, _to);
170 | }
171 |
172 | /* Vincula um pokemon ao seu treinador */
173 | function addPokemonToMaster(address _pokemonOwner, uint256 _pokemonID) internal returns (address pokeOwner, uint[] pokemons, uint pokemonsTotal) {
174 | if (msg.sender != owner && msg.sender != pokeMarketAddress) throw;
175 |
176 | uint ownerID = pokeOwnerIndex[_pokemonOwner];
177 | PokemonMaster o = pokeMasters[ownerID];
178 | uint[] pokeList = o.pokemons;
179 |
180 | /* usando array.push ele adiciona 0,_pokemonID no array */
181 | // o.pokemons.push(_pokemonID);
182 |
183 | /*
184 | Ao invés de simplesmente adicionar um pokemon ao final da lista, verifica se há slot zerado no array, senao adiciona ao final.
185 | O blockchain não apaga itens, o uso de 'delete array[x]' substitui o item por 0.
186 | Ex:
187 | array[] = [ 1, 2, 3, 4 ]
188 | delete array[3];
189 | array[] = [ 1, 2, 0, 4 ]
190 | */
191 |
192 | bool slot;
193 | for (uint i=0; i < pokeList.length; i++){
194 | if (pokeList[i] == 0){
195 | slot = true;
196 | break;
197 | }
198 | }
199 | if (slot == true){
200 | o.pokemons[i] = _pokemonID;
201 | } else {
202 | uint j = pokeList.length++;
203 | o.pokemons[j] = _pokemonID;
204 | }
205 | balanceOf[_pokemonOwner] = cleanArray(o.pokemons);
206 |
207 | qtdePokemons(_pokemonOwner);
208 | UpdateMasterPokemons(_pokemonOwner, o.pokemons.length);
209 | return (_pokemonOwner, o.pokemons, o.pokemons.length);
210 | }
211 |
212 | /* Desvincula um pokemon do seu treinador */
213 | function delPokemonFromMaster(address _pokemonOwner, uint256 _pokemonID) internal returns (address pokeOwner, uint[] pokemons, uint pokemonsTotal) {
214 | if (msg.sender != owner && msg.sender != pokeMarketAddress) throw;
215 |
216 | uint ownerID = pokeOwnerIndex[_pokemonOwner];
217 | PokemonMaster o = pokeMasters[ownerID];
218 | uint[] pokeList = o.pokemons;
219 |
220 | for (uint i=0; i < pokeList.length; i++){
221 | if (pokeList[i] == _pokemonID){
222 | delete pokeList[i];
223 | }
224 | }
225 |
226 | // http://ethereum.stackexchange.com/questions/3373/how-to-clear-large-arrays-without-blowing-the-gas-limit
227 | o.pokemons=cleanArray(pokeList); // Rearranja o array, eliminando os itens zerados, a custo de gas
228 |
229 | balanceOf[_pokemonOwner] = cleanArray(o.pokemons);
230 |
231 | qtdePokemons(_pokemonOwner);
232 | UpdateMasterPokemons(_pokemonOwner, o.pokemons.length);
233 | return (_pokemonOwner, o.pokemons, o.pokemons.length);
234 | }
235 |
236 | /* Funcao ilustrativa: lista pokemons de um treinador pois o browser solidity não mostra o conteúdo dos arrays no struct e no mapping */
237 | function listPokemons( address _pokeOwner ) returns (address, uint[]){
238 | uint ownerID = pokeOwnerIndex[_pokeOwner];
239 | PokemonMaster o = pokeMasters[ownerID];
240 |
241 | /* Lista pokemons tanto do struct quanto do mapping. */
242 | return ( _pokeOwner, balanceOf[_pokeOwner] );
243 | }
244 |
245 | /* Conta a qtde de pokemons em um array que possui zeros */
246 | function qtdePokemons( address _pokeOwner) internal returns (uint qtde){
247 | if (msg.sender != owner && msg.sender != pokeMarketAddress) throw;
248 |
249 | uint ownerID = pokeOwnerIndex[_pokeOwner];
250 | PokemonMaster o = pokeMasters[ownerID];
251 | uint[] pokeList = o.pokemons;
252 | uint count = 0;
253 | for (uint i=0; i < pokeList.length; i++){
254 | if ( pokeList[i] > 0 ){
255 | count++;
256 | }
257 | }
258 | totalPokemonsFromMaster[_pokeOwner] = count;
259 | return count;
260 | }
261 |
262 | /* Exemplo 2: Conta a qtde de pokemons diretamente do mapping */
263 | function qtdePokemonsMapping( address _pokeOwner) internal returns (uint qtde){
264 | uint[] tempList = balanceOf[_pokeOwner];
265 | totalPokemonsFromMaster[_pokeOwner] = tempList.length;
266 | return tempList.length;
267 | }
268 |
269 |
270 | /* Esta funcao elimina todos os itens com zero do array, ao custo de gas */
271 | function cleanArray(uint[] pokeList) internal returns (uint[]){
272 | uint[] memory tempArray = new uint[](pokeList.length);
273 | uint j = 0;
274 | for (uint i=0; i < pokeList.length; i++){
275 | if ( pokeList[i] > 0 ){
276 | tempArray[j] = pokeList[i];
277 | j++;
278 | }
279 | }
280 | uint[] memory tempArray2 = new uint[](j);
281 | for (i=0; i< j; i++) tempArray2[i] = tempArray[i];
282 | return tempArray2;
283 | }
284 |
285 | /* Se tentarem enviar ether para o end desse contrato, ele rejeita */
286 | function () {
287 | throw;
288 | }
289 | }
290 |
--------------------------------------------------------------------------------
/app/javascripts/mercadopokemon.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2016 Edilson Osorio Junior - OriginalMy.com
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | var Web3 = require('web3');
24 | var web3 = new Web3();
25 | var eth = web3.eth;
26 |
27 | var txutils = lightwallet.txutils;
28 | var signing = lightwallet.signing;
29 | var encryption = lightwallet.encryption;
30 |
31 | /* ABI dos três Dapps */
32 | var abiPokeCoin = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"marketAddress","type":"address"}],"name":"updatePokeMarketAddress","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"standard","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"pokeMarketAddress","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"qtdCoinsToDelete","type":"uint256"}],"name":"vanishCoins","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"newSupply","type":"uint256"}],"name":"issueNew","outputs":[],"type":"function"},{"constant":false,"inputs":[],"name":"owned","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"type":"function"},{"inputs":[{"name":"initialSupply","type":"uint256"},{"name":"account1Demo","type":"address"},{"name":"account2Demo","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}];
33 | var abiPokeCentral = [{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"marketAddress","type":"address"}],"name":"updatePokeMarketAddress","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"totalPokemonSupply","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"pokeOwnerIndex","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pokeMasters","outputs":[{"name":"pokeMaster","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"pokeMarketAddress","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pokemonToMaster","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pokemons","outputs":[{"name":"pokeNumber","type":"uint256"},{"name":"pokeName","type":"string"},{"name":"pokeType","type":"string"},{"name":"pokeCP","type":"uint256"},{"name":"pokeHP","type":"uint256"},{"name":"pokemonHash","type":"bytes32"},{"name":"pokeOwner","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_pokemonID","type":"uint256"},{"name":"_cp","type":"uint256"},{"name":"_hp","type":"uint256"}],"name":"updatePokemon","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"pokemonNumber","type":"uint256"},{"name":"cp","type":"uint256"},{"name":"hp","type":"uint256"}],"name":"newPokemon","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_pokemonID","type":"uint256"}],"name":"transferPokemon","outputs":[{"name":"pokemonID","type":"uint256"},{"name":"from","type":"address"},{"name":"to","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"name":"pokemonNameTypes","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"pokemonMaster","type":"address"}],"name":"newPokemonMaster","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"owned","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_pokeOwner","type":"address"}],"name":"listPokemons","outputs":[{"name":"","type":"address"},{"name":"","type":"uint256[]"}],"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"totalPokemonsFromMaster","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"inputs":[{"name":"account1Demo","type":"address"},{"name":"account2Demo","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"cp","type":"uint256"},{"indexed":false,"name":"hp","type":"uint256"}],"name":"CreatePokemon","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"cp","type":"uint256"},{"indexed":false,"name":"hp","type":"uint256"}],"name":"UpdatePokemon","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"total","type":"uint256"}],"name":"UpdateMasterPokemons","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"number","type":"uint256"}],"name":"Log1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"message","type":"string"}],"name":"Log2","type":"event"}];
34 | var abiPokeMarket = [{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pokeSales","outputs":[{"name":"pokeSeller","type":"address"},{"name":"pokeBuyer","type":"address"},{"name":"pokeID","type":"uint256"},{"name":"pokePrice","type":"uint256"},{"name":"pokeSold","type":"bool"},{"name":"pokeSellActive","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"newPokecoinAddress","type":"address"},{"name":"newPokecentralAddress","type":"address"}],"name":"updatePokecoinAndPokemarketAddresses","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pokeSaleIndex","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pokeSelling","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"pokeSellerAddress","type":"address"},{"name":"pokemonID","type":"uint256"},{"name":"pokemonSalePrice","type":"uint256"}],"name":"newSale","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"totalPokemonSales","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"pokeCoin","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"pokeSellerAddress","type":"address"},{"name":"pokemonID","type":"uint256"}],"name":"stopSale","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"pokeCentral","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"pokeBuyerAddress","type":"address"},{"name":"pokemonID","type":"uint256"}],"name":"buyPokemon","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"totalActiveSales","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"owned","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"pokeMasterSelling","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"type":"function"},{"inputs":[{"name":"pokeCoinAddress","type":"address"},{"name":"pokeCentralAddress","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"pokeSellerAddress","type":"address"},{"indexed":false,"name":"pokemonID","type":"uint256"},{"indexed":false,"name":"pokemonSalePrice","type":"uint256"}],"name":"NewSale","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"pokeSellerAddress","type":"address"},{"indexed":false,"name":"pokemonID","type":"uint256"}],"name":"StopSale","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"pokeBuyerAddress","type":"address"},{"indexed":false,"name":"pokeSellerAddress","type":"address"},{"indexed":false,"name":"pokemonID","type":"uint256"}],"name":"PokeTrade","type":"event"}];
35 |
36 | /* Endereços dos Dapps */
37 | var pokeCoinAddress = '0x2ba25711fa1f94998d875bf80acbc2cccdf9abbb';
38 | var pokeCentralAddress = '0xe46a592b722ead6cec7e0eb736deb59dbb325cab';
39 | var pokeMarketAddress = '0x6a25a406758bd91766191c39a3d94a429c98dd11';
40 |
41 | /* Carregamento dos Contratos */
42 | var MyPokeCoinContract = web3.eth.contract(abiPokeCoin);
43 | var pokeCoin = MyPokeCoinContract.at(pokeCoinAddress);
44 |
45 | var MyPokeCentralContract = web3.eth.contract(abiPokeCentral);
46 | var pokeCentral = MyPokeCentralContract.at(pokeCentralAddress);
47 |
48 | var MyPokeMarketContract = web3.eth.contract(abiPokeMarket);
49 | var pokeMarket = MyPokeMarketContract.at(pokeMarketAddress);
50 |
51 | var keystore;
52 |
53 | var accountAddress = "xxx";
54 | var password = 'mercadopokemon';
55 |
56 | /* Inicializa conexão com o node local */
57 | web3.setProvider(new web3.providers.HttpProvider());
58 |
59 | function setWeb3Provider(keystore) {
60 | var web3Provider = new HookedWeb3Provider({
61 | host: "http://localhost:8545",
62 | transaction_signer: keystore
63 | });
64 |
65 | web3.setProvider(web3Provider);
66 | };
67 |
68 | /* Criação/carregamento do account */
69 | lightwallet.keystore.deriveKeyFromPassword(password, function(err, pwDerivedKey) {
70 |
71 | /* Se for criar uma nova conta com um novo seed, descomente as duas linhas abaixo */
72 |
73 | //var extraEntropy = 'mercadopokemon129387612348917236';
74 | //seed = lightwallet.keystore.generateRandomSeed(extraEntropy);
75 |
76 | keystore = new lightwallet.keystore(seed, pwDerivedKey);
77 | keystore.generateNewAddress(pwDerivedKey, 1);
78 |
79 | accountAddress = keystore.getAddresses()[0];
80 |
81 | document.getElementById("accountAddress").innerText = '0x'+accountAddress;
82 | document.getElementById("seed").innerText = seed;
83 |
84 | web3.eth.defaultAccount = eth.accounts[0];
85 |
86 | });
87 |
88 | function showStatus(){
89 | var currentBalance = pokeCoin.balanceOf('0x'+accountAddress).toNumber();
90 | var qtdePokemons = pokeCentral.totalPokemonsFromMaster('0x'+accountAddress);
91 | document.getElementById("currbalance").innerText = 'Balance: ' + currentBalance + ' pkc';
92 | document.getElementById("totalPokemons").innerText = 'Qtde : ' + qtdePokemons + ' pokemon(s)';
93 |
94 |
95 | /* Constrói informações sobre cada Pokémon da conta */
96 | var html = '
';
97 | html += '
ID
Pokemon
Tipo
CP
HP
'
98 | for (i=0; i'
100 | var pokeID = pokeCentral.balanceOf('0x'+accountAddress, i);
101 | html += '