Skip to content

Commit

Permalink
Merge pull request #32 from StellarCN/dev
Browse files Browse the repository at this point in the history
rewrite builder and fix bugs. support new manage_data operation.
  • Loading branch information
manran committed Jun 15, 2016
2 parents 9c6029a + b36f627 commit a4930eb
Show file tree
Hide file tree
Showing 31 changed files with 6,127 additions and 5,713 deletions.
152 changes: 151 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,158 @@

[![Build Status](https://travis-ci.org/StellarCN/py-stellar-base.svg)](https://travis-ci.org/StellarCN/py-stellar-base)

# install
`pip install stellar-base.whl`
pip install stellar-base.whl


# usage

## Create a Stellar keypair?
```python
from stellar_base.keypair import Keypair
kp = Keypair.random()
```
**or**
```python
from __future__ import unicode_literals
master = u'中文'.encode('utf-8')
kp = Keypair.deterministic(master)
```
then we can get key/secret from random:

publickey = kp.address().decode()
secret = kp.seed().decode()


let's start with my favourite keypair in TESTNET.

publickey = 'GDVDKQFP665JAO7A2LSHNLQIUNYNAAIGJ6FYJVMG4DT3YJQQJSRBLQDG'
secret = 'SCVLSUGYEAUC4MVWJORB63JBMY2CEX6ATTJ5MXTENGD3IELUQF4F6HUB'




##Account

### base info
```python
from stellar_base.account import Account
publickey = 'GDVDKQFP665JAO7A2LSHNLQIUNYNAAIGJ6FYJVMG4DT3YJQQJSRBLQDG'
account = Account(account=publickey)
# account = Account(account=publickey,network='public') for livenet.
account.get()
```
now you can check account.`balance` ,`sequence` ,`flags` ,`signers`, `manage_data` etc.

### check payments
`account.payments()`will give you latest 10 payments.

there are three params using for query : `limit`, `order` and `cursor`(paging_token). and the default value for them is 10, asc and 0

so need check payments after a specific cursor?try `account.payments(cursor='4225135422738433',limit=20,order=asc)`

Horizon have SSE support for push data ,if you really want, use like this: `account.payment(sse=True,cursor='4225135422738433')`

###like check payments, you can check `transactions`,`effects`,`offers`,and `operations`.
remember , offers have not SSE support.


## Transaction Builder

### create a Transaction Builder at first

from stellar_base.builder import Builder
builder = Builder(secret=secret)
# builder = Builder(secret=secret, network='public') for LIVENET.

### operations
how about make a tips to bob?

bob_address = 'GABCDEFGHIJKLMNOPQRSTUVW'
builder.append_payment_op(bob_address,'100','XLM')
or

CNY_ISSUER='GCNYISSUERABCDEFGHIJKLMNOPQ'
builder.append_payment_op(bob_address,'100','CNY',CNY_ISSUER)

### then maybe need carry a message

builder.add_text_memo('Have a nice day!') # string length <= 28 bytes

### sign & sumbit

builder.sign()
builder.sumbit()

Done.

### sign a muilt-sig transaction

you get a xdr string (or transaction envlope xdr)from a friend or partner ,which decribe a multi-sig transaction .
They need you sign on it too.

builder = Builder(secret=secret)
# or builder = Builder(secret=secret, network='public') for LIVENET.
builder.import_from_xdr(xdr_string)
builder.sign()
builder.to_xdr() # generate new xdr string
# or builder.submit() #submit to stellar network



## A payment example without wrapper


from stellar_base.keypair import Keypair
from stellar_base.asset import Asset
from stellar_base.operation import Payment
from stellar_base.transaction import Transaction
from stellar_base.transaction_envelope import TransactionEnvelope as Te
from stellar_base.memo import TextMemo
from stellar_base.horizon import horizon_testnet, horizon_pubic

alice_seed = 'SAZJ3EDATROKTNNN4WZBZPRC34AN5WR43VEHAFKT5D66UEZTKDNKUHOK'
bob_address = 'GDLP3SP4WP72L4BAJWZUDZ6SAYE4NAWILT5WQDS7RWC4XCUNUQDRB2A4'
CNY_ISSUER = 'GDVDKQFP665JAO7A2LSHNLQIUNYNAAIGJ6FYJVMG4DT3YJQQJSRBLQDG'
amount = '100'

Alice = Keypair.from_seed(alice_seed)
horizon = horizon_testnet()

asset = Asset('CNY', CNY_ISSUER)
# create op
op = Payment({
# 'source' : Alice.address().decode(),
'destination': bob_address,
'asset': asset,
'amount': amount
})
# create a memo
msg = TextMemo('Have a nice day!')

# get sequence of Alice
sequence = horizon.account(Alice.address()).get('sequence')

# construct Tx
tx = Transaction(
source=Alice.address().decode(),
opts={
'sequence': sequence,
# 'timeBounds': [],
'memo': msg,
# 'fee': 100,
'operations': [
op,
],
},
)


# build envelope
envelope = Te(tx=tx, opts={"network_id": "TESTNET"})
# sign
envelope.sign(Alice)
# submit
xdr = envelope.xdr()
horizon.submit(xdr)

14 changes: 8 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# coding: utf-8
import codecs

from setuptools import setup, find_packages

with open('README.md') as file:
with codecs.open('README.md', encoding='utf-8') as file:
long_description = file.read()

setup(
name='stellar-base',
version='0.0.1',
version='0.1.0',
description='stellar-base in python.',
long_description=long_description,
url='http://github.com/stellarCN/py-stellar-base/',
Expand All @@ -21,14 +24,13 @@
'License :: OSI Approved :: Apache License',
'Operating System :: OS Independent',
'Programming Language :: Python',
# 'Programming Language :: Python :: 2',
# 'Programming Language :: Python :: 2.6',
# 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Software Development :: Libraries :: Python Modules',
],
install_requires=[
'ed25519', 'crc16', 'requests', 'SSEClient', 'base58'
'ed25519', 'crc16', 'requests', 'SSEClient', 'numpy'
]
)
87 changes: 87 additions & 0 deletions stellar_base/address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# encoding: utf-8

import requests

from .horizon import Horizon
from .keypair import Keypair
from .utils import AccountNotExistError, NotValidParamError
from .horizon import HORIZON_LIVE, HORIZON_TEST


class Address(object):
""" check address info from stellar network using horizon rest api or SSE.
"""

def __init__(self, address=None, secret=None, network='TESTNET', horizon=None):
if address is None and secret is None:
raise Exception('oops,need a stellar address or secret')
if address is None and secret is not None:
self.address = Keypair.from_seed(secret).address().decode()
else:
self.address = address
self.secret = secret

if network.upper() != 'PUBLIC':
self.network = 'TESTNET'
else:
self.network = 'PUBLIC'
if horizon:
self.horizon = Horizon(horizon)
elif network.upper() == 'PUBLIC':
self.horizon = Horizon(HORIZON_LIVE)
else:
self.horizon = Horizon(HORIZON_TEST)

self.sequence = None
self.balances = None
self.paging_token = None
self.thresholds = None
self.flags = None
self.signers = None
self.data = None

def get(self):
try:
acc = self.horizon.account(self.address)
if acc.get('sequence'):
self.sequence = acc.get('sequence')
self.balances = acc.get('balances')
self.paging_token = acc.get('paging_token')
self.thresholds = acc.get('thresholds')
self.flags = acc.get('flags')
self.signers = acc.get('signers')
self.data = acc.get('data')
elif acc.get('status') == 404:
raise AccountNotExistError(acc.get('title'))
else:
raise Exception(acc.get('detail'))
except requests.ConnectionError:
raise Exception('network problem')

def payments(self, sse=False, **kwargs):
check_params(kwargs)
return self.horizon.account_payments(self.address, params=kwargs, sse=sse)

def offers(self, **kwargs):
check_params(kwargs)
return self.horizon.account_offers(self.address, params=kwargs)

def transactions(self, sse=False, **kwargs):
check_params(kwargs)
return self.horizon.account_transactions(self.address, params=kwargs, sse=sse)

def operations(self, sse=False, **kwargs):
check_params(kwargs)
return self.horizon.account_operations(self.address, params=kwargs, sse=sse)

def effects(self, sse=False, **kwargs):
check_params(kwargs)
return self.horizon.account_effects(self.address, params=kwargs, sse=sse)


def check_params(data):
params = {'cursor', 'limit', 'order'}
for key in data.keys():
if key not in params:
raise NotValidParamError('not valid params')
8 changes: 7 additions & 1 deletion stellar_base/asset.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# coding: utf-8

from .utils import XdrLengthError, account_xdr_object, encode_check
from .stellarxdr import StellarXDR_pack as Xdr
from .stellarxdr import Xdr
import base64


class Asset(object):
Expand Down Expand Up @@ -51,6 +52,11 @@ def to_xdr_object(self):
xdr_type = Xdr.const.ASSET_TYPE_CREDIT_ALPHANUM12
return Xdr.types.Asset(type=xdr_type, alphaNum12=x)

def xdr(self):
asset = Xdr.StellarXDRPacker()
asset.pack_Asset(self.to_xdr_object())
return base64.b64encode(asset.get_buffer())

@classmethod
def from_xdr_object(cls, asset_xdr_object):
if asset_xdr_object.type == Xdr.const.ASSET_TYPE_NATIVE:
Expand Down
Loading

0 comments on commit a4930eb

Please sign in to comment.