0

I am using Blockchain.info's API to send multiple payments. I believe I have everything how it should be however when I run the code I get the following Error: RuntimeError: ERROR: Invalid Recipients JSON. Please make sure it is url encoded and consult the docs. The docs can be found here: https://blockchain.info/api/blockchain_wallet_api

The Python library I am using can be found here: https://github.com/p4u/blockchain.py/blob/master/blockchain.py

The only other post on this issue is posted by the original creator of the library, he said the problem was that the amounts cannot be a decimal, mine are not however.Post can be found here: https://bitcointalk.org/index.php?topic=600870.0

Here is my code:

from __future__ import print_function
from itertools import islice, imap
import csv, requests, json, math
from collections import defaultdict
import requests
import urllib
import json
from os.path import expanduser
import configparser


class Wallet: 
    guid        = 'g'
    isAccount   = 0
    isKey       = 0
    password1   = 'x'
    password2   = 'y'
    url         = ''

def __init__(self, guid = 'g', password1 = 'x', password2 = 'y'):

    if guid.count('-') > 0:
        self.isAccount = 1
        if password1 == '': # wallet guid's contain - 
            raise ValueError('No password with guid.')
    else:
        self.isKey = 1

    self.guid = guid
    self.url = 'https://blockchain.info/merchant/' + guid + '/'

    self.password1 = password1
    self.password2 = password2

    r = requests.get('http://api.blockcypher.com/v1/btc/main/addrs/A/balance')
    balance = r.json()['balance']

    with open("Entries#x1.csv") as f,open("winningnumbers.csv") as nums:
        nums = set(imap(str.rstrip, nums))
        r = csv.reader(f)
        results = defaultdict(list)
        for row in r:
            results[sum(n in nums for n in islice(row, 1, None))].append(row[0])

    self.number_matched_0 = results[0]
    self.number_matched_1 = results[1]
    self.number_matched_2 = results[2]
    self.number_matched_3 = results[3]
    self.number_matched_4 = results[4]
    self.number_matched_5 = results[5]

    self.number_matched_5_json = json.dumps(self.number_matched_5, sort_keys = True, indent = 4)

    print(self.number_matched_5_json)

    if len(self.number_matched_3) == 0:
        print('Nobody matched 3 numbers')
    else:
        self.tx_amount_3 = int((balance*0.001)/ len(self.number_matched_3))

    if len(self.number_matched_4) == 0:
        print('Nobody matched 4 numbers')
    else:
        self.tx_amount_4 = int((balance*0.1)/ len(self.number_matched_4))

    if len(self.number_matched_5) == 0:
        print('Nobody matched 3 numbers')
    else:
        self.tx_amount_5 = int((balance*0.4)/ len(self.number_matched_5))

    self.d = {el: self.tx_amount_5 for el in json.loads(self.number_matched_5_json)}
    print(self.d)

    self.d_url_enc = urllib.urlencode(self.d)

def Call(self, method, data = {}):
    if self.password1 != '':
        data['password'] = self.password1 
    if self.password2 != '':
        data['second_password'] = self.password2

    response = requests.post(self.url + method,params=data)

    json = response.json()
    if 'error' in json:
        raise RuntimeError('ERROR: ' + json['error'])

    return json

def SendPayment(self, toaddr, amount, fromaddr = 'A', shared = 0, fee = 0.0001, note = True):
    data = {}
    data['to'] = toaddr
    data['amount'] = self.tx_amount_5
    data['fee'] = fee
    data['recipients'] = self.d_url_enc

    if fromaddr:
        data['from'] = fromaddr

    if shared:
        data['shared'] = 'true'

    if note:
        data['note'] = 'n'

    response = self.Call('payment',data)

def SendManyPayment(self, fromaddr = True, shared = False, fee = 0.0001, note = True):
    data = {}
    recipients = self.d_url_enc
    data['recipients'] = recipients.__str__().replace("'",'"')
    data['fee'] = str(fee)
    if fromaddr:
        data['from'] = 'A'
    if shared:
        data['shared'] = 'true'
    else:
        data['shared'] = 'false'
    if note:
        data['note'] = 'n'
    response = self.Call('sendmany',data)

    return response

print(Wallet().SendManyPayment())


Complete runtime error: Traceback (most recent call last):
  File "D:\Documents\B\Code\A\jsontest.py", line 125, in <module>
    print(Wallet().SendManyPayment())
  File "D:\Documents\B\Code\A\jsontest.py", line 121, in SendManyPayment
    response = self.Call('sendmany',data)
  File "D:\Documents\B\Code\A\jsontest.py", line 86, in Call
    raise RuntimeError('ERROR: ' + json['error'])
RuntimeError: ERROR: Invalid Recipients JSON. Please make sure it is url encoded and consult the docs.
3
  • Show the whole traceback. Commented Oct 8, 2015 at 22:08
  • Added the complete traceback to the end of the code. Commented Oct 8, 2015 at 22:14
  • @ekhumoro Do you have any ideas what is going on here? Commented Oct 9, 2015 at 19:08

1 Answer 1

1

What does data['recipients'] contain inside of your SendManyPayment() function? It looks like you are trying to do some manual encoding instead of using json.dumps(recipients)

The docs say it should look like this:

{
    "1JzSZFs2DQke2B3S4pBxaNaMzzVZaG4Cqh": 100000000,
    "12Cf6nCcRtKERh9cQm3Z29c9MWvQuFSxvT": 1500000000,
    "1dice6YgEVBf88erBFra9BHf6ZMoyvG88": 200000000
}

Try this out for send many:

def SendManyPayment(self, fromaddr = True, shared = False, fee = 0.0001, note = True):
    data = {}
    recipients = self.d_url_enc
    # recipients should be a json string FIRST!
    data['recipients'] = json.dumps(recipients)
    data['fee'] = str(fee)
    if fromaddr:
        data['from'] = 'A'
    if shared:
        data['shared'] = 'true'
    else:
        data['shared'] = 'false'
    if note:
        data['note'] = 'n'
    response = self.Call('sendmany',data)

    return response
Sign up to request clarification or add additional context in comments.

5 Comments

My JSON code looks like this {u'35xfg4UnpEJeHDo55HNwJbr1V3G1ddCuVA': 543859, u'3D3iAR9M4HDETajfD79gs9BM8qhMSq5izX': 543859}
The URL encoded version looks like this: 35xfg4UnpEJeHDo55HNwJbr1V3G1ddCuVA=543859&3D3iAR9M4HDETajfD79gs9BM8qhMSq5izX=543859 judging from the docs this is what I should be posting.
That isn't json code, that is a dict. Then it is being url encoded as multiple parameters instead of json data urlencoded. You need to turn recipients into a json string and then assign it to data['recipients'].
Perfect thankyou, I am new to JSON so I wasnt to sure at first. This really helped thanks man!
You are welcome. I figured there was a disconnect on the json encoding part. Their api is also strange in that it wants form data with some of the items containing json data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.