Code Monkey home page Code Monkey logo

django-cc's Introduction

django-cc

Build Status

Django-cryptocurrencies web wallet for Bitcoin and a few other cryptocurrencies.

Simple pluggable application inspired by django-bitcoin.

Python 3

Features

  • Multi-currency
  • Celery support
  • Withdraw and Deposit
  • 3 types of balances: balance, unconfirmed, holded
  • Works over bitcoind json-rpc

Quick start

Edit Currency model

from cc.models import Currency

currency = Currency.objects.create(
    label = 'Bitcoin',
    ticker = 'BTC',
    api_url = 'http://root:toor@localhost:8332'
)

Start Celery worker

$ celery worker -A tst.cel.app

Get new addresses for wallets

$ celery call cc.tasks.refill_addresses_queue

Now you can create wallets, deposit and withdraw funds

from cc.models import Wallet

wallet = Wallet.objects.create(
    currency=currency
)

wallet.get_address()

wallet.withdraw_to_address('mvEnyQ9b9iTA11QMHAwSVtHUrtD4CTfiDB', Decimal('0.01'))

After creating a withdraw transaction, you need to run

$ celery call cc.tasks.process_withdraw_transactions

Query for new deposit transactions:

$ cc.tasks.query_transactions

If you want to catch event from bitcoind, but these calls options in bitcoin.conf file

walletnotify=~/env/bin/celery call cc.tasks.query_transaction --args='["BTC", "'%s'"]'
blocknotify=~/env/bin/celery call cc.tasks.query_transactions --args='["BTC"]'

where "BTC" - ticker (short name) of the Currency

More details

Limitations

  • Works with full node. For each cryptocurrency you will need to run a full node, which usually requires a lot of disk space. But by running full node you are actually helping the network, so it is a good thing.
  • Coins are mixed between wallets. When you withdraw funds from the wallet, you can't choose which UTXO will be used.
  • During the withdrawal you can't choose transaction fee. 'Django-cc' uses 'send_many' RPC call, bitcoind calculates how much you will spend on transaction fee. When withdraw is finished, spent fee will be subtracted from wallet balance. To reduce fees, change 'txconfirmtarget' in your bitcoin.conf.

Configuring Celery tasks

This library relies heavily on Celery for running tasks in the background. You need to add it to your Project. There are a few tasks which djano-cc should do periodically:

  • 'refill_addresses_queue'. It queries bitcoind for new addresses and store them in DB. Each time you create a wallet and call 'wallet.get_address()' unused address will be attached to the wallet. By default, it keeps amount for new addresses to 20. You can tune this by changing 'CC_ADDRESS_QUEUE' in your project settings. Usually running this task once in an hour is enought.
  • 'process_withdraw_transactions'. It queries DB for any new withdraw transactions and executes them. By running it not so often, you can batch transactions, this will help you reduce network fees.
  • 'query-transactions'. It queries bitcoind for new incoming transactions and updates wallets balances. Bitcoin network creates one block per approximately 10 minutes, so no need to run it more often.

But it is better to run 'query-transactions' in response to new events from bitcoind. You can do this by adding these lines to bitcoin.conf

walletnotify=~/env/bin/celery call cc.tasks.query_transaction --args='["BTC", "'%s'"]'
blocknotify=~/env/bin/celery call cc.tasks.query_transactions --args='["BTC"]'

Each time bitcoin will receive new tx or block, you will get an instant update on balances.

If bitcoind works in another environment, you can send this events by HTTP hooks. Expose 'django-cc' views in urls.py:

urlpatterns = [
...
url(r'^cc/', include('cc.urls')),
]

Then you can send http requests to trigger actions:

curl -k "https://yourhost/cc/blocknotify/?currency=BTC"
curl -k "https://yourhost/cc/walletnotify/?currency=BTC&txid=$1"

API

Withdraw to network:

wallet.withdraw_to_address('mvEnyQ9b9iTA11QMHAwSVtHUrtD4CTfiDB', Decimal('0.01'))

Transfer from wallet to wallet:

wallet1.transfer(wallet1.balance, wallet2, None, 'description')

Get wallet history:

for operation in wallet.get_operations():
    print(operation.created)
    print(operation.balance)
    print(operation.reason.txid)
    print(operation.reason.address)

Database transactions

When you write applications that are working with money, it is extremely important to use Database transactions. Currenly django-cc doesn't inclues any '@transaction.atomic'. You should do this by yourself.

