Tutorial: creating a bitcoin instawallet clone with python and django

December 25th, 2011

Bitcoin is great and crazy innovation. Ability to transfer electronic money around the world, with low transaction costs might be a revolutionary concept. However, bitcoin is a very young and only time will tell if it succeeds or not. In every case, Bitcoin needs huge amount of inrastructure around it to be successful. That is why there is django-bitcoin library, to make development of bitcoin web apps easier.

From a developer perspective bitcoin is great because bitcoins are so easy to move around. You can automate all aspects of money transfers. In this tutorial I will show you how to create a simple instawallet clone using python language, django web framework and django-bitcoin library. The resulting code of this tutorial is in github.

Instawallet is a very simple bitcoin web app. It allows anyone to set up a simple bitcoin wallet, where you can store bitcoins and move them easily around without installing the bitcoin client. If you are using this kind of service, you are putting a huge trust on the service owner. The benefits of using instawallet is that it makes bitcoin transfers more anonymous, and also makes using bitcoins easier.

Now let’s start coding! First we need to setup the app from django. We start a new django application, start a new “wallets” django app, and clone django_bitcoin from github.

Note that it is usually a good practice to use virtualenv, which we are not using now.

pip install django
django-admin.py startproject instawallet
cd instawallet

python manage.py startapp wallets

git clone git://github.com/kangasbros/django-bitcoin.git
cd django-bitcoin
python setup.py install

Next we need to setup some settings for our django project to file “settings.py”. For this project we are using sqlite, which we first install via command line.

pip install pysqlite

We set up the sqlite database as a file “dev.db”. After that we add “django_bitcoin” and “wallets” to INSTALLED_APPS so that django can find our apps. Also we specify a templates directory. Create a folder “templates” inside the project root.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'dev.db',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

...

INSTALLED_APPS = (
    ….
    'django_bitcoin',
    'wallets',
)

...

import os

PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))

TEMPLATE_DIRS = (
    os.path.join(PROJECT_ROOT, "templates"),
)

And finally, we need to setup the bitcoin daemon. For this, you must download the official bitcoin client, and edit the bitcoin.conf. Example bitcoin.conf for development purposes:

testnet=1
server=1
rpcuser=admin
rpcpassword=1234
rpcallowip=*

Then you need to configure your bitcoin daemon to django settings.py file. Here we use 0 confirmations for testing purposes.

BITCOIND_CONNECTION_STRING = "http://login:password@localhost:8332"
BITCOIN_MINIMUM_CONFIRMATIONS = 0

Now everything is set up! Now we start the real coding. We start with models. We will use only one model in this application. That is the online wallet. It will have only two fields, one is the random and unique identifier (uuid) of the wallet, and second is a foreign key to the django_bitcoin Wallet object, which faciliates the actual transactions. The following model goes to “wallets/models.py” file.

class InstaWallet(models.Model):
    """A wallet model"""

    uuid = models.CharField(blank=True, max_length=50)
    wallet = models.ForeignKey(Wallet, null=True)

    def __unicode__(self):
        return u"Wallet "+self.uuid+" "+self.name

    def url(self):
        return "/wallet/"+self.uuid

We need also one form for this app, which resides in the “wallets/forms.py” file. The form is used to send transactions from a specific instawallet.

class SendForm(forms.Form):
    address_to = forms.CharField(min_length=3, max_length=40)
    amount = forms.DecimalField(min_value=Decimal("0.0001"))

Now we have the database structure defined in models.py, and we can sync the initial database.

python manage.py syncdb

Now the logic part of this application. This resides in the “wallets/views.py” file. Before we implement the logic, we have to define the “urls.py” file, which defines what kind of urls we can use.

We define two addresses for this app: the “home” address, which always just generates a new wallet and redirects to it. The other is address for each invidual instawallet.

urlpatterns = patterns('',
    url(r'^$', 'wallets.views.home', name='home'),
    url(r'^wallet/(?P<uuid>.*?)$', 'wallets.views.wallet', name='wallet'),
)

Now for the actual views. First the home view. In this view, we generate a new wallet with a random uuid. For a better random, we use system random function os.urandom(), which is better than the pseudorandom function provided by python. We redirect to the wallet address right away.

def home(request):
    # just generate a new wallet
    new_wallet=InstaWallet.objects.create(uuid=generateuniquehash(extradata=str(os.urandom(32))),\
        wallet=Wallet.objects.create())

    return HttpResponseRedirect(new_wallet.url())

Now the actual wallet view, which is the core functionality of our instawallet. We get the wallet uuid as a parameter. If the InstaWallet object isn’t found with that uuid, we redirect to 404.

If the request is GET, there is nothing to do. Otherwise we have received an transaction request.

