Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "Getting Started" documentation for tokens #306

Merged
merged 5 commits into from
Nov 24, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 114 additions & 2 deletions docs/gettingstarted/mint_tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,118 @@ nav_order: 9

---

## Work in progress
## Quick reference

... the tokens APIs are under development
- FireFly provides an abstraction layer for multiple types of tokens
- Tokens are grouped into _pools_, which each represent a particular type or class of token
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonder if an example worthwhile here, such as?

Examples of how a pool might be used by a given token connector implementation:
- ERC-721: A contract instance, ready for issuance of NFTs within unique identities in the pool
- ERC-20 / ERC-777: A token contract instance, with a single fungible pool of value - "a coin"
- ERC-1155: An efficient to allocate isolated pool of fungible or non-fungible tokens (see ref implementation)
- ERC-1400 (and related security token standards): An partition within an overall fungible pool, representing part of the value of an overall non-fungible asset

Could do with @jimthematrix checking on the terminology above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be, and maybe not limited to pools... Maybe we need an extra section of "Example uses" to lay out a few examples of how you could map common token standards/use cases onto FireFly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree with the suggestion to add some details how a pool is mapped to the various contract specs.

agree with the suggested mapping above to ERC721, ERC20/777 and ERC1155.

on ERC-1400, however, a pool should be mapped to a contract instance instead of a partition. in ERC-1410 which describes the spec for partially fungible tokens, the interface methods that are compatible with ERC-20/ERC-777 all operate on the sum of all partitions. For example the balanceOf() method, same for totalSupply(): (ethereum/EIPs#1410):

balanceOf

Aggregates a token holders balances across all partitions. Equivalent to balanceOf in the ERC-20/777 specification.

MUST count the sum of all partition balances assigned to a token holder.

function balanceOf(address _tokenHolder) external view returns (uint256);

In addition, a token transfer is allowed to be received into a partition that is different than the partition it's sent from:

transferByPartition

When transferring tokens from a particular partition, it is useful to know on-chain (i.e. not just via an event being fired) the destination partition of those tokens. The destination partition will be determined by the implementation of this function and will vary depending on use-case.

_The function MUST return the bytes32 partition of the receiver.

function transferByPartition(bytes32 _partition, address _to, uint256 _value, bytes _data) external returns (bytes32)

Given the above interface in ERC-1410 (main spec of the security token standard captured by ERC-1400 as a compendium), the operations that target the sum of all partitions (eg balanceOf(), totalSupply(), authorizeOperator(), etc.) are already supported by the current tokens API interface when a pool is mapped to the contract instance, and it'd be straightforward to add support for partition based operations (eg balanceOfByPartition(), transferByPartition(), authorizeOperatorByPartition()) by simply adding additional payload parameters to indicate target partitions to the existing API endpoints.

On the other hand, if pools are mapped to partitions, then we have to add support for cross-pool transfers and aggregates in order to properly support the ERC-1410 operations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we agree with the above, we should also add that the current API endpoints support the ERC20, ERC777, ERC1155 and ERC721 contracts, while future work is needed to support ERC1400, in particular to support partitions (metadata to fungible tokens) within pools.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a new section with some of these examples.

- Each pool is classified as _fungible_ or _non-fungible_
- In the case of _non-fungible_ tokens, the pool is subdivided into individual tokens with a unique _token index_
- Within a pool, you may _mint_, _transfer_, and _burn_ tokens
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest adding operational aliases (issue vs. mint, redeem vs. burn) used in different token specs:

Within a pool, you may mint (issue), transfer, and burn (redeem) tokens

- Each operation can be optionally accompanied by a broadcast or private message, which will be recorded alongside the transfer on-chain
- FireFly tracks a history of all token operations along with all current token balances
- The blockchain backing each token connector may be the same _or_ different from the one backing FireFly message pinning

## Create a pool

Every application will need to create at least one token pool. At a minimum, you must always
specify a `name` and `type` (fungible or nonfungible) for the pool.

`POST` `/api/v1/namespaces/default/tokens/pools`

```json
{
"name": "testpool",
"type": "fungible"
}
```

Other parameters:
- You must specify a `connector` if you have configured multiple token connectors
- You may pass through a `config` object of additional parameters, if supported by your token connector
- You may specify a `key` understood by the connector (i.e. an Ethereum address) if you'd like to use a non-default signing identity

awrichar marked this conversation as resolved.
Show resolved Hide resolved
## Mint tokens

Once you have a token pool, you can mint tokens within it. With the default `firefly-tokens-erc1155` connector,
only the creator of a pool is allowed to mint - but each connector may define its own permission model.

`POST` `/api/v1/namespaces/default/tokens/mint`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the token pool name part is missing from this path

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay actually I see now that it just works if there's only one pool defined. Does this URL break if there is more than one pool?

Copy link
Contributor Author

@awrichar awrichar Nov 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pool name is not in the new paths (if there is only one pool, the name is optional; if there is more than one pool, you pass it in the body). The old path with the pool name is deprecated.


```json
{
"amount": 10
}
```

Other parameters:
- You must specify a `pool` name if you've created more than one pool
- You may specify a `key` understood by the connector (i.e. an Ethereum address) if you'd like to use a non-default signing identity
- You may specify `to` if you'd like to send the minted tokens to a specific identity (default is the same as `key`)

## Transfer tokens

You may transfer tokens within a pool by specifying an amount and a destination understood by the connector (i.e. an Ethereum address).
With the default `firefly-tokens-erc1155` connector, only the owner of a token may transfer it away - but each connector may define its
own permission model.

`POST` `/api/v1/namespaces/default/tokens/transfers`

```json
{
"amount": 1,
"to": "0x07eab7731db665caf02bc92c286f51dea81f923f"
}
```

Other parameters:
- You must specify a `pool` name if you've created more than one pool
- You must specify a `tokenIndex` for non-fungible pools (and the `amount` should be 1)
- You may specify a `key` understood by the connector (i.e. an Ethereum address) if you'd like to use a non-default signing identity
- You may specify `from` if you'd like to send tokens from a specific identity (default is the same as `key`)
awrichar marked this conversation as resolved.
Show resolved Hide resolved

## Sending data with a transfer

All transfers (as well as mint/burn operations) support an optional `message` parameter that contains a broadcast or private
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we effectively hijacked the _data field of the various operations that may have been needed for further on-chain authorizations (e.g signatures by parties other than the sender to indicate approval). as a mental note we should consider supporting an additional payload parameter to include into the _data field as-is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jimthematrix yes, you're correct. The token connector exposes a data field, and FireFly packs JSON into this field to identify messages and other metadata. But FireFly itself does not (currently) expose any way for the user to control or add to this field from the level of the FireFly APIs.

message to be sent along with the transfer. This message follows the same convention as other FireFly messages, and may be comprised
of text or blob data, and can provide context, metadata, or other supporting information about the transfer. The message will be
batched, hashed, and pinned to the primary blockchain as described in [key concepts](/keyconcepts/broadcast.html).

The message hash will also be sent to the token connector as part of the transfer operation, to be written to the token blockchain
when the transaction is submitted. All recipients of the message will then be able to correlate the message with the token transfer.

`POST` `/api/v1/namespaces/default/tokens/transfers`

```json
{
"amount": 1,
"to": "0x07eab7731db665caf02bc92c286f51dea81f923f",
"message": {
"data": [{
"value": "payment for goods"
}]
}
}
```

By default, a broadcast message is used. In order to send a private message, specify `"type": "transfer_private"` in the message header,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a sample payload for a private message would be useful here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

and include a `"group"` entry specifying the recipients. All parties in the network will be able to see the transfer (including the
message hash), but only the recipients of the message will be able to view the actual message data.

## Burn tokens

You may burn tokens by simply specifying an amount. With the default `firefly-tokens-erc1155` connector, only the owner of a token may
burn it - but each connector may define its own permission model.

`POST` `/api/v1/namespaces/default/tokens/burn`

```json
{
"amount": 1,
}
```

Other parameters:
- You must specify a `pool` name if you've created more than one pool
- You must specify a `tokenIndex` for non-fungible pools (and the `amount` should be 1)
- You may specify a `key` understood by the connector (i.e. an Ethereum address) if you'd like to use a non-default signing identity
- You may specify `from` if you'd like to burn tokens from a specific identity (default is the same as `key`)