In my code I have a higher level wrapper with @transaction.atomic and to get wallets I'm always using select for update, like 'Wallet.objects.select_for_update().get(addresses=address)' to get a lock over the Wallet.

Supported cryptocurrencies

In general django-cc should work with most Bitcoin forks. I've tested it against: Bitcoin, Litecoin, Zcash (not anonymous transactions), Dogecoin and Dash.

When you are adding any other than Bitcoin Currency, you should define magicbyte and dust values. Use tables below to get the values.

Magic bytes

Magic bytes are used to verify withdraw addresses. They are different for each cryptocurrency.

CC Mainnet Testnet
Bitcoin 0,5 111,196
Litecoin 48,50 58
Zcash 28 29
Dogecoin 30,22
Dash 76,16 140

Dust

Minimal amount of valid transaction

CC Dust size
Bitcoin 0.00005430
Litecoin 0.00054600

Settings

CC_CONFIRMATIONS - how many confirmations incoming transaction needs to increase wallet balance. Default is 2. CC_ADDRESS_QUEUE - how many addresses generate during refill_addresses_queue. Default is 20. CC_ALLOW_NEGATIVE_BALANCE - minimal amount of Wallet to be able to withdraw funds from it. Default is Decimal('0.001'). CC_ACCOUNT - Bitcoind once had an account system. Now it is deprecated. Do not change this. Default is '' — empty string. CC_ALLOWED_HOSTS - list of addresses how can call /cc/blocknotify and /cc/walletnotify. Default is ['localhost', '127.0.0.1'].

Testing

Tests are written using Regtest. To run them you need docker and docker-compose. Simply run docker-compose up and it will build and run all tests for you. Usually it takes about 5 min to run all the tests.

django-cc's People

Contributors

acerix avatar gitter-badger avatar kcyeu avatar limpbrains avatar mrs83 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-cc's Issues

Support for shielded transactions

@limpbrains see you're still active on this project, and I was hoping to use it for a zcash fork that only uses z_ operations.

Wanted to know if you were working on adding such functionality. I've forked it and have started trying to update things on my end, but I was wondering if you might have time to talk with me to clear up some questions I have.

I've added a boolean to the currency model for 'shielded_transactions', and have been able to get refill_address_queue working:

@shared_task()
def refill_addresses_queue():
    for currency in Currency.objects.all():
        coin = AuthServiceProxy(currency.api_url)
        count = Address.objects.filter(currency=currency, active=True, wallet=None).count()

        if count < settings.CC_ADDRESS_QUEUE:
            for i in range(count, settings.CC_ADDRESS_QUEUE):
                try:
                    if currency.shielded_transactions:
                        Address.objects.create(address=coin.z_getnewaddress(settings.CC_ACCOUNT), currency=currency)
                    else:
                        Address.objects.create(address=coin.getnewaddress(settings.CC_ACCOUNT), currency=currency)
                except (socket_error, CannotSendRequest) :
                    pass

Wanted to pick your brain if you're game...

monero support

