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

Create FungibleTokenMetadataViews contract #89

Merged
merged 58 commits into from
Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
289436a
Create FungibleTokenMetadataViews contract, include MetadataViews con…
alilloig Sep 1, 2022
6d0479f
Apply suggestions from code review
alilloig Sep 2, 2022
2e21f84
Fix CI
alilloig Sep 2, 2022
2573a1e
Remove unnecesary init parameter on ftvaultdata
alilloig Sep 7, 2022
dd005a6
Fix CI
alilloig Sep 7, 2022
735e141
Remove thumbnail and images from FTDisplay, add logo as only image an…
alilloig Sep 7, 2022
d46d521
Restore files after the testing crisis
alilloig Sep 15, 2022
875b8d9
Fix setup account from view test
alilloig Sep 15, 2022
b1fc12a
Add auxiliary function for returning views and the case for returning…
alilloig Sep 15, 2022
04f740c
Change logo (media) for logos (medias) at FTView
alilloig Sep 15, 2022
0b2a526
Add comments and use of getFTView function instead of resolveView
alilloig Sep 19, 2022
3b2eb7d
Add scripts for read metadata
alilloig Sep 19, 2022
e3f6ae0
Delete returnview functions
alilloig Sep 20, 2022
55593cb
Switch to MetadataPublicPath
alilloig Sep 20, 2022
ebc54c8
Add metadata path
alilloig Sep 20, 2022
5e3b73c
Change balance for metadata path at transactions. Fix FTVaultData con…
alilloig Sep 20, 2022
a7b1387
Add default implementation for MetadataViews.Resolver methods
alilloig Sep 20, 2022
1a705a0
Update contracts/FungibleToken.cdc
alilloig Sep 30, 2022
fae90d4
Update contracts/FungibleToken.cdc
alilloig Sep 30, 2022
511cf48
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
117b960
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
0f2afd8
Update contracts/FungibleToken.cdc
alilloig Sep 30, 2022
98870e3
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
c08d96f
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
d8de708
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
867a6d9
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
6db2782
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
9703dc2
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
dddedba
Add consistency about vaultData field name
alilloig Sep 30, 2022
cb68701
Fix spelling typos
alilloig Sep 16, 2022
e1c6c00
FT metadata docs section
alilloig Sep 19, 2022
48167ad
Finish docs
alilloig Sep 19, 2022
cfa52c3
avoid oppressive terminology
turbolent Oct 12, 2022
3a53138
avoid oppressive terminology
turbolent Oct 12, 2022
c2d30c5
add metadata views to go tests
joshuahannan Oct 24, 2022
41c84af
move view methods to the balance interface
joshuahannan Oct 24, 2022
8ca58e6
Remove MetadataViews import from FungibleToken contract
alilloig Nov 16, 2022
49fd8e4
Normalize flow.json
alilloig Nov 16, 2022
ffa52cc
Split test suites
alilloig Nov 16, 2022
9e6e418
Move timeout to jest config instead of per test suite
alilloig Nov 16, 2022
5549c6e
Update go test for metadataviews
alilloig Nov 16, 2022
57791fc
get go tests working
joshuahannan Nov 16, 2022
b78c2ad
update ci
joshuahannan Nov 16, 2022
03177c8
Change references to ResolvePublicPath for VaultPublicPath
alilloig Nov 17, 2022
1cb57de
Separate metadata tests from core features
alilloig Nov 17, 2022
27bb63b
Create folder only for metadata transactions
alilloig Nov 17, 2022
6536fe9
Rename utilityContracts folder as utility
alilloig Nov 17, 2022
5d04b1a
Remove the need of linking a resolver on the provider for returning a…
alilloig Nov 17, 2022
09930d8
Add test case for FTDisplay and kill bug on ExampleToken catched with…
alilloig Nov 17, 2022
9f8a857
Fix github ci to get latest Flow CLI version
alilloig Nov 17, 2022
5adbf97
Fix bug on event from issue #92
alilloig Nov 23, 2022
c313d16
Standarize comments on Example Token
alilloig Nov 23, 2022
7e33650
Standarize comments to docgen tool format on the FungibleToken contra…
alilloig Nov 23, 2022
0820c16
Include contracts docs
alilloig Nov 23, 2022
f287fa2
Fix broken links
alilloig Nov 23, 2022
ee3dd49
Update package.json version
alilloig Nov 29, 2022
ff1f5ef
Fix typos
alilloig Nov 29, 2022
ffa7f24
Fix public path after merge conflicts
alilloig Nov 29, 2022
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.16.x'
go-version: '1.18.x'
- uses: actions/cache@v1
with:
path: ~/go/pkg/mod
Expand All @@ -22,7 +22,7 @@ jobs:
cache: 'npm'
cache-dependency-path: lib/js/test/package-lock.json
- name: Install Flow CLI
run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v0.33.1-sc-m5
run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)"
- name: Flow cli Version
run: flow version
- name: Update PATH
Expand Down
80 changes: 65 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Right now we are using unsigned 64-bit fixed point numbers `UFix64` as the type

6 - Destroying a Vault