With our instawallet, we can generate two types of transactions. If the address provided is between 30-37 characters, we assume that the address is an actual bitcoin address, and we generate a bitcoin transaction. This is done by using the send_to_address() -function of the django_bitcoin “Wallet” object.

Otherwise, we assume that the user tries to send the funds to an another instawallet app. We try to search if there are any InstaWallet objects, whose uuid start with the address provided. Then if a right InstaWallet object is found, we send bitcoins to it with the send_to_wallet() function. No actual bitcoin transaction is generated, and the funds are sent between our web app users.

Why is this useful? This way the users of this web app can send instant transactions between each other, without a need for actual bitcoin transactions.

def wallet(request, uuid):
    try:
        instawallet=InstaWallet.objects.get(uuid=uuid)
    except:
        return HttpResponseRedirect('/404')

    if request.method == 'POST': # If the form has been submitted...
        form = SendForm(request.POST) # A form bound to the POST data
        if form.is_valid(): # All validation rules pass
            # check if
            if len(form.cleaned_data["address_to"])>30 \
                and len(form.cleaned_data["address_to"])<37:
                try:
                    instawallet.wallet.send_to_address(form.cleaned_data["address_to"], form.cleaned_data["amount"])
                    messages.add_message(request, messages.SUCCESS, \
                        _(u"Transaction successfully sent to bitcoin address "+form.cleaned_data["address_to"]))
                except:
                    messages.add_message(request, messages.ERROR, sys.exc_info()[0])
            else:
                otherwallets=InstaWallet.objects.filter(uuid__startswith=form.cleaned_data["address_to"])
                if len(otherwallets)==1:
                    instawallet.wallet.send_to_wallet(otherwallets[0].wallet, form.cleaned_data["amount"])
                    messages.add_message(request, messages.SUCCESS, \
                        _(u"Transaction successfully sent to another instawallet "+form.cleaned_data["address_to"]))
                else:
                    messages.add_message(request, messages.ERROR, _(u"Address not an valid bitcoin address or wallet uuid not found."))
    else:
        form = SendForm() # An unbound form

    return render_to_response("instawallet.html", {
        "instawallet": instawallet,
        "form": form,
        }, context_instance=RequestContext(request))

Almost done! Now we only need to do the HTML template for the app. This file is “templates/instawallet.html”.

We are using several templatetags provided by django_bitcoin templatetag file “currency_conversions”. The first is wallet_tagline, which displays the wallet balance, money received and sent, and the balance approximation in USD.

The second is bitcoin_payment_qr, which displays a simple qr code for our bitcoin receiving address. The Wallet.receiving_address() function shows the wallet receiving address, where we can send bitcoins.

The final one is wallet_history tag, which shows all of the transactions of our bitcoin wallet as a table.

{% load i18n %}
{% load currency_conversions %}
<html>
<head>
<title>{% trans "Bitcoin Instawallet" %}: {{ instawallet.uuid }}</title>
</head>
<body>
<h1>{% trans "Your instawallet" %}: {{ instawallet.uuid }}</h1>

{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}

<b>{% wallet_tagline instawallet.wallet %}</b><br/>

{% trans "Send bitcoins to following address to receive coins" %}:

{% bitcoin_payment_qr instawallet.wallet.receiving_address %}

<h2>{% trans "Send payments" %}</h2>

<form id="newform" action="{{ instawallet.url }}" method="POST">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Send!"/>
</form>

<h2>{% trans "Transaction log" %}</h2>

{% wallet_history instawallet.wallet %}

Now all the code is created, and you can run the application and test it at “http://localhost:8000/”.

python manage.py runserver

Now we can see that the instawallet is really working, and can test sending coins back and forth.

Main View and QR code

The transaction log of our instawallet.

As you can see, creating an instawallet-style app doesn’t require truckloads of code, as most of the functionality is provided by the django_bitcoin library. Feel free to develop the project further and explore the django_bitcoin library.

If you plan to run django_bitcoin based app in the production, make sure to change the confirmation count setting to something higher, and do some serious testing before you deploy anything!

The code is at https://github.com/kangasbros/django-bitcoin-instawallet

And finally, if you liked this tutorial, you can send a small donation to bitcoin address 1DaVAZ1kytYPqaDVse9HUcrCQfD6NpNamp ;)

Is javascript cryptography bad for your health?

November 16th, 2011

Recently I launched two little web apps in my spare time. Those both involved heavy use of javascript cryptography.

After spreading the word about these services, I received some heavy criticism about the usage of javascript cryptography. The reasons were that it creates a false sense of security, is un-trustable and the persons who would use or need cryptography prefer to use more traditional and time-tested software.