hi there,
Nice project.
Have you tested with monero?
How do you derive the magic byte values for crypto (sorry couldn't find a definitive answer from google)
Thanks!

Thread or process safety issues

Is it safe to update the balance? If different threads or processes update the balance of a wallet at the same time, will there be any problems?

How i insert this address on a view

celery call -b redis:localhost:6379/0 cc.task.refill_addresses_queue

i want to create a address for user how i cant insert this celery task on view
i mean call task always return a address how i insert this on view? only call without write it manually

Missing documentation?

Hello,

your Project seems intressting to me but i dont know how to use it?

Can you please create a documentation where we have some examples in place. I currently dont understand how to create Wallets for my users or how to get things setup Witz the current doc.

Thanks

Multisig transactions

Hi!
If i wanted to use multisig would I need to tweak the models myself or is it something that is already implemented?
Thanks

should Wallet model methods be atomic?

Hi, I'm interested in using this codebase for a project. One thing I was wondering about is why, for example, Wallet.withdraw_to_address doesn't wrap everything in a transaction. It seems there could be various race conditions between the time when the model is first fetched from database, and when .save() is called.

I am a bit new to django as well, though, is there some reason why locking would not be necessary?

Generation of new address

Hi,
First off thanks for great library.
Quick question, after I initially import my address from my bitcoind wallet.dat file using the refill_address_queue
What happens when I require say another 100 address? Are they automatically generated or do I need to run a script to ensure that fresh address are being generated periodically by bitcoind.
Finally from what I understand btc address are a one use thing therefore each time a confirmed transaction hits the wallet i should generate a new address for the wallet and update the wallet model with the new address?
Thanks again

When adding a new currency, what should "last_block" be?

I'm trying to add my cryptocurrency, Zeal, and it is not working (wallet.get_address() for a newly created wallet is None). I think my magicbyte and dust values are correct. I think it's the last_block that is throwing things off. Also, my api_url is my full node. Is that alright?

My coin is a Litecoin 0.8.7.5 fork.

What’s currency?

Hello mate.
Tell me pls, what kind of currencies do you support?
Bitcoin = BTC
BitcoinCash = BCH or BCC
Litecoin = LTC
Dash = DASH
Dogecoin = DOGE
Is this correct? What else?
Thank you for support.

Use celery as a python function, not at the command line?

How to use the celery worker -A tst.cel.app and celery call cc.tasks.refill_addresses_queue celery commands as a python function, except for the command line?

Included in the following commands
celery call cc.tasks.process_withdraw_transactions
cc.tasks.query_transactions

import celery

def celery(self):
    a = celery call cc.tasks.process_withdraw_transactions
    return a

As an example; I would do it like this?

refill_address_queue key error

Hi, I am receiving the following error when i start my celery worker
KeyError: 'wallet.tasks.refill_addresses_queue'
I have my broker running, as well as bitcoind, and have an instance of my currency model within my database.
Do i require the django-celery backend in order to save the results of the task to the DB?
thanks

Improve documentation

  • talk about advantages and disadvantages: you need to run a full node, can't calculate fee in advance
  • how configure celery. Run tasks periodically vs on events. How to bunch withdraw tx's
  • how to get list wallet transactions
  • how to transfer funds from wallet to wallet

How to do the deposit transaction

Hi, I'm just integrating this repo with my django app, i' m able to do the withdraw transaction. but i don't know how to do the deposit transaction with celery . please help me out also please put the deposit transaction example in readme @limpbrains

running celery tasks as celery beat task

Hi again,
Just a quick question,
I am currently running refill_address_queue
Process_withdraw_transaction and query_transaction as a celery beat task configured in settings and am calling it directly from cc.tasks is this the correct way to have it configured or should I be doing it differently?
Thanks!

Negative balance

Hi!
Just another quick question,
Currently when withdrawing the account balance will go into negative, I'm assuming this is due to blockchain transaction fee.
To prevent this from happening do you think only allowing a user to withdraw at most 98% of there funds at a time is a suitable approach?
Thanks

cant start celery

hello.

can you please help me, i cant start celery worker. i did make Currency model in python, but celery gives me error:

(venv) kamba@kubuThink:~/www/escrow$ celery worker -A tst.cel.app
Error:
Unable to load celery application.
The module tst was not found.

start ui error

1.linux ui
ml@ubuntu:~/django-cc/testproject$ python3 manage.py runserver 0.0.0.0:8332
Performing system checks...

System check identified no issues (0 silenced).
March 30, 2019 - 08:13:27
Django version 2.1.7, using settings 'testproject.settings'
Starting development server at http://0.0.0.0:8332/
Quit the server with CONTROL-C.
Invalid HTTP_HOST header: '0.0.0.0:8332'. You may need to add '0.0.0.0' to ALLOWED_HOSTS.
Bad Request: /
[30/Mar/2019 08:13:36] "GET / HTTP/1.1" 400 65136
Invalid HTTP_HOST header: '0.0.0.0:8332'. You may need to add '0.0.0.0' to ALLOWED_HOSTS.
Bad Request: /favicon.ico
[30/Mar/2019 08:13:38] "GET /favicon.ico HTTP/1.1" 400 65118
Not Found: /
[30/Mar/2019 08:14:03] "GET / HTTP/1.1" 404 2030
Not Found: /favicon.ico
[30/Mar/2019 08:14:07] "GET /favicon.ico HTTP/1.1" 404 2081
Not Found: /
[30/Mar/2019 08:14:17] "GET / HTTP/1.1" 404 2030
Not Found: /
[30/Mar/2019 08:14:25] "GET / HTTP/1.1" 404 2030
2.
Page not found (404)
Request Method: GET
Request URL: http://localhost:8332/

Using the URLconf defined in testproject.urls, Django tried these URL patterns, in this order:

admin/
^cc/

The empty path didn't match any of these.

You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.