Javascript
Get Started
Prerequisite and Requirements
npm
or yarn
should be installed.$ npm --version
v16.10.0
$ node --version
7.24.0
Installation
Using npm,
$ npm install mitumc
Using yarn,
$ yarn add mitumc
Using Git,
$ git clone https://github.com/ProtoconNet/mitum-js-util.git
$ cd mitum-js-util
$ sudo npm install -g
$ cd YOUR_PACKAGE
$ npm link mitumc
Make Your First Operation
create-account
by mitum-js-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
.import { Generator } from 'mitumc'
const generator = new Generator('mitum')
const 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)
const key1 = currencyGenerator.key("kpYjRwq6gQrjvzeqQ91MNiCcR9Beb9sD67SuhQ6frPGwmpu", 50) // key(pub, weight)
const key2 = currencyGenerator.key("pWoFhRP3C7ocebSRPxTPfeaJZpnyKpEkxQqi6fAD4SHompu", 50) // key(pub, weight)
const keys = currencyGenerator.keys([key1, key2], 100) // createKeys([key1, key2], threshold)
const amount1 = currencyGenerator.amount("MCC", "10000") // amount(currencyId, amount)
const amount2 = currencyGenerator.amount("PEN", "20000") // amount(currencyId, amount)
const amounts = currencyGenerator.amounts([amount1, amount2]); // createAmounts([amount1, amount2])
const createAccountsItem = currencyGenerator.getCreateAccountsItem(keys, amounts); // createCreateAccountsItem(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.
const senderAddress = "CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca" // sender's account address; replace with your address
const createAccountsFact = currencyGenerator.getCreateAccountsFact(senderAddress, [createAccountsItem]) // getCreateAccountsFact(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
.const senderPrivateKey = "KxD8T82nfwsUmQu3iMXENm93YTTatGFp1AYDPqTo5e6ycvY1xNXpmpr" // sender's private key; replace with your private key
const createAccounts = generator.getOperation(createAccountsFact, "") // getOperation(fact, memo)
createAccounts.addSign(senderPrivateKey); // addSign(private key) add fact signature to fact_signs
Generator.getOperation(fact, memo)
for create operations, not Generator.currency.getOperation(fact, memo)
.Create Seal
operation
itself is enough to create an account.const anyPrivateKey = "KyK7aMWCbMtCJcneyBZXGG6Dpy2jLRYfx3qp7kxXJjLFnppRYt7wmpr"
const operations = [createAccounts]
const seal = generator.getSeal(anyPrivateKey, 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.
import { Generator } from 'mitumc'
const generator = new Generator('mitum')
const currencyGenerator = generator.currency
const key1 = currencyGenerator.key("kpYjRwq6gQrjvzeqQ91MNiCcR9Beb9sD67SuhQ6frPGwmpu", 50)
const key2 = currencyGenerator.key("pWoFhRP3C7ocebSRPxTPfeaJZpnyKpEkxQqi6fAD4SHompu", 50)
const keys = currencyGenerator.keys([key1, key2], 100)
const amount1 = currencyGenerator.amount("MCC", "10000")
const amount2 = currencyGenerator.amount("PEN", "20000")
const amounts = currencyGenerator.amounts([amount1, amount2]);
const createAccountsItem = currencyGenerator.getCreateAccountsItem(keys, amounts);
const senderAddress = "CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca"
const createAccountsFact = currencyGenerator.getCreateAccountsFact(senderAddress, [createAccountsItem])
const senderPrivateKey = "KxD8T82nfwsUmQu3iMXENm93YTTatGFp1AYDPqTo5e6ycvY1xNXpmpr"
const createAccounts = generator.getOperation(createAccountsFact, "")
createAccounts.addSign(senderPrivateKey);
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.import { Generator } from 'mitumc'
const generator = new Generator('mitum')
const currencyGenerator = generator.currency
const targetAddress = "JDhSSB3CpRjwM8aF2XX23nTpauv9fLhxTjWsQRm9cJ7umca"
const targetPrivateKey = "KzejtzpPZFdLUXo2hHouamwLoYoPtoffKo5zwoJXsBakKzSvTdbzmpr"
const newPub1 = currencyGenerator.key("22ndFZw57ax28ydC3ZxzLJMNX9oMSqAfgauyWhC17pxDpmpu", 100)
const newPub2 = currencyGenerator.key("22wD5RWsRFAr8mHkYmmyUDzKf6VBNgjHcgc3YhKxCvrZDmpu", 100)
const newKeys = currencyGenerator.keys([newPub1, newPub2], 100)
const keyUpdaterFact = currencyGenerator.getKeyUpdaterFact(targetAddress, "MCC", newKeys) // getKeyUpdaterFact(target address, currency for fee, new keys)
const keyUpdater = generator.getOperation(keyUpdaterFact, "")
keyUpdater.addSign(targetPrivateKey) // only one signature since the account is single-sig
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
import { Generator } from 'mitumc'
const generator = new Generator('mitum')
const currencyGenerator = generator.currency
const senderPrivateKey = "KzdeJMr8e2fbquuZwr9SEd9e1ZWGmZEj96NuAwHnz7jnfJ7FqHQBmpr"
const senderAddress = "2D5vAb2X3Rs6ZKPjVsK6UHcnGxGfUuXDR1ED1hcvUHqsmca"
const receiverAddress = "CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca"
const amount1 = currencyGenerator.amount("MCC", "1000000")
const amount2 = currencyGenerator.amount("PEN", "15000")
const amounts = currencyGenerator.amounts([amount1, amount2])
const transfersItem = currencyGenerator.getTransfersItem(receiverAddress, amounts) // getTransfersItem(receiver address, amounts)
const transfersFact = currencyGenerator.getTransfersFact(senderAddress, [transfersItem]) // getTransfersFact(sender address, item list)
const transfers = generator.getOperation(transfersFact, "")
transfers.addSign(senderPrivateKey) // suppose sender is single-sig
Currency Extension
Create Contract Account
import { Generator } from 'mitumc'
const networkId = 'mitum'
const generator = new Generator(networkId)
const currencyGenerator = generator.currency
const key1 = currencyGenerator.key("kpYjRwq6gQrjvzeqQ91MNiCcR9Beb9sD67SuhQ6frPGwmpu", 50)
const key2 = currencyGenerator.key("pWoFhRP3C7ocebSRPxTPfeaJZpnyKpEkxQqi6fAD4SHompu", 50)
const keys = currencyGenerator.keys([key1, key2], 100)
const amount1 = currencyGenerator.amount("MCC", "10000")
const amount2 = currencyGenerator.amount("PEN", "20000")
const amounts = currencyGenerator.amounts([amount1, amount2]);
const createAccountsItem = currencyGenerator.extension.getCreateContractAccountsItem(keys, amounts);
const senderAddress = "CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca"
const createAccountsFact = currencyGenerator.extension.getCreateContractAccountsFact(senderAddress, [createAccountsItem])
const senderPrivateKey = "KxD8T82nfwsUmQu3iMXENm93YTTatGFp1AYDPqTo5e6ycvY1xNXpmpr"
const createContractAccounts = generator.getOperation(createContractAccounts, "")
createContractAccounts.addSign(senderPrivateKey);
Withdraw
import { Generator } from 'mitumc';
const generator = new Generator('mitum')
const currencyGenerator = generator.currency
const amount = currencyGenerator.amount("MCC", "100");
const amounts = currencyGenerator.amounts([amount]);
const targetAddress = "2D5vAb2X3Rs6ZKPjVsK6UHcnGxGfUuXDR1ED1hcvUHqsmca";
const withdrawsItem = currencyGenerator.extension.getWithdrawsItem(targetAddress, amounts);
const senderAddress = "CY1pkxsqQK6XMbnK4ssDNbDR2K7mitSwdS27DwBjd3Gcmca";
const withdrawsFact = currencyGenerator.extension.getWithdrawsFact(senderAddress, [withdrawsItem])
const senderPrivateKey = "KxD8T82nfwsUmQu3iMXENm93YTTatGFp1AYDPqTo5e6ycvY1xNXpmpr";
const withdraws = generator.getOperation(withdrawsFact, "")
withdraws.addSign(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.addSign(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
.import { Signer } from 'mitumc'
const networkId = "mitum"
const signKey = "L3CQHoKPJnK61LZhvvvfRouvAjVVabx2RQXHHhPHbBssgcewjgNimpr"
const signer = new Signer(networkId, signKey)
const operationJsonPath = "../createAccount.json" // it's an example; replace with your operation path
const operationObject = createAccount.dict() // createAccount is the operation created by Generator.createOperation
const signedFromPath = signer.signOperation(operationJsonPath)
const signedFromObject = signer.signOperation(operationObject)
signedFromPath
and signedFromObject
results in operation with the same fact signatures.Operation
object of mitum-js-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()
.import { getNewKeypair } from 'mitumc'
const kp = getNewKeypair() // returns Keypair
kp.getPrivateKey() // KzF4ia7G8in3hm7TzSr5k7cNtx46BdEFTzVdnh82vAopqxJG8rHompr
kp.getPublicKey() // 25jrVNpKr59bYxrWH8eTkbG1iQ8hjvSFKVpfCcDT8oFf8mpu
kp.getRawPrivateKey() // KzF4ia7G8in3hm7TzSr5k7cNtx46BdEFTzVdnh82vAopqxJG8rHo
kp.getRawPublicKey() // 25jrVNpKr59bYxrWH8eTkbG1iQ8hjvSFKVpfCcDT8oFf8mpu
Get Keypair From Your Private Key
import { getKeypairFromPrivateKey } from 'mitumc'
const kp = getKeypairFromPrivateKey("Kz5b6UMxnRvgL91UvNMuRoTfUEAUw7htW2z4kV2PEZUCVPFmdbXimpr")
kp.getPrivateKey() // Kz5b6UMxnRvgL91UvNMuRoTfUEAUw7htW2z4kV2PEZUCVPFmdbXimpr
kp.getPublicKey() // 239uA6z7MxkZfwp5zYKZ6eBbRWk38AvxeyzfHGQM8o2H8mpu
kp.getRawPrivateKey() // Kz5b6UMxnRvgL91UvNMuRoTfUEAUw7htW2z4kV2PEZUCVPFmdbXi
kp.getRawPublicKey() //239uA6z7MxkZfwp5zYKZ6eBbRWk38AvxeyzfHGQM8o2H8
Get Keypair from your seed
import { getKeypairFromSeed } from 'mitumc'
const kp = getKeypairFromSeed("Thelengthofseedshouldbelongerthan36characters.Thisisaseedfortheexample.")
kp.getPrivateKey() // KynL1wNZjuXvZDboEugU4sWKZ6ck5GTMqtv6eod8Q7C4NaB4kfZPmpr
kp.getPublicKey() // fyLbH5cUwNTihaW2YkJkAzeoLvTNTzf98r8dtCkjXbuqmpu
kp.getRawPrivateKey() // KynL1wNZjuXvZDboEugU4sWKZ6ck5GTMqtv6eod8Q7C4NaB4kfZP
kp.getRawPublicKey() // fyLbH5cUwNTihaW2YkJkAzeoLvTNTzf98r8dtCkjXbuq
Get Account Address with Keys
key1: (vmk1iprMrs8V1NkA9DsSL3XQNnUW9SmFL5RCVJC24oFYmpu, 40)
key2: (29BQ8gcVfJd5hPZCKj335WSe4cyDe7TGrjam7fTrkYNunmpu, 30)
key3: (uJKiGLBeXF3BdaDMzKSqJ4g7L5kAukJJtW3uuMaP1NLumpu, 30)
threshold: 100
import { Generator } from 'mitumc'
const gn = new Generator('mitum').currency
const key1 = gn.key("vmk1iprMrs8V1NkA9DsSL3XQNnUW9SmFL5RCVJC24oFYmpu", 40)
const key2 = gn.key("29BQ8gcVfJd5hPZCKj335WSe4cyDe7TGrjam7fTrkYNunmpu", 30)
const key3 = gn.key("uJKiGLBeXF3BdaDMzKSqJ4g7L5kAukJJtW3uuMaP1NLumpu", 30)
const keys = gn.keys([key1, key2, key3], 100)
const address = keys.address // this is what you want to get!
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
.
import { Generator } from 'mitumc'
const networkId = 'mitum'
const generator = new Generator(networkId)
const currencyGenerator = generator.currency
const extensionGenerator = generator.currency.extension
const documentGenerator = generator.document
const feefiGenerator = generator.feefi
const nftGenerator = generator.nft
Generator
provides are,/* For Mitum Currency */
Generator.currency.key(key, weight) // 1 <= $weight <= 100
Generator.currency.amount(currencyId, amount) // typeof $amount === "string"
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 Feefi */
Generator.feefi.getPoolRegisterFact(sender, target, initFee, incomeCid, outlayCid, currencyId)
Generator.feefi.getPoolPolicyUpdaterFact(sender, target, fee, incomeCid, outlayCid, currencyId)
Generator.feefi.getPoolDepositsFact(sender, pool, incomeCid, outlayCid, amount)
Generator.feefi.getPoolWithdrawFact(sender, pool, incomeCid, outlayCid, amounts)
/* For 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, currencyId)
Generator.nft.getTransferItem(receiver, nftId, currencyId)
Generator.nft.getBurnItem(nftId, currencyId)
Generator.nft.getApproveItem(approved, nftId, currencyId)
Generator.nft.getDelegateItem(collection, agent, mode, currencyId)
Generator.nft.getSignItem(qualification, nftId, cid)
Generator.nft.getCollectionRegisterFact(sender, form, currencyId)
Generator.nft.getCollectionPolicyUpdaterFact(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-js-util.import { Generator, JSONParser } from 'mitumc'
const generator = new Generator('mitum')
const currencyGenerator = generator.currency
// ... omitted
// ... create operations
// ... refer to above `Make Your First Operation`
// ... suppose you have already made operations - createAccount, keyUpdater, transfer and a seal - seal
JSONParser.toJSONString(createAccount.dict()) // print operation createAccount in JSON
JSONParser.toJSONString(keyUpdater.dict()) // print operation keyUpdater in JSON
JSONParser.toJSONString(transfer.dict()) // print operation transfer in JSON
JSONParser.toJSONString(seal) // print seal seal in JSON
JSONParser.getFile(createAccount.dict(), 'createAccount.json'); // getFile(dict object, file path)
JSONParser.getFile(keyUpdater.dict(), 'keyUpdater.json');
JSONParser.getFile(transfer.dict(), 'transfer.json');
JSONParser.getFile(seal, 'seal.json');