Rell integration
In the bootstrap project, the rell/src
directory gets configured to be the
Rell project's root module. rell/src/lib/ft3
directory contains the
FT3 module.
You can use the rell/src/module.rell
file that already has some template code that could serve as an entry point for your dapp, although you can choose any module structure you like.
Defining dapp_account entity
You can use the account
entity that's provided by .lib.ft3.account
module for account management. But your dapp might need to record more
information about the user, like username, email address, etc. We can add an entity to record that information.
An example of dapp's account could be as follows:
import acc: .lib.ft3.account;
entity dapp_account {
key account: acc.account;
key username: text;
}
In this user model, there is no public key or user ID. acc.account
provides these details.
acc.account
has an id
property that uniquely identifies an account,
and access gets controlled by acc.account_auth_descriptor
that includes the user's public key.
The underlying structure of acc.account
and
acc.account_auth_descriptor
is available in Account Management.
After you define the dapp_account
entity, the next step is to define the operation used to create an instance of dapp_account
:
operation create_dapp_account(
username: text,
user_auth: acc.auth_descriptor
) {
val account_id = acc.create_account_with_auth(user_auth);
create dapp_account (
username,
acc.account @ { account_id }
);
}
query get_dapp_accounts() {
return dapp_account @? {} ( id = dapp_account.account.id, first_name = .first_name, last_name = .last_name, age = .age);
}
Restart the node for changes to take effect. Because you've changed
the database structure, you need to add the -W
option to delete the database
and add a new dapp_account
table:
postchain/bin/run-node.sh <dapp_name> -W
Make sure to update your client's Blockchain RID config with the newly generated blockchainRID.
On the client side, you can use ft3-lib
(or
postchain-client
) as follows:
import DirectoryService from "./lib/directory-service";
import { util } from "postchain-client";
import { blockchainRID } from "../configs/constants";
import {
op,
Blockchain,
SingleSignatureAuthDescriptor,
FlagsType,
User,
} from "ft3-lib";
const keyPair = util.makeKeyPair();
const user = new User(
keyPair,
new SingleSignatureAuthDescriptor(keyPair.pubKey, [
FlagsType.Account,
FlagsType.Transfer,
])
);
const blockchain = await Blockchain.initialize(
blockchainRID,
new DirectoryService()
);
const session = blockchain.newSession(user);
await session.call(
op("create_dapp_account", "John", "Doe", 30, user.authDescriptor)
);
You can use the get_dapp_accounts
query to verify whether the create_dapp_account
operation ran successfully:
const rest = pcl.restClient.createRestClient(nodeApiUrl, blockchainRID, 5);
const gtx = pcl.gtxClient.createClient(
rest,
Buffer.from(blockchainRID, "hex"),
[]
);
const allDappAccoounts = await gtx.query("get_dapp_accounts");
Modules
This section reviews some of the built-in utilities that FT3 modules provide.
It would be best to remember that the built-in operations and queries all have a matching interface in the JavaScript library.
Account module
import acc: .lib.ft3.account;
Functions:
function create_account_with_auth (auth_descriptor): byte_array
Create a new FT3 account using the provided
ft3.account.auth_descriptor
auth_descriptor
: Theauth_descriptor
used to create this account.- return:
account.id
(equal toauth_descriptor.hash()
)
function auth_and_log(account_id: byte_array, auth_descriptor_id: byte_array, required_flags: list<text>): account
Authorize given auth_descriptor
for required authorization flags, and
apply the rate limiter constraints configured in config.template.xml
.
This is the default authorization mechanism for operations.
account_id
: id of the accountauth_descriptor_id
: is equal toauth_descriptor.hash()
required_flags
: list of required authorization flags (see Account Management)- return: the account instance
function require_auth (account, descriptor_id: byte_array, required_flags: list<text>)
Authorizes given auth_descriptor
, but doesn't apply rate limiter constraints.
function _add_auth_descriptor (account, auth_descriptor)
function _delete_auth_descriptor(auth_descriptor: account_auth_descriptor)
function _delete_all_auth_descriptors_exclude(account, auth_descriptor_id: byte_array)
Utilities for managing auth_descriptors
.
Operations:
operation delete_auth_descriptor (account_id: byte_array, auth_descriptor_id: byte_array, delete_descriptor_id: byte_array)
operation delete_all_auth_descriptors_exclude(account_id: byte_array, auth_descriptor_id: byte_array)
operation add_auth_descriptor (account_id: byte_array, auth_id: byte_array, new_desc: acc.auth_descriptor)
Queries:
query get_account_auth_descriptors(id: byte_array)
query get_account_by_id(id: byte_array)
query get_account_by_auth_descriptor(auth_descriptor)
query get_accounts_by_participant_id(id: byte_array)
query get_accounts_by_auth_descriptor_id(descriptor_id: byte_array)
Core module
import core: .lib.ft3.core;
Functions:
function register_asset (name, issuing_chain_rid: byte_array): asset
Register a new asset on the chain.
function _get_asset_balances(account_id: byte_array): list<(id:byte_array,name:text,amount:integer,chain_id:byte_array)>
Get asset balance of an account.
function ensure_balance(acc.account, asset): balance
Get account's balance of an asset, or create one if it doesn't exist.
struct xfer_input {
account_id: byte_array;
asset_id: byte_array;
auth_descriptor_id: byte_array;
amount: integer;
extra: map<text, gtv>;
}
struct xfer_output {
account_id: byte_array;
asset_id: byte_array;
amount: integer;
extra: map<text, gtv>;
}
function _transfer (inputs: list<xfer_input>, outputs: list<xfer_output>)
Perform an asset transfer from accounts described in xfer_input
to
accounts in xfer_output
.
If xfer_output.extra
map contains a reg_auth_desc
key, then the
value is auth_descriptor
to create a new account (meaning you can create a new account and then transfer the asset to it immediately in one transaction).
Operations:
operation transfer (inputs: list<ft3.xfer_input>, outputs: list<ft3.xfer_output>)
Queries:
query get_asset_balances(account_id: byte_array)
query get_asset_balance(account_id: byte_array, asset_id: byte_array)
query get_asset_by_name(name)
query get_asset_by_id(asset_id: byte_array)
query get_all_assets()
query get_payment_history(account_id: byte_array, after_block: integer)