Python library for the Factom Asset Token standard. Currently supports FAT-0 and FAT-1 token standards.
The easiest way to install is with pip
or pipenv
from PyPi:
pipenv install fat
You can also clone the repo and build it from source. The recommended way to do this is with pipenv
:
git clone git@github.com:samuelvanderwaal/fat-py.git
cd fat-py
Install requirements from the Pipfile:
pipenv install
Activate the virtual environment:
pipenv shell
See pipenv
's documentation for more usage details.
Issue a new token:
from fat.fat0 import Issuance
from factom import Factomd
factomd = Factomd()
issuance = Issuance(
token_id="mytoken",
issuer_id="8888...",
supply=-1,
symbol="tkn1",
ec_address="EC3...",
ec_priv_key="ES3...",
server_priv_key="sk1..."
)
issuance.issue_token(factomd)
Build and submit a token transaction:
from fat.fat0 import Transaction
from fat import FATd
fatd = FATd()
address1 = "FA2gCmih3PaSYRVMt1jLkdG4Xpo2koebUpQ6FpRRnqw5FfTSN2vW"
private_fct_key1 = "Fs..."
address2 = "FA3j68XNwKwvHXV2TKndxPpyCK3KrWTDyyfxzi8LwuM5XRuEmhy6"
chain_id = "a9d7791caffd852f8e3710e3c38f1ad1b056d4ecb2d4d54216581dfd0dac8edd"
tx1 = Transaction()
tx1.add_input(address1, 100)
tx1.add_output(address2, 100)
tx1.add_signer(private_fct_key1)
tx1.set_chain_id(chain_id)
tx1.sign()
fatd.submit_transaction(tx1)
The two main ways to use this library are the Issuance and Transaction classes. In addition, the library exposes all the fatd RPC methods which can be accessed through the FATd class.
The Issuance class supports object initialization through multiple methods:
Individual property assignment:
issuance = Issuance()
issuance.token_id = "mytoken"
issuance.issuer_id = "888888a37cbf303c0bfc8d0cc7e77885c42000b757bd4d9e659de994477a0904"
issuance.supply = -1
issuance.symbol = "tkn1"
issuance.ec_address = "EC3cQ1QnsE5rKWR1B5mzVHdTkAReK5kJwaQn5meXzU9wANyk7Aej"
issuance.ec_priv_key = "ES..."
issuance.server_priv_key = "sk1..."
Passing all values as part of the constructor:
issuance = Issuance(
token_id="mytoken",
issuer_id="8888...",
supply=-1,
symbol="tkn1",
ec_address="EC3...",
ec_priv_key="ES3...",
server_priv_key="sk1..."
)
Once the issuance object has all the required values, the issue_token()
method can be used to perform all the necessary factomd
calls to issue and initialize a new token.
from fat.fat0 import Issuance
from factom import Factomd
factomd = Factomd()
issuance = Issuance(
token_id="mytoken",
issuer_id="8888...",
supply=-1,
symbol="tkn1",
ec_address="EC3...",
ec_priv_key="ES3...",
server_priv_key="sk1..."
)
issuance.issue_token(factomd)
Issuance supports both the Python native str
type and key objects from the factom_keys
library for EC and server ID keys. When strings are passed to it, internally it uses the factom_keys
library to validate the key and address values.
...
from factom_keys.ec import ECAddress
ec_address1 = ECAddress(key_string="EC3cQ1QnsE5rKWR1B5mzVHdTkAReK5kJwaQn5meXzU9wANyk7Aej")
ec_address2 = "EC3cQ1QnsE5rKWR1B5mzVHdTkAReK5kJwaQn5meXzU9wANyk7Aej"
issuance = Issuance()
...
issuance.ec_address = ec_address1
# or
issuance.ec_address = ec_address2
FAT-0 and FAT-1 issuance has the same usage, just import the specific Issuance class needed. Use import aliases if both are required simultaneously:
from fat.fat0 import Issuance as FAT0Issuance
from fat.fat1 import Issuance as FAT1Issuance
The Transaction class also supports multiple methods of initialization:
Passing all values through the constructor:
tx1 = Transaction(
inputs={"FA...": 100, "FA3...": 50},
outputs={"FA3Z...": 150},
chain_id="a9d7791caffd852f8e3710e3c38f1ad1b056d4ecb2d4d54216581dfd0dac8edd",
signers=["FS...", "Fs..."]
)
tx1.sign()
Adding values individually:
tx1 = Transaction()
tx1.add_input(coinbase_address, 100)
tx1.add_output(address1, 50)
tx1.add_output(address2, 50)
tx1.add_signer(issuer_signer)
tx1.set_chain_id(chain_id)
tx1.sign()
Builder method:
tx1 = Transaction()
(
tx1.add_input(coinbase_address, 100)
.add_output(address1, 50)
.add_output(address2, 50)
.add_signer(issuer_signer)
.set_chain_id(chain_id)
.sign()
)
Transaction supports both the native Python str
type and key objects from the factom_keys
library for Factoid private keys, Factoid addresses and for server ID private keys.
...
from factom_keys.ec import FactoidAddress, FactoidPrivateKey
from factom_keys.serverid import ServerIDPrivateKey
address1 = FactoidAddress(address_string="FA2gCmih3PaSYRVMt1jLkdG4Xpo2koebUpQ6FpRRnqw5FfTSN2vW")
address2 = "FA2gCmih3PaSYRVMt1jLkdG4Xpo2koebUpQ6FpRRnqw5FfTSN2vW"
fct_priv_key1 = FactoidPrivateKey(key_string="Fs...")
fct_priv_key2 = "Fs..."
tx = Transaction()
tx.add_input(address1, 50)
tx.add_signer(fct_priv_key1)
# or
tx.add_input(address2, 50)
tx.add_signer(fct_priv_key2)
Once a transaction has been built and signed, it can be passed to the submit_transaction()
method on FATd for submission to the blockchain.
FAT-0:
from fat.fat0 import Transaction
from fat import FATd
fatd = FATd()
address1 = "FA2gCmih3PaSYRVMt1jLkdG4Xpo2koebUpQ6FpRRnqw5FfTSN2vW"
private_fct_key1 = "Fs..."
address2 = "FA3j68XNwKwvHXV2TKndxPpyCK3KrWTDyyfxzi8LwuM5XRuEmhy6"
chain_id = "a9d7791caffd852f8e3710e3c38f1ad1b056d4ecb2d4d54216581dfd0dac8edd"
tx1 = Transaction()
tx1.add_input(address1, 100)
tx1.add_output(address2, 100)
tx1.add_signer(private_fct_key1)
tx1.set_chain_id(chain_id)
tx1.sign()
fatd.submit_transaction(tx1)
FAT-1:
from fat.fat1 import Transaction
from fat import FATd
fatd = FATd()
address1 = "FA2gCmih3PaSYRVMt1jLkdG4Xpo2koebUpQ6FpRRnqw5FfTSN2vW"
private_fct_key1 = "Fs..."
address2 = "FA3j68XNwKwvHXV2TKndxPpyCK3KrWTDyyfxzi8LwuM5XRuEmhy6"
chain_id = "a9d7791caffd852f8e3710e3c38f1ad1b056d4ecb2d4d54216581dfd0dac8edd"
tx1 = Transaction()
tx1.add_input(address1, [1,3])
tx1.add_output(address2, [1,3])
tx1.add_signer(private_fct_key1)
tx1.set_chain_id(chain_id)
tx1.sign()
fatd.submit_transaction(tx1)
All FATd RPC and Daemon methods are exposed via the FATd class:
from fat import FATd
fatd= FATd()
chain_id = "a9d7791caffd852f8e3710e3c38f1ad1b056d4ecb2d4d54216581dfd0dac8edd"
address = "FA2gCmih3PaSYRVMt1jLkdG4Xpo2koebUpQ6FpRRnqw5FfTSN2vW"
fatd.get_issuance(chain_id=chain_id)
fad.get_balance(address, chain_id=chain_id)
fatd.get_daemon_properties()