About FT and NFT token standard update
It has been 11 months since the last NFT MetadataView standard was released. Flow Fungible tokens also ushered in MetadataView standard, although is still in the testing stage, We can look forward to the formal adoption of the standard. This upgrade not only brings us the
MetadataView
standard contract of Fungible tokens.
FungibleTokenSwitchboard can implement a general collection of Receiver resources to solve the previous NFTMetadataView Royalty configuration problem.This upgrade is also carried out in the way of low modification to the standard contract, and the overall design idea is the same as that of NFTMetadataViews. For more details of NFTMetadataViews, you can go here read the introduction article I wrote earlier, and this one is about the design practice and explanation of Flow NFT and FT.
This article will be introduced and explained according to two major updates to the FT standard contract.
Main points:
- This update and upgrade is only deployed in the testnet, and the new features need to be supported by a new spork.
- The existing FT contract does not force to upgrades, you can choose not to upgrade, which will not affect normal use.
- The Vault resources that have been initialized by the user do not need to be reinitialized. If the contract implementation upgrades the function, the resources that have been initialized by the user will be inherited automatically.
- In addition to basic FT information, resource information and type information will also be included (guess is in preparation for information aggregation display on-chain)
- Similar to NFTMetadataView, FTMetadataView also has the ability to display
type
extensions to support more Metadata types in the future.
- FungibleTokenSwitchboard, as an additional routing resource, preserves the FT Receiver resources under the user's account, and can receive multiple type of FT token through one resource as a router.
FungibleTokenMetadataViews
The
FTView
structure is defined, including FTDisplay
and FTVaultData
- FTDisplay contains the information, such as names, symbols, descriptions, external links, Logo links and some social account links needed for FT display, which can be understood as the basic information of Token.
- FTVaultData this contains the resource information of FTVault and some type information of the interface, as well as an initialization function
createEmptyVault
to create Vault.
From the perspective of implementation,
FTDisplay
is designed to enrich the basic information on-chain of FungibleToken, while FTVaultData
is designed to facilitate third-party integration to integrate Token on-chain. Various types of FungibleToken
can be compatible with the standard MetadataViews
interface.Of course, the premise of this assumption is that
FungibleToken
has implemented the required interfaces of MetadataViews
.
Let's see what changes and upgrades have been made to FungibleToken
pub fun getViews(): [Type] { return [] } pub fun resolveView(_ view: Type): AnyStruct? { return nil }
In fact,
FungibleToken
only adds getViews
and resolveView
functions to the existing Balance
interface, and returns the type of optional.
The newly added contract dependency is not introduced here, but is introduced in ExampleToken of the example:Note: the changes of FungibleToken are slightly different here. Because of the addition of the implementation function in the Balance interface type, it will cause problems with the existing resources that inherit FungibleToken.Balance in the network. (normally speaking, a contract that inherits FungibleToken.Balance but does not implement getViews and resolveView cannot be properly deployed.) During a discussion with B.T.Wood, he told me a recent update of Cadence, if you inherit the resources of the interface, even if you do not implement the methods defined by the interface. Cadence will uses the default method of the interface itself, so that the above problems do not occur. This feature will be updated in future spork.
These two new interfaces are implemented in Vault resource:
pub fun getViews(): [Type]{ return [Type<FungibleTokenMetadataViews.FTView>(), Type<FungibleTokenMetadataViews.FTDisplay>(), Type<FungibleTokenMetadataViews.FTVaultData>()] }
Three types of structures,
FTView
, include FTDisplay
and FTVaultData
, are defined.
After upgrading, we can directly call getViews in the existing Balance interface of FungibleToken to get the current MetadataView types supported by Token, and obtain specific Metadata information through resolveView
.This code structure not only achieves the effect of backward compatibility, but also meets the requirement of dynamically adding Metadata types according to the needs in the future. We can enrich the chain metadata of FT by extending the types supported by FungibleTokenMetadataViews.
FungibleTokenSwitchboard
We can think of
FungibleTokenSwitchboard
as an aggregate routing resource in an account. It implements the interface of FungibleToken.Receiver
and acts as a universal collection in the standard. Through the receiverCapabilities
in the resources, the Receiver
of Vault
under the user account can be saved and forwarded to the corresponding Receiver
with only one path.
receiverCapabilities
is defined in the Switchboard
resource to aggregate the collection resources of FungibleToken
:pub resource Switchboard: FungibleToken.Receiver, SwitchboardPublic { access(contract) var receiverCapabilities: {Type: Capability<&{FungibleToken.Receiver}>} //.... }
receiverCapabilities
takes Type
as the key, and the receipt Capability
of Vault
as value, that is the core of routing collectionAt the same time, it provides a way to manage routes:
- addNewVault Add a new
Vault
route toSwitchboard
viaCapability
- addNewVaultsByPath Batch add to
Switchboard
through the array of resource paths
- removeVault remove
Because
Switchboard
inherits FungibleToken.Receiver
, the deposit
function needs to be implemented.pub fun deposit(from: @FungibleToken.Vault) { // Get the capability from the ones stored at the switchboard let depositedVaultCapability = self .receiverCapabilities[from.getType()] ?? panic ("The deposited vault is not available on this switchboard") // Borrow the reference to the desired vault let vaultRef = depositedVaultCapability.borrow() ?? panic ("Can not borrow a reference to the the vault") vaultRef.deposit(from: <-from) }
This deposit function implements a function of forwarding deposits and routes the collection to the specific resources in the configuration. We can also see that if the corresponding value of
receiverCapabilities
is not found here, the program Panic will cause the transaction of deposit to fail.
For the convenience of third parties, the interface type of SwitchboardPublic
is defined and three functions are defined:getVaultTypes
get theVault
types that supports reception
- deposit as mention berfore
- the secure deposit function
safeDeposit
does not cause Panic even if it fails, but returns the@FungibleToken.Vault
resource
- same as
Deposit
, receiving@FungibleToken.Vault
resource
- will first determine whether
receiverCapabilities
has a receiving resource configured for the corresponding resource.
- if it is not found and the deposit amount is greater than zero, the event of deposit failure will be triggered and the input
@ FungibleToken.Vault
resource will be returned.
- otherwise, destroy the top-up resources directly and return
nil
pub fun safeDeposit(from: @FungibleToken.Vault): @FungibleToken.Vault? { // Try to get the proper vault capability from the switchboard // If the desired vault is present on the switchboard... if let depositedVaultCapability = self .receiverCapabilities[from.getType()] { // We try to borrow a reference to the vault from the capability // If we can borrow a reference to the vault... if let vaultRef = depositedVaultCapability.borrow() { // We deposit the funds on said vault vaultRef.deposit(from: <-from.withdraw(amount: from.balance)) } } // if deposit failed for some reason if from.balance > 0.0 { emit NotCompletedDeposit(type: from.getType(), amount: from.balance, switchboardOwner: self.owner?.address) return <-from } destroy from return nil }
In short, the
Switchboard
resource, as a third-party routing resource, provides a general collection method for users, so that the royalty configuration of Royalty in the previous NFTMetadataViews
can receive a variety of FT assets.
From an application point of view, third-party developers or wallet portals are still required to integrate and introduce new contracts, which makes it easy for users to manually configure and manage the resources in Switchboard
.NFT borrowNFTSafe
Btw, the standard contract of NFT has also released update, has added a borrowNFTSafe function to the resource interface of NFT
CollectionPublic
to prevent errors in script execution due to the failure to find the NFT of the specific ID under the account during the execution of the query script.
Improve the query and development experience of developers.Summary
This update is still in the stage of Test Network deployment, where developers can experience the features of new standards and new contracts. After the future main network spork, these new codes will be deployed. Then FT will have the ability to query Metadata on-chain, and the original FT publishers can implement new functions and upgrade their contracts according to the example FT project.
In this way, catalog products that support FT should not be far away.