mitum-feefi-sdk is Javascript SDK that helps create operations for mitum-feefi model.
You can create operations of the following models with this SDK:
- Mitum Currency
- Mitum Currency Extension
- Mitum Feefi
This project has been developed in the following environments:
$ node --version
v18.9.0
$ npm --version
8.19.1
Before installing mitum-feefi-sdk, if you cannot install mitum-sdk using npm, you must install it locally first.
$ git clone https://github.com/ProtoconNet/mitum-sdk-js
$ cd mitum-sdk-js
$ npm i
$ npm i -g
You can install this package locally using this command:
$ git clone https://github.com/ProtoconNet/mitum-feefi-sdk-js
$ cd mitum-feefi-sdk-js
$ npm i
Run the following command if you installed mitum-sdk locally:
$ npm link mitum-sdk
Then, if you installed mitum-sdk locally, run npm link mitum-sdk
.
Or, You can install mitum-feefi-sdk by npm: Not yet published
$ npm i mitum-feefi-sdk
Before testing, check TEST_ID
, TEST_NODE
, TEST_GENESIS
, and TEST_ACCOUNT
in mitum.config.js.
You can test mitum-feefi-sdk using this command:
$ npm test
To set the mitum version of all hints and the network id, refer to Set version of hints and Set network id of operations.
mitum-feefi-sdk supports two signature methods:
- mitum1: v1
- mitum2: v2
You can generate key pairs in the following ways:
-
Generate a random KeyPair
-
Generate a KeyPair from a private key
-
Generate a KeyPair from a seed
-
private key: [key]mpr
-
public key: [key]mpu
The following functions are prepared for key pair generation.
import { KPGen } from "mitum-feefi-sdk";
// m1 key pair
var ekp1 = KPGen.random();
var ekp2 = KPGen.randomN(/* the number of keypairs */);
var ekp3 = KPGen.fromPrivateKey(/* string private key */);
var ekp4 = KPGen.fromSeed(/* string seed */);
// m2 key pair
const { m2 } = KPGen;
var skp1 = m2.random();
var skp2 = m2.randomN(/* the number of keypairs */);
var skp3 = m2.fromPrivateKey(/* string private key */);
var skp4 = m2.fromSeed(/* string seed */);
If you need a key pair for m2 signatures, use KPGen.m2.(function)
instead of KPGen.(function)
.
import { KPGen } from "mitum-feefi-sdk";
const keypair = KPGen.random(); // KeyPair instance
const priv = keypair.privateKey; // Key instance
const pub = keypair.publicKey; // Key instance
const priveStr = priv.toString(); // KwSKzHfNFKELkWs5gqbif1BqQhQjGhruKubqqU7AeKu5JPR36vKrmpr
const pubStr = pub.toString(); // 22PVZv7Cizt7T2VUkL4QuR7pmfrprMqnFDEXFkDuJdWhSmpu
import { KPGen } from "mitum-feefi-sdk";
const n = 5
// keys: Keys[Keys] instance; with 5 MKey(pub, weight) and threshold
// keypairs: Array; 5 KeyPair(priv, pub)
const { keys, keypairs } = KPGen.randomN(5);
const address = keys.address // Address instance
import { KPGen } from "mitum-feefi-sdk";
const keypair = KPGen.fromPrivateKey("KwkuLfcHsxY3yGLT2wYWNgbuGD3Q1j3c7DJvaRLfmT8ujmayJUaJmpr"); // KeyPair instance
const priv = keypair.privateKey; // Key instance
const pub = keypair.publicKey; // Key instance
const priveStr = priv.toString(); // KwkuLfcHsxY3yGLT2wYWNgbuGD3Q1j3c7DJvaRLfmT8ujmayJUaJmpr
const pubStr = pub.toString(); // r3W57ffVSjnyMFQ6132ZoPj1jnbFhoSFCnDYYRq2tXQVmpu
The seed string length must be at least 36.
import { KPGen } from "mitum-feefi-sdk";
const keypair = KPGen.fromSeed("Hello, world! ㅍㅅㅍ~ Hello, world! ㅍㅅㅍ~"); // KeyPair instance
const priv = keypair.privateKey; // Key instance
const pub = keypair.publicKey; // Key instance
const priveStr = priv.toString(); // L1BpsqZVzgMhkVCCvR1pyFLHNxBPYi5758uFzPdeLpjejfLxzd7Xmpr
const pubStr = pub.toString(); // j3XadE7SLSDS5B7hgTrXmAvZBGWE38WDNyLQKWxn6N96mpu
Each general account in Mitum Currency consists of the following elements:
- public keys
- weights: each weight is paired with a public key
- threshold
- address
The address is calculated based on the account's public key
s, weight
s, and threshold
.
In the case of a multi-sig account, the sum of the weights of all public keys that signed the operation must be greater than or equal to the threshold. Otherwise, the operation will not be processed.
Each weight and threshold range is 0 < weight, threshold <= 100. An account can have up to 10 public keys.
- mitum general address: [address]mca
To obtain an address from public keys, you must use the following classes:
import { PubKey, Keys } from "mitum-feefi-sdk";
var pub = new PubKey(/* public key; string */, /* weight; number */);
var keys = new Keys(/* pub keys; PubKey Array */, /* threshold; number */);
var address = keys.address.toString();
Let's do the following as an example.
- 5 public keys
- each weight: 20
- threshold: 60
Since 20 * 3 = 60, you must sign the operation with at least three keys when using this account to transfer the operation.
import { PubKey, Keys } from "mitum-feefi-sdk";
const pubs = [
{
weight: 20,
key: "23RWZ9McmTt5EpPYdLBeGYDn7nwyEB6qiPdU8DMjZ3dnkmpu",
},
{
weight: 20,
key: "vcsQ2fYSU5YVW5zRtpACXSLHtppkjCUo3tJ5witmAyZPmpu",
},
{
weight: 20,
key: "23jEC2vNwdfJn7PAKcFjy5CTVmELWdiAm6ZENEMr62cnsmpu",
},
{
weight: 20,
key: "282UNbzEAZQf3GdWJRPUrSaHWF88u297WTQbxfkytpcTsmpu",
},
{
weight: 20,
key: "bkPHGdsHSzRGe3NZ2hkzTSPyJx42BRaXetzy1bgBmbaAmpu",
},
]¸
const threshold = 60;
const mpubs = pubs.map(pub => new PubKey(pub.key, pub.weight));
const mkeys = new Keys(mpubs, threshold); // Keys[Keys] instance
const address = mkeys.address // Address instance;
const stringAddress = address.toString(); // string address
See mitum-sdk-js.
Feefi can handle a total of 7 operations.
- pool-register
- pool-policy-updater
- pool-deposits
- pool-withdraw
- airdrop-register
- airdrop-withdraw
- airdrop-close
See Appendix for other instructions on how to use Operation
.
pool-register is an operation to register a pool in a contract account.
import { TimeStamp, Feefi, Operation } from "mitum-feefi-sdk";
const token = new TimeStamp().UTC(); // any unique string
const senderAddress = "DBa8N5of7LZkx8ngH4mVbQmQ2NHDd6gL2mScGfhAEqddmca";
const senderPrivate = "KzFERQKNQbPA8cdsX5tCiCZvR4KgBou41cgtPk69XueFbaEjrczbmpr";
const poolAddress = "5hybo4cLkcoJN9UKesbySGAm6NepYFqVh9UWTmKhoATfmca";
const initialFee = "1000000";
const incomeCid = "MCC";
const outlayCid = "PEN";
const currency = "PEN"; // currency id for fee
const fact = new Feefi.PoolRegisterFact(token, senderAddress, poolAddress, initFee, incomeCid, outlayCid, currency);
const memo = ""; // any string
const operation = new Operation(fact, memo, []);
operation.sign(senderPrivate);
pool-policy-updater is an operation to update a pool policy.
import { TimeStamp, Feefi, Operation } from "mitum-feefi-sdk";
const token = new TimeStamp().UTC(); // any unique string
const senderAddress = "DBa8N5of7LZkx8ngH4mVbQmQ2NHDd6gL2mScGfhAEqddmca";
const senderPrivate = "KzFERQKNQbPA8cdsX5tCiCZvR4KgBou41cgtPk69XueFbaEjrczbmpr";
const poolAddress = "5hybo4cLkcoJN9UKesbySGAm6NepYFqVh9UWTmKhoATfmca";
const initialFee = "1000000";
const incomeCid = "MCC";
const outlayCid = "PEN";
const currency = "PEN"; // currency id for fee
const item = new Feefi.PoolPolicyUpdaterItem();
const fact = new Feefi.PoolPolicyUpdaterFact(token, senderAddress, poolAddress, initialFee, incomeCid, outlayCid, currency);
const memo = ""; // any string
const operation = new Operation(fact, memo, []);
operation.sign(senderPrivate);
pool-deposits is an operation to deposit an amount in a pool.
import { TimeStamp, Amount, Feefi, Operation } from "mitum-feefi-sdk";
const token = new TimeStamp().UTC(); // any unique string
const senderAddress = "DBa8N5of7LZkx8ngH4mVbQmQ2NHDd6gL2mScGfhAEqddmca";
const senderPrivate = "KzFERQKNQbPA8cdsX5tCiCZvR4KgBou41cgtPk69XueFbaEjrczbmpr";
const poolAddress = "5hybo4cLkcoJN9UKesbySGAm6NepYFqVh9UWTmKhoATfmca";
const incomeCid = "MCC";
const outlayCid = "PEN";
const amount = "10000" // amount to deposit
const fact = new Feefi.PoolDepositsFact(token, senderAddress, poolAddress, incomeCid, outlayCid, amount);
const memo = ""; // any string
const operation = new Operation(fact, memo, []);
operation.sign(senderPrivate);
pool-withdraw is an operation to withdraw the amount from the pool.
import { TimeStamp, Amount, Feefi, Operation } from "mitum-feefi-sdk";
const token = new TimeStamp().UTC(); // any unique string
const senderAddress = "DBa8N5of7LZkx8ngH4mVbQmQ2NHDd6gL2mScGfhAEqddmca";
const senderPrivate = "KzFERQKNQbPA8cdsX5tCiCZvR4KgBou41cgtPk69XueFbaEjrczbmpr";
const poolAddress = "5hybo4cLkcoJN9UKesbySGAm6NepYFqVh9UWTmKhoATfmca";
const incomeCid = "MCC";
const outlayCid = "PEN";
const am1 = new Amount("MCC", "10000"); // amount to withdraw
const am2 = new Amount("PEN", "1000");
const fact = new Feefi.PoolWithdrawFact(token, senderAddress, poolAddress, incomeCid, outlayCid, [am1, am2]);
const memo = ""; // any string
const operation = new Operation(fact, memo, []);
operation.sign(senderPrivate);
airdrop-register is an operation to for registering airdrops.
import { TimeStamp, Amount, Feefi, Operation } from "mitum-feefi-sdk";
const token = new TimeStamp().UTC(); // any unique string
const senderAddress = "DBa8N5of7LZkx8ngH4mVbQmQ2NHDd6gL2mScGfhAEqddmca";
const senderPrivate = "KzFERQKNQbPA8cdsX5tCiCZvR4KgBou41cgtPk69XueFbaEjrczbmpr";
const poolAddress = "5hybo4cLkcoJN9UKesbySGAm6NepYFqVh9UWTmKhoATfmca";
const incomeCid = "MCC";
const outlayCid = "PEN";
const amount = new Amount("MCC", "10000");
const start = "2023-01-12T02:03:40Z";
const end = "2023-01-12T02:05:40Z";
const fact = new Feefi.AirdropRegisterFact(token, senderAddress, poolAddress, incomeCid, outlayCid, start, end, amount);
const memo = ""; // any string
const operation = new Operation(fact, memo, []);
operation.sign(senderPrivate);
airdrop-withdraw is an operation for withdrawing from airdrop.
import { TimeStamp, Amount, Feefi, Operation } from "mitum-feefi-sdk";
const token = new TimeStamp().UTC(); // any unique string
const senderAddress = "DBa8N5of7LZkx8ngH4mVbQmQ2NHDd6gL2mScGfhAEqddmca";
const senderPrivate = "KzFERQKNQbPA8cdsX5tCiCZvR4KgBou41cgtPk69XueFbaEjrczbmpr";
const poolAddress = "5hybo4cLkcoJN9UKesbySGAm6NepYFqVh9UWTmKhoATfmca";
const incomeCid = "MCC";
const outlayCid = "PEN";
const amount = new Amount("MCC", "10000");
const fact = new Feefi.AirdropWithdrawFact(token, senderAddress, poolAddress, incomeCid, outlayCid, amount);
const memo = ""; // any string
const operation = new Operation(fact, memo, []);
operation.sign(senderPrivate);
airdrop-close is an operation to close airdrop.
import { TimeStamp, Feefi, Operation } from "mitum-feefi-sdk";
const token = new TimeStamp().UTC(); // any unique string
const senderAddress = "DBa8N5of7LZkx8ngH4mVbQmQ2NHDd6gL2mScGfhAEqddmca";
const senderPrivate = "KzFERQKNQbPA8cdsX5tCiCZvR4KgBou41cgtPk69XueFbaEjrczbmpr";
const poolAddress = "5hybo4cLkcoJN9UKesbySGAm6NepYFqVh9UWTmKhoATfmca";
const incomeCid = "MCC";
const outlayCid = "PEN";
const currency = "MCC"; // currency id for fee
const fact = new Feefi.AirdropCloseFact(token, senderAddress, poolAddress, incomeCid, outlayCid, currency);
const memo = ""; // any string
const operation = new Operation(fact, memo, []);
operation.sign(senderPrivate);
seal is not used in mitum2. Therefore, only operations with sig-type: DEFAULT or M1 can be added to seal.
Here's how to create a seal:
import { Seal } from "mitum-sdk";
const nodePrivateKey = "KzFERQKNQbPA8cdsX5tCiCZvR4KgBou41cgtPk69XueFbaEjrczbmpr";
const seal = new Seal([operation0, operation1, operation2, ...]); // Operation instances or json objects
seal.sign(nodePrivateKey);
// seal.dict(); seal object
To change the mitum version of every objects, add the following code to the part where the app is initialized or required.
The default version is v0.0.1
.
import { useV } from "mitum-sdk";
useV("v0.0.2");
To apply your network id to operations, add the following code to the part where the app is initialized or required.
The default id is mitum
.
import { useId } from "mitum-sdk";
useId("mainnet");
If your operation is for mitum1 and accounts of mitum2, you don't need to include the option for the code sign(priv, option)
.
Just leave it null
.
However, if the operation is a node operation(not account operation) of mitum2, you must include the option { node: "node address; string" }
.
const operation = new Operation(/* fact, etc... */);
operation.sign(/* sender's private key */, null); // mitum1(account, node), mitum2(account)
operation.sign(/* sender's private key */, { node: "node addres" }); // mitum2(node)
- Set fact-signs without signing
All fact-signs must have the same instance type(M1FactSign | M2FactSign | M2NodeFactSign).
operation.setFactSigns(/* FactSign instances */);
FactSign
can be created by...
import { FactSign } from "mitum-sdk";
const m1fs = new M1FactSign(/* signer */, /* signature; buffer */, /* signed_at */);
const m2fs = new M2FactSign(/* signer */, /* signature; buffer */, /* signed_at */);
const m2nodefs = new M2NodeFactSign(/* node address */, /* signer */, /* signature; buffer */, /* signed_at */);
- Send the operation directly to the network via Digest API.
operation.request(/* digest api address */, /* headers */); // `headers` can be null or undefined
- You can export operation json to a file.
operation.export(/* file path */);
The request
and export
methods are also available in Seal instance.