Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Digital Objects #1543

Open
wants to merge 5 commits into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 38 additions & 10 deletions api/blockchain_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@
from config import BTAPIKEY
from rpcclient import gettxout
from cacher import *
import config

if config.TESTNET:
# neither blockchain.info nor blockonomics support testnet
BLOCKCHAININFO_API_URL = "https://blockchain.info"
BLOCKONOMICS_API_URL = "https://www.blockonomics.co/api"

BLOCKR_API_URL = "http://tbtc.blockr.io/api/v1"
BLOCKTRAIL_API_URL = "https://api.blocktrail.com/v1/tbtc"
BLOCKCYPHER_API_URL = "https://api.blockcypher.com/v1/btc/test3"
BITGO_API_URL = "https://test.bitgo.com/api/v1"
else:
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"

try:
expTime=config.BTCBAL_CACHE
Expand All @@ -15,7 +33,7 @@ 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))
r = requests.get(BLOCKTRAIL_API_URL + '/address/'+address+'/unspent-outputs?api_key='+str(BTAPIKEY)+'&limit=200&page='+str(page))
if r.status_code == 200:
response = r.json()
unspents = response['data']
Expand All @@ -40,7 +58,7 @@ 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')
r = requests.get(BLOCKCYPHER_API_URL + '/addrs/'+address+'?unspentOnly=true')

if r.status_code == 200:
unspents = r.json()['txrefs']
Expand All @@ -65,7 +83,7 @@ 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')
r = requests.get(BLOCKR_API_URL + '/address/unspent/'+address+'?unconfirmed=1')

if r.status_code == 200:
#Process and format response from blockr.io
Expand All @@ -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)
Expand All @@ -117,7 +139,7 @@ def bc_getbalance(address):

def bc_getbalance_bitgo(address):
try:
r= requests.get('https://www.bitgo.com/api/v1/address/'+address)
r= requests.get(BITGO_API_URL + '/address/'+address)
if r.status_code == 200:
balance = int(r.json()['balance'])
return {"bal":balance , "error": None}
Expand All @@ -128,7 +150,7 @@ def bc_getbalance_bitgo(address):

def bc_getbalance_blockcypher(address):
try:
r= requests.get('https://api.blockcypher.com/v1/btc/main/addrs/'+address+'/balance')
r= requests.get(BLOCKCYPHER_API_URL + '/addrs/'+address+'/balance')
if r.status_code == 200:
balance = int(r.json()['balance'])
return {"bal":balance , "error": None}
Expand All @@ -139,7 +161,7 @@ def bc_getbalance_blockcypher(address):

def bc_getbalance_blockr(address):
try:
r= requests.get('http://btc.blockr.io/api/v1/address/balance/'+address)
r= requests.get(BLOCKR_API_URL + '/address/balance/'+address)
if r.status_code == 200:
balance = int(r.json()['data']['balance']*1e8)
return {"bal":balance , "error": None}
Expand Down Expand Up @@ -222,7 +244,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(BLOCKONOMICS_API_URL + '/balance',json.dumps({"addr":formatted}))
if r.status_code == 200:
balances = r.json()['response']
retval = {}
Expand All @@ -243,7 +268,7 @@ def bc_getbulkbalance_blockr(addresses):
formatted=formatted+","+address

try:
r= requests.get('http://btc.blockr.io/api/v1/address/balance/'+formatted)
r= requests.get(BLOCKR_API_URL + '/address/balance/'+formatted)
if r.status_code == 200:
balances = r.json()['data']
retval = {}
Expand All @@ -263,7 +288,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 = {}
Expand Down
3 changes: 3 additions & 0 deletions api/config.py.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 2 additions & 1 deletion api/rpcclient.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import requests, getpass
import time, json
import config

class RPCHost():
def __init__(self):
USER=getpass.getuser()
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:
Expand Down
6 changes: 3 additions & 3 deletions api/send.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand All @@ -18,7 +19,7 @@ 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'][0] in ['true', 'True'] ):
testnet =True
magicbyte = 111
Expand All @@ -32,8 +33,6 @@ def send_form_response(response_dict):
else:
response_status='invalid pubkey'
pubkey=None

print response_dict
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrewrothman please do not remove this, it is actually used when checking user reports of tx issues to verify what the api was received


from_addr=response_dict['from_address'][0]
if not is_valid_bitcoin_address_or_pubkey(from_addr):
Expand Down Expand Up @@ -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))


