Initial design & interactions
Began porting some function and state names to more generic descriptors like inputToken & outputToken thats align more closely with the proposed UX model in this design. Needs discussion.
21
.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
11487
package-lock.json
generated
21
package.json
@ -1,25 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "uniswap",
|
"name": "uniswap",
|
||||||
"homepage": ".",
|
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"metamask-logo": "^2.1.3",
|
"react": "^16.2.0",
|
||||||
"ramda": "^0.25.0",
|
"react-dom": "^16.2.0",
|
||||||
"react": "^16.1.1",
|
"react-helmet": "^5.2.0",
|
||||||
"react-dom": "^16.1.1",
|
"react-scripts": "1.1.0",
|
||||||
"react-scripts": "1.0.14",
|
"react-select": "^1.2.1",
|
||||||
"react-web3": "^0.4.3",
|
"react-web3": "^0.4.4",
|
||||||
"web3": "^1.0.0-beta.26"
|
"web3": "1.0.0-beta.18"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test --env=jsdom",
|
"test": "react-scripts test --env=jsdom",
|
||||||
"eject": "react-scripts eject",
|
"eject": "react-scripts eject"
|
||||||
"deploy": "npm run build&&gh-pages -d build"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"gh-pages": "^1.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
uniswap.io
|
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
@ -1,4 +1,4 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
@ -8,12 +8,8 @@
|
|||||||
manifest.json provides metadata used when your web app is added to the
|
manifest.json provides metadata used when your web app is added to the
|
||||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||||
-->
|
-->
|
||||||
|
<!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json"> -->
|
||||||
|
<link rel="shortcut icon" href="%PUBLIC_URL%/🦄.ico">
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
|
||||||
<link rel="shortcut icon" href="./favicon.ico">
|
|
||||||
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> -->
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "favicon.ico",
|
"src": "favicon.ico",
|
||||||
"sizes": "192x192",
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
"type": "image/png"
|
"type": "image/x-icon"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_url": "./index.html",
|
"start_url": "./index.html",
|
||||||
|
BIN
public/🦄.png
Normal file
After Width: | Height: | Size: 14 KiB |
@ -1,49 +0,0 @@
|
|||||||
pragma solidity 0.4.18;
|
|
||||||
|
|
||||||
/// @title SafeMath
|
|
||||||
/// @dev Math operations with safety checks that throw on error
|
|
||||||
library SafeMath {
|
|
||||||
/// @dev Multiplies a times b
|
|
||||||
function mul(uint256 a, uint256 b)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (uint256)
|
|
||||||
{
|
|
||||||
uint256 c = a * b;
|
|
||||||
assert(a == 0 || c / a == b);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Divides a by b
|
|
||||||
function div(uint256 a, uint256 b)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (uint256)
|
|
||||||
{
|
|
||||||
// assert(b > 0); // Solidity automatically throws when dividing by 0
|
|
||||||
uint256 c = a / b;
|
|
||||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Subtracts a from b
|
|
||||||
function sub(uint256 a, uint256 b)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (uint256)
|
|
||||||
{
|
|
||||||
assert(b <= a);
|
|
||||||
return a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Adds a to b
|
|
||||||
function add(uint256 a, uint256 b)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (uint256)
|
|
||||||
{
|
|
||||||
uint256 c = a + b;
|
|
||||||
assert(c >= a);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,164 +0,0 @@
|
|||||||
pragma solidity ^0.4.18;
|
|
||||||
|
|
||||||
contract ERC20Token {
|
|
||||||
uint256 public totalSupply;
|
|
||||||
function balanceOf(address who) public constant returns (uint256);
|
|
||||||
function transfer(address to, uint256 value) public returns (bool);
|
|
||||||
function allowance(address owner, address spender) public constant returns (uint256);
|
|
||||||
function transferFrom(address from, address to, uint256 value) public returns (bool);
|
|
||||||
function approve(address spender, uint256 value) public returns (bool);
|
|
||||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
|
||||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
|
||||||
}
|
|
||||||
|
|
||||||
library SafeMath {
|
|
||||||
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
|
|
||||||
uint256 c = a * b;
|
|
||||||
assert(a == 0 || c / a == b);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
function div(uint256 a, uint256 b) internal constant returns (uint256) {
|
|
||||||
// assert(b > 0); // Solidity automatically throws when dividing by 0
|
|
||||||
uint256 c = a / b;
|
|
||||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
|
|
||||||
assert(b <= a);
|
|
||||||
return a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
function add(uint256 a, uint256 b) internal constant returns (uint256) {
|
|
||||||
uint256 c = a + b;
|
|
||||||
assert(c >= a);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contract StandardToken is ERC20Token {
|
|
||||||
using SafeMath for uint256;
|
|
||||||
|
|
||||||
mapping(address => uint256) balances;
|
|
||||||
mapping (address => mapping (address => uint256)) internal allowed;
|
|
||||||
|
|
||||||
function transfer(address _to, uint256 _value) public returns (bool) {
|
|
||||||
require(_to != address(0));
|
|
||||||
require(_value <= balances[msg.sender]);
|
|
||||||
|
|
||||||
// SafeMath.sub will throw if there is not enough balance.
|
|
||||||
balances[msg.sender] = balances[msg.sender].sub(_value);
|
|
||||||
balances[_to] = balances[_to].add(_value);
|
|
||||||
Transfer(msg.sender, _to, _value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
|
|
||||||
require(_to != address(0));
|
|
||||||
require(_value <= balances[_from]);
|
|
||||||
require(_value <= allowed[_from][msg.sender]);
|
|
||||||
|
|
||||||
balances[_from] = balances[_from].sub(_value);
|
|
||||||
balances[_to] = balances[_to].add(_value);
|
|
||||||
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
|
|
||||||
Transfer(_from, _to, _value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function approve(address _spender, uint256 _value) public returns (bool) {
|
|
||||||
allowed[msg.sender][_spender] = _value;
|
|
||||||
Approval(msg.sender, _spender, _value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
|
|
||||||
return allowed[_owner][_spender];
|
|
||||||
}
|
|
||||||
|
|
||||||
function increaseApproval (address _spender, uint _addedValue) public returns (bool success) {
|
|
||||||
allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
|
|
||||||
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function decreaseApproval (address _spender, uint _subtractedValue) public returns (bool success) {
|
|
||||||
uint oldValue = allowed[msg.sender][_spender];
|
|
||||||
if (_subtractedValue > oldValue) {
|
|
||||||
allowed[msg.sender][_spender] = 0;
|
|
||||||
} else {
|
|
||||||
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
|
|
||||||
}
|
|
||||||
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function balanceOf(address _owner) public constant returns (uint256 balance) {
|
|
||||||
return balances[_owner];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contract Ownable {
|
|
||||||
|
|
||||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
|
||||||
|
|
||||||
address public owner;
|
|
||||||
|
|
||||||
modifier onlyOwner() {
|
|
||||||
require(msg.sender == owner);
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ownable() {
|
|
||||||
owner = msg.sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function transferOwnership(address newOwner) onlyOwner public {
|
|
||||||
require(newOwner != address(0));
|
|
||||||
OwnershipTransferred(owner, newOwner);
|
|
||||||
owner = newOwner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contract MintableToken is StandardToken, Ownable {
|
|
||||||
event Mint(address indexed to, uint256 amount);
|
|
||||||
event MintFinished();
|
|
||||||
|
|
||||||
bool public mintingFinished = false;
|
|
||||||
|
|
||||||
modifier canMint() {
|
|
||||||
require(!mintingFinished);
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Function to mint tokens
|
|
||||||
* @param _to The address that will receive the minted tokens.
|
|
||||||
* @param _amount The amount of tokens to mint.
|
|
||||||
* @return A boolean that indicates if the operation was successful.
|
|
||||||
*/
|
|
||||||
function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
|
|
||||||
totalSupply = totalSupply.add(_amount);
|
|
||||||
balances[_to] = balances[_to].add(_amount);
|
|
||||||
Mint(_to, _amount);
|
|
||||||
Transfer(0x0, _to, _amount);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Function to stop minting new tokens.
|
|
||||||
* @return True if the operation was successful.
|
|
||||||
*/
|
|
||||||
function finishMinting() onlyOwner public returns (bool) {
|
|
||||||
mintingFinished = true;
|
|
||||||
MintFinished();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contract uniTestToken is MintableToken {
|
|
||||||
string public constant name = "UNI Test Token";
|
|
||||||
string public constant symbol = "UNT";
|
|
||||||
uint8 public constant decimals = 6;
|
|
||||||
}
|
|
@ -1,162 +0,0 @@
|
|||||||
pragma solidity ^0.4.18;
|
|
||||||
|
|
||||||
/// @title SafeMath
|
|
||||||
/// @dev Math operations with safety checks that throw on error
|
|
||||||
library SafeMath {
|
|
||||||
/// @dev Multiplies a times b
|
|
||||||
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
|
||||||
uint256 c = a * b;
|
|
||||||
assert(a == 0 || c / a == b);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Divides a by b
|
|
||||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
|
||||||
// assert(b > 0); // Solidity automatically throws when dividing by 0
|
|
||||||
uint256 c = a / b;
|
|
||||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Subtracts a from b
|
|
||||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
|
||||||
assert(b <= a);
|
|
||||||
return a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Adds a to b
|
|
||||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
|
||||||
uint256 c = a + b;
|
|
||||||
assert(c >= a);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
contract Ownable {
|
|
||||||
|
|
||||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
|
||||||
|
|
||||||
address public owner;
|
|
||||||
|
|
||||||
modifier onlyOwner() {
|
|
||||||
require(msg.sender == owner);
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ownable() public {
|
|
||||||
owner = msg.sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function transferOwnership(address newOwner) onlyOwner public {
|
|
||||||
require(newOwner != address(0));
|
|
||||||
OwnershipTransferred(owner, newOwner);
|
|
||||||
owner = newOwner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
contract ERC20Token {
|
|
||||||
uint256 public totalSupply;
|
|
||||||
function balanceOf(address who) public constant returns (uint256);
|
|
||||||
function transfer(address to, uint256 value) public returns (bool);
|
|
||||||
function allowance(address owner, address spender) public constant returns (uint256);
|
|
||||||
function transferFrom(address from, address to, uint256 value) public returns (bool);
|
|
||||||
function approve(address spender, uint256 value) public returns (bool);
|
|
||||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
|
||||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
contract uniswap is Ownable{
|
|
||||||
using SafeMath for uint256;
|
|
||||||
|
|
||||||
event TokenPurchase(address indexed buyer, uint256 tokensPurchased, uint256 ethSpent);
|
|
||||||
event EthPurchase(address indexed buyer, uint256 ethPurchased, uint256 tokensSpent);
|
|
||||||
|
|
||||||
uint256 public totalEthQuantity;
|
|
||||||
uint256 public totalTokenQuantity;
|
|
||||||
uint256 public invariant = 0;
|
|
||||||
address public tokenAddress;
|
|
||||||
ERC20Token token;
|
|
||||||
|
|
||||||
function uniswap(address _tokenAddress) public payable {
|
|
||||||
tokenAddress = _tokenAddress;
|
|
||||||
token = ERC20Token(tokenAddress);
|
|
||||||
totalEthQuantity = msg.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function initiateUniswap(uint256 initialTokenQuantity) public onlyOwner {
|
|
||||||
require(invariant == 0);
|
|
||||||
token.transferFrom(msg.sender, address(this), initialTokenQuantity);
|
|
||||||
totalTokenQuantity = initialTokenQuantity;
|
|
||||||
invariant = initialTokenQuantity.mul(totalEthQuantity);
|
|
||||||
require(invariant > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function ethToTokens(uint256 minimumTokens, uint256 timeout) public payable {
|
|
||||||
require(msg.value != 0 && timeout != 0);
|
|
||||||
uint256 fee = msg.value/500;
|
|
||||||
uint256 ethInPurchase = msg.value.sub(fee);
|
|
||||||
uint256 newTotalEth = totalEthQuantity.add(ethInPurchase);
|
|
||||||
uint256 newTotalTokens = invariant/newTotalEth;
|
|
||||||
uint256 purchasedTokens = totalTokenQuantity.sub(newTotalTokens);
|
|
||||||
require(purchasedTokens >= minimumTokens);
|
|
||||||
require(now < timeout);
|
|
||||||
token.transfer(msg.sender, purchasedTokens);
|
|
||||||
totalEthQuantity = newTotalEth;
|
|
||||||
totalTokenQuantity = newTotalTokens;
|
|
||||||
TokenPurchase(msg.sender, purchasedTokens, ethInPurchase);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function tokenToEth(uint256 sellQuantity, uint256 minimumEth, uint256 timeout) public {
|
|
||||||
require(sellQuantity!=0 && minimumEth != 0 && timeout != 0);
|
|
||||||
token.transferFrom(msg.sender, address(this), sellQuantity);
|
|
||||||
uint256 fee = sellQuantity/500;
|
|
||||||
uint256 tokensInPurchase = sellQuantity - fee;
|
|
||||||
uint256 newTotalTokens = totalTokenQuantity.add(tokensInPurchase);
|
|
||||||
uint256 newTotalEth = invariant/newTotalTokens;
|
|
||||||
uint256 purchasedEth = totalEthQuantity.sub(newTotalEth);
|
|
||||||
require(purchasedEth >= minimumEth);
|
|
||||||
require(now < timeout);
|
|
||||||
msg.sender.transfer(purchasedEth);
|
|
||||||
totalTokenQuantity = newTotalTokens;
|
|
||||||
totalEthQuantity = newTotalEth;
|
|
||||||
EthPurchase(msg.sender, purchasedEth, tokensInPurchase);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function ownerTokenDeposit(uint256 tokenAmount) public onlyOwner {
|
|
||||||
require(tokenAmount !=0);
|
|
||||||
token.transferFrom(msg.sender, address(this), tokenAmount);
|
|
||||||
totalTokenQuantity = totalTokenQuantity.add(tokenAmount);
|
|
||||||
invariant = totalTokenQuantity.mul(totalEthQuantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function ownerEthDeposit() public payable onlyOwner {
|
|
||||||
require(msg.value != 0);
|
|
||||||
totalEthQuantity = totalEthQuantity.add(msg.value);
|
|
||||||
invariant = totalEthQuantity.mul(totalTokenQuantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function ownerTokenWithdraw(uint256 tokenAmount) public onlyOwner {
|
|
||||||
require(tokenAmount !=0);
|
|
||||||
token.transfer(msg.sender, tokenAmount);
|
|
||||||
totalTokenQuantity = totalTokenQuantity.sub(tokenAmount);
|
|
||||||
invariant = totalTokenQuantity.mul(totalEthQuantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function ownerEthWithdraw(uint256 ethAmount) public onlyOwner {
|
|
||||||
require(ethAmount !=0);
|
|
||||||
msg.sender.transfer(ethAmount);
|
|
||||||
totalEthQuantity = totalEthQuantity.sub(ethAmount);
|
|
||||||
invariant = totalEthQuantity.mul(totalTokenQuantity);
|
|
||||||
}
|
|
||||||
}
|
|
286
src/App.css
@ -1,200 +1,152 @@
|
|||||||
@font-face {
|
body{
|
||||||
font-family: 'LeveloLineBold'; /*a name to be used later*/
|
margin: 0;
|
||||||
src: url('./fonts/LoveloLineBold.otf'); /*URL to font*/
|
padding: 0;
|
||||||
|
font-family: "Inter UI", sans-serif;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes blinker {
|
input{
|
||||||
50% { opacity: 0.55; }
|
font-size: 24px;
|
||||||
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.App {
|
p{
|
||||||
text-align: center;
|
margin: 0px;
|
||||||
background-size: 100%;
|
|
||||||
height:100vh;
|
|
||||||
background-image: url('./images/background.jpg');
|
|
||||||
background-repeat: repeat-y;
|
|
||||||
font-family: Optima, sans-serif;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.noICO {
|
/* .app{
|
||||||
position:fixed;
|
margin: 10rem;
|
||||||
font-size: 14px;
|
margin-top: 5rem;
|
||||||
top:3vh;
|
} */
|
||||||
left: 40vw;
|
|
||||||
right: 28vw;
|
.pa2 {
|
||||||
color: rgb(216, 169, 236);
|
padding: 3rem;
|
||||||
text-shadow: 1px 1px 5px #ff69f0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ethLogo {
|
.title{
|
||||||
position: fixed;
|
display: flex;
|
||||||
right: 22vh;
|
flex-direction: row;
|
||||||
position: fixed;
|
}
|
||||||
height: 10vh;
|
.border{
|
||||||
z-index: 1;
|
border: 1px solid #f2f2f2;
|
||||||
margin-top: 1vh;
|
}
|
||||||
margin-right: 5vh;
|
.title {
|
||||||
opacity: 0.6;
|
width: 100%;
|
||||||
-webkit-filter: invert(.8);
|
}
|
||||||
filter: invert(.8);
|
.logo{
|
||||||
-moz-user-select: -moz-none;
|
/* width: 10vw; */
|
||||||
-khtml-user-select: none;
|
display: flex;
|
||||||
-webkit-user-select: none;
|
justify-content: center;
|
||||||
-o-user-select: none;
|
align-items: center;
|
||||||
user-select: none;
|
}
|
||||||
}.ethLogo:hover {
|
.connection{
|
||||||
opacity: 1;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
color: #27AE60;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unicorn {
|
.connection a{
|
||||||
position: fixed;
|
text-decoration: none;
|
||||||
right: 0;
|
color: #27AE60;
|
||||||
clear: both;
|
|
||||||
z-index: 1;
|
|
||||||
height:25vh;
|
|
||||||
opacity: 0.9;
|
|
||||||
-moz-user-select: -moz-none;
|
|
||||||
-khtml-user-select: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-o-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}.unicorn:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.Warning {
|
.order {
|
||||||
position: fixed;
|
width: 100%;
|
||||||
z-index: 3;
|
display: flex;
|
||||||
text-align: center;
|
flex-direction: row;
|
||||||
left: 35vw;
|
/* justify-content: space-between; */
|
||||||
color: rgb(238, 0, 0);
|
|
||||||
text-shadow: 2px 2px 10px #2daae0;
|
|
||||||
animation: blinker 1s linear infinite;
|
|
||||||
}
|
}
|
||||||
|
.arrow{
|
||||||
.Account-info {
|
max-width: 100vw;
|
||||||
position: fixed;
|
display: flex;
|
||||||
z-index: 2;
|
justify-content: center;
|
||||||
text-align: left;
|
align-items: center;
|
||||||
font-size: 14px;
|
flex: 1;
|
||||||
top: 13vh;
|
}
|
||||||
left: 40vw;
|
.value{
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
text-shadow: 1px 1px 5px #2daae0;
|
|
||||||
width: 35vw;
|
width: 35vw;
|
||||||
display: -webkit-box;
|
display: flex;
|
||||||
-webkit-line-clamp: 2;
|
justify-content: space-between;
|
||||||
-webkit-box-orient: vertical;
|
align-items: center;
|
||||||
overflow: auto;
|
}
|
||||||
text-overflow: ellipsis;
|
.value input, select{
|
||||||
-webkit-transition-duration: 0.5s;
|
width: 100%;
|
||||||
transition-duration: 0.5s;
|
height: 100%;
|
||||||
}.Account-info:hover{
|
border: none;
|
||||||
color: rgb(209, 151, 245);
|
}
|
||||||
text-shadow: 1px 1px 5px #ff69f0;
|
.value input:focus{
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pinkText {
|
.dropdown{
|
||||||
position: fixed;
|
transform: rotate(-90deg);
|
||||||
font-size: 16px;
|
opacity: .4;
|
||||||
z-index: 3;
|
position: relative;
|
||||||
color: rgb(216, 169, 236);
|
z-index: -99;
|
||||||
text-shadow: 1px 1px 5px #ff69f0;
|
left: -5px;
|
||||||
text-align: left;
|
|
||||||
-webkit-transition-duration: 0.5s;
|
|
||||||
transition-duration: 0.5s;
|
|
||||||
/*overflow-x: auto;*/
|
|
||||||
}.pinkText:hover{
|
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
text-shadow: 1px 1px 5px #2daae0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.approveButtonContainer{
|
input[type=number]::-webkit-inner-spin-button,
|
||||||
position:fixed;
|
input[type=number]::-webkit-outer-spin-button {
|
||||||
z-index: 3;
|
-webkit-appearance: none;
|
||||||
right: 10vw;
|
margin: 0;
|
||||||
top: 30vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.approveButton {
|
.rate-info{
|
||||||
position: fixed;
|
display: flex;
|
||||||
font-family: Optima, sans-serif;
|
flex-direction: row;
|
||||||
font-size: 18px;
|
justify-content: space-between;
|
||||||
font-weight: bolder;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
color: rgb(220, 160, 245);
|
|
||||||
background-color: rgba(126, 228, 255, 0.25);
|
|
||||||
border: 2px solid rgba(180, 81, 179, 0.55);
|
|
||||||
-webkit-transition-duration: 0.5s;
|
|
||||||
transition-duration: 0.5s;
|
|
||||||
}.approveButton:hover {
|
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
border: 2px solid rgb(122, 251, 255);
|
|
||||||
text-shadow: 1px 1px 5px #2daae0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.exchange {
|
.info{
|
||||||
position: fixed;
|
display: flex;
|
||||||
font-family: Optima, sans-serif;
|
flex-direction: row;
|
||||||
font-size: 18px;
|
justify-content: space-between;
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
text-shadow: 1px 1px 5px #2daae0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.exchange-buyTokens {
|
.links{
|
||||||
margin-left: 35vw;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exchange-buyEth {
|
.link{
|
||||||
margin-left: 60vw;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex: 1;
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exchange-buyEth, .exchange-buyTokens {
|
.link:hover .underline{
|
||||||
position: fixed;
|
text-decoration: underline;
|
||||||
float: left;
|
|
||||||
bottom: 72vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.exchange-buyEthInput, .exchange-buyTokensInput{
|
.swap{
|
||||||
width: 10vw;
|
display: flex;
|
||||||
height: 4.2vh;
|
flex-direction: row;
|
||||||
text-align: center;
|
justify-content: center;
|
||||||
color: rgb(209, 151, 245);
|
align-items: center;
|
||||||
vertical-align: middle;
|
background-color: #f2f2f2;
|
||||||
border: 1px solid rgba(180, 81, 179, 0.55);
|
color: blue;
|
||||||
border-radius: 8px 0 0 8px;
|
height: 48px;
|
||||||
background-color: rgba(122, 251, 255, 0.15);
|
transition: height .3s ease;
|
||||||
font-size: 18px;
|
|
||||||
font-family: Optima, sans-serif;
|
|
||||||
-webkit-transition-duration: 0.8s;
|
|
||||||
transition-duration: 0.8s;
|
|
||||||
}.exchange-buyEthInput:hover, .exchange-buyTokensInput:hover{
|
|
||||||
border: 1px solid rgb(122, 251, 255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.exchange-buyEthButton, .exchange-buyTokensButton{
|
.red{
|
||||||
position: fixed;
|
color: red;
|
||||||
font-size: 1.55vw;
|
}
|
||||||
width: 7vw;
|
|
||||||
text-shadow: 3px 3px 10px #1c5f7c;
|
.dim .order, .rate{
|
||||||
margin-top: 10px;
|
opacity: .4;
|
||||||
height: 4.2vh;
|
}
|
||||||
text-align: center;
|
|
||||||
color: rgb(220, 160, 245);
|
.hidden{
|
||||||
text-shadow: 1px 1px 5px #ff69f0;
|
padding: 0px;
|
||||||
background-color: rgba(126, 228, 255, 0.25);
|
height: 0px;
|
||||||
vertical-align: middle;
|
border: 0px solid #f2f2f2;
|
||||||
margin-top: 0px;
|
|
||||||
border: 1px solid rgb(180, 81, 179);
|
|
||||||
border-radius: 0 8px 8px 0;
|
|
||||||
font-family: Optima, sans-serif;
|
|
||||||
-webkit-transition-duration: 0.8s;
|
|
||||||
transition-duration: 0.8s;
|
|
||||||
}.exchange-buyEthButton:hover, .exchange-buyTokensButton:hover{
|
|
||||||
cursor: pointer;
|
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
text-shadow: 2px 2px 10px #1c5f7c;
|
|
||||||
border: 1px solid rgb(122, 251, 255);
|
|
||||||
}
|
}
|
||||||
|
409
src/App.js
@ -1,62 +1,65 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import Web3 from 'web3';
|
import Web3 from 'web3';
|
||||||
|
|
||||||
|
import Head from './components/Head'
|
||||||
|
import NetworkStatus from './components/NetworkStatus'
|
||||||
|
import HelperMessages from './components/HelperMessages'
|
||||||
|
import SelectToken from './components/SelectToken'
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import Title from './components/misc/Title';
|
|
||||||
import Instructions from './components/menus/Instructions';
|
import {uniswapABI, tokenABI} from './helpers/abi.js'
|
||||||
import unicorn from './images/unicornNoBackground.png';
|
|
||||||
import ethLogo from './images/ethLogo.png';
|
|
||||||
|
|
||||||
var localweb3;
|
var localweb3;
|
||||||
|
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
constructor(props){
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
if (typeof props.metamask !== 'undefined'){
|
||||||
|
localweb3 = new Web3(window.web3.currentProvider)
|
||||||
|
} else {
|
||||||
|
localweb3 = null
|
||||||
|
}
|
||||||
|
|
||||||
localweb3 = new Web3(window.web3.currentProvider);
|
|
||||||
|
|
||||||
var uniswapABI = [{"constant":false,"inputs":[{"name":"tokenAmount","type":"uint256"}],"name":"ownerTokenWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokenAmount","type":"uint256"}],"name":"ownerTokenDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"ethAmount","type":"uint256"}],"name":"ownerEthWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sellQuantity","type":"uint256"},{"name":"minimumEth","type":"uint256"},{"name":"timeout","type":"uint256"}],"name":"tokenToEth","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalTokenQuantity","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"minimumTokens","type":"uint256"},{"name":"timeout","type":"uint256"}],"name":"ethToTokens","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"initialTokenQuantity","type":"uint256"}],"name":"initiateUniswap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalEthQuantity","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"invariant","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"ownerEthDeposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_tokenAddress","type":"address"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"tokensPurchased","type":"uint256"},{"indexed":false,"name":"ethSpent","type":"uint256"}],"name":"TokenPurchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"ethPurchased","type":"uint256"},{"indexed":false,"name":"tokensSpent","type":"uint256"}],"name":"EthPurchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
|
|
||||||
const uniswapAddress = '0x60e5f3cd0381c501971b6fbbddaa49cfd58a4fa1';
|
const uniswapAddress = '0x60e5f3cd0381c501971b6fbbddaa49cfd58a4fa1';
|
||||||
const uniContract = new localweb3.eth.Contract(uniswapABI, uniswapAddress);
|
const uniContract = new localweb3.eth.Contract(uniswapABI, uniswapAddress);
|
||||||
|
|
||||||
var tokenABI = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"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"}]
|
|
||||||
const tokenAddress = '0xca9901076d02f89794262869aad1340bd45d8489';
|
const tokenAddress = '0xca9901076d02f89794262869aad1340bd45d8489';
|
||||||
const tokContract = new localweb3.eth.Contract(tokenABI, tokenAddress);
|
const tokenContract = new localweb3.eth.Contract(tokenABI, tokenAddress);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
this.state = {uniswapAddress: '0x60e5f3cd0381c501971b6fbbddaa49cfd58a4fa1',
|
uniswapAddress: '0x60e5f3cd0381c501971b6fbbddaa49cfd58a4fa1',
|
||||||
tokenAddress: '0xca9901076d02f89794262869aad1340bd45d8489',
|
tokenAddress: '0xca9901076d02f89794262869aad1340bd45d8489',
|
||||||
uniswapContract: uniContract,
|
uniswapContract: uniContract,
|
||||||
tokenContract: tokContract,
|
tokenContract: tokenContract,
|
||||||
ethBalance: 0,
|
ethBalance: 0,
|
||||||
tokenBalance: 0,
|
tokenBalance: 0,
|
||||||
tokenAllowance: null,
|
tokenAllowance: null,
|
||||||
currentMaskAddress: '0x0000000000000000000000000000000000000000',
|
currentMaskAddress: '0x0000000000000000000000000000000000000000',
|
||||||
minimumTokensPurchased: null,
|
minimumTokensPurchased: null,
|
||||||
minimumEthPurchased: null,
|
minimumEthPurchased: null,
|
||||||
invariant: 0,
|
invariant: 0,
|
||||||
marketEth: 0,
|
marketEth: 0,
|
||||||
marketTokens: 0,
|
marketTokens: 0,
|
||||||
tokenBuyRate: 0,
|
tokenBuyRate: 0,
|
||||||
ethBuyRate: 0,
|
ethBuyRate: 0,
|
||||||
tokenCost: 0, //eth price of tokens
|
tokenCost: 0, //eth price of tokens
|
||||||
ethCost: 0, //token price of eth
|
ethCost: 0, //token price of eth
|
||||||
tokenFee: 0,
|
tokenFee: 0,
|
||||||
ethFee: 0,
|
ethFee: 0,
|
||||||
networkMessage: '',
|
networkMessage: '',
|
||||||
locked: false
|
locked: false,
|
||||||
|
connected: false,
|
||||||
|
interaction: 'disconnected',
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
inputToken: { value: 'ETH', label: 'ETH', clearableValue: false },
|
||||||
|
outputToken: { value: 'OMG', label: 'OMG', clearableValue: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.onBuyEthInputChange = this.onBuyEthInputChange.bind(this);
|
this.onBuyEthInputChange = this.onBuyEthInputChange.bind(this);
|
||||||
this.onBuyTokensInputChange = this.onBuyTokensInputChange.bind(this);
|
this.onBuyTokensInputChange = this.onBuyTokensInputChange.bind(this);
|
||||||
this.tokenBuyRate = this.tokenBuyRate.bind(this);
|
this.tokenBuyRate = this.tokenBuyRate.bind(this);
|
||||||
this.ethBuyRate = this.ethBuyRate.bind(this);
|
this.ethBuyRate = this.ethBuyRate.bind(this);
|
||||||
// this.isMetaMaskLocked = this.isMetaMaskLocked.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount(){
|
componentWillMount(){
|
||||||
@ -87,54 +90,18 @@ class App extends Component {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNetwork() {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
localweb3.eth.net.getNetworkType((err, netId) => {
|
|
||||||
switch (netId) {
|
|
||||||
case "main":
|
|
||||||
self.setState({networkMessage: 'MetaMask connected to Ethereum Mainet. Switch to Rinkeby and refresh!'});
|
|
||||||
break
|
|
||||||
case "morden":
|
|
||||||
self.setState({networkMessage: 'MetaMask connected to Morden testnet. Switch to Rinkeby and refresh!'});
|
|
||||||
break
|
|
||||||
case "kovan":
|
|
||||||
self.setState({networkMessage: 'MetaMask connected to Kovan testnet. Switch to Rinkeby and refresh!'});
|
|
||||||
break
|
|
||||||
case "ropsten":
|
|
||||||
self.setState({networkMessage: 'MetaMask connected to Ropstein testnet. Switch to Rinkeby and refresh!'})
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
console.log('Connected to ' + netId);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
approveAllowance(value) {
|
|
||||||
this.state.tokenContract.methods.approve(this.uniswapAddress, value).send(
|
|
||||||
{from: this.state.currentMaskAddress},
|
|
||||||
function(err, txHash) {})
|
|
||||||
}
|
|
||||||
|
|
||||||
getMetaMaskAddress() {
|
getMetaMaskAddress() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
localweb3.eth.getAccounts(function(error, result){
|
||||||
localweb3.eth.getAccounts().then(function(result, error){
|
if(!error)
|
||||||
var address = result[0];
|
self.setState({currentMaskAddress: result[0]})
|
||||||
if (address === undefined) {
|
else
|
||||||
console.log('MetaMask locked');
|
self.setState({locked: true})
|
||||||
alert('Found MetaMask but no account. Please unlock MetaMask and refresh')
|
})
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.setState({currentMaskAddress: address})
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getEthBalance() {
|
getEthBalance() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
localweb3.eth.getBalance(this.state.currentMaskAddress, function(error, balance) {
|
localweb3.eth.getBalance(this.state.currentMaskAddress, function(error, balance) {
|
||||||
var ethValue = (balance/10**18);
|
var ethValue = (balance/10**18);
|
||||||
var roundedValue=Math.round(ethValue*10000)/10000;
|
var roundedValue=Math.round(ethValue*10000)/10000;
|
||||||
@ -144,13 +111,6 @@ class App extends Component {
|
|||||||
|
|
||||||
getTokenBalance() {
|
getTokenBalance() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// tokenContract.methods.balanceOf(this.state.currentMaskAddress).call().then(function(result, error){
|
|
||||||
// var amount = result/10**6
|
|
||||||
// console.log(result);
|
|
||||||
// self.setState({tokenBalance: amount});
|
|
||||||
// })
|
|
||||||
|
|
||||||
this.state.tokenContract.methods.balanceOf(this.state.currentMaskAddress).call(function(error, balance) {
|
this.state.tokenContract.methods.balanceOf(this.state.currentMaskAddress).call(function(error, balance) {
|
||||||
var amount = balance/10**6;
|
var amount = balance/10**6;
|
||||||
self.setState({tokenBalance: amount});
|
self.setState({tokenBalance: amount});
|
||||||
@ -159,37 +119,116 @@ class App extends Component {
|
|||||||
|
|
||||||
getAllowance() {
|
getAllowance() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
// this.state.tokenContract.methods.allowance(this.state.currentMaskAddress, this.uniswapAddress).call().then(function(result, error){
|
||||||
|
// var amount = result/10**6
|
||||||
|
// self.setState({tokenAllowance: amount});
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
this.state.tokenContract.methods.allowance(this.state.currentMaskAddress, this.uniswapAddress).call().then(function(result, error){
|
checkNetwork() {
|
||||||
var amount = result/10**6
|
var self = this;
|
||||||
self.setState({tokenAllowance: amount});
|
|
||||||
|
localweb3.eth.net.getNetworkType((err, networkId) => {
|
||||||
|
console.log(networkId)
|
||||||
|
switch (networkId) {
|
||||||
|
case "main":
|
||||||
|
self.setState({networkMessage: 'Ethereum Mainet', connected: false, interaction: 'disconnected'});
|
||||||
|
break;
|
||||||
|
case "morden":
|
||||||
|
self.setState({networkMessage: 'Morden testnet', connected: false, interaction: 'disconnected'});
|
||||||
|
break;
|
||||||
|
case "ropsten":
|
||||||
|
self.setState({networkMessage: 'Ropsten testnet', connected: false, interaction: 'disconnected'});
|
||||||
|
break;
|
||||||
|
case "rinkeby":
|
||||||
|
self.setState({networkMessage: '', connected: true, interaction: 'connected'});
|
||||||
|
break;
|
||||||
|
case "kovan":
|
||||||
|
self.setState({networkMessage: 'Kovan testnet', connected: false, interaction: 'disconnected'});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
self.setState({networkMessage: 'an Unknown network', connected: false, interaction: 'disconnected'});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getInvarient() {
|
getInvarient() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.state.uniswapContract.methods.invariant().call().then(function(result, error){
|
this.state.uniswapContract.methods.invariant().call().then(function(result, error){
|
||||||
self.setState({invariant: result});
|
self.setState({invariant: result});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getMarketEth() {
|
getMarketEth() {
|
||||||
var self = this
|
var self = this
|
||||||
|
|
||||||
this.state.uniswapContract.methods.totalEthQuantity().call().then(function(result, error){
|
this.state.uniswapContract.methods.totalEthQuantity().call().then(function(result, error){
|
||||||
self.setState({marketEth: result});
|
self.setState({marketEth: result});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getMarketTokens() {
|
getMarketTokens() {
|
||||||
var self = this
|
var self = this
|
||||||
|
|
||||||
this.state.uniswapContract.methods.totalTokenQuantity().call().then(function(result, error){
|
this.state.uniswapContract.methods.totalTokenQuantity().call().then(function(result, error){
|
||||||
self.setState({marketTokens: result});
|
self.setState({marketTokens: result});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tokenBuyRate(buyTokensInput) {
|
||||||
|
if(buyTokensInput >= this.state.marketTokens/10**6) {
|
||||||
|
this.setState(
|
||||||
|
{tokenBuyRate: 0,
|
||||||
|
tokenCost: 0,
|
||||||
|
tokenFee: 0,
|
||||||
|
tokenBuyError: 'Not enough tokens'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
var tokensPurchased = buyTokensInput;
|
||||||
|
var invar = this.state.invariant/10**24;
|
||||||
|
var totalTokens = this.state.marketTokens/10**6;
|
||||||
|
var totalEth = this.state.marketEth/10**18;
|
||||||
|
var newTotalEth = invar/(totalTokens-tokensPurchased);
|
||||||
|
var fee = (newTotalEth - totalEth)/500;
|
||||||
|
var ethRequired = newTotalEth - totalEth + fee;
|
||||||
|
var rate = tokensPurchased/ethRequired;
|
||||||
|
//add 1% to cost displayed, some people will get more tokens than purchased
|
||||||
|
//less TX's will fail the minTokens smart contract check
|
||||||
|
var adjustedTokenCost = ethRequired*1.01;
|
||||||
|
this.setState(
|
||||||
|
{tokenBuyRate: rate,
|
||||||
|
tokenCost: adjustedTokenCost,
|
||||||
|
tokenFee: fee
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ethBuyRate(buyEthInput) {
|
||||||
|
if(buyEthInput >= this.state.marketEth/10**18) {
|
||||||
|
this.setState(
|
||||||
|
{ethBuyRate: 0,
|
||||||
|
ethCost: 0,
|
||||||
|
ethFee: 0,
|
||||||
|
ethBuyError: 'Not enough tokens'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
var ethPurchased = buyEthInput;
|
||||||
|
var invar = this.state.invariant/10**24;
|
||||||
|
var totalEth = this.state.marketEth/10**18;
|
||||||
|
var totalTokens = this.state.marketTokens/10**6;
|
||||||
|
var newTotalTokens = invar/(totalEth-ethPurchased);
|
||||||
|
var fee = (newTotalTokens - totalTokens)/500;
|
||||||
|
var tokensRequired = newTotalTokens - totalTokens + fee;
|
||||||
|
var rate = ethPurchased/(tokensRequired);
|
||||||
|
//add 1% to cost displayed, some people will get more eth than purchased
|
||||||
|
//less TX's will fail the minEth smart contract check
|
||||||
|
var adjustedEthCost = tokensRequired*1.01;
|
||||||
|
this.setState(
|
||||||
|
{ethBuyRate: rate,
|
||||||
|
ethCost: adjustedEthCost,
|
||||||
|
ethFee: fee
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buyTokens() {
|
buyTokens() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var minTokens = this.state.minimumTokensPurchased
|
var minTokens = this.state.minimumTokensPurchased
|
||||||
@ -220,7 +259,19 @@ class App extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onBuyTokensInputChange(event) {
|
onSelectToken = (selected, type) => {
|
||||||
|
console.log(selected)
|
||||||
|
console.log(type)
|
||||||
|
if (type === 'input'){
|
||||||
|
this.setState({inputToken: selected});
|
||||||
|
// do something here to update invariants and values
|
||||||
|
} else if (type === 'output'){
|
||||||
|
this.setState({outputToken: selected});
|
||||||
|
// do something here to update invariants and values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBuyTokensInputChange = (event) => {
|
||||||
var buyTokensInput = event.target.value;
|
var buyTokensInput = event.target.value;
|
||||||
if(buyTokensInput && buyTokensInput !== 0){
|
if(buyTokensInput && buyTokensInput !== 0){
|
||||||
this.setState({ minimumTokensPurchased: buyTokensInput });
|
this.setState({ minimumTokensPurchased: buyTokensInput });
|
||||||
@ -228,117 +279,79 @@ class App extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onBuyEthInputChange(event) {
|
onBuyEthInputChange = (event) => {
|
||||||
var buyEthInput = event.target.value;
|
var buyEthInput = event.target.value;
|
||||||
if(buyEthInput && buyEthInput !== 0){
|
if(buyEthInput && buyEthInput !== 0){
|
||||||
this.setState({ minimumEthPurchased: buyEthInput });
|
this.setState({ minimumEthPurchased: buyEthInput, input: buyEthInput, output: this.state.tokenBuyRate.toFixed(3)*buyEthInput, interaction: 'input'});
|
||||||
this.ethBuyRate(buyEthInput);
|
this.ethBuyRate(buyEthInput);
|
||||||
|
} else {
|
||||||
|
this.setState({input: buyEthInput, output: this.state.tokenBuyRate.toFixed(3)*buyEthInput, interaction: 'connected'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenBuyRate(buyTokensInput) {
|
|
||||||
if(buyTokensInput >= this.state.marketTokens/10**6) {
|
|
||||||
this.setState({tokenBuyRate: 0,
|
|
||||||
tokenCost: 0,
|
|
||||||
tokenFee: 0,
|
|
||||||
tokenBuyError: 'Not enough tokens'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
var tokensPurchased = buyTokensInput;
|
|
||||||
var invar = this.state.invariant/10**24;
|
|
||||||
var totalTokens = this.state.marketTokens/10**6;
|
|
||||||
var totalEth = this.state.marketEth/10**18;
|
|
||||||
var newTotalEth = invar/(totalTokens-tokensPurchased);
|
|
||||||
var fee = (newTotalEth - totalEth)/500;
|
|
||||||
var ethRequired = newTotalEth - totalEth + fee;
|
|
||||||
var rate = tokensPurchased/ethRequired;
|
|
||||||
//add 1% to cost displayed, some people will get more tokens than purchased
|
|
||||||
//less TX's will fail the minTokens smart contract check
|
|
||||||
var adjustedTokenCost = ethRequired*1.01;
|
|
||||||
this.setState({tokenBuyRate: rate,
|
|
||||||
tokenCost: adjustedTokenCost,
|
|
||||||
tokenFee: fee
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ethBuyRate(buyEthInput) {
|
|
||||||
if(buyEthInput >= this.state.marketEth/10**18) {
|
|
||||||
this.setState({ethBuyRate: 0,
|
|
||||||
ethCost: 0,
|
|
||||||
ethFee: 0,
|
|
||||||
ethBuyError: 'Not enough tokens'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
var ethPurchased = buyEthInput;
|
|
||||||
var invar = this.state.invariant/10**24;
|
|
||||||
var totalEth = this.state.marketEth/10**18;
|
|
||||||
var totalTokens = this.state.marketTokens/10**6;
|
|
||||||
var newTotalTokens = invar/(totalEth-ethPurchased);
|
|
||||||
var fee = (newTotalTokens - totalTokens)/500;
|
|
||||||
var tokensRequired = newTotalTokens - totalTokens + fee;
|
|
||||||
var rate = ethPurchased/(tokensRequired);
|
|
||||||
//add 1% to cost displayed, some people will get more eth than purchased
|
|
||||||
//less TX's will fail the minEth smart contract check
|
|
||||||
var adjustedEthCost = tokensRequired*1.01;
|
|
||||||
this.setState({ethBuyRate: rate,
|
|
||||||
ethCost: adjustedEthCost,
|
|
||||||
ethFee: fee
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
console.log(localweb3)
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className={this.state.connected ? "App" : "App dim"}>
|
||||||
<Title />
|
<Head />
|
||||||
<div className="noICO">UNI is an ERC20 test token. This is not an ICO.</div>
|
<section className="title">
|
||||||
<img src={unicorn} className="unicorn" alt="unicorn"/>
|
<div className="logo border pa2">
|
||||||
<img src={ethLogo} className="ethLogo" alt = "ethLogo"/>
|
<span role="img" aria-label="Unicorn">🦄</span>
|
||||||
<div className="Warning">{this.state.networkMessage}</div>
|
|
||||||
<div className="Account-info">
|
|
||||||
Account Detected: {this.state.ethBalance} ETH
|
|
||||||
{this.state.tokenBalance.toFixed(2)} UNI<br/>
|
|
||||||
{this.state.currentMaskAddress}
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
</div>
|
|
||||||
<Instructions />
|
|
||||||
<div className="approveButtonContainer">
|
|
||||||
<button className="approveButton" onClick={() => {this.approveAllowance(20000*10**6) }}>Approve</button><br/><br/>
|
|
||||||
{/*Tokens approved: {this.state.tokenAllowance} */}
|
|
||||||
</div>
|
|
||||||
<div className="exchange">
|
|
||||||
<div className="exchange-buyTokens">
|
|
||||||
<input
|
|
||||||
className="exchange-buyTokensInput"
|
|
||||||
//value={this.state.value}
|
|
||||||
onChange={this.onBuyTokensInputChange}
|
|
||||||
/>
|
|
||||||
<input className="exchange-buyTokensButton" type="exchange-button" defaultValue="Buy UNI" readOnly="readOnly" onClick={() => {this.buyTokens() }}/>
|
|
||||||
<p className="pinkText">
|
|
||||||
Rate : {this.state.tokenBuyRate.toFixed(3)} UNI/ETH<br/>
|
|
||||||
Cost : {this.state.tokenCost.toFixed(5)} ETH<br/>
|
|
||||||
Fee : {this.state.tokenFee.toFixed(5)} ETH<br/>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="exchange-buyEth">
|
<NetworkStatus network={this.state.networkMessage} connected={this.state.connected} address={this.state.currentMaskAddress}/>
|
||||||
<input
|
</section>
|
||||||
className="exchange-buyEthInput"
|
<HelperMessages interaction={this.state.interaction} inputToken={this.state.inputToken} outputToken={this.state.outputToken}/>
|
||||||
//value={this.state.value}
|
<section className="order">
|
||||||
onChange={this.onBuyEthInputChange}
|
<div className="value border pa2">
|
||||||
/>
|
<input type="number" value={this.state.input} placeholder="0" onChange={this.onBuyEthInputChange} onChange={this.onBuyEthInputChange} />
|
||||||
<input className="exchange-buyEthButton" type="exchange-button" defaultValue="Buy ETH" readOnly="readOnly" onClick={() => {this.buyEth() }}/>
|
<SelectToken token={this.state.inputToken} onSelectToken={this.onSelectToken} type="input" />
|
||||||
<p className="pinkText">
|
<p className="dropdown">{'<'}</p>
|
||||||
Rate : {this.state.ethBuyRate.toFixed(4)} ETH/UNI<br/>
|
|
||||||
Cost : {this.state.ethCost.toFixed(5)} UNI<br/>
|
|
||||||
Fee : {this.state.ethFee.toFixed(5)} UNI
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="arrow border pa2">
|
||||||
|
<p>→</p>
|
||||||
|
</div>
|
||||||
|
<div className="value border pa2">
|
||||||
|
<input type="number" value={this.state.output} placeholder="0" onChange={this.onBuyTokensInputChange}/>
|
||||||
|
<SelectToken token={this.state.outputToken} onSelectToken={this.onSelectToken} type="output"/>
|
||||||
|
<p className="dropdown">{'<'}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section className="rate border pa2">
|
||||||
|
<span className="rate-info">
|
||||||
|
<p>Rate</p>
|
||||||
|
<p>{this.state.tokenBuyRate.toFixed(3)} UNI/ETH</p>
|
||||||
|
</span>
|
||||||
|
<span className="rate-info">
|
||||||
|
<p>Cost</p>
|
||||||
|
<p>{this.state.tokenCost.toFixed(5)} ETH</p>
|
||||||
|
</span>
|
||||||
|
<span className="rate-info">
|
||||||
|
<p>Fee</p>
|
||||||
|
<p>{this.state.tokenFee.toFixed(5)} ETH</p>
|
||||||
|
</span>
|
||||||
|
</section>
|
||||||
|
{this.state.interaction === 'input' ?
|
||||||
|
<section className="swap border pa2">
|
||||||
|
<a href="">{"I want to swap " + this.state.input + " " + this.state.inputToken.value + " for " + this.state.output + " " + this.state.outputToken.value}</a>
|
||||||
|
</section>
|
||||||
|
: <section className="swap hidden border pa2"></section>}
|
||||||
|
<section className="links">
|
||||||
|
<a href="" className="link border pa2">
|
||||||
|
<p className="underline">Provide Liquidity to collect fees</p>
|
||||||
|
<p>+</p>
|
||||||
|
</a>
|
||||||
|
<a href="" className="link border pa2">
|
||||||
|
<p className="underline">Add a new token</p>
|
||||||
|
<p>+</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<section className="links">
|
||||||
|
<a href="" className="link border pa2">
|
||||||
|
<p className="underline">About</p>
|
||||||
|
<p>↘</p>
|
||||||
|
</a>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
9
src/App.test.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
ReactDOM.render(<App />, div);
|
||||||
|
ReactDOM.unmountComponentAtNode(div);
|
||||||
|
});
|
16
src/components/Head.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {Helmet} from "react-helmet";
|
||||||
|
|
||||||
|
import unicorn from '../images/🦄.png'
|
||||||
|
|
||||||
|
function Head(props) {
|
||||||
|
return (
|
||||||
|
<Helmet>
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<link rel="icon" href={unicorn} sizes="32x32" type="image/png" />
|
||||||
|
<title>Uniswap - ERC20 Market Maker</title>
|
||||||
|
</Helmet>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Head;
|
24
src/components/HelperMessages.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
function HelperMessages(props) {
|
||||||
|
let message = ''
|
||||||
|
switch (props.interaction) {
|
||||||
|
case 'connected':
|
||||||
|
message = "Nice! You're connected. Enter a value below to get started."
|
||||||
|
break;
|
||||||
|
case 'input':
|
||||||
|
message = "You're swapping " + props.inputToken.value + " for " + props.outputToken.value + ". Want to know more about how the prices are determined?"
|
||||||
|
// message = "Oops, looks like this address doesn't have a enough " + props.inputToken.value + " to make this trade. Add more funds to make this swap."
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message = "Hi there! This site helps you swap ERC20 tokens. Looks like you aren't connected. Need help?"
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<section className="info border pa2">
|
||||||
|
<p>{message}</p>
|
||||||
|
<p>↓</p>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HelperMessages;
|
22
src/components/NetworkStatus.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
function NetworkStatus(props) {
|
||||||
|
let isConnected = props.connected
|
||||||
|
if (isConnected){
|
||||||
|
return (
|
||||||
|
<div className="connection border pa2">
|
||||||
|
<a href={'https://etherscan.io/search?q=' + props.address}>{props.address}</a>
|
||||||
|
<p>●</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div className="connection red border pa2">
|
||||||
|
<p>{'MetaMask connected to ' + props.network + ' Switch to Rinkeby and refresh!'}</p>
|
||||||
|
<p>●</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NetworkStatus;
|
235
src/components/SelectToken.css
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/**
|
||||||
|
* React Select
|
||||||
|
* ============
|
||||||
|
* Created by Jed Watson and Joss Mackison for KeystoneJS, http://www.keystonejs.com/
|
||||||
|
* https://twitter.com/jedwatson https://twitter.com/jossmackison https://twitter.com/keystonejs
|
||||||
|
* MIT License: https://github.com/JedWatson/react-select
|
||||||
|
*/
|
||||||
|
.Select-input {
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: calc(100% - 20px);
|
||||||
|
}
|
||||||
|
.Select {
|
||||||
|
position: relative;
|
||||||
|
/* width: 100%; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select-control{
|
||||||
|
width: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select-clear-zone{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select-value{
|
||||||
|
position: absolute;
|
||||||
|
width: 5rem;
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select-input{
|
||||||
|
width: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select-menu-outer {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-top-color: #e6e6e6;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-top: -1px;
|
||||||
|
max-height: 200px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 100%;
|
||||||
|
width: 100%;
|
||||||
|
width: 200px;
|
||||||
|
z-index: 1;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
.Select-menu {
|
||||||
|
max-height: 198px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select-option {
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #666666;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select .Select-aria-only {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
height: 1px;
|
||||||
|
width: 1px;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
overflow: hidden;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select-option {
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #666666;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
.Select-option.is-selected {
|
||||||
|
background-color: #f5faff;
|
||||||
|
background-color: rgba(0, 126, 255, 0.04);
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.Select-option.is-focused {
|
||||||
|
background-color: #ebf5ff;
|
||||||
|
background-color: rgba(0, 126, 255, 0.08);
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.Select-option.is-disabled {
|
||||||
|
color: #cccccc;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.Select-noresults {
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #999999;
|
||||||
|
cursor: default;
|
||||||
|
display: block;
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
.Select--multi .Select-input {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.Select--multi.Select--rtl .Select-input {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.Select--multi.has-value .Select-input {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
.Select--multi .Select-value {
|
||||||
|
background-color: #ebf5ff;
|
||||||
|
background-color: rgba(0, 126, 255, 0.08);
|
||||||
|
/* border: 1px solid #c2e0ff;
|
||||||
|
border: 1px solid rgba(0, 126, 255, 0.24); */
|
||||||
|
color: #007eff;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 0.9em;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.Select--multi .Select-value-icon,
|
||||||
|
.Select--multi .Select-value-label {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.Select--multi .Select-value-label {
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
|
border-top-right-radius: 2px;
|
||||||
|
cursor: default;
|
||||||
|
padding: 2px 5px;
|
||||||
|
}
|
||||||
|
.Select--multi a.Select-value-label {
|
||||||
|
color: #007eff;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.Select--multi a.Select-value-label:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.Select--multi .Select-value-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom-left-radius: 2px;
|
||||||
|
border-top-left-radius: 2px;
|
||||||
|
border-right: 1px solid #c2e0ff;
|
||||||
|
border-right: 1px solid rgba(0, 126, 255, 0.24);
|
||||||
|
padding: 1px 5px 3px;
|
||||||
|
}
|
||||||
|
.Select--multi .Select-value-icon:hover,
|
||||||
|
.Select--multi .Select-value-icon:focus {
|
||||||
|
background-color: #d8eafd;
|
||||||
|
background-color: rgba(0, 113, 230, 0.08);
|
||||||
|
color: #0071e6;
|
||||||
|
}
|
||||||
|
.Select--multi .Select-value-icon:active {
|
||||||
|
background-color: #c2e0ff;
|
||||||
|
background-color: rgba(0, 126, 255, 0.24);
|
||||||
|
}
|
||||||
|
.Select--multi.Select--rtl .Select-value {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.Select--multi.Select--rtl .Select-value-icon {
|
||||||
|
border-right: none;
|
||||||
|
border-left: 1px solid #c2e0ff;
|
||||||
|
border-left: 1px solid rgba(0, 126, 255, 0.24);
|
||||||
|
}
|
||||||
|
.Select--multi.is-disabled .Select-value {
|
||||||
|
background-color: #fcfcfc;
|
||||||
|
border: 1px solid #e3e3e3;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.Select--multi.is-disabled .Select-value-icon {
|
||||||
|
cursor: not-allowed;
|
||||||
|
border-right: 1px solid #e3e3e3;
|
||||||
|
}
|
||||||
|
.Select--multi.is-disabled .Select-value-icon:hover,
|
||||||
|
.Select--multi.is-disabled .Select-value-icon:focus,
|
||||||
|
.Select--multi.is-disabled .Select-value-icon:active {
|
||||||
|
background-color: #fcfcfc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select input::-webkit-contacts-auto-fill-button,
|
||||||
|
.Select input::-webkit-credentials-auto-fill-button {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.Select input::-ms-clear {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.Select input::-ms-reveal {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.Select,
|
||||||
|
.Select div,
|
||||||
|
.Select input,
|
||||||
|
.Select span {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.Select input:focus{
|
||||||
|
/* outline: none; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select.is-searchable.is-open > .Select-control {
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
.Select.is-searchable.is-focused:not(.is-open) > .Select-control {
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select.Select--rtl {
|
||||||
|
direction: rtl;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.Select.is-open .Select-input {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select.is-open .Select-input,
|
||||||
|
.Select.is-open .Select-input input {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select.is-open .Select-input input {
|
||||||
|
text-indent: 1px;
|
||||||
|
}
|
38
src/components/SelectToken.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
import Select from 'react-select'
|
||||||
|
import './SelectToken.css'
|
||||||
|
|
||||||
|
class SelectToken extends Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
selectedOption: this.props.token,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleChange = (selectedOption) => {
|
||||||
|
this.setState({ selectedOption })
|
||||||
|
this.props.onSelectToken(selectedOption, this.props.type)
|
||||||
|
console.log(`Selected: ${selectedOption.label}`)
|
||||||
|
}
|
||||||
|
render () {
|
||||||
|
const { selectedOption } = this.state
|
||||||
|
const value = selectedOption && selectedOption.value
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
name="form-field-name"
|
||||||
|
value={value}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
className="select"
|
||||||
|
options={[
|
||||||
|
{ value: 'OMG', label: 'OMG', clearableValue: false },
|
||||||
|
{ value: 'ETH', label: 'ETH', clearableValue: false },
|
||||||
|
{ value: 'BNT', label: 'BNT', clearableValue: false },
|
||||||
|
{ value: 'FOM', label: 'FOAM', clearableValue: false },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectToken;
|
@ -1,57 +0,0 @@
|
|||||||
.instructions {
|
|
||||||
position: fixed;
|
|
||||||
background-color: rgba(0,0,0,0.4);
|
|
||||||
bottom: 1vh;
|
|
||||||
border-radius: 15px;
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: rgb(122, 251, 255);
|
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
text-shadow: 2px 2px 10px #2daae0;
|
|
||||||
margin-left: 35vw;
|
|
||||||
margin-right: 1vw;
|
|
||||||
max-height: 55vh;
|
|
||||||
-webkit-transition-duration: 0.5s;
|
|
||||||
transition-duration: 0.5s;
|
|
||||||
overflow-y: scroll;
|
|
||||||
} .instructions:hover{
|
|
||||||
color: rgb(216, 169, 236);
|
|
||||||
text-shadow: 1px 1px 5px #ff69f0;
|
|
||||||
border-color: rgb(180, 81, 179);
|
|
||||||
background-color: rgba(0,0,0,0.55);
|
|
||||||
}
|
|
||||||
|
|
||||||
.instructions-title {
|
|
||||||
text-align: left;
|
|
||||||
padding-left: 40px;
|
|
||||||
padding-top: 10px;
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.instructions-text {
|
|
||||||
font-size: 15px;
|
|
||||||
padding-top: 10px;
|
|
||||||
text-align: left;
|
|
||||||
padding-left: 25px;
|
|
||||||
padding-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.instructions a:link, .instructions a:visited, .instructions-highlight {
|
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
text-shadow: 2px 2px 10px #2daae0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.instructions a:hover, .instructions-highlight:hover {
|
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.instructions-approve {
|
|
||||||
font-size: 12px;
|
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: rgb(122, 251, 255);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 1px 2px;
|
|
||||||
text-shadow: none;
|
|
||||||
}.instructions-approve:hover {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import './Instructions.css';
|
|
||||||
|
|
||||||
class Instructions extends Component{
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="instructions">
|
|
||||||
<div className="instructions-title">Instructions and Info</div>
|
|
||||||
<div className="instructions-text">
|
|
||||||
1) Add UNI test token address to MetaMask (first time only)<br/>
|
|
||||||
Token Address: <span className="instructions-highlight">0xca9901076d02f89794262869aad1340bd45d8489</span><br/><br/>
|
|
||||||
2) Check that MetaMask is connected to the Rinkeby Testnet<br/><br/>
|
|
||||||
3) You can now buy UNI test tokens with ETH! Visit the
|
|
||||||
<a href= "https://faucet.rinkeby.io/">Rinkeby faucet</a> to aquire testnet ETH <br/><br/>
|
|
||||||
4) To buy ETH with UNI you must approve the Uniswap smart contract to transfer UNI tokens on your behalf. Click the
|
|
||||||
<span className="instructions-approve"><b>Approve</b></span> button now! (first time only)<br/><br/>
|
|
||||||
5) Rate is variable based on token availiblity, enter number of tokens to see rate and cost.<br/><br/>
|
|
||||||
6) This is a proof-of-concept for a decentralized Market Maker exchange. Stay tuned for ENS support, token-to-token pairs, the ability to become a liquidity provider and collect fees,
|
|
||||||
and a Mainet launch! :) <br/> <br/>
|
|
||||||
7) This demo was hastily programmed by a single developer <i>(Hi, my name is Hayden!)</i>. Please reach out to me with any questions, comments, complaints, or bug reports.<br/><br/>
|
|
||||||
Email: <span className="instructions-highlight">hayden@uniswap.io</span>
|
|
||||||
GitHub: <a href= "https://github.com/haydenadams/uniswap">https://github.com/haydenadams/uniswap<br/></a>
|
|
||||||
ETH Address: <span className="instructions-highlight">0x4779721CaC18A46DbCF148f2Dd7A8E6cc1F90078</span><br/><br/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Instructions;
|
|
@ -1,11 +0,0 @@
|
|||||||
.install-metamask {
|
|
||||||
width: 100vw;
|
|
||||||
top: 70vh;
|
|
||||||
position: fixed;
|
|
||||||
font-family: Optima, sans-serif;
|
|
||||||
font-size: 26px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.install-metamask a {
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import './Splashscreen.css';
|
|
||||||
|
|
||||||
var ModelViewer = require('metamask-logo')
|
|
||||||
|
|
||||||
// To render with fixed dimensions:
|
|
||||||
var viewer = ModelViewer({
|
|
||||||
|
|
||||||
// Dictates whether width & height are px or multiplied
|
|
||||||
// pxNotRatio: true,
|
|
||||||
// width: 500,
|
|
||||||
// height: 400,
|
|
||||||
pxNotRatio: false,
|
|
||||||
width: 1,
|
|
||||||
height: 0.7,
|
|
||||||
|
|
||||||
// To make the face follow the mouse.
|
|
||||||
followMouse: true,
|
|
||||||
|
|
||||||
// head should slowly drift (overrides lookAt)
|
|
||||||
// slowDrift: true,
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
var metamaskLink = 'https://metamask.io';
|
|
||||||
|
|
||||||
class Splashscreen extends Component{
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="install-metamask">
|
|
||||||
Uniswap requires MetaMask to connect to the Ethereum blockchain.<br/><br/>
|
|
||||||
<a href="https://metamask.io"> {metamaskLink} </a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Splashscreen;
|
|
@ -1,74 +0,0 @@
|
|||||||
@font-face {
|
|
||||||
font-family: 'LeveloLineBold'; /*a name to be used later*/
|
|
||||||
src: url('../../fonts/LoveloLineBold.otf'); /*URL to font*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-family: 'LeveloLineBold';
|
|
||||||
/*font-family: Optima, sans-serif;*/
|
|
||||||
position: fixed;
|
|
||||||
font-size: 10vh;
|
|
||||||
margin-top: 2vh;
|
|
||||||
margin-left: 2vh;
|
|
||||||
float: left;
|
|
||||||
text-shadow: 3px 3px 10px #f29ae1;
|
|
||||||
color: rgb(220, 173, 247);
|
|
||||||
font-weight: bold;
|
|
||||||
-webkit-text-stroke-width: 1px;
|
|
||||||
-webkit-text-stroke-color: rgb(180, 81, 179);
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* entire container, keeps perspective */
|
|
||||||
.titled-container {
|
|
||||||
position: fixed;
|
|
||||||
perspective: 800px;
|
|
||||||
/*border: 2px solid rgb(207, 9, 158);*/
|
|
||||||
}
|
|
||||||
/* flip the pane when hovered */
|
|
||||||
.titled-container:hover > .title{
|
|
||||||
transform: rotateX(180deg);
|
|
||||||
color: rgb(122, 251, 255);
|
|
||||||
text-shadow: 3px 3px 10px #2daae0;
|
|
||||||
font-weight: bold;
|
|
||||||
-webkit-text-stroke-width: 2px;
|
|
||||||
-webkit-text-stroke-color: rgb(22, 177, 210);
|
|
||||||
}
|
|
||||||
|
|
||||||
.titled-container, .front, .back {
|
|
||||||
width: 26vw;
|
|
||||||
height: 11vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.front, .back {
|
|
||||||
width: 0.1vh;
|
|
||||||
height: 0.001vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* flip speed goes here */
|
|
||||||
.title {
|
|
||||||
transition: 2.5s;
|
|
||||||
transform-style: preserve-3d;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* hide back of pane during swap */
|
|
||||||
.front, .back {
|
|
||||||
backface-visibility: hidden;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* front pane, placed above back */
|
|
||||||
.front {
|
|
||||||
z-index: 2;
|
|
||||||
/* for firefox 31 */
|
|
||||||
transform: rotateX(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* back, initially hidden pane */
|
|
||||||
.back {
|
|
||||||
transform: rotateX(180deg);
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import './Title.css';
|
|
||||||
|
|
||||||
class Title extends Component{
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="titled-container">
|
|
||||||
<div className="title">
|
|
||||||
<div className="front">UNISWAP</div>
|
|
||||||
<div className="back">UNISWAP</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Title;
|
|
4
src/helpers/abi.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module.exports.uniswapABI = [{"constant":false,"inputs":[{"name":"tokenAmount","type":"uint256"}],"name":"ownerTokenWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokenAmount","type":"uint256"}],"name":"ownerTokenDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"ethAmount","type":"uint256"}],"name":"ownerEthWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sellQuantity","type":"uint256"},{"name":"minimumEth","type":"uint256"},{"name":"timeout","type":"uint256"}],"name":"tokenToEth","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalTokenQuantity","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"minimumTokens","type":"uint256"},{"name":"timeout","type":"uint256"}],"name":"ethToTokens","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"initialTokenQuantity","type":"uint256"}],"name":"initiateUniswap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalEthQuantity","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"invariant","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"ownerEthDeposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_tokenAddress","type":"address"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"tokensPurchased","type":"uint256"},{"indexed":false,"name":"ethSpent","type":"uint256"}],"name":"TokenPurchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"ethPurchased","type":"uint256"},{"indexed":false,"name":"tokensSpent","type":"uint256"}],"name":"EthPurchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
|
||||||
|
|
||||||
|
|
||||||
|
module.exports.tokenABI = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"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"}]
|
Before Width: | Height: | Size: 941 KiB |
Before Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 57 KiB |
BIN
src/images/🦄.png
Normal file
After Width: | Height: | Size: 14 KiB |
@ -2,5 +2,4 @@ body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
15
src/index.js
@ -2,20 +2,7 @@ import React from 'react';
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import Splashscreen from './components/misc/Splashscreen'
|
|
||||||
import registerServiceWorker from './registerServiceWorker';
|
import registerServiceWorker from './registerServiceWorker';
|
||||||
|
|
||||||
function Detect(props) {
|
ReactDOM.render(<App metamask={window.web3} />, document.getElementById('root'));
|
||||||
const metamask = props.metamask;
|
|
||||||
if(typeof metamask === 'undefined') {
|
|
||||||
return <Splashscreen />
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return <App />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactDOM.render(
|
|
||||||
<Detect metamask={window.web3} />, document.getElementById('root')
|
|
||||||
);
|
|
||||||
registerServiceWorker();
|
registerServiceWorker();
|
||||||
|
@ -32,12 +32,21 @@ export default function register() {
|
|||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||||
|
|
||||||
if (!isLocalhost) {
|
if (isLocalhost) {
|
||||||
// Is not local host. Just register service worker
|
|
||||||
registerValidSW(swUrl);
|
|
||||||
} else {
|
|
||||||
// This is running on localhost. Lets check if a service worker still exists or not.
|
// This is running on localhost. Lets check if a service worker still exists or not.
|
||||||
checkValidServiceWorker(swUrl);
|
checkValidServiceWorker(swUrl);
|
||||||
|
|
||||||
|
// Add some additional logging to localhost, pointing developers to the
|
||||||
|
// service worker/PWA documentation.
|
||||||
|
navigator.serviceWorker.ready.then(() => {
|
||||||
|
console.log(
|
||||||
|
'This web app is being served cache-first by a service ' +
|
||||||
|
'worker. To learn more, visit https://goo.gl/SC7cgQ'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Is not local host. Just register service worker
|
||||||
|
registerValidSW(swUrl);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|