Python
Get Started
Prerequisite and Requirements
$ python --version
Python 3.9.2
Installation
Using Git,
$ git clone https://github.com/ProtoconNet/mitum-py-util.git
$ cd mitum-py-util
$ python setup.py install
$ pip install -r requirements.txt
Make Your First Operation
create-account
by mitum-py-util.Get Available Account
1. pairs of (public key, weight); aka `keys`
- public key has suffix `mpu`
- The range of each weight should be in 1 <= weight <= 100
- If an account have single public key, the account is called 'single-sig account', or it's called 'multi-sig account'
1. threshold
- The range of threshold should be in 1 <= threshold <= 100
- The sum of all weights of the account should be over or equal to threshold
sender
.Create Generator
Generator
.Generator.currency
.Generator
, network id
should be provided.network id
is up to each network.mitum
.from mitumc import Generator
generator = Generator('mitum')
currencyGenerator = generator.currency
Generator
, go to Major Classes and refer to Generator.Create Operation Item
sender
, token
, etc…1. The keys and threshold of the account will be,
- keys(public key, weight): (kpYjRwq6gQrjvzeqQ91MNiCcR9Beb9sD67SuhQ6frPGwmpu, 50), (pWoFhRP3C7ocebSRPxTPfeaJZpnyKpEkxQqi6fAD4SHompu, 50)
- threshold: 100
2. The initial balance of the account will be,
- balance(currency id, amount): (MCC, 10000), (PEN, 20000)
key1 = currencyGenerator.key("kpYjRwq6gQrjvzeqQ91MNiCcR9Beb9sD67SuhQ6frPGwmpu", 50) # key(public key, weight)
key2 = currencyGenerator.key("pWoFhRP3C7ocebSRPxTPfeaJZpnyKpEkxQqi6fAD4SHompu", 50)
keys = currencyGenerator.keys([key1, key2], 100) # keys(keyList, threshold)
amount1 = currencyGenerator.amount('MCC', 1000) # amount(currency, amount)
amount1 = currencyGenerator.amount('PEN', 20000)
amounts = currencyGenerator.amounts([amount]) # amounts(amountList)
createAccountsItem = currencyGenerator.getCreateAccountsItem(keys, amounts)
First, create each key by
Generator.currency.key(public key, weight)
.Second, combine all keys with account threshold by
Generator.currency.keys(key list, threshold)
.Third, create each amount by
Generator.currency.amount(currencyId, amount)
.Forth, combine all amounts by
Generator.currency.amounts(amount list)
.Finally, create an item by
Generator.currency.getCreateAccountsItem(keys, amounts)
- `Keys` created by `keys` can contain up to 10 key pairs.
- `Amounts` created by `amounts` can contain up to 10 amount pairs.
- Moreover, a `fact` can contain multiple items. The number of items in a fact is up to 10, either.
Create Operation Fact
items
, sender
, token
, and fact hash
.token
and fact hash
because they will be filled automatically by SDK.items
and sender
.sender
.1. The account which has been created already.
2. The account which has sufficient balance of currencies in items.
3. The account that you(or owners of the account) know its private keys corresponding account public keys.
senderAddress = "CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca" # sender's account address; replace with your address
createAccountsFact = currencyGenerator.getCreateAccountsFact(senderAddress, [createAccountsItem]) # createCreateAccountsFact(sender's address, item list)
Generator.currency.getCreateAccountsFact(sender's address, item list)
as an array.Create Operation
fact_signs
as a fact signature.fact_signs
should exceed or be equal to the sender
’s threshold.memo
in operation but it is not necessary. You can enter something if you need, but be careful because that memo
also affects the operation hash
.sender
is a single-sig account which means only a single key exists in the sender’s account.sender
is a multi-sig account, you may add multiple signatures to fact_signs
.senderPrivateKey = "KxD8T82nfwsUmQu3iMXENm93YTTatGFp1AYDPqTo5e6ycvY1xNXpmpr" # sender's private key; replace with your private key
createAccounts = generator.getOperation(createAccountsFact, "") # getOperation(fact, memo)
createAccounts.addFactSign(senderPrivateKey); # addFactSign(private key) add fact signature to fact_signs
Generator.createOperation(fact, memo)
for create operations, not Generator.currency.createOperation(fact, memo)
.Create Seal
operation
itself is enough to create an account.signKey = "L1V19fBjhnxNyfuXLWw6Y5mjFSixzdsZP4obkXEERskGQNwSgdm1mpr"
operations = [createAccounts]
seal = generator.getSeal(signKey, operations)
getOperation
, use Generator.getSeal(signer, operation list)
.Support Operations
Model |
Support Operations |
---|---|
Currency |
create account, key updater, transfer |
Currency Extension |
create contract account, withdraw |
Document |
create document, update document, (sign document) |
Feefi |
pool register, pool policy updater, pool deposit, pool withdraw |
NFT |
collection register, collection policy updater, mint, transfer, burn, sign, approve, delegate |
Currency
Create Account
create-account
have been already explained but it’ll be re-introduced in one code-block.The information of the new account: account keys as pairs of (public key, weight), threshold, initial balance as pairs of (currency id, amount).
Sender’s account that has existed already - especially sender’s account address and private keys.
from mitumc import Generator
senderPrivateKey = "L1V19fBjhnxNyfuXLWw6Y5mjFSixzdsZP4obkXEERskGQNwSgdm1mpr"
senderAddress = "5fbQg8K856KfvzPiGhzmBMb6WaL5AsugUnfutgmWECPbmca"
generator = Generator('mitum')
gn = generator.currency
key = gn.key("2177RF13ZZXpdE1wf7wu5f9CHKaA2zSyLW5dk18ExyJ84mpu", 100)
keys = gn.keys([key], 100)
amount = gn.amount('MCC', 100)
amounts = gn.amounts([amount])
createAccountsItem = gn.getCreateAccountsItem(keys, amounts)
createAccountsFact = gn.getCreateAccountsFact(srcAddr, [createAccountsItem])
createAccounts = generator.getOperation(createAccountsFact, "")
createAccounts.addFactSign(srcPriv)
Key Updater
- I have an single sig account with keys: (kpYjRwq6gQrjvzeqQ91MNiCcR9Beb9sD67SuhQ6frPGwmpu, 100), threshold: 100
- But I want to replace keys of the account with keys: (22ndFZw57ax28ydC3ZxzLJMNX9oMSqAfgauyWhC17pxDpmpu, 50), (22wD5RWsRFAr8mHkYmmyUDzKf6VBNgjHcgc3YhKxCvrZDmpu, 50), threshold: 100
- Then you can use key-updater operation to reach the goal!
The account(target) information you want to change the keys - account address and private keys; what private keys need is up to threshold and key weights.
New keys: pairs of (public key, weights) and threshold
Sufficient balance in a currency id to pay a fee.
create-account
and transfer
need item
to create an operation but key-updater
don’t need any item for it.from mitumc import Generator
targetPrivateKey = "KzejtzpPZFdLUXo2hHouamwLoYoPtoffKo5zwoJXsBakKzSvTdbzmpr"
targetAddress = "JDhSSB3CpRjwM8aF2XX23nTpauv9fLhxTjWsQRm9cJ7umca"
generator = Generator('mitum')
gn = generator.currency
key1 = gn.key("22ndFZw57ax28ydC3ZxzLJMNX9oMSqAfgauyWhC17pxDpmpu", 50)
key2 = gn.key("22wD5RWsRFAr8mHkYmmyUDzKf6VBNgjHcgc3YhKxCvrZDmpu", 50)
keys = gn.keys([key1, key2], 100)
keyUpdaterFact = gn.getKeyUpdaterFact(targetAddress, keys, "MCC") # getKeyUpdaterFact(target address, new keys, currency id for fee)
keyUpdater = generator.getOperation(keyUpdaterFact, "")
keyUpdater.addFactSign(targetPrivateKey)
After updating keys of the account, the keys used before become useless. You should sign operation with private keys of new keypairs of the account.
So record new private keysthreshold somewhere else before sending a key-updater operation to the network.
Transfer
Sender’s account information - account address, and private keys
Pairs of (currency id, amount) to transfer
create-account
, you must create item before making fact.1000000 MCC token
15000 PEN token
CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca
from mitumc import Generator
generator = Generator('mitum')
gn = generator.currency
senderPrivateKey = "KzdeJMr8e2fbquuZwr9SEd9e1ZWGmZEj96NuAwHnz7jnfJ7FqHQBmpr"
senderAddress = "2D5vAb2X3Rs6ZKPjVsK6UHcnGxGfUuXDR1ED1hcvUHqsmca"
receiverAddress = "CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca"
amount = gn.amount('MCC', 1000000)
amount = gn.amount('PEN', 15000)
amounts = gn.amounts([amount1, amount2])
transfersItem = gn.getTransfersItem(receiverAddress, amounts) # getTransfersItem(receiver address, amounts)
transfersFact = gn.getTransfersFact(senderAddress, [transfersItem]) # getTransfersFact(sender addrewss, item list)
transfers = generator.getOperation(transfersFact, "")
transfers.addFactSign(senderPrivateKey)
Currency Extension
Create Contract Account
from mitumc import Generator
senderPrivateKey = "L1V19fBjhnxNyfuXLWw6Y5mjFSixzdsZP4obkXEERskGQNwSgdm1mpr"
senderAddress = "5fbQg8K856KfvzPiGhzmBMb6WaL5AsugUnfutgmWECPbmca"
generator = Generator('mitum')
gn = generator.currency
key = gn.key("2177RF13ZZXpdE1wf7wu5f9CHKaA2zSyLW5dk18ExyJ84mpu", 100)
keys = gn.keys([key], 100)
amount = gn.amount('MCC', 100)
amounts = gn.amounts([amount])
createContractAccountsItem = gn.extension.getCreateContractAccountsItem(keys, amounts)
createContractAccountsFact = gn.extension.getCreateContractAccountsFact(srcAddr, [createContractAccountsItem])
createContractAccounts = generator.getOperation(createContractAccountsFact, "")
createContractAccounts.addFactSign(srcPriv)
Withdraw
from mitumc import Generator
generator = Generator('mitum')
gn = generator.currency
senderPrivateKey = "KzdeJMr8e2fbquuZwr9SEd9e1ZWGmZEj96NuAwHnz7jnfJ7FqHQBmpr"
senderAddress = "2D5vAb2X3Rs6ZKPjVsK6UHcnGxGfUuXDR1ED1hcvUHqsmca"
targetAddress = "CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca"
amount = gn.amount('MCC', 1000000)
amount = gn.amount('PEN', 15000)
amounts = gn.amounts([amount1, amount2])
withdrawsItem = gn.extension.getWithdrawsItem(targetAddress, amounts)
withdrawsFact = gn.extension.getWithdrawsFact(senderAddress, [withdrawsItem])
withdraws = generator.getOperation(withdrawsFact, "")
withdraws.addFactSign(senderPrivateKey)
Sign
Has every signature been signed by the private key of the account?
Is the sum of every weight for each signer greater than or equal to the account threshold?
(pub1, 30)
(pub2, 30)
(pub3, 30)
threshold: 50
CASE1: fact signatures signed by pub1’s private key and pub2’s private key
the sum of pub1’s weight and pub2’s weight: 60
the sum of weights = 60 > threshold = 50
So the operation with these two fact signatures is available
CASE2: fact signatures signed by pub2’s private key and pub3’s private key
the sum of pub2’s weight and pub3’s weight: 60
the sum of weights = 60 > threshold = 50
So the operation with these two fact signatures is available
CASE3: fact signatures signed by pub1’s private key and pub3’s private key
the sum of pub1’s weight and pub3’s weight: 60
the sum of weights = 60 > threshold = 50
So the operation with these two fact signatures is available
CASE4: fact signatures signed by pub1’s private key, pub2’s private key, pub3’s private key
the sum of pub1’s weight, pub2’s weight and pub3’s weight: 90
the sum of weights = 90 > threshold = 50
So the operation with these two fact signatures is available
Operation.addFactSign(private key)
)Add Fact Sign to Operation
Private key to sign - it should be that of the sender of the operation.
Operation as JS dictionary object, or external JSON file.
Network ID
Signer
with network id
like Generator
.from mitumc import Signer
networkId = 'mitum'
signKey = 'L1V19fBjhnxNyfuXLWw6Y5mjFSixzdsZP4obkXEERskGQNwSgdm1mpr'
signer = Signer(networkId, signKey)
signed = signer.signOperation('operation.json') # signOperation(filePath)
Operation
object of mitum-py-util. It’s just a dictionary object.Signer
.Details
Get Mitum Keypair
Account Address:
mca
Private Key:
mpr
Public Key:
mpu
Account Address:
9XyYKpjad2MSPxR4wfQHvdWrZnk9f5s2zc9Rkdy2KT1gmca
Private Key:
L11mKUECzKouwvXwh3eyECsCnvQx5REureuujGBjRuYXbMswFkMxmpr
Public Key:
28Hhy6jwkEHx75bNLmG66RQu1LWiZ1vodwRTURtBJhtPWmpu
Just Create New Keypair
getNewKeypair()
.from mitumc.key import getNewKeypair
# get new Keypair
kp = getNewKeypair() # returns BTCKeyPair
kp.privateKey # KzafpyGojcN44yme25UMGvZvKWdMuFv1SwEhsZn8iF8szUz16jskmpr
kp.publicKey # 24TbbrNYVngpPEdq6Zc5rD1PQSTGQpqwabB9nVmmonXjqmpu
Get Keypair From Your Private Key
from mitumc.key import getKeypairFromPrivateKey
# get Keypair from your private key
pkp = getKeypairFromPrivateKey("L2ddEkdgYVBkhtdN8HVXLZk5eAcdqXxecd17FDTobVeFfZNPk2ZDmpr")
Get Keypair From Your Seed
from mitumc.key import getKeypairFromSeed
# get Keypair from your seed
skp = getKeypairFromSeed("Thisisaseedforthisexample.len(seed)>=36.")
Get Account Address with Keys
key1: (vmk1iprMrs8V1NkA9DsSL3XQNnUW9SmFL5RCVJC24oFYmpu, 40)
key2: (29BQ8gcVfJd5hPZCKj335WSe4cyDe7TGrjam7fTrkYNunmpu, 30)
key3: (uJKiGLBeXF3BdaDMzKSqJ4g7L5kAukJJtW3uuMaP1NLumpu, 30)
threshold: 100
from mitumc import Generator
gn = Generator('mitum').currency
pub1 = "vmk1iprMrs8V1NkA9DsSL3XQNnUW9SmFL5RCVJC24oFYmpu"
pub2 = "29BQ8gcVfJd5hPZCKj335WSe4cyDe7TGrjam7fTrkYNunmpu"
pub3 = "uJKiGLBeXF3BdaDMzKSqJ4g7L5kAukJJtW3uuMaP1NLumpu"
key1 = gn.key(pub1, 40)
key2 = gn.key(pub2, 30)
key3 = gn.key(pub3, 30)
keys = gn.keys([key1, key2, key3], 100)
address = keys.address # your address
Major Classes
Generator
Generator
is the class that helps generate operations for Mitum Currency.Generator
, network id
must be set.For Mitum Currency, use
Generator.currency
.For Mitum Currency Extension, use
Generator.currency.extension
.For Mitum Document, use
Generator.document
.For Mitum Feefi, use
Generator.feefi
.For Mitum NFT, use
Generator.nft
.
from mitumc import Generator
generator = Generator('mitum')
currencyGenerator = generator.currency
extensionGenerator = generator.currency.extension
documentGenerator = generator.document
feefiGenerator = generator.feefi
nftGenerator = generator.nft
Generator
provides are,# For Mitum Currency
Generator.currency.key(key, weight) # 1 <= $weight <= 100
Generator.currency.amount(currencyId, amount)
Generator.currency.keys(keys, threshold) # 1 <= $threshold <= 100
Generator.currency.amounts(amounts)
Generator.currency.getCreateAccountsItem(keys, amounts)
Generator.currency.getTransfersItem(receiver, amounts)
Generator.currency.getCreateAccountsFact(sender, items)
Generator.currency.getKeyUpdaterFact(target, currencyId, keys)
Generator.currency.getTransfersFact(sender, items)
# For Mitum Currency Extension
Generator.currency.extension.getCreateContractAccountsItem(keys, amounts)
Generator.currency.extension.getWithdrawsItem(target, amounts)
Generator.currency.extension.getCreateContractAccountsFact(sender, items)
Generator.currency.extension.getWithdrawsFact(sender, items)
# For Mitum Document
Generator.document.getCreateDocumentsItem(document, currencyId)
Generator.document.getUpdateDocumentsItem(document, currencyId)
Generator.document.getCreateDocumentsFact(sender, items)
Generator.document.getUpdateDocumentsFact(sender, items)
# For Blocksign
Generator.document.blocksign.user(address, signcode, signed)
Generator.document.blocksign.document(documentId, owner, fileHash, creator, title, size, signers)
Generator.document.blocksign.getSignDocumentsItem(documentId, owner, currencyId)
Generator.document.blocksign.getSignDocumentsFact(sender, items)
# For Blockcity
Generator.document.blockcity.candidate(address, nickname, manifest, count)
Generator.document.blockcity.userStatistics(hp, strength, agility, dexterity, charisma intelligence, vital)
Generator.document.blockcity.userDocument(documentId, owner, gold, bankGold, userStatistics)
Generator.document.blockcity.landDocument(documentId, owner, address, area, renter, account, rentDate, period)
Generator.document.blockcity.voteDocument(documentId, owner, round, endTime, candidates, bossName, account, office)
Generator.document.blockcity.historyDocument(documentId, owner, name, account, date, usage, application)
# For Mitum Feefi
Generator.feefi.getPoolRegisterFact(sender, target, initFee, incomeCid, outgoCid, cid)
Generator.feefi.getPoolPolicyUpdaterFact(sender, target, fee, incomeCid, outgoCid, cid)
Generator.feefi.getPoolDepositsFact(sender, pool, incomeCid, outgoCid, amount)
Generator.feefi.getPoolWithdrawFact(sender, pool, incomeCid, outgoCid, amounts)
# For Mitum NFT
Generator.nft.signer(account, share, signed)
Generator.nft.signers(total, _signers)
Generator.nft.collectionRegisterForm(target, symbol, name, royalty, uri, whites)
Generator.nft.collectionPolicy(name, royalty, uri, whites)
Generator.nft.mintForm(hash, uri, creators, copyrighters)
Generator.nft.getMintItem(collection, form, cid)
Generator.nft.getTransferItem(receiver, nid, cid)
Generator.nft.getBurnItem(nid, cid)
Generator.nft.getApproveItem(approved, nid, cid)
Generator.nft.getDelegateItem(collection, agent, mode, cid) # mode: ["allow" || "cancel"]
Generator.nft.getSignItem(qualification, nid, cid) # qualification: ["creator" || "copyrighter"]
Generator.nft.getCollectionRegisgerFact(sender, form, cid)
Generator.nft.getCollectioPolicyUpdaterFact(sender, collection, policy, cid)
Generator.nft.getMintFact(sender, items)
Generator.nft.getTransferFact(sender, items)
Generator.nft.getBurnFact(sender, items)
Generator.nft.getApproveFact(sender, items)
Generator.nft.getDelegateFact(sender, items)
Generator.nft.getSignFact(sender, items)
# Common
Generator.getOperation(fact, memo)
Generator.getSeal(signKey, operations)
Signer
Signer
is the class for adding new fact signature to already create operations.Generator
, network id
must be set.Signer
provides only one method, that is,Signer.signOperation(operation)
Signer
, go back to Make Your First Operation - Sign.JSONParser
Operation
to file or to print it in JSON format, you don’t need to use JSONParser
of mitum-py-util.from mitumc import JSONParser
# ... omitted
# ... create operations
# ... refer to above `Make Your First Operation`
# ... suppose you have already made operations - createAccount, keyUpdater, transfer and a seal - seal
JSONParser.toString(createAccount.dict()) # print operation createAccount in JSON
JSONParser.toString(keyUpdater.dict()) # print operation keyUpdater in JSON
JSONParser.toString(transfer.dict()) # print operation transfer in JSON
JSONParser.toString(seal) # print seal seal in JSON
JSONParser.toFile(createAccount.dict(), 'createAccount.json') # toFile(dict object, file path)
JSONParser.toFile(keyUpdater.dict(), 'keyUpdater.json')
JSONParser.toFile(transfer.dict(), 'transfer.json')
JSONParser.toFile(seal, 'seal.json')