Expand Down
27 changes: 27 additions & 0 deletions www/assets/img/icons/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions www/assets/img/icons/up.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
<script src="/js/filters/TimeAgo.js"></script>
<script src="/js/filters/BigJS.js"></script>
<script src="/js/directives/Combobox.js"></script>
<script src="/js/directives/VatomIcon.js"></script>
<script src="/js/directives/VatomCard.js"></script>
<script src="/js/directives/VatomFullscreen.js"></script>
<script src="/js/factories/AddressModelFactory.js"></script>
<script src="/js/factories/AssetModelFactory.js"></script>
<script src="/js/factories/TransactionModelFactory.js"></script>
Expand Down Expand Up @@ -93,6 +96,7 @@
<script src="/js/controllers/assets/CrowdsaleParticipationController.js"></script>
<script src="/js/controllers/assets/CrowdsaleController.js"></script>
<script src="/js/controllers/assets/IssuanceController.js"></script>
<script src="/js/controllers/assets/ObjectController.js"></script>
<script src="/js/controllers/assets/DetailsController.js"></script>
<script src="/js/controllers/explorer/AssetsController.js"></script>
<script src="/js/controllers/explorer/CrowdsaleController.js"></script>
Expand All @@ -114,6 +118,7 @@
<script src="/js/CreateWalletController.js"></script>
<script src="/js/cryptUtil.js"></script>
<script src="/js/cryptUtilAsync.js"></script>
<script src="/js/vatomic-sdk.min.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
Expand All @@ -139,7 +144,10 @@

<div class="alert alert-danger text-center animate-show" ng-show="showError"><strong> {{error.message}}</strong> <button type="button" class="close" aria-label="Close"><span aria-hidden="true" ng-click="showError=!showError">&times;</span></button></div>
<div class="panel panel-default panel-main">
<div class="om-title text-center" ng-show="account.loggedIn && !wallet.loaded">{{ 'COMMON.LOADING' | translate}}...</div>
<div class="om-title text-center loading-panel" ng-show="account.loggedIn && !wallet.loaded">
<img src="/assets/img/spinner.gif" />
{{ 'COMMON.LOADING' | translate}}...
</div>
<div class="panel-body" ng-view></div>
</div>
</div>
Expand Down
14 changes: 7 additions & 7 deletions www/js/LoginController.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ function Login($injector, $scope, $http, $location, $modalInstance, $q, Account,
});
} else {

Account.login(login.uuid,login.password,login.mfatoken).then(function(wallet){
$modalInstance.close()
$location.path('/wallet');
$idle.watch();
},function(error){
$scope.loginInProgress=false;
angular.extend($scope,error);
Account.login(login.uuid, login.password, login.mfatoken).then(function (wallet) {
$modalInstance.close()
$location.path('/wallet');
$idle.watch();
}, function (error) {
$scope.loginInProgress = false;
angular.extend($scope, error);
})
}
};
Expand Down
2 changes: 1 addition & 1 deletion www/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ var app = angular.module('omniwallet', [
$routeProvider.when('/assets/:page?', {
templateUrl: function(route) {
//new views added here
var availableViews = ['issue','crowdsale'];
var availableViews = ['issue','crowdsale','object'];

var view;
var viewFound = availableViews.indexOf(route.page);
Expand Down
55 changes: 55 additions & 0 deletions www/js/controllers/assets/ObjectController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
angular.module("omniControllers")
.controller("AssetsObjectController", ["$scope", "PropertyManager", "Transaction", "ADDRESS_EXPLORER_URL", "SATOSHI_UNIT",
function AssetsIssuanceController($scope, PropertyManager, Transaction, ADDRESS_EXPLORER_URL, SATOSHI_UNIT) {
$scope.tokenStep = 1;
$scope.tokenMin = 0;
$scope.tokenMax = "9223372036854775807";
$scope.issuerData = {};
$scope.propertyDetails = { propertyType: 1, propertyCategory: 'Object' };
$scope.ecosystem = 2;

// $scope.setEcosystem = function (ecosystem) {
// $scope.ecosystem = ecosystem;
// };

// $scope.setEcosystem(2);

$scope.confirm = function () {
//TODO: VALIDATIONS
var fee = new Big($scope.issuerData.minerFees);
var assetCreation = new Transaction(50, $scope.issuerData.selectedAddress, fee, {
transaction_version: 0,
ecosystem: $scope.ecosystem,
property_type: $scope.propertyDetails.propertyType,
previous_property_id: 0,
property_category: $scope.propertyDetails.propertyCategory || '',
property_subcategory: '',
property_name: $scope.propertyDetails.propertyName,
property_url: $scope.propertyDetails.propertyUrl || '',
property_data: $scope.propertyDetails.propertyData || '',
number_properties: +new Big($scope.numberProperties).valueOf(),
donate: $scope.account.getSetting("donate")
});


$scope.modalManager.openConfirmationModal({
dataTemplate: '/views/modals/partials/issuance.html',
scope: {
title: "ASSET.ISSUANCE.MODALTITLE",
divisible: false,
propertyName: $scope.propertyDetails.propertyName,
propertyData: $scope.propertyDetails.propertyData,
propertyCategory: $scope.propertyDetails.propertyCategory,
propertySubcategory: '',
propertyUrl: $scope.propertyDetails.propertyUrl,
numberProperties: $scope.numberProperties,
totalCost: assetCreation.totalCost,
confirmText: "ASSET.OBJECT.CREATE",
explorerUrl: ADDRESS_EXPLORER_URL,
successRedirect: "/wallet/assets"
},
transaction: assetCreation
})
}
}
])
Loading