diff --git a/api/blockchain_utils.py b/api/blockchain_utils.py
index 2d6f3ab88..49fa757ba 100644
--- a/api/blockchain_utils.py
+++ b/api/blockchain_utils.py
@@ -5,6 +5,21 @@
from config import BTAPIKEY
from rpcclient import gettxout
from cacher import *
+import config
+
+BLOCKCHAININFO_API_URL = "https://blockchain.info/"
+BLOCKR_API_URL = "http://btc.blockr.io/api/v1"
+BLOCKTRAIL_API_URL = "https://api.blocktrail.com/v1/btc/"
+BLOCKCYPHER_API_URL = "https://api.blockcypher.com/v1/btc/main/"
+BITGO_API_URL = "https://www.bitgo.com/api/v1/"
+BLOCKONOMICS_API_URL = "https://www.blockonomics.co/api"
+
+# note: "blockchain.info" does not support testnet
+# note: "blockonomics" does not appear to support testnet
+TESTNET_BLOCKR_API_URL = "http://tbtc.blockr.io/api/v1"
+TESTNET_BLOCKTRAIL_API_URL = "https://api.blocktrail.com/v1/tbtc/"
+TESTNET_BLOCKCYPHER_API_URL = "https://api.blockcypher.com/v1/btc/test3/"
+TESTNET_BITGO_API_URL = "https://test.bitgo.com/api/v1/"
try:
expTime=config.BTCBAL_CACHE
@@ -15,7 +30,8 @@ def bc_getutxo(address, ramount, page=1, retval=None, avail=0):
if retval==None:
retval=[]
try:
- r = requests.get('https://api.blocktrail.com/v1/btc/address/'+address+'/unspent-outputs?api_key='+str(BTAPIKEY)+'&limit=200&page='+str(page))
+ apiUrl = BLOCKTRAIL_API_URL if not config.TESTNET else TESTNET_BLOCKTRAIL_API_URL
+ r = requests.get(apiUrlr + '/address/'+address+'/unspent-outputs?api_key='+str(BTAPIKEY)+'&limit=200&page='+str(page))
if r.status_code == 200:
response = r.json()
unspents = response['data']
@@ -40,7 +56,8 @@ def bc_getutxo(address, ramount, page=1, retval=None, avail=0):
def bc_getutxo_blockcypher(address, ramount):
try:
- r = requests.get('https://api.blockcypher.com/v1/btc/main/addrs/'+address+'?unspentOnly=true')
+ apiUrl = BLOCKCYPHER_API_URL if not config.TESTNET else TESTNET_BLOCKCYPHER_API_URL
+ r = requests.get(apiUrl + '/addrs/'+address+'?unspentOnly=true')
if r.status_code == 200:
unspents = r.json()['txrefs']
@@ -65,7 +82,8 @@ def bc_getutxo_blockcypher(address, ramount):
def bc_getutxo_blockr(address, ramount):
try:
- r = requests.get('http://btc.blockr.io/api/v1/address/unspent/'+address+'?unconfirmed=1')
+ apiUrl = BLOCKR_API_URL if not config.TESTNET else TESTNET_BLOCKR_API_URL
+ r = requests.get(apiUrl + '/address/unspent/'+address+'?unconfirmed=1')
if r.status_code == 200:
#Process and format response from blockr.io
@@ -92,8 +110,12 @@ def bc_getutxo_blockr(address, ramount):
def bc_getpubkey(address):
+ # note: only supports mainnet
try:
- r = requests.get('https://blockchain.info/q/pubkeyaddr/'+address)
+ if config.TESTNET:
+ return "error: tried using blockchain.info api with testnet enabled"
+
+ r = requests.get(BLOCKCHAININFO_API_URL + '/q/pubkeyaddr/'+address)
if r.status_code == 200:
return str(r.text)
@@ -117,7 +139,8 @@ def bc_getbalance(address):
def bc_getbalance_bitgo(address):
try:
- r= requests.get('https://www.bitgo.com/api/v1/address/'+address)
+ apiUrl = BITGO_API_URL if not config.TESTNET else TESTNET_BITGO_API_URL
+ r= requests.get(apiUrl + '/address/'+address)
if r.status_code == 200:
balance = int(r.json()['balance'])
return {"bal":balance , "error": None}
@@ -128,7 +151,8 @@ def bc_getbalance_bitgo(address):
def bc_getbalance_blockcypher(address):
try:
- r= requests.get('https://api.blockcypher.com/v1/btc/main/addrs/'+address+'/balance')
+ apiUrl = BLOCKCYPHER_API_URL if not config.TESTNET else TESTNET_BLOCKCYPHER_API_URL
+ r= requests.get(apiUrl + '/addrs/'+address+'/balance')
if r.status_code == 200:
balance = int(r.json()['balance'])
return {"bal":balance , "error": None}
@@ -139,7 +163,8 @@ def bc_getbalance_blockcypher(address):
def bc_getbalance_blockr(address):
try:
- r= requests.get('http://btc.blockr.io/api/v1/address/balance/'+address)
+ apiUrl = BLOCKR_API_URL if not config.TESTNET else TESTNET_BLOCKR_API_URL
+ r= requests.get(apiUrl + '/address/balance/'+address)
if r.status_code == 200:
balance = int(r.json()['data']['balance']*1e8)
return {"bal":balance , "error": None}
@@ -222,7 +247,10 @@ def bc_getbulkbalance_blockonomics(addresses):
formatted=formatted+" "+address
try:
- r = requests.post('https://www.blockonomics.co/api/balance',json.dumps({"addr":formatted}))
+ if config.TESTNET:
+ return "error: tried using blockonomics api with testnet enabled"
+
+ r = requests.post(apiUrl + '/balance',json.dumps({"addr":formatted}))
if r.status_code == 200:
balances = r.json()['response']
retval = {}
@@ -243,7 +271,8 @@ def bc_getbulkbalance_blockr(addresses):
formatted=formatted+","+address
try:
- r= requests.get('http://btc.blockr.io/api/v1/address/balance/'+formatted)
+ apiUrl = BLOCKR_API_URL if not config.TESTNET else TESTNET_BLOCKR_API_URL
+ r= requests.get(apiUrl + '/address/balance/'+formatted)
if r.status_code == 200:
balances = r.json()['data']
retval = {}
@@ -263,7 +292,10 @@ def bc_getbulkbalance_blockchain(addresses):
else:
formatted=formatted+"|"+address
try:
- r= requests.get('https://blockchain.info/balance?active='+formatted)
+ if config.TESTNET:
+ return "error: tried using blockchain.info api with testnet enabled"
+
+ r= requests.get(BLOCKCHAININFO_API_URL + '/balance?active='+formatted)
if r.status_code == 200:
balances = r.json()
retval = {}
diff --git a/api/config.py b/api/config.py
new file mode 100644
index 000000000..06c760915
--- /dev/null
+++ b/api/config.py
@@ -0,0 +1,37 @@
+RECAPTCHA_PRIVATE = None #replace private key text here
+DOMAIN = None #Replace with domain to override email domain lookup, otherwise system hostname is used
+EMAILFROM = "omniwallet@vatomic.io" #Is set to None, use noreply@domain
+SMTPUSER = "postmaster@sandboxd311510a82c5491ca65ef71fb65ed076.mailgun.org" #If your smtp server requires authentication define it here
+SMTPPASS = "8473aba8f839e68810f890613be7213e" #If your smtp server requires authentication define it here
+SMTPDOMAIN = 'smtp.mailgun.org' #smtp server to use for sending, default 'localhost'
+SMTPPORT = 25 #smtp port, default 25
+SMTPSTARTTLS = True # Use starttls before SMTP login
+WELCOMECID = None #mailgun campaign id for welcome email stats
+
+#For wallets and session store you can switch between disk and the database
+LOCALDEVBYPASSDB = 0 #Set to 1 to use local storage/file system, Set to 0 to use database
+
+#Used to generate challange/response hash
+SERVER_SECRET = 'SoSecret!'
+SESSION_SECRET = 'SuperSecretSessionStuff'
+WEBSOCKET_SECRET = 'SocketSecret!'
+
+#used for encrypting/decrypting secure values.
+#NOTE: If these values change, anything previously encrypted with them will need to be updated / encrypted with the new values
+AESKEY='aaaaaaaabbbbbbbb'
+AESIV='aaaaaaaabbbbbbbb'
+
+#Donation Address Pubkey (We need the pubkey so that if an address hasn't sent a tx before we don't need the private key to get the pubkey)
+D_PUBKEY = '04ec31f456cc70a60793ff2033d9d2094541a5de8cac67ab1e5b1441187c6bed1601dc64c447244618268af0bd449d90d2ce71816efc69dc7921a226ed60fe926b'
+
+#Blocktrail API Key (used for lookups of utxo's)
+BTAPIKEY = None
+
+#Redis Connection Info
+REDIS_HOST='172.31.11.207'
+REDIS_PORT=6379
+
+REDIS_DB=0
+REDIS_ADDRSPACE=""
+
+TESTNET = True
diff --git a/api/config.py.example b/api/config.py.example
index bfe04cdcd..0b0c02ab4 100644
--- a/api/config.py.example
+++ b/api/config.py.example
@@ -34,6 +34,9 @@ REDIS_DB=0
#Use if you want custom address namespace (multiple servers on same box)
#Must prefix custom name with : example ":stage"
REDIS_ADDRSPACE=""
+
#How long, in seconds, to cache BTC balance info for new addresses, Default 10min (600)
BTCBAL_CACHE=600
+
+TESTNET = False
diff --git a/api/rpcclient.py b/api/rpcclient.py
index 5ff6f2cce..7d8d99eac 100644
--- a/api/rpcclient.py
+++ b/api/rpcclient.py
@@ -1,5 +1,6 @@
import requests, getpass
import time, json
+import config
class RPCHost():
def __init__(self):
@@ -7,7 +8,7 @@ def __init__(self):
self._session = requests.Session()
try:
with open('/home/'+USER+'/.bitcoin/bitcoin.conf') as fp:
- RPCPORT="8332"
+ RPCPORT= "8332"
RPCHOST="localhost"
RPCSSL=False
for line in fp:
diff --git a/api/send.py b/api/send.py
index 86b30fef6..7b5b5dd88 100644
--- a/api/send.py
+++ b/api/send.py
@@ -7,6 +7,7 @@
from blockchain_utils import *
from msc_apps import *
import random
+import traceback
def send_form_response(response_dict):
expected_fields=['from_address', 'to_address', 'amount', 'currency', 'fee']
@@ -18,8 +19,8 @@ def send_form_response(response_dict):
if len(response_dict[field]) != 1:
info('Multiple values for field '+field)
return (None, 'Multiple values for field '+field)
-
- if 'testnet' in response_dict and ( response_dict['testnet'] in ['true', 'True'] ):
+
+ if 'testnet' in response_dict and ( response_dict['testnet'][0] in ['true', 'True'] ):
testnet =True
magicbyte = 111
else:
@@ -32,8 +33,6 @@ def send_form_response(response_dict):
else:
response_status='invalid pubkey'
pubkey=None
-
- print response_dict
from_addr=response_dict['from_address'][0]
if not is_valid_bitcoin_address_or_pubkey(from_addr):
@@ -103,6 +102,7 @@ def send_form_response(response_dict):
return (response, None)
except Exception as e:
print "error creating unsigned tx", e
+ traceback.print_exc()
return (None, str(e))
@@ -251,10 +251,10 @@ def prepare_send_tx_for_signing(from_address, to_address, marker_address, curren
# under dust limit leave all remaining as fees
pass
- tx=mktx(inputs_outputs)
- #tx.pybitcointools.mktx(ins,outs)
- #info('inputs_outputs are '+str(ins)+' '+str(outs))
- info('inputs_outputs are '+inputs_outputs)
+ #tx=mktx(inputs_outputs)
+ tx=pybitcointools.mktx(ins,outs)
+ info('inputs_outputs are '+str(ins)+' '+str(outs))
+ #info('inputs_outputs are '+inputs_outputs)
info('parsed tx is '+str(get_json_tx(tx)))
hash160=bc_address_to_hash_160(from_address).encode('hex_codec')
diff --git a/www/assets/img/icons/close.svg b/www/assets/img/icons/close.svg
new file mode 100644
index 000000000..3d67832ce
--- /dev/null
+++ b/www/assets/img/icons/close.svg
@@ -0,0 +1,27 @@
+
+
\ No newline at end of file
diff --git a/www/index.html b/www/index.html
index 22ca128b6..c85222cad 100644
--- a/www/index.html
+++ b/www/index.html
@@ -64,6 +64,8 @@
+
+
@@ -114,6 +116,7 @@
+
-->
\ No newline at end of file