Cryptographic javascript libraries such as Stanford Javascript Crypto Library are relatively new. However, at the very basic level it is pretty easy to validate these libraries by comparing the results to more stable software. Hashes are gonna hash and encryption is gonna encrypt.

Also using javascript-enabled encryption is probably safer than not using an encryption at all. Javascript cryptography allows very easy and accessible cryptography-enabled web services, which makes cryptography more usable for common people.

Some ways to sign & verify javascript code could be implemented, so that it is easier for users to trust cryptographically-enabled web services. This could be achieved somewhat user-friendly way via browser plugins, which could cache or automatically compare different javascript source files.

After all I think javascript cryptography is a good thing. Cryptography should be available for everyone, and common developers shouldn’t be afraid to use cryptography in their apps.

The services I created: first was cryptedmemo.com, which let’s you store secret notes online, and the second one was SHA1_Pass.js, which is an implementation handy sentence-based password-system.

Why I don’t use TDD or BDD

September 4th, 2010

Everyone nowadays is writing tests like crazy, and even using TDD so that tests are always written before actual code. Right? No.

I have used TDD for one project and I wasn’t happy, it was waste of time. Nowadays I write unit tests very seldomly (in my case they are more integration-tests than unit tests) and never follow BDD-style development. That is mostly because I’m a lazy-ass bastard, but there are other reasons as well, such as:

  • “Examples” of unit tests suck donkey balls every time. If you are going to keep a presentation about how cool unit tests are, try to show me the practical benefits with a code example, not some lame-ass “Hello world” example or hand-waving. I haven’t seen any convincing real-world cases.
  • They seem to be a great way to spend some extra time doing time consuming, not very hard work.. And if you are a sub-contractor/consultant, that is pretty good because it means more billable hours. So good for consultants, not for me.
  • You have to think about the “evil” business side too. OK, I believe how TDD/BDD will make my project ultra-maintainable, and unit tests will alert me if something gets broken. But what if my project does not need maintaining because it wasn’t commercially successful? Often I just want to get something out of the door quickly, and I want to minimize my time developing the software.
  • Unit tests=more code. This is just a personal belief; I think the less code, the better. I’m a minimalist.

Don’t get this wrong, use BDD/TDD if you really believe in them and think they benefit your project. I just personally haven’t found any use for them in any of my projects or my clients’ projects.

Python/Django unicode/utf-8 usage, how hard can it be?

September 17th, 2009

Regarding character encodings, big boys have always told me a rule of thumb: use utf-8 for everything. In my last project, I tried to follow this simple guideline, but still managed to get several headaches with utf-8/unicode problems.

First step: Set your text editor/IDE to use always utf-8. I guess most editors (eg. textmate, which I mostly use) do this automatically nowadays. For vim I have used following line in my .vimrc:

set encoding=utf8

If you have old files lying around in other encodings, it is recommended to convert them to utf-8. This can be easily accomplished with iconv or other similar tools.

OK, now the text editor should default to utf-8 when creating new files. However, don’t be surprised if django throws an error looking something like this:

(“Non-ASCII character ‘\\xc3′ in file views.py on line 303, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details”, (‘views.py’, 303, 0, None))

That is because python doesn’t get that your files are utf-8, unless your editor places a byte-order-mark automatically in each file. Textmate doesn’t seem to, and that’s why I need to place following in each .py file.

# coding=utf8

That fixed the problem! Another common error I caught was:

UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xc3 in position 4: ordinal not in range(128)

Usually it turned out that I had done something like “str”+unicodeObject. This can be solved by marking strings as u”this is a unicode object” or using the unicode(“string”) object.

Reading & writing files with unicode turned out to be problematic too. For example, the common way to read files is:

with file.open(filename, "r" ) as fin:
    for line in fin:

However, with this method every line variable is a str object and we need to convert them to unicode object separately. Easier method is to use the codecs library (assuming that input file is utf-8):

import codecs
with codecs.open(filename, "r", "utf-8" ) as fin:
        for line in fin:

That way, every input line is automatically an unicode object, and we don’t need to convert the strings to unicode later.

As a last thing, when you create python script which outputs utf-8 like this:

# -*- coding: utf-8 -*-
print u"unicode object äöäö"

I works normally when the output is printed to terminal, but when you do file redirect like this

$ python script.py > test.txt

the familiar UnicodeEncodeError pops out:

Traceback (most recent call last):
File “script.py”, line 2, in
print u”unicode object äöäö”
UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 15-18: ordinal not in range(128)

This is fixed by manually setting stdout encoding:

# -*- coding: utf-8 -*-
import sys
import codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

print u"unicode object äöäö"

This is because python doesn’t define output encoding when redirecting to a file.