If a `Vault` is explicitly destroyed using Cadence's `destroy` keyword, the balance of the destroyed vault must be subracted from the total supply.
If a `Vault` is explicitly destroyed using Cadence's `destroy` keyword, the balance of the destroyed vault must be subtracted from the total supply.

7 - Standard for Token Metadata

Expand All @@ -135,10 +135,60 @@ This spec covers much of the same ground that a spec like ERC-20 covers, but wit
- Transfers can trigger actions because users can define custom `Receivers` to execute certain code when a token is sent.
- Cadence integer types protect against overflow and underflow, so a `SafeMath`-equivalent library is not needed.

### Metadata
## FT Metadata

A standard for token metadata is still an unsolved problem in the general blockchain world and we are still thinking about ways to solve it in Cadence. We hope to be able to store all metadata on-chain and are open to any ideas or feedback on how this could be implemented.
FT Metadata is represented in a flexible and modular way using both the [standard proposed in FLIP-0636](https://github.com/onflow/flow/blob/master/flips/20210916-nft-metadata.md) and the [standard proposed in FLIP-1087](https://github.com/onflow/flips/blob/main/flips/20220811-fungible-tokens-metadata.md).

When writing an NFT contract, you should implement the [`MetadataViews.Resolver`](contracts/utility/MetadataViews.cdc#L20-L23) interface, which allows your `Vault` resource to implement one or more metadata types called views.

Views do not specify or require how to store your metadata, they only specify
the format to query and return them, so projects can still be flexible with how they store their data.

### Fungible token Metadata Views

The [Example Token contract](contracts/ExampleToken.cdc) defines three new views that can used to communicate any fungible token information:

1. `FTView` A view that wraps the two other views that actually contain the data.
1. `FTDisplay` The view that contains all the information that will be needed by other dApps to display the fungible token: name, symbol, description, external URL, logos and links to social media.
1. `FTVaultData` The view that can be used by other dApps to interact programmatically with the fungible token, providing the information about the public and private paths used by default by the token, the public and private linked types for exposing capabilities and the function for creating new empty vaults. You can use this view to [setup an account using the vault stored in other account without the need of importing the actual token contract.](transactions/setup_account_from_vault_reference.cdc)

### How to implement metadata

The [Example Token contract](contracts/ExampleToken.cdc) shows how to implement metadata views for fungible tokens.

### How to read metadata

In this repository you can find examples on how to read metadata, accessing the `ExampleToken` display (name, symbol, logos, etc.) and its vault data (paths, linked types and the method to create a new vault).

First step will be to borrow a reference to the token's vault stored in some account:

```cadence
let vaultRef = account
.getCapability(ExampleToken.VaultPublicPath)
.borrow<&{MetadataViews.Resolver}>()
?? panic("Could not borrow a reference to the vault resolver")
```

Latter using that reference you can call methods defined in the [Fungible Token Metadata Views contract](contracts/FungibleTokenMetadataViews.cdc) that will return you the structure containing the desired information:

```cadence
let ftView = FungibleTokenMetadataViews.getFTView(viewResolver: vaultRef)
```

Alternatively you could call directly the `resolveView(_ view: Type): AnyStruct?` method on the `ExampleToken.Vault`, but the `getFTView(viewResolver: &{MetadataViews.Resolver}): FTView`, `getFTDisplay(_ viewResolver: &{MetadataViews.Resolver}): FTDisplay?` and `getFTVaultData(_ viewResolver: &{MetadataViews.Resolver}): FTVaultData?` defined on the `FungibleMetadataViews` contract will ease the process of dealing with optional types when retrieving this views.

Finally you can return the whole of structure or just log some values from the views depending on what you are aiming for:

```cadence
return ftView
````

```cadence
/*
When you retrieve a FTView both the FTDisplay and the FTVaultData views contained on it are optional values, meaning that the token could not be implementing then.
*/
log(ftView.ftDisplay!.symbol)
```

## Bonus Features

Expand Down Expand Up @@ -171,14 +221,14 @@ A standard for token metadata is still an unsolved problem in the general blockc
12 - Cloning the token to create a new token with the same distribution

13 - Restricted ownership (For accredited investors and such)
- whitelisting
- blacklisting
- allowlisting
- denylisting

# How to use the Fungible Token contract

To use the Flow Token contract as is, you need to follow these steps:

1. If you are using the Playground, you need to deploy the `FungibleToken` definition to account 1 yourself and import it in `ExampleToken`. It is a predeployed interface in the emulator, testnet, and mainnet and you can import definition from those accounts:
1. If you are using the Playground, you need to deploy the `FungibleToken` definition to account 1 yourself and import it in `ExampleToken`. It is a pre-deployed interface in the emulator, testnet, and mainnet and you can import definition from those accounts:
- `0xee82856bf20e2aa6` on emulator
- `0x9a0766d93b6608b7` on testnet
- `0xf233dcee88fe0abe` on mainnet
Expand All @@ -202,15 +252,15 @@ To use the Flow Token contract as is, you need to follow these steps:

Users willing to use the Fungible Token Switchboard will need to setup their accounts by creating a new `FungibleTokenSwitchboard.Switchboard` resource and saving it to their accounts at the `FungibleTokenSwitchboard.StoragePath` path.

This can be acomplished by executing the transaction found in this repository `transactions/switchboard/setup_account.cdc`. This transaction will create and save a Switchboard resource to the signer's account,
This can be accomplished by executing the transaction found in this repository `transactions/switchboard/setup_account.cdc`. This transaction will create and save a Switchboard resource to the signer's account,
and it also will create the needed public capabilities to access it. After setting up their switchboard, in order to make it support receiving a certain token, users will need to add the desired token's receiver capability to their switchboard resource.

## Adding a new vault to the switchboard
When a user wants to receive a new fungible token through their switchboard, they will need to add a new public capability linked to said FT to their switchboard resource. This can be accomplished in two different ways:

1. Adding a single capability using `addNewVault(capability: Capability<&{FungibleToken.Receiver}>)`
* Before calling this method on a transaction you should first retrieve the capability to the token's vault you are
willing to add to the switchboard, as is done in the template transaction `transactions/switchboard/add_vault_capabilty.cdc`.
willing to add to the switchboard, as is done in the template transaction `transactions/switchboard/add_vault_capability.cdc`.

```cadence
transaction {
Expand All @@ -219,7 +269,7 @@ To use the Flow Token contract as is, you need to follow these steps:

prepare(signer: AuthAccount) {
// Get the example token vault capability from the signer's account
self.exampleTokenVaultCapabilty =
self.exampleTokenVaultCapability =
signer.getCapability<&{FungibleToken.Receiver}>
(ExampleToken.ReceiverPublicPath)
// Get a reference to the signers switchboard
Expand All @@ -230,7 +280,7 @@ To use the Flow Token contract as is, you need to follow these steps:

execute {
// Add the capability to the switchboard using addNewVault method
self.switchboardRef.addNewVault(capability: self.exampleTokenVaultCapabilty)
self.switchboardRef.addNewVault(capability: self.exampleTokenVaultCapability)
}
}
```
Expand Down Expand Up @@ -279,7 +329,7 @@ This can be observed in the template transaction `transactions/switchboard/remov

prepare(signer: AuthAccount) {
// Get the example token vault capability from the signer's account
self.exampleTokenVaultCapabilty = signer.getCapability
self.exampleTokenVaultCapability = signer.getCapability
<&{FungibleToken.Receiver}>(ExampleToken.ReceiverPublicPath)
// Get a reference to the signers switchboard
self.switchboardRef = signer.borrow<&FungibleTokenSwitchboard.Switchboard>
Expand All @@ -291,14 +341,14 @@ This can be observed in the template transaction `transactions/switchboard/remov
execute {
// Remove the capability from the switchboard using the
// removeVault method
self.switchboardRef.removeVault(capability: self.exampleTokenVaultCapabilty)
self.switchboardRef.removeVault(capability: self.exampleTokenVaultCapability)
}
}
```
This function will panic if is not possible to `.borrow()` a reference to a `&{FungibleToken.Receiver}` from the passed capability.

## Transfering tokens through the switchboard
The Fungible Token Switchboad provides two different ways of depositing tokens to it, using the `deposit(from: @FungibleToken.Vault)` method enforced by the `{FungibleToken.Receiver}` or using the `safeDeposit(from: @FungibleToken.Vault): @FungibleToken`:
## Transferring tokens through the switchboard
The Fungible Token Switchboard provides two different ways of depositing tokens to it, using the `deposit(from: @FungibleToken.Vault)` method enforced by the `{FungibleToken.Receiver}` or using the `safeDeposit(from: @FungibleToken.Vault): @FungibleToken`:

1. Using the first method will be just the same as depositing to `&{FungibleToken.Receiver}`. The path for the Switchboard receiver is defined in `FungibleTokenSwitchboard.ReceiverPublicPath`,
the generic receiver path `/public/GenericFTReceiver` that can also be obtained from the NFT MetadataViews contract.
Expand Down Expand Up @@ -336,7 +386,7 @@ This can be observed in the template transaction `transactions/switchboard/remov
}
```

2. The `safeDeposit(from: @FungibleToken.Vault): @FungibleToken` works in a similar way, with the difference that it will not panic if the desired FT Vault can not be obtained from the Switchboard. The method will return the passed vault, empty if the funds were deposited sucessfully or still containing the funds if the transfer of the funds was not possible. Keep in mind that when using this method on a transaction you will allways have to deal with the returned resource. An example of this can be found on `transactions/switchboard/safe_transfer_tokens.cdc`:
2. The `safeDeposit(from: @FungibleToken.Vault): @FungibleToken` works in a similar way, with the difference that it will not panic if the desired FT Vault can not be obtained from the Switchboard. The method will return the passed vault, empty if the funds were deposited successfully or still containing the funds if the transfer of the funds was not possible. Keep in mind that when using this method on a transaction you will always have to deal with the returned resource. An example of this can be found on `transactions/switchboard/safe_transfer_tokens.cdc`:
```cadence
transaction(to: Address, amount: UFix64) {
// The reference to the vault from the payer's account
Expand Down
Loading