Created
December 13, 2016 11:11
-
-
Save miladmostavi/7111585112b93cfc41df2b62592776ef to your computer and use it in GitHub Desktop.
Gnosis token launch javascript code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var token_abi = [{"inputs": [], "constant": true, "type": "function", "name": "name", "outputs": [{"type": "string", "name": ""}]}, {"inputs": [{"type": "address", "name": "_spender"}, {"type": "uint256", "name": "_value"}], "constant": false, "type": "function", "name": "approve", "outputs": [{"type": "bool", "name": "success"}]}, {"inputs": [], "constant": true, "type": "function", "name": "totalSupply", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [{"type": "address", "name": "from"}, {"type": "address", "name": "to"}, {"type": "uint256", "name": "value"}], "constant": false, "type": "function", "name": "transferFrom", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "decimals", "outputs": [{"type": "uint8", "name": ""}]}, {"inputs": [{"type": "address", "name": "_for"}, {"type": "uint256", "name": "tokenCount"}], "constant": false, "type": "function", "name": "issueTokens", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [{"type": "address", "name": "_owner"}], "constant": true, "type": "function", "name": "balanceOf", "outputs": [{"type": "uint256", "name": "balance"}]}, {"inputs": [], "constant": true, "type": "function", "name": "symbol", "outputs": [{"type": "string", "name": ""}]}, {"inputs": [{"type": "address", "name": "to"}, {"type": "uint256", "name": "value"}], "constant": false, "type": "function", "name": "transfer", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [{"type": "address", "name": "_owner"}, {"type": "address", "name": "_spender"}], "constant": true, "type": "function", "name": "allowance", "outputs": [{"type": "uint256", "name": "remaining"}]}, {"inputs": [], "type": "constructor"}, {"inputs": [{"indexed": true, "type": "address", "name": "from"}, {"indexed": true, "type": "address", "name": "to"}, {"indexed": false, "type": "uint256", "name": "value"}], "type": "event", "name": "Transfer", "anonymous": false}, {"inputs": [{"indexed": true, "type": "address", "name": "owner"}, {"indexed": true, "type": "address", "name": "spender"}, {"indexed": false, "type": "uint256", "name": "value"}], "type": "event", "name": "Approval", "anonymous": false}]; | |
var auction_abi = [{"inputs": [], "constant": true, "name": "TOTAL_TOKENS", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [], "constant": true, "name": "etherWallet", "payable": false, "outputs": [{"type": "address", "name": ""}], "type": "function"}, {"inputs": [], "constant": true, "name": "MAX_TOKENS_SOLD", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [], "constant": false, "name": "bid", "payable": true, "outputs": [], "type": "function"}, {"inputs": [], "constant": true, "name": "endTime", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [], "constant": true, "name": "calcTokenPrice", "payable": false, "outputs": [{"type": "uint256", "name": "tokenPrice"}], "type": "function"}, {"inputs": [], "constant": true, "name": "FUNDING_GOAL", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [], "constant": false, "name": "claimTokens", "payable": false, "outputs": [], "type": "function"}, {"inputs": [], "constant": true, "name": "startBlock", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [], "constant": true, "name": "daoToken", "payable": false, "outputs": [{"type": "address", "name": ""}], "type": "function"}, {"inputs": [{"type": "address", "name": ""}], "constant": true, "name": "bids", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [], "constant": true, "name": "WAITING_PERIOD", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [{"type": "address", "name": "_daoToken"}, {"type": "address", "name": "_tokenWallet"}, {"type": "address", "name": "_etherWallet"}], "constant": false, "name": "setup", "payable": false, "outputs": [], "type": "function"}, {"inputs": [], "constant": true, "name": "owner", "payable": false, "outputs": [{"type": "address", "name": ""}], "type": "function"}, {"inputs": [], "constant": true, "name": "finalPrice", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [], "constant": true, "name": "tokenWallet", "payable": false, "outputs": [{"type": "address", "name": ""}], "type": "function"}, {"inputs": [], "constant": true, "name": "stage", "payable": false, "outputs": [{"type": "uint8", "name": ""}], "type": "function"}, {"inputs": [], "constant": false, "name": "updateStage", "payable": false, "outputs": [{"type": "uint8", "name": "_stage"}], "type": "function"}, {"inputs": [], "constant": true, "name": "totalRaised", "payable": false, "outputs": [{"type": "uint256", "name": ""}], "type": "function"}, {"inputs": [], "constant": false, "name": "calcCurrentTokenPrice", "payable": false, "outputs": [{"type": "uint256", "name": "tokenPrice"}], "type": "function"}, {"inputs": [], "constant": true, "name": "calcStopPrice", "payable": false, "outputs": [{"type": "uint256", "name": "stopPrice"}], "type": "function"}, {"inputs": [], "constant": false, "name": "tokenLaunched", "payable": false, "outputs": [{"type": "bool", "name": "launched"}], "type": "function"}, {"inputs": [], "type": "constructor"}, {"inputs": [{"indexed": true, "type": "address", "name": "investor"}, {"indexed": false, "type": "uint256", "name": "amount"}], "type": "event", "name": "BidSubmission", "anonymous": false}]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/* Filters */ | |
angular.module('tokenLaunchFilters', []) | |
.filter('bigNumber', function() { | |
return function(big_number) { | |
if(big_number) { | |
var string_split = String(big_number.toString(10)).split('.'); | |
var new_string = ""; | |
var places = string_split[0].length - 1; | |
for (var i=places; i>=0; i--) { | |
new_string = string_split[0][i] + new_string; | |
if (i > 0 && (places - i + 1) % 3 == 0) { | |
new_string = ',' + new_string; | |
} | |
} | |
if (string_split.length == 2) { | |
new_string += '.' + string_split[1].substring(0, 2); | |
} | |
return new_string; | |
} | |
return null; | |
}; | |
}) | |
.filter('dateFormat', function() { | |
return function(date_input) { | |
if(date_input != 0) { | |
return moment(date_input).format('YYYY-MM-DD HH:mm:ss'); | |
} | |
return '-'; | |
}; | |
}) | |
.filter('dateFormatFromNow', function() { | |
function filter(date_input) { | |
if(date_input != 0) { | |
return moment(new Date(date_input)).fromNow(); | |
} | |
return '-'; | |
}; | |
filter.$stateful = true; | |
return filter; | |
}) | |
.filter('feeToPercentage', function() { | |
return function(fee) { | |
if (fee) { | |
return fee.dividedBy(1000).toString(10); | |
} | |
return ""; | |
}; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/* Services */ | |
var tokenLaunchServices = angular.module('tokenLaunchServices', []); | |
tokenLaunchServices.factory('stateService', function($rootScope, EthereumService, $timeout, $q) { | |
var state = { | |
isWalletCreating: false, | |
EthereumService: EthereumService, | |
walletService: EthereumService.walletService, | |
updates: 0, | |
blocknumber: 0, | |
sharesIssued: true, | |
tokenPrice: null, | |
stage: null, | |
funding_method: null, | |
bid: null, | |
tokens_fungible: false, | |
}; | |
state.stages = { | |
AuctionStarted: 0, | |
AuctionEnded: 1, | |
}; | |
state.set = function(newState, isExternalCall) { | |
state = Object.assign(state, newState); | |
if(isExternalCall) { | |
$rootScope.$digest(); | |
} | |
}; | |
state.showPasswordPrompt = function(cb) { | |
state.show_password_prompt = 1; | |
state.password_prompt_cb = cb; | |
state.last_main_zindex = $('#main').css('z-index'); | |
$('#main').css('z-index', 5000); | |
try { | |
$rootScope.$digest(); | |
} catch(e) {} | |
}; | |
state.hidePasswordPrompt = function() { | |
state.show_password_prompt = 0; | |
if(state.password_prompt_cb && state.EthereumService.transaction_awaiting_pw_deferred) { | |
state.EthereumService.transaction_awaiting_pw_deferred.reject('Wallet password was not provided'); | |
state.EthereumService.transaction_awaiting_pw_deferred = null; | |
} | |
state.password_prompt_cb = null; | |
$timeout(function() { | |
$('#main').css('z-index', state.last_main_zindex); | |
}); | |
}; | |
state.update = function(skip_increment) { | |
$q.all([ | |
EthereumService.updateBalance(), | |
EthereumService.getTokenPrice(), | |
EthereumService.getCurrentBid(), | |
getCurrentStage(), | |
getTokensFungibleState(), | |
EthereumService.getTotalRaised(), | |
]).then(function(results) { | |
EthereumService.walletService.balances = EthereumService.balances; | |
EthereumService.walletService.eth_balance = web3.fromWei(EthereumService.balances.wei); | |
state.tokenPrice = results[1]; | |
state.bid = results[2]; | |
state.updates++; | |
try { | |
$rootScope.$digest(); | |
} catch(e) {} | |
//update stats section | |
updateState({ | |
total_funds: web3.fromWei(results[5]).toString(), | |
token_price: web3.fromWei(state.tokenPrice).toString(), | |
current_block: state.blocknumber, | |
}); | |
}); | |
}; | |
function getCurrentStage() { | |
var deferred = $q.defer(); | |
auction_contract.updateStage.call(function(err, stage) { | |
if (!err) { | |
state.stage = stage.toNumber(); | |
deferred.resolve(stage.toNumber()); | |
} else { | |
console.error(err); | |
} | |
}); | |
return deferred.promise; | |
} | |
function getTokensFungibleState() { | |
var deferred = $q.defer(); | |
auction_contract.tokenLaunched.call(function(err, tokenLaunched) { | |
if (!err) { | |
state.tokens_fungible = tokenLaunched; | |
deferred.resolve(tokenLaunched); | |
} else { | |
console.error(err); | |
} | |
}); | |
return deferred.promise; | |
} | |
state.updateBlocknumber = function() { | |
EthereumService.getBlocknumber().then(function(blocknumber) { | |
if(state.blocknumber != blocknumber) { | |
state.blocknumber = blocknumber; | |
state.update(); | |
EthereumService.checkPendingTransactions(); | |
EthereumService.updateTransactions(); | |
} | |
}).finally(function() { | |
$timeout(function() { | |
state.updateBlocknumber(); | |
}, 5000); | |
}); | |
}; | |
state.updateBlocknumber(); | |
//circular reference | |
EthereumService.stateService = state; | |
window.state_service = state; | |
return state; | |
}); | |
tokenLaunchServices.service('walletService', function($rootScope, localStorageService, $http, $window) { | |
var wallet = this; | |
wallet.keystore = null; | |
wallet.EthereumService = null; | |
wallet.balances = { | |
tokens: null, | |
wei: null, | |
}; | |
wallet.shouldRestore = function(value) { | |
localStorageService.set('wallet_should_restore', value); | |
}; | |
wallet.useMetamask = function(value) { | |
localStorageService.set('use_metamask', value); | |
}; | |
wallet.isUsingMetamask = function(value) { | |
return localStorageService.get('use_metamask') ? wallet.isMetamaskProviderSetCorrect() : false; | |
}; | |
wallet.getMetamaskSelectedAddress = function() { | |
return angular.fromJson($window.localStorage.getItem('MetaMask-Config')).selectedAddress; | |
}; | |
wallet.isMetamaskProviderSetCorrect = function() { | |
var provider_type = angular.fromJson($window.localStorage.getItem('MetaMask-Config')).provider.type; | |
if(tokenlaunch_config.metamask_provider_type != 'rpc' && tokenlaunch_config.metamask_provider_type == provider_type) { | |
return true; | |
} else if (tokenlaunch_config.metamask_provider_type == 'rpc') { | |
var rpc_target = angular.fromJson($window.localStorage.getItem('MetaMask-Config')).provider.rpcTarget; | |
if(! rpc_target) { | |
return false; | |
} | |
if(rpc_target == tokenlaunch_config.default_node) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
wallet.exists = function() { | |
if(window.metamask_web3 && wallet.isUsingMetamask()) { | |
return true; | |
} | |
if(localStorageService.get('wallet_should_restore')) { | |
return false; | |
} | |
return localStorageService.get('keystore') ? true : false; | |
}; | |
wallet.save = function() { | |
localStorageService.set('keystore', this.keystore.serialize()); | |
this.connect(wallet.EthereumService); | |
setTimeout(function() { | |
$rootScope.$digest(); | |
}, 1); | |
return this; | |
}; | |
wallet.upload = function(element, cb) { | |
var reader = new FileReader(); | |
reader.onload = function() { | |
var text = reader.result; | |
try { | |
localStorageService.set('keystore', text); | |
if(wallet.restore(wallet.EthereumService)) { | |
if(cb) { cb(); } | |
} | |
$rootScope.$digest(); | |
} catch (err) {} | |
}; | |
reader.readAsText(element.files[0]); | |
}; | |
wallet.download = function() { | |
if(wallet.isUsingMetamask()) { | |
alert('Action not allowed when using metamask'); | |
return false; | |
} | |
if (!localStorageService.get('keystore')) { | |
alert("No wallet exists!"); | |
return; | |
} | |
var blob = new Blob([localStorageService.get('keystore')], { | |
type: "text/plain;charset=utf-8" | |
}); | |
saveAs(blob, "gnosis_wallet_" + wallet.getAddress() + ".txt"); | |
}; | |
wallet.restore = function(EthereumService) { | |
if(wallet.isUsingMetamask()) { | |
wallet.connect(EthereumService); | |
return true; | |
} | |
try { | |
this.keystore = lightwallet.keystore.deserialize(localStorageService.get('keystore')); | |
wallet.connect(EthereumService); | |
wallet.shouldRestore(false); | |
return true; | |
} catch (e) { | |
console.error(e); | |
this.destroy(); | |
alert('We could not restore your wallet. Make sure you are using a compatible format.'); | |
return false; | |
} | |
}; | |
wallet.getAddress = function() { | |
if(wallet.isUsingMetamask()) { | |
return wallet.getMetamaskSelectedAddress(); | |
} | |
return "0x" + this.keystore.getAddresses()[0]; | |
}; | |
wallet.destroy = function() { | |
if(wallet.isUsingMetamask()) { | |
wallet.useMetamask(false); | |
} | |
localStorageService.remove('keystore'); | |
this.keystore = null; | |
wallet.balances = { | |
tokens: null, | |
wei: null, | |
}; | |
return this; | |
}; | |
wallet.connect = function(EthereumService) { | |
if(wallet.isUsingMetamask()) { | |
EthereumService.connectToMetamask(); | |
ga('set', 'dimension1', 'Metamask'); | |
} else { | |
this.keystore.passwordProvider = function (callback) { | |
wallet.EthereumService.stateService.showPasswordPrompt(callback); | |
}; | |
EthereumService.connectProvider(); | |
ga('set', 'dimension1', 'Http provider'); | |
} | |
if(EthereumService.stateService) { | |
EthereumService.stateService.update(); | |
} | |
}; | |
window.Wallet = this; | |
}); | |
tokenLaunchServices.factory('EthereumService', ['$interval', '$timeout', '$http', '$rootScope', 'localStorageService', 'walletService', '$q', '$window', | |
function($interval, $timeout, $http, $rootScope, localStorageService, walletService, $q, $window) { | |
if($window.web3 && $window.web3.currentProvider.constructor.name == "MetamaskInpageProvider") { | |
$window.metamask_web3 = $window.web3; | |
} | |
window.web3 = new Web3(); | |
/* service config */ | |
var BLOCK_TIME = 15; // in seconds | |
var UPDATE_BLOCKCHAIN = BLOCK_TIME * 1000; // every 15 seconds | |
/* default setting values */ | |
var DEFAULT_GAS = 150000; | |
var DEFAULT_ETHEREUM_NODE = window.tokenlaunch_config.default_node; | |
var DEFAULT_CONTRACT_ADDRESS = window.tokenlaunch_config.fund_address; | |
var factory = {}; | |
factory.DEFAULT_GAS = DEFAULT_GAS; | |
factory.walletService = walletService; | |
factory.balances = { | |
wei: null, | |
tokens: null, | |
}; | |
factory.transactions = []; | |
/* add and persists transaction in local storage */ | |
function addTransaction(transaction) { | |
factory.transactions.push(transaction); | |
//trigger UI update | |
factory.stateService.updates++; | |
localStorageService.set('transactions', angular.toJson(factory.transactions)); | |
} | |
factory.addTransaction = addTransaction; | |
/* update information about pending transactions */ | |
function updateTransactions() { | |
var pending_transactions = factory.transactions.filter(function(tx) {if(!tx.receipt) return tx}); | |
for (var i=0; i<pending_transactions.length; i++) { | |
web3.eth.getTransactionReceipt(pending_transactions[i].hash, function(err, receipt) { | |
if(!err) { | |
for (var j=0; j<factory.transactions.length; j++) { | |
if(receipt && factory.transactions[j].hash == receipt.transactionHash) { | |
factory.transactions[j].receipt = receipt; | |
localStorageService.set('transactions', angular.toJson(factory.transactions)); | |
} | |
} | |
} | |
else { | |
logError(err); | |
} | |
}); | |
} | |
} | |
factory.updateTransactions = updateTransactions; | |
factory.getEthereumNode = function() { | |
return localStorageService.get('ethereum_node') || DEFAULT_ETHEREUM_NODE; | |
}; | |
factory.setContractAddress = function(contract_address) { | |
if (web3.isAddress(contract_address)) { | |
localStorageService.set('contract_address', angular.toJson(contract_address)); | |
} | |
}; | |
factory.setEthereumNode = function(ethereum_node) { | |
if (angular.isDefined(ethereum_node)) { | |
localStorageService.set('ethereum_node', ethereum_node); | |
} | |
}; | |
factory.resetSettings = function() { | |
localStorageService.set('contract_address', ""); | |
localStorageService.set('ethereum_node', ""); | |
}; | |
factory.getBlocknumber = function() { | |
var deferred = $q.defer(); | |
web3.eth.getBlockNumber(function(err, current_block) { | |
if(!err) { | |
deferred.resolve(current_block); | |
} | |
else { | |
deferred.reject(err); | |
} | |
}); | |
return deferred.promise; | |
} | |
factory.logout = function () { | |
factory.balances = { | |
wei: null, | |
tokens: null, | |
}; | |
factory.transactions = []; | |
factory.shares = {}; | |
localStorageService.set('transactions', ''); | |
}; | |
factory.withdraw = function(receiver_address, value) { | |
var deferred = $q.defer(); | |
web3.eth.sendTransaction({ | |
from: walletService.getAddress(), | |
to: receiver_address, | |
value: value, | |
gas: 23000, | |
gasPrice: rpc_web3.eth.gasPrice | |
}, | |
function(err, tx_hash) { | |
if (!err) { | |
addTransaction({ | |
'hash': tx_hash, | |
'subject': 'withdraw', | |
'token': 'ETH', | |
'value': web3.fromWei(value), | |
'receipt': null, | |
'from': walletService.getAddress(), | |
'to': receiver_address, | |
'date': new Date() | |
}); | |
deferred.resolve(tx_hash); | |
} else { | |
deferred.reject(err); | |
console.error(err); | |
} | |
} | |
); | |
factory.transaction_awaiting_pw_deferred = deferred; | |
return deferred.promise; | |
}; | |
/* initializes web3 library and interface contract*/ | |
var AuctionContract = web3.eth.contract(auction_abi); | |
window.auction_contract = AuctionContract.at(tokenlaunch_config.auction_address); | |
var TokenContract = web3.eth.contract(token_abi); | |
window.token_contract = TokenContract.at(tokenlaunch_config.token_address); | |
/* connect provider with keystore */ | |
factory.connectProvider = function() { | |
window.provider = new HookedWeb3Provider({ | |
host: factory.getEthereumNode(), | |
transaction_signer: walletService.keystore | |
}); | |
web3.setProvider(provider); | |
factory.connectRpcProvider(); | |
window.is_connected = true; | |
try { | |
factory.transactions = angular.fromJson(localStorageService.get('transactions')) || []; | |
updateTransactions(); | |
} catch(e) { | |
} | |
}; | |
/* use metamask */ | |
factory.connectToMetamask = function() { | |
web3.setProvider($window.metamask_web3.currentProvider); | |
factory.connectRpcProvider(); | |
window.is_connected = true; | |
try { | |
factory.transactions = angular.fromJson(localStorageService.get('transactions')) || []; | |
updateTransactions(); | |
} catch(e) { | |
} | |
}; | |
factory.connectRpcProvider = function() { | |
window.rpc_provider = new HookedWeb3Provider({ | |
host: factory.getEthereumNode() | |
}); | |
window.rpc_web3 = new Web3(); | |
window.rpc_web3.setProvider(rpc_provider); | |
}; | |
/* update balance info */ | |
factory.updateBalance = function() { | |
var deferred_eth = $q.defer(); | |
var deferred_tokens = $q.defer(); | |
web3.eth.getBalance(walletService.getAddress(), function(err, balance) { | |
if (!err) { | |
factory.balances.wei = balance; | |
deferred_eth.resolve(balance); | |
} else { | |
console.error(err); | |
} | |
}); | |
token_contract.balanceOf.call(walletService.getAddress(), function(err, balance) { | |
if (!err) { | |
factory.balances.tokens = balance; | |
deferred_tokens.resolve(balance) | |
} else { | |
console.error(err); | |
} | |
}); | |
return $q.all([ | |
deferred_eth.promise, | |
deferred_tokens.promise, | |
]); | |
}; | |
factory.transferTokens = function(receiver_address, value) { | |
var deferred = $q.defer(); | |
token_contract.transfer.sendTransaction( | |
receiver_address, | |
value, | |
{from: walletService.getAddress(), value: 0, gas: DEFAULT_GAS, gasPrice: rpc_web3.eth.gasPrice}, | |
function (err, tx_hash) { | |
if(!err) { | |
addTransaction({ | |
'hash': tx_hash, | |
'subject': 'withdraw', | |
'token': 'GNO', | |
'value': web3.fromWei(value), | |
'receipt': null, | |
'from': walletService.getAddress(), | |
'to': receiver_address, | |
'date': new Date() | |
}); | |
deferred.resolve(tx_hash); | |
} | |
else { | |
deferred.reject(err); | |
console.error(err); | |
} | |
} | |
); | |
factory.transaction_awaiting_pw_deferred = deferred; | |
return deferred.promise; | |
}; | |
factory.buyTokens = function(value) { | |
var deferred = $q.defer(); | |
var value_bn = new BigNumber(value); | |
var token_price = factory.stateService.tokenPrice; | |
var human_readable_tokens_count = value_bn.div(token_price).toNumber();; | |
auction_contract.bid.sendTransaction( | |
{from: walletService.getAddress(), value: value, gas: DEFAULT_GAS, gasPrice: rpc_web3.eth.gasPrice}, | |
function (err, tx_hash) { | |
if(!err) { | |
addTransaction({ | |
'hash': tx_hash, | |
'subject': 'bid', | |
'token': 'ETH', | |
'value': web3.fromWei(value_bn), | |
'receipt': null, | |
'from': walletService.getAddress(), | |
'to': tokenlaunch_config.auction_address, | |
'date': new Date() | |
}); | |
deferred.resolve(tx_hash); | |
} | |
else { | |
deferred.reject(err); | |
console.error(err); | |
} | |
} | |
); | |
factory.transaction_awaiting_pw_deferred = deferred; | |
return deferred.promise; | |
}; | |
factory.depositRevenue = function(value) { | |
var deferred = $q.defer(); | |
fund_contract.depositRevenue.sendTransaction( | |
{from: walletService.getAddress(), value: value, gas: DEFAULT_GAS, gasPrice: rpc_web3.eth.gasPrice}, | |
function (err, tx_hash) { | |
if(!err) { | |
addTransaction({ | |
'hash': tx_hash, | |
'subject': 'addRevenue', | |
'token': 'ETH', | |
'value': web3.fromWei(value), | |
'receipt': null, | |
'from': walletService.getAddress(), | |
'to': tokenlaunch_config.fund_address, | |
'date': new Date() | |
}); | |
deferred.resolve(tx_hash); | |
} | |
else { | |
deferred.reject(err); | |
console.error(err); | |
} | |
} | |
); | |
factory.transaction_awaiting_pw_deferred = deferred; | |
return deferred.promise; | |
}; | |
factory.withdrawForWorkshop = function() { | |
var deferred = $q.defer(); | |
auction_contract.withdrawForWorkshop.sendTransaction( | |
{from: walletService.getAddress(), value: 0, gas: DEFAULT_GAS, gasPrice: rpc_web3.eth.gasPrice}, | |
function (err, tx_hash) { | |
if(!err) { | |
addTransaction({ | |
'hash': tx_hash, | |
'subject': 'withdrawForWorkshop', | |
'token': 'ETH', | |
'value': 0, | |
'receipt': null, | |
'from': walletService.getAddress(), | |
'to': tokenlaunch_config.auction_address, | |
'date': new Date() | |
}); | |
deferred.resolve(tx_hash); | |
} | |
else { | |
deferred.reject(err); | |
console.error(err); | |
} | |
} | |
); | |
factory.transaction_awaiting_pw_deferred = deferred; | |
return deferred.promise; | |
}; | |
factory.pending_transactions = {}; | |
factory.waitForTransactionReceipt = function(tx_hash) { | |
var deferred = $q.defer(); | |
factory.pending_transactions[tx_hash] = { | |
callback: deferred.resolve, | |
}; | |
return deferred.promise; | |
}; | |
factory.checkPendingTransactions = function() { | |
for(var tx_hash in factory.pending_transactions) { | |
web3.eth.getTransactionReceipt(tx_hash, function(err, receipt) { | |
if(!err && receipt) { | |
for (var j=0; j<factory.transactions.length; j++) { | |
if(receipt && factory.transactions[j].hash == receipt.transactionHash) { | |
factory.transactions[j].receipt = receipt; | |
localStorageService.set('transactions', angular.toJson(factory.transactions)); | |
} | |
} | |
factory.pending_transactions[tx_hash].callback(); | |
delete factory.pending_transactions[tx_hash]; | |
} | |
}); | |
} | |
}; | |
factory.getTokenPrice = function() { | |
var deferred = $q.defer(); | |
auction_contract.calcCurrentTokenPrice.call(function(err, wei_per_share) { | |
if (!err) { | |
deferred.resolve(wei_per_share) | |
} else { | |
console.error(err); | |
} | |
}); | |
return deferred.promise; | |
}; | |
factory.getCurrentBid = function() { | |
var deferred = $q.defer(); | |
auction_contract.bids.call(walletService.getAddress(), function(err, bid) { | |
if (!err) { | |
deferred.resolve(bid) | |
} else { | |
console.error(err); | |
} | |
}); | |
return deferred.promise; | |
}; | |
factory.getTotalSupply = function() { | |
var deferred = $q.defer(); | |
token_contract.totalSupply.call(function(err, totalSupply) { | |
if (!err) { | |
deferred.resolve(totalSupply); | |
} else { | |
console.error(err); | |
} | |
}); | |
return deferred.promise; | |
}; | |
factory.getTotalRaised = function() { | |
var deferred = $q.defer(); | |
auction_contract.totalRaised.call(function(err, totalRaised) { | |
if (!err) { | |
deferred.resolve(totalRaised); | |
} else { | |
console.error(err); | |
} | |
}); | |
return deferred.promise; | |
}; | |
factory.getRevenueShare = function() { | |
var deferred = $q.defer(); | |
fund_contract.withdrawRevenue.call( | |
{from: walletService.getAddress()}, | |
function(err, revenue_share) { | |
if (!err) { | |
deferred.resolve(revenue_share); | |
} else { | |
console.error(err); | |
} | |
} | |
); | |
return deferred.promise; | |
}; | |
factory.claimTokens = function() { | |
var deferred = $q.defer(); | |
auction_contract.claimTokens.sendTransaction( | |
{from: walletService.getAddress(), value: 0, gas: DEFAULT_GAS, gasPrice: rpc_web3.eth.gasPrice}, | |
function (err, tx_hash) { | |
if(!err) { | |
addTransaction({ | |
'hash': tx_hash, | |
'subject': 'claimTokens', | |
'token': 'ETH', | |
'value': 0, | |
'receipt': null, | |
'from': walletService.getAddress(), | |
'to': tokenlaunch_config.auction_address, | |
'date': new Date() | |
}); | |
deferred.resolve(tx_hash); | |
} | |
else { | |
deferred.reject(err); | |
console.error(err); | |
} | |
} | |
); | |
factory.transaction_awaiting_pw_deferred = deferred; | |
return deferred.promise; | |
}; | |
factory.updateStatsWidgets = function() { | |
$q.all([ | |
factory.getTotalRaised(), | |
factory.getTokenPrice(), | |
factory.getBlocknumber(), | |
]).then(function(results) { | |
updateState({ | |
total_funds: web3.fromWei(results[0]).toString(), | |
token_price: web3.fromWei(results[1]).toString(), | |
current_block: results[2], | |
}, true); | |
}); | |
}; | |
if (walletService.exists()) { | |
walletService.restore(factory); | |
} | |
walletService.EthereumService = factory; | |
window.service = factory; | |
return factory; | |
} | |
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var app = angular.module('token_launch', [ | |
'LocalStorageModule', | |
'tokenLaunchServices', | |
'tokenLaunchFilters', | |
'ui-notification', | |
'angular-clipboard', | |
'tokenLaunchTestTools' | |
]); | |
app.controller('StatusCtrl', function($scope, walletService, EthereumService, stateService, Notification, clipboard, $timeout) { | |
$scope.tokenlaunch_enabled = window.tokenlaunch_config.enabled; | |
$scope.$watch(function() { | |
return walletService.exists() && ! stateService.isWalletCreating; | |
}, function(newVal) { | |
if (!newVal) { | |
$scope.is_shown = 0; | |
} else { | |
$scope.address = walletService.getAddress(); | |
$scope.is_shown = 1; | |
} | |
}); | |
$scope.$watch(function() { | |
return stateService.blocknumber + stateService.updates; | |
}, function(newVal) { | |
$scope.tokens = walletService.balances.tokens ? new BigNumber(web3.fromWei(walletService.balances.tokens, 'ether').toFixed(4)).toFormat() : '...'; | |
$scope.eth_balance = walletService.balances.wei ? new BigNumber(web3.fromWei(walletService.balances.wei, 'ether').toFixed(4)).toFormat() : '...'; | |
$scope.commited_eth_balance = 0; | |
$scope.total_potential_tokens = 0; | |
$scope.transactions = getTransactions(); | |
$scope.token_price = stateService.tokenPrice; | |
$scope.stage = stateService.stage; | |
if(stateService.bid) { | |
$scope.current_bid = new BigNumber(web3.fromWei(stateService.bid, 'ether').toFixed(4)).toFormat(); | |
$scope.current_tokens = stateService.bid.greaterThan(0) ? new BigNumber(stateService.bid.div(stateService.tokenPrice).toFixed(6)).toFormat() : 0; | |
} | |
}); | |
$scope.isBuyShown = function() { | |
return $scope.is_shown && $scope.stage == stateService.stages.AuctionStarted; | |
}; | |
$scope.isClaimTokensShown = function() { | |
return $scope.is_shown && $scope.stage == stateService.stages.AuctionEnded && $scope.current_tokens; | |
}; | |
function getTransactions() { | |
return _.sortBy(EthereumService.transactions , function(o) { | |
return new Date(o.date).getTime(); | |
}).reverse(); | |
} | |
$scope.show_deposit = 0; | |
$scope.show_withdraw = 0; | |
$scope.show_tx_history = 0; | |
$scope.cancelWalletAction = function() { | |
$scope.show_deposit = 0; | |
$scope.show_withdraw = 0; | |
$scope.show_tx_history = 0; | |
$timeout(function() { | |
$('html, body').animate({ | |
scrollTop: $("#wallet-status").offset().top | |
}, 400); | |
}); | |
}; | |
$scope.showDeposit = function() { | |
$scope.show_deposit = 1; | |
$scope.show_withdraw = 0; | |
$scope.show_tx_history = 0; | |
$timeout(function() { | |
$('html, body').animate({ | |
scrollTop: $("#wallet-deposit").offset().top | |
}, 400); | |
}); | |
}; | |
$scope.showWithdraw = function() { | |
$scope.show_deposit = 0; | |
$scope.show_withdraw = 1; | |
$scope.show_tx_history = 0; | |
$scope.withdraw_amount = null; | |
$timeout(function() { | |
$('html, body').animate({ | |
scrollTop: $("#wallet-withdraw").offset().top | |
}, 400); | |
}); | |
}; | |
$scope.showTxHistory = function() { | |
$scope.show_deposit = 0; | |
$scope.show_withdraw = 0; | |
$scope.show_tx_history = 1; | |
$scope.withdraw_amount = null; | |
$scope.transactions = getTransactions(); | |
$timeout(function() { | |
$('html, body').animate({ | |
scrollTop: $("#wallet-txhistory").offset().top | |
}, 400); | |
}); | |
}; | |
$scope.copyAddressToClipboard = function() { | |
if (!clipboard.supported) { | |
Notification.error('Sorry, copy to clipboard is not supported on your device'); | |
return false; | |
} | |
if(tokenlaunch_config.testnet) { | |
Notification.warning('Warning: you are on the ' + tokenlaunch_config.testnet + '. Be careful not to transfer real funds to this account.'); | |
} | |
clipboard.copyText(walletService.getAddress()); | |
Notification.info('Address copied to clipboard'); | |
}; | |
$scope.openShapeshiftPopup = function($event) { | |
$event.preventDefault(); | |
if(tokenlaunch_config.testnet) { | |
alert("Warning: THIS IS A TEST. If you use shapeshift, the resulting funds (ETH) will be available on the live Ethereum network, NOT ON THIS Morden Test-Net!!!\n\nMake sure your lightwallet is backed up before continuing. In the case real ETH is sent to your Test-Net Wallet you can recover your real ETH from the lightwallet here: https://singulardtv.com/lightwallet"); | |
} | |
var link = $event.target.href; | |
window.open(link,'1418115287605','width=700,height=500,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=0,left=0,top=0'); | |
}; | |
$scope.logout = function() { | |
walletService.destroy(); | |
EthereumService.logout(); | |
stateService.funding_method = null; | |
window.location.reload(); | |
}; | |
$scope.withdraw = function() { | |
$scope.withdraw_error = {}; | |
if($scope.withdraw_token == 'ETH') { | |
if(walletService.balances.wei.equals(0)) { | |
$scope.withdraw_error.amount = true; | |
$scope.withdraw_error.message = "You don't have any ETH in your wallet"; | |
return false; | |
} | |
try { | |
var value = web3.toWei($scope.withdraw_amount); | |
var gas_cost = new BigNumber(rpc_web3.eth.gasPrice * 23000); | |
var gas_cost_eth = web3.fromWei(gas_cost); | |
var max_value = web3.fromWei(new BigNumber(walletService.balances.wei).minus(gas_cost)); | |
var total_cost = new BigNumber(value).plus(gas_cost); | |
if(total_cost.greaterThan(walletService.balances.wei)) { | |
$scope.withdraw_error.amount = true; | |
$scope.withdraw_error.message = 'Not enough funds. Gas cost is: ' + gas_cost_eth + ' ETH; The maximum amount you can withdraw is: ' + max_value + ' ETH'; | |
return false; | |
} | |
} catch(e) { | |
console.log(e); | |
$scope.withdraw_error.amount = true; | |
$scope.withdraw_error.message = 'Amount must be a valid number'; | |
return false; | |
} | |
if(! web3.isAddress($scope.withdraw_to)) { | |
$scope.withdraw_error.to = true; | |
$scope.withdraw_error.message = 'Invalid Ethereum address'; | |
return false; | |
} | |
if($scope.withdraw_to == walletService.getAddress()) { | |
$scope.withdraw_error.to = true; | |
$scope.withdraw_error.message = 'Destination address should be different than yours'; | |
return false; | |
} | |
$scope.withdrawing = true; | |
stateService.EthereumService.withdraw($scope.withdraw_to, value).then(function(tx_hash) { | |
Notification.info('Your withdrawal transaction was sent, it may take up to 20 seconds. Awaiting confirmation...'); | |
stateService.EthereumService.waitForTransactionReceipt(tx_hash).then(function() { | |
Notification.success('Withdrawal transaction confirmed.'); | |
}); | |
$scope.closeWithdraw(); | |
}).catch(function(err) { | |
Notification.error('Transaction was not sent.'); | |
console.log(err); | |
}).finally(function() { | |
$scope.withdrawing = false; | |
}); | |
} | |
if($scope.withdraw_token == 'GNO') { | |
if(walletService.balances.tokens.equals(0)) { | |
$scope.withdraw_error.amount = true; | |
$scope.withdraw_error.message = "You don't have any GNO tokens in your wallet"; | |
return false; | |
} | |
if(! stateService.tokens_fungible) { | |
$scope.withdraw_error.amount = true; | |
$scope.withdraw_error.message = "GNO tokens are not transferable just yet. 1 week should pass from the auction closing date."; | |
return false; | |
} | |
var gas_cost = new BigNumber(rpc_web3.eth.gasPrice * stateService.EthereumService.DEFAULT_GAS); | |
var gas_cost_eth = web3.fromWei(gas_cost); | |
if(gas_cost.greaterThan(walletService.balances.wei)) { | |
$scope.withdraw_error.amount = true; | |
$scope.withdraw_error.message = 'Not enough ETH funds for gas cost. Please deposit at least ' + gas_cost_eth + ' ETH in your account first'; | |
return false; | |
} | |
try { | |
var tokens = web3.toWei($scope.withdraw_amount); | |
var tokens_bn = new BigNumber(tokens); | |
if(tokens_bn.greaterThan(walletService.balances.tokens)) { | |
$scope.withdraw_error.amount = true; | |
$scope.withdraw_error.message = 'You can transfer a maximum of ' + web3.fromWei(walletService.balances.tokens) + ' GNO tokens.'; | |
return false; | |
} | |
} catch(e) { | |
console.log(e); | |
$scope.withdraw_error.amount = true; | |
$scope.withdraw_error.message = 'Amount must be a valid number'; | |
return false; | |
} | |
if(! web3.isAddress($scope.withdraw_to)) { | |
$scope.withdraw_error.to = true; | |
$scope.withdraw_error.message = 'Invalid Ethereum address'; | |
return false; | |
} | |
if($scope.withdraw_to == walletService.getAddress()) { | |
$scope.withdraw_error.to = true; | |
$scope.withdraw_error.message = 'Destination address should be different than yours'; | |
return false; | |
} | |
if($scope.withdraw_to == tokenlaunch_config.token_address) { | |
$scope.withdraw_error.to = true; | |
$scope.withdraw_error.message = 'Destination address should be different than GNO token contract address'; | |
return false; | |
} | |
if($scope.withdraw_to == tokenlaunch_config.auction_address) { | |
$scope.withdraw_error.to = true; | |
$scope.withdraw_error.message = 'Destination address should be different than Gnosis Auction contract address'; | |
return false; | |
} | |
$scope.withdrawing = true; | |
stateService.EthereumService.transferTokens($scope.withdraw_to, tokens).then(function(tx_hash) { | |
Notification.info('Your withdrawal transaction was sent, it may take up to 20 seconds. Awaiting confirmation...'); | |
stateService.EthereumService.waitForTransactionReceipt(tx_hash).then(function() { | |
Notification.success('Withdrawal transaction confirmed.'); | |
}); | |
$scope.closeWithdraw(); | |
}).catch(function(err) { | |
Notification.error('Transaction was not sent.'); | |
console.log(err); | |
}).finally(function() { | |
$scope.withdrawing = false; | |
}); | |
} | |
}; | |
var skip_buy_form_recalc = false; | |
$scope.$watch(function() { | |
return $scope.buy_eth_amount; | |
}, function(newVal, oldValue) { | |
if(! newVal) { | |
$scope.potential_tokens = null; | |
$scope.buy_eth_amount = null; | |
$scope.buy_eth_amount_bn = null; | |
return; | |
} | |
try { | |
$scope.buy_eth_amount_bn = new BigNumber(newVal); | |
$scope.potential_tokens = new BigNumber(web3.toWei($scope.buy_eth_amount_bn)).div(stateService.tokenPrice).toNumber(); | |
} catch(e) { | |
console.error(e); | |
$scope.buy_eth_amount = oldValue; | |
} | |
}); | |
$scope.buyTokens = function() { | |
$scope.buy_error = {}; | |
if(walletService.balances.wei.equals(0)) { | |
$scope.buy_error.amount = true; | |
$scope.buy_error.message = "You don't have any ETH in your wallet"; | |
return false; | |
} | |
try { | |
var value = web3.toWei($scope.buy_eth_amount_bn); | |
var gas_cost = new BigNumber(rpc_web3.eth.gasPrice * stateService.EthereumService.DEFAULT_GAS); | |
var gas_cost_eth = web3.fromWei(gas_cost); | |
if(gas_cost.greaterThan(walletService.balances.wei)) { | |
$scope.buy_error.amount = true; | |
$scope.buy_error.message = 'Not enough ETH funds for gas cost. Please deposit at least ' + gas_cost_eth + ' ETH in your account first'; | |
return false; | |
} | |
var gas_cost = new BigNumber(rpc_web3.eth.gasPrice * stateService.EthereumService.DEFAULT_GAS); | |
var gas_cost_eth = web3.fromWei(gas_cost); | |
var max_value = web3.fromWei(new BigNumber(walletService.balances.wei).minus(gas_cost)); | |
var total_cost = new BigNumber(value).plus(gas_cost); | |
if(total_cost.greaterThan(walletService.balances.wei)) { | |
$scope.buy_error.amount = true; | |
$scope.buy_error.message = 'Not enough funds. Gas cost is: ' + gas_cost_eth + ' ETH; The maximum amount you can buy with is: ' + max_value + ' ETH'; | |
return false; | |
} | |
} catch(e) { | |
console.log(e); | |
$scope.buy_error.amount = true; | |
$scope.buy_error.message = 'Amount must be a valid number'; | |
return false; | |
} | |
if(value <= 0) { | |
$scope.buy_error.amount = true; | |
$scope.buy_error.message = 'ETH amount is required'; | |
return false; | |
} | |
$scope.buying = true; | |
stateService.EthereumService.buyTokens(value).then(function(tx_hash) { | |
Notification.info('Your buy transaction was sent, it may take up to 20 seconds. Awaiting confirmation...'); | |
sendGaEvent('tokenlaunch', 'buy', 'sngls', $scope.buy_sngls_amount); | |
stateService.EthereumService.waitForTransactionReceipt(tx_hash).then(function() { | |
Notification.success('Buy transaction confirmed.'); | |
$scope.buying = false; | |
$scope.buy_eth_amount = null; | |
EthereumService.updateStatsWidgets(); | |
}); | |
}).catch(function(err) { | |
Notification.error('Transaction was not sent.'); | |
console.log(err); | |
$scope.buying = false; | |
}).finally(function() { | |
// | |
}); | |
}; | |
$scope.closeWithdraw = function() { | |
$scope.withdraw_amount = null; | |
$scope.withdraw_to = null; | |
$scope.withdraw_error = {}; | |
$scope.cancelWalletAction(); | |
}; | |
$scope.claimTokens = function() { | |
$scope.claim_tokens = {}; | |
var gas_cost = new BigNumber(rpc_web3.eth.gasPrice * stateService.EthereumService.DEFAULT_GAS); | |
var gas_cost_eth = web3.fromWei(gas_cost); | |
if(gas_cost.greaterThan(walletService.balances.wei)) { | |
$scope.claim_tokens.message = 'Not enough ETH funds for gas cost. Please deposit at least ' + gas_cost_eth + ' ETH in your account first'; | |
return false; | |
} | |
$scope.claim_tokens.loading = true; | |
stateService.EthereumService.claimTokens().then(function(tx_hash) { | |
Notification.info('Your claimTokens transaction was sent, it may take up to 20 seconds. Awaiting confirmation...'); | |
stateService.EthereumService.waitForTransactionReceipt(tx_hash).then(function() { | |
Notification.success('claimTokens transaction confirmed.'); | |
$scope.claim_tokens.loading = false; | |
}); | |
}).catch(function(err) { | |
Notification.error('Transaction was not sent.'); | |
console.log(err); | |
$scope.claim_tokens.loading = false; | |
}).finally(function() { | |
// | |
}); | |
}; | |
$scope.isUsingMetamask = function() { | |
return walletService.isUsingMetamask(); | |
}; | |
}); | |
app.controller('FundMethodCtrl', function($scope, stateService, walletService, $window, EthereumService, Notification) { | |
$scope.show_continue = false; | |
$scope.fund_method = null; | |
$scope.$watch(function() { | |
return stateService.funding_method; | |
}, function(newVal) { | |
if (!newVal) { | |
$scope.is_shown = !walletService.exists(); | |
} else { | |
$scope.is_shown = 0; | |
} | |
}); | |
$scope.fundMethodChange = function() { | |
$scope.show_continue = true; | |
}; | |
$scope.goToNextStep = function() { | |
if($scope.fund_method == 'Metamask') { | |
if(! $window.metamask_web3) { | |
Notification.error('You need to install Metamask first.'); | |
return false; | |
} | |
if(! walletService.isMetamaskProviderSetCorrect()) { | |
Notification.error($scope.getMetamaskNetworkInstructions()); | |
return false; | |
} | |
walletService.useMetamask(true); | |
walletService.restore(EthereumService); | |
} | |
stateService.funding_method = $scope.fund_method; | |
$scope.fund_method = null; | |
$scope.show_continue = false; | |
}; | |
$scope.isMetamaskInstalled = function() { | |
return $window.metamask_web3 != null; | |
} | |
$scope.getMetamaskNetworkInstructions = function() { | |
if(! $scope.isMetamaskInstalled() || walletService.isMetamaskProviderSetCorrect()) { | |
return null; | |
} | |
var instructions = null; | |
if(tokenlaunch_config.metamask_provider_type == 'rpc') { | |
instructions = 'Set metamask network to custom: ' + tokenlaunch_config.default_node + ' and reload the page'; | |
} else { | |
if(tokenlaunch_config.metamask_provider_type == 'mainnet') { | |
instructions = 'Set the Metamask netowork to Main Ethereum Network and reload the page'; | |
} | |
if(tokenlaunch_config.metamask_provider_type == 'testnet') { | |
instructions = 'Set the Metamask netowork to Morden Test Network and reload the page'; | |
} | |
} | |
return instructions; | |
} | |
}); | |
app.controller('LightWalletCtrl', function($scope, walletService, $http, stateService, $interval) { | |
// States | |
$scope.is_shown = 0; | |
$scope.wallet_init = 0; | |
$scope.wallet_generate_seed = 0; | |
$scope.wallet_password = 0; | |
$scope.wallet_backup = 0; | |
$scope.wallet_recover = 0; | |
$scope.wallet_recover_seed = 0; | |
$scope.wallet_new_generated = 0; | |
// Control | |
$scope.should_restore = 0; | |
// Info | |
$scope.wallet_seed = null; | |
$scope.wallet_data = { | |
password: '', | |
password_verify: '' | |
}; | |
$scope.recovery_seed = null; | |
$scope.recovery_seed_form_error = 0; | |
$scope.$watch(function() { | |
return stateService.funding_method === "Lightwallet" && !walletService.exists(); | |
}, function(newVal) { | |
if (newVal) { | |
$scope.is_shown = 1; | |
$scope.wallet_init = 1; | |
} else { | |
$scope.is_shown = 0; | |
} | |
}); | |
// Starts the process of lightwallet generation | |
$scope.initGenerateWallet = function() { | |
var entropy_limit = 5000; | |
var percentage = 0; | |
var interval_timer; | |
$scope.wallet_init = 0; | |
$scope.wallet_generate_seed = 1; | |
// When generating a new wallet, we force the user to recover it afterwards | |
// to make sure it's safely stored. | |
$scope.shouldRestore(true); | |
$scope.should_restore = 1; | |
// Mark the creation state | |
stateService.set({ | |
isWalletCreating: true | |
}); | |
// Style that reflects the amount the bar has filled | |
$scope.seed_progress = 0; | |
$scope.fillStyle = { | |
'width': $scope.seed_progress + '%' | |
}; | |
// Generate the seed | |
EntropyCollector.start(); | |
interval_timer = $interval(function() { | |
if (EntropyCollector.estimatedEntropy > entropy_limit) { | |
// Sets visual progress | |
$scope.seed_progress = 100; | |
$scope.fillStyle = { | |
'width': $scope.seed_progress + '%' | |
}; | |
// Saves seed | |
$scope.wallet_seed = lightwallet.keystore.generateRandomSeed(String.fromCharCode.apply(null, new Uint16Array(EntropyCollector.buffer))); | |
EntropyCollector.stop(); | |
// Update to next state | |
$scope.wallet_generate_seed = 0; | |
$scope.wallet_password = 1; | |
// Remove event listeners & cancer inverval | |
document.removeEventListener('mousemove', function() {}); | |
document.removeEventListener('touchmove', function() {}); | |
$interval.cancel(interval_timer); | |
} else { | |
percentage = parseInt(EntropyCollector.estimatedEntropy / entropy_limit * 100); | |
if (percentage > $scope.seed_progress) { | |
$scope.seed_progress = percentage; | |
$scope.fillStyle = { | |
'width': $scope.seed_progress + '%' | |
}; | |
} | |
} | |
}, 1000 / 30); | |
}; | |
// Validates that wallet password respects our standards | |
$scope.validateWalletPassword = function() { | |
if ($scope.wallet_data) { | |
// password length | |
if ($scope.wallet_data.password && $scope.wallet_data.password.length < 8) { | |
$scope.password_form.password.$setValidity('length', false); | |
} else { | |
$scope.password_form.password.$setValidity('length', true); | |
} | |
// passwords match | |
if ($scope.wallet_data.password_verify && $scope.wallet_data.password != $scope.wallet_data.password_verify) { | |
$scope.password_form.password_verify.$setValidity('match', false); | |
} else { | |
$scope.password_form.password_verify.$setValidity('match', true); | |
} | |
} | |
}; | |
// Starts creation of wallet | |
$scope.createWallet = function() { | |
var action_url = '/token/validate-register-form'; | |
if ($scope.password_form.$valid) { | |
$scope.creating_wallet = 1; // button spinner on | |
$http.post(action_url, { | |
password: $scope.wallet_data.password, | |
verifypassword: $scope.wallet_data.password_verify, | |
}).success(function(response, status, headers, config) { | |
if (response.success === 1) { | |
$scope.registerWallet($scope.wallet_seed, $scope.wallet_data.password); | |
} | |
}).error(function(data, status, headers, config) { | |
$scope.creating_wallet = 0; // button spinner off | |
}).finally(function() {}); | |
} | |
}; | |
$scope.registerWallet = function(seed, password) { | |
lightwallet.keystore.createVault({ | |
password: password, | |
seedPhrase: seed | |
}, function(err, ks) { | |
ks.keyFromPassword(password, function(err, pwDerivedKey) { | |
if (err) throw err; | |
ks.generateNewAddress(pwDerivedKey, 1); | |
Wallet.keystore = ks; | |
Wallet.save(); | |
// reset form | |
$scope.password_form.$setPristine(); | |
$scope.password_form.$setUntouched(); | |
$scope.wallet_data.password = ""; | |
$scope.wallet_data.password_verify = ""; | |
$scope.creating_wallet = 0; // button spinner off | |
// Update to next state | |
$scope.wallet_password = 0; | |
$scope.wallet_backup = 1; | |
sendGaEvent('lightwallet', 'generated'); | |
}); | |
}); | |
}; | |
// Download wallet | |
$scope.downloadWallet = function() { | |
$scope.wallet_backup_continue = 1; | |
$scope.wallet_backup_email = 0; | |
Wallet.download(); | |
}; | |
// Email wallet | |
$scope.emailWallet = function() { | |
var action_url = '/token/send'; | |
if ($scope.email_form.$valid) { | |
$scope.email_wallet_submit = 1; | |
$http.post(action_url, { | |
keystore: Wallet.keystore.serialize(), | |
email: $scope.email_wallet.email, | |
address: Wallet.getAddress() | |
}).success(function(response, status, headers, config) { | |
if (response.success === 1) { | |
$scope.email_wallet_success = 1; | |
$scope.wallet_backup_continue = 1; | |
} else { | |
alert('Our mail server seems to be down. Please try to download the wallet instead.'); | |
} | |
// Clear form | |
$scope.email_form.$setPristine(); | |
$scope.email_form.$setUntouched(); | |
$scope.email_wallet.email = ""; | |
$scope.email_wallet_submit = 0; | |
$scope.wallet_backup_email = 0; | |
}).error(function(data, status, headers, config) { | |
alert('Our mail server seems to be down. Please try to download the wallet instead.'); | |
}).finally(function() {}); | |
} | |
}; | |
$scope.createWalletFinish = function() { | |
$scope.wallet_backup = 0; | |
// Set backup screen defaults | |
$scope.wallet_backup_continue = 0; | |
$scope.wallet_backup_email = 0; | |
$scope.email_wallet_success = 0; | |
if ($scope.should_restore) { | |
$scope.should_restore = 0; | |
$scope.wallet_recover = 1; | |
$scope.wallet_new_generated = 1; | |
} else { | |
$scope.endRecovery(); | |
walletService.shouldRestore(false); | |
} | |
// Mark finishing of wallet creation | |
stateService.set({ | |
isWalletCreating: false | |
}); | |
}; | |
$scope.setRecoveringWallet = function() { | |
$scope.wallet_init = 0; | |
$scope.wallet_new_generated = 0; | |
$scope.wallet_recover = 1; | |
}; | |
// Should restart everything | |
$scope.endRecovery = function() { | |
$scope.wallet_init = 1; | |
$scope.wallet_generate_seed = 0; | |
$scope.wallet_password = 0; | |
$scope.wallet_backup = 0; | |
$scope.wallet_recover = 0; | |
$scope.wallet_recover_seed = 0; | |
$scope.wallet_new_generated = 0; | |
$scope.should_restore = 0; | |
$scope.wallet_seed = null; | |
$scope.wallet_data = { | |
password: '', | |
password_verify: '' | |
}; | |
$scope.recovery_seed = null; | |
$scope.recovery_seed_form_error = 0; | |
}; | |
$scope.uploadWallet = function(element) { | |
walletService.upload(element, $scope.endRecovery); | |
angular.element(element).val(null); | |
return walletService; | |
}; | |
$scope.recoverBySeed = function() { | |
$scope.recovery_seed_form_error = 0; | |
if (!lightwallet.keystore.isSeedValid($scope.recovery_seed)) { | |
$scope.recovery_seed_form_error = 1; | |
return false; | |
} | |
// Marking the end of seed recovery | |
$scope.wallet_new_generated = 0; | |
$scope.wallet_recover = 0; | |
$scope.wallet_recover_seed = 0; | |
$scope.recovery_seed_form_error = 0; | |
// Making user go through the password step | |
$scope.wallet_seed = $scope.recovery_seed; | |
$scope.wallet_password = 1; | |
// Mark we are still creating the wallet | |
stateService.set({ | |
isWalletCreating: true | |
}); | |
// TODO: This is what makes walletService.exists() to yield true and keep the creation process w/ password going | |
walletService.shouldRestore(true); | |
}; | |
$scope.shouldRestore = function(val) { | |
walletService.shouldRestore(val); | |
}; | |
$scope.backToFundingMethods = function() { | |
stateService.funding_method = null; | |
}; | |
}); | |
app.controller('PasswordPromptCtrl', function($scope, stateService) { | |
$scope.$watch(function() { | |
return stateService.show_password_prompt; | |
}, function(newVal) { | |
if (!newVal) { | |
$scope.is_shown = 0; | |
} else { | |
$('html').addClass('popup-open'); | |
$scope.is_shown = 1; | |
} | |
}); | |
$scope.unlockWallet = function() { | |
$scope.deriving_key = true; | |
$scope.wallet_password_error = false; | |
if(! $scope.wallet_password) { | |
$scope.deriving_key = false; | |
$scope.wallet_password_error = true; | |
return false; | |
} | |
var keystore = stateService.walletService.keystore; | |
keystore.keyFromPassword($scope.wallet_password, function(err, pwDerivedKey) { | |
$scope.deriving_key = false; | |
if(! err && keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
stateService.password_prompt_cb(null, $scope.wallet_password); | |
stateService.password_prompt_cb = null; | |
$scope.wallet_password = null; | |
$scope.wallet_password_error = false; | |
$('html').removeClass('popup-open'); | |
stateService.hidePasswordPrompt(); | |
} else { | |
$scope.wallet_password_error = true; | |
$scope.$digest(); | |
} | |
}); | |
}; | |
$scope.close = function() { | |
$('html').removeClass('popup-open'); | |
stateService.hidePasswordPrompt(); | |
}; | |
}); | |
app.controller('MistCtrl', function($scope, walletService, stateService, clipboard, Notification) { | |
$scope.$watch(function() { | |
return stateService.funding_method; | |
}, function(newVal) { | |
if (newVal === "MIST") { | |
$scope.is_shown = 1; | |
} else { | |
$scope.is_shown = 0; | |
} | |
}); | |
$scope.copyTokenLaunchAddressToClipboard = function() { | |
if (!clipboard.supported) { | |
Notification.error('Sorry, copy to clipboard is not supported on your device'); | |
return false; | |
} | |
if(tokenlaunch_config.testnet) { | |
Notification.warning('Warning: you are on the ' + tokenlaunch_config.testnet + '. Be careful not to transfer real funds to this address.'); | |
} | |
clipboard.copyText(tokenlaunch_config.crowdfunding_address); | |
Notification.info('Token Launch Contract Address copied to clipboard'); | |
}; | |
$scope.copyTokenLaunchAbiToClipboard = function() { | |
if (!clipboard.supported) { | |
Notification.error('Sorry, copy to clipboard is not supported on your device'); | |
return false; | |
} | |
clipboard.copyText('[{"inputs":[],"constant":true,"name":"etherWallet","payable":false,"outputs":[{"type":"address","name":""}],"type":"function"},{"inputs":[],"constant":false,"name":"bid","payable":true,"outputs":[],"type":"function"},{"inputs":[],"constant":true,"name":"FUNDING_GOAL","payable":false,"outputs":[{"type":"uint256","name":""}],"type":"function"},{"inputs":[],"constant":false,"name":"claimTokens","payable":false,"outputs":[],"type":"function"},{"inputs":[],"constant":true,"name":"startBlock","payable":false,"outputs":[{"type":"uint256","name":""}],"type":"function"},{"inputs":[],"constant":true,"name":"finalPrice","payable":false,"outputs":[{"type":"uint256","name":""}],"type":"function"},{"inputs":[],"constant":true,"name":"stage","payable":false,"outputs":[{"type":"uint8","name":""}],"type":"function"},{"inputs":[],"constant":true,"name":"totalRaised","payable":false,"outputs":[{"type":"uint256","name":""}],"type":"function"},{"inputs":[],"constant":false,"name":"calcCurrentTokenPrice","payable":false,"outputs":[{"type":"uint256","name":"tokenPrice"}],"type":"function"},{"inputs":[],"constant":true,"name":"calcStopPrice","payable":false,"outputs":[{"type":"uint256","name":"stopPrice"}],"type":"function"},{"inputs":[],"constant":false,"name":"tokenLaunched","payable":false,"outputs":[{"type":"bool","name":"launched"}],"type":"function"}]'); | |
Notification.info("Gnosis Token Launch Contract's Json Interface copied to clipboard"); | |
}; | |
$scope.copyTokenAddressToClipboard = function() { | |
if (!clipboard.supported) { | |
Notification.error('Sorry, copy to clipboard is not supported on your device'); | |
return false; | |
} | |
clipboard.copyText(tokenlaunch_config.token_address); | |
Notification.info('Gnosis Token Contract Address copied to clipboard'); | |
}; | |
$scope.backToFundingMethods = function() { | |
stateService.funding_method = null; | |
}; | |
}); | |
app.controller('ChartCtrl', function($scope, $window) | |
{ | |
var ctx = document.getElementById("myChart"); | |
// var data_points = []; | |
//var initial_block = 10; | |
//var final_block = 1000000; | |
//// Valuation after first day | |
//for(var i = 1; i<20; i++){ | |
// var block = (final_block - initial_block)/i; | |
// var valuation = 20000 * 10000000 / ( block-initial_block); | |
// data_points.push( | |
// { | |
// x: block, | |
// y: valuation | |
// } | |
// ) | |
//} | |
//var customDataPoint = { | |
// label: 'Valuation', | |
// data: data_points | |
//}; | |
//$window.chart = customDataPoint; | |
var customDataPoint = { | |
pointBorderColor: 'rgba(0,164,194,1)', | |
borderColor: 'rgba(0,164,194,1)', | |
borderCapStyle: 'round', | |
pointBackgroundColor: '#182a36', | |
borderWidth: 2, | |
pointHoverBackgroundColor: 'rgba(0,164,194,1)', | |
pointHoverBorderColor: '#182a36', | |
data: [ | |
{ | |
x: 0, | |
y: 200 | |
}, | |
{ | |
x: 0.5, | |
// y: 69444444.44 | |
y: 69.45 | |
}, | |
{ | |
x: 1, | |
// y: 34722222.22 | |
y: 34.72 | |
}, | |
{ | |
x: 2, | |
// y: 17361111.11 | |
y: 17.36 | |
}, | |
{ | |
x: 3, | |
// y: 11574074.07 | |
y: 11.57 | |
}, | |
{ | |
x: 4, | |
// y: 8680555.556 | |
y: 8.68 | |
}, | |
{ | |
x: 5, | |
// y: 6944444.444 | |
y: 6.94 | |
}, | |
{ | |
x: 6, | |
// y: 5787037.037 | |
y: 5.79 | |
}, | |
{ | |
x: 7, | |
// y: 4960317.46 | |
y: 4.96 | |
}, | |
{ | |
x: 8, | |
// y: 4340277.778 | |
y: 4.34 | |
}, | |
{ | |
x: 9, | |
// y: 3858024.691 | |
y: 3.86 | |
}, | |
{ | |
x: 10, | |
// y: 3472222.222 | |
y: 3.47 | |
}, | |
{ | |
x: 11, | |
// y: 3156565.657 | |
y: 3.16 | |
}, | |
{ | |
x: 12, | |
// y: 2893518.519 | |
y: 2.89 | |
}, | |
{ | |
x: 13, | |
// y: 2670940.171 | |
y: 2.67 | |
}, | |
{ | |
x: 14, | |
// y: 2480158.73 | |
y: 2.48 | |
} | |
] | |
}; | |
var myChart = new Chart(ctx, { | |
type: 'line', | |
data: { | |
datasets: [ | |
customDataPoint | |
] | |
}, | |
options: { | |
scales: { | |
xAxes: [{ | |
type: 'linear', | |
position: 'bottom' | |
}], | |
yAxes: [{ | |
ticks: { | |
beginAtZero: true | |
} | |
}] | |
}, | |
legend: { | |
display: false | |
}, | |
tooltips: { | |
backgroundColor: 'rgba(15,27,36,1)', | |
// X Value of the tooltip as a string | |
xLabel: "Day", | |
callbacks: { | |
title: function(item, data) { | |
return 'Day '+item[0].xLabel; | |
}, | |
label: function(item, data) { | |
return 'Price: ' + (item.yLabel/10).toFixed(3)+' ETH'; | |
}, | |
afterLabel: function(item, data){ | |
return 'Valuation: '+item.yLabel+ 'M ETH'; | |
} | |
} | |
} | |
} | |
}); | |
}); | |
app.config(function($httpProvider) { | |
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; | |
$httpProvider.defaults.transformRequest = function(data) { | |
if (data === undefined) { | |
return data; | |
} | |
return $.param(data); | |
} | |
}); | |
app.filter('nl2br', function() { | |
return function(msg) { | |
var breakTag = '<br>'; | |
var msg = (msg + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2'); | |
return msg; | |
} | |
}); | |
app.directive('laddaLoading', function($filter, $timeout) { | |
return { | |
scope: true, | |
link: function(scope, element, attrs) { | |
var $element = $(element); | |
scope.$watch(attrs.laddaLoading, function(newVal) { | |
if (newVal) { | |
if (!$element.hasClass('ladda-button')) { | |
$element.addClass('ladda-button'); | |
$element.attr('data-style', 'zoom-in'); | |
} | |
scope.ladda_object = Ladda.create($element.get(0)); | |
scope.ladda_object.start(); | |
} else if (scope.ladda_object) { | |
scope.ladda_object.stop() | |
} | |
}); | |
} | |
}; | |
}); | |
app.directive('focusMe', function($timeout) { | |
return { | |
link: function(scope, element, attrs) { | |
scope.$watch(attrs.focusMe, function(value) { | |
if (value === 1) { | |
$timeout(function() { | |
element[0].focus(); | |
}); | |
} | |
}); | |
} | |
}; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment