MultiChain / multichain-explorer

Web-based explorer for MultiChain blockchains
GNU Affero General Public License v3.0
177 stars 140 forks source link

getaddressbalances and getunspent #35

Open seyacat opened 6 years ago

seyacat commented 6 years ago

Hi coders, i make 2 handlers to abe.py, they output in json addressbalance and unspent TX of especific asset, this information its nesesary to build transaction on cold enviroment. Hope it helps someone.

getaddressbalances/address getunspent/address/asset-ref

def handle_getaddressbalances(abe, page):
    chain = page['chain']
    page['template'] = "%(body)s"

    page['body'] = "";
    #page['body'] += "ok";

    #page['body'] +=json.dumps({'4': 5, '6': 7}, sort_keys=True,indent=4, separators=(',', ': '));

    data = {};
    data["result"] = [];
    address = wsgiref.util.shift_path_info(page['env'])
    if address in (None, '') or page['env']['PATH_INFO'] != '':
        raise PageNotFound()
    version, pubkeyhash = util.decode_check_address_multichain(address)
    if pubkeyhash is None:
        raise PageNotFound()

    try:
        row = abe.store.selectrow("""select pubkey_id from pubkey where pubkey_hash = ?""",
                                  (abe.store.binin(pubkeyhash),) )
        assets_resp = abe.store.get_assets(chain)
        if len(assets_resp) is 0:
            body += ['None']
        elif row is not None:
            pubkey_id = int(row[0])                

            assetdict = {}
            for asset in assets_resp:
                # use escaped form as dict key
                name = asset.get('name','').encode('unicode-escape')
                assetdict[name] = asset
            print(assetdict);
            for row in abe.store.selectall("""
                select a.name, a.prefix, b.balance from asset_address_balance b join asset a on (a.asset_id=b.asset_id)
                where b.balance>0 and b.pubkey_id=?""",
                                   (pubkey_id, )):
                name, prefix, balance = row
                if name is None:
                    name=''
                name = name.encode('unicode-escape')
                asset = assetdict[ name ]
                assetref = asset['assetref']

                num_tx = abe.store.get_number_of_transactions_for_asset_address(chain, assetref, pubkey_id)

                if assetref.endswith(str(prefix)):
                    balance_display_qty = util.format_display_quantity(asset, balance)
                    """body += ['<tr><td><a href="../../' + escape(chain.name) + '/assetref/' + assetref + '">' + name + '</a>',
                         '</td><td><a href="../../' + escape(chain.name) + '/assetref/' + assetref + '">' + assetref + '</a>',
                         '</td><td><a href="../../' + escape(chain.name) + '/assetaddress/' + address + '/' + assetref + '">' + str(num_tx) + '</a>',
                         '</td><td>', balance,
                         '</td><td>', balance_display_qty,
                         '</td></tr>']"""
                    #{"result":[{"name":"celtoken","assetref":"181-267-63185","qty":2466}],"error":null,"id":1510266218,"hash":"aee3bc630b94161ca2817f1f8b326328"}
                    #print(escape(chain.name))
                    data["result"].append({"name":name,"assetref":assetref,"qty":balance})
            #body += ['</table>']
        data["error"]=None;
        data["hash"]=1;
    except Exception as e:
        print( ['<div class="alert alert-danger" role="alert">', 'Failed to get asset information: '+str(e), '</div>']);
        data["error"]=str(e);
        data["hash"]=1;
        pass
    page['body'] += json.dumps(data);
    return;

def handle_getunspent(abe, page):
    chain = page['chain']
    page['template'] = "%(body)s"        
    page['body'] = "";        
    data = {};
    #data["result"] = [];

    chain = page['chain']

    # shift address
    address = wsgiref.util.shift_path_info(page['env'])
    if address in (None, ''): # or page['env']['PATH_INFO'] != '':
        raise PageNotFound()

    # Shift asset ref
    assetref = wsgiref.util.shift_path_info(page['env'])
    if assetref in (None, '') or page['env']['PATH_INFO'] != '':
         raise PageNotFound()

    url = abe.store.get_url_by_chain(chain)
    multichain_name = abe.store.get_multichain_name_by_id(chain.id)

    # get asset information and issue tx as json
    try:
        resp = util.jsonrpc(multichain_name, url, "listassets", assetref)
        asset = resp[0]
        #data['asset']=asset;
    except util.JsonrpcException as e:
        msg= "JSON-RPC error({0}): {1}".format(e.code, e.message)
        # Example error: JSON-RPC error(-8): Asset with this reference not found: 5-264-60087
        body += ['<div class="alert alert-danger" role="warning">', msg ,'</div>']
        return
    except IOError as e:
        body += ['<div class="alert alert-danger" role="warning">', e ,'</div>']
        return

    name = asset.get('name','').encode('unicode-escape')        

    transactions = abe.store.get_transactions_for_asset_address(chain, assetref, address)
    if transactions is None:
        #body += ['No transactions']
        return        

    #data['transactions']=transactions;
    #data['transactions']={};
    #data['net_amount']=0;
    data['unspent'] = [];
    for tx in transactions:
        tx_hash = tx['hash']
        try:
            t = abe.store.export_tx(tx_hash = tx_hash, format = 'browser')
        except DataStore.MalformedHash:
            continue
        if t is None:
            continue            
        #data['transactions'][tx_hash]={};                        

        c=0;
        for vout,txobj in enumerate(t['out']):
            #print(tx_hash,vout);
            gettxout = util.jsonrpc(multichain_name, url, "gettxout", tx_hash , vout);
            if(gettxout is not None):
                if( len(gettxout[u'assets'])>0 ):
                    addresses = gettxout[u'scriptPubKey'][u'addresses'];
                    for addr in addresses:
                        if(addr==address):
                            data['unspent'].append( {'txid':tx_hash,'vout':vout} );
                            c=c+1;
                            if(c>3):
                                break;
                            pass
            #tx = get_vouts(txobj, 'o', 'i', asset, chain)

    page['body'] += json.dumps(data);
    return`