• Stars
    star
    136
  • Rank 267,670 (Top 6 %)
  • Language Cadence
  • License
    The Unlicense
  • Created over 4 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The Fungible Token standard on the Flow Blockchain

Fungible Token Standard

This is a description of the Flow standard for fungible token contracts. It is meant to contain the minimum requirements to implement a safe, secure, easy to understand, and easy to use fungible token contract. It also includes an example implementation to show how a concrete smart contract would actually implement the interface.

What is Flow?

Flow is a new blockchain for open worlds. Read more about it here.

What is Cadence?

Cadence is a new Resource-oriented programming language for developing smart contracts for the Flow Blockchain. Read more about it here and see its implementation here

We recommend that anyone who is reading this should have already completed the Cadence Tutorials so they can build a basic understanding of the programming language.

Resource-oriented programming, and by extension Cadence, is the perfect programming environment for currencies, because users are able to store their tokens directly in their accounts and transact peer-to-peer. Please see the blog post about resources to understand why they are perfect for digital assets.

Import Addresses

The FungibleToken, FungibleTokenMetadataViews, and FungibleTokenSwitchboard contracts are already deployed on various networks. You can import them in your contracts from these addresses. There is no need to deploy them yourself.

(note: default deployment of FungibleTokenMetadataViews and FungibleTokenSwitchboard is still pending for emulator/canary, so you will still have to deploy those yourself on those networks)

Network Contract Address
Emulator/Canary 0xee82856bf20e2aa6
Testnet 0x9a0766d93b6608b7
Sandboxnet 0xe20612a0776ca4bf
Mainnet 0xf233dcee88fe0abe

Basics of the Standard:

The code for the standard is in contracts/FungibleToken.cdc. An example implementation of the standard that simulates what a simple token would be like is in contracts/ExampleToken.cdc.

The exact smart contract that is used for the official Flow Network Token is in contracts/FlowToken.cdc

Example transactions that users could use to interact with fungible tokens are located in the transactions/ directory. These templates are mostly generic and can be used with any fungible token implementation by providing the correct addresses, names, and values.

The standard consists of a contract interface called FungibleToken that requires implementing contracts to define a Vault resource that represents the tokens that an account owns. Each account that owns tokens will have a Vault stored in its account storage. Users call functions on each other's Vaults to send and receive tokens.

Right now we are using unsigned 64-bit fixed point numbers UFix64 as the type to represent token balance information. This type has 8 decimal places and cannot represent negative numbers.

Core Features (All contained in the main FungibleToken interface)

1- Getting metadata for the token smart contract via the fields of the contract:

  • pub var totalSupply: UFix64
    • The only required field of the contract. It would be incremented when new tokens are minted and decremented when they are destroyed.
  • Event that gets emitted when the contract is initialized
    • pub event TokensInitialized(initialSupply: UFix64)

2- Retrieving the token fields of a Vault in an account that owns tokens.

  • Balance interface
    • pub var balance: UFix64
      • The only required field of the Vault type

3- Withdrawing a specific amount of tokens amount using the withdraw function of the owner's Vault

  • Provider interface
    • pub fun withdraw(amount: UFix64): @FungibleToken.Vault
      • Conditions
        • the returned Vault's balance must equal the amount withdrawn
        • The amount withdrawn must be less than or equal to the balance
        • The resulting balance must equal the initial balance - amount
    • Users can give other accounts a reference to their Vault cast as a Provider to allow them to withdraw and send tokens for them. A contract can define any custom logic to govern the amount of tokens that can be withdrawn at a time with a Provider. This can mimic the approve, transferFrom functionality of ERC20.
  • withdraw event
    • Indicates how much was withdrawn and from what account the Vault is stored in. If the Vault is not in account storage when the event is emitted, from will be nil.
    • pub event TokensWithdrawn(amount: UFix64, from: Address?)

4 - Depositing a specific amount of tokens from using the deposit function of the recipient's Vault

  • Receiver interface

    • pub fun deposit(from: @FungibleToken.Vault)
    • Conditions
      • from balance must be non-zero
      • The resulting balance must be equal to the initial balance + the balance of from
  • deposit event

    • Indicates how much was deposited and to what account the Vault is stored in. If the Vault is not in account storage when the event is emitted, to will be nil.
    • pub event TokensDeposited(amount: UFix64, to: Address?)
  • Users could create custom Receivers to trigger special code when transfers to them happen, like forwarding the tokens to another account, splitting them up, and much more.

  • It is important that if you are making your own implementation of the fungible token interface that you cast the input to deposit as the type of your token. let vault <- from as! @ExampleToken.Vault The interface specifies the argument as @FungibleToken.Vault, any resource that satisfies this can be sent to the deposit function. The interface checks that the concrete types match, but you'll still need to cast the Vault before storing it.

5 - Creating an empty Vault resource

  • pub fun createEmptyVault(): @FungibleToken.Vault
  • Defined in the contract To create an empty Vault, the caller calls the function in the contract and stores the Vault in their storage.
  • Conditions:
    • the balance of the returned Vault must be 0

6 - Destroying a Vault

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

  • not sure what this should be yet
  • Could be a dictionary, could be an IPFS hash, could be json, etc.
  • need suggestions!

Comparison to Similar Standards in Ethereum

This spec covers much of the same ground that a spec like ERC-20 covers, but without most of the downsides.

  • Tokens cannot be sent to accounts or contracts that don't have owners or don't understand how to use them, because an account has to have a Vault in its storage to receive tokens. No safetransfer is needed.
  • If the recipient is a contract that has a stored Vault, the tokens can just be deposited to that Vault without having to do a clunky approve, transferFrom
  • Events are defined in the contract for withdrawing and depositing, so a recipient will always be notified that someone has sent them tokens with the deposit event.
  • The approve, transferFrom pattern is not included, so double spends are not permitted
  • 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.

FT Metadata

FT Metadata is represented in a flexible and modular way using both the standard proposed in FLIP-0636 and the standard proposed in FLIP-1087.

When writing an NFT contract, you should implement the MetadataViews.Resolver 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 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.
  2. 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.
  3. 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.

How to implement metadata

The Example Token contract 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:

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 that will return you the structure containing the desired information:

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:

return ftView
/*
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

Minting and Burning are not included in the standard but are included in the FlowToken example contract to illustrate what minting and burning might look like for a token in Flow.

8 - Minting or Burning a specific amount of tokens using a specific minter resource that an owner can control

  • MintandBurn Resource
    • function to mintTokens
    • tokens minted event
    • Each minter has a set amount of tokens that they are allowed to mint. This cannot be changed and a new minter needs to be created to add more allowance.
    • function to burnTokens
    • tokens Burnt event
    • Each time tokens are minted or burnt, that value is added or subtracted to or from the total supply.

The following features could each be defined as a separate interface. It would be good to make standards for these, but not necessary to include in the main standard interface and are not currently defined in this example.

9 - Withdrawing a specific amount of tokens from someone else's Vault by using their provider reference.

  • approved withdraw event
  • Providing a resource that only approves an account to send a specific amount per transaction or per day/month/etc.
  • Returning the amount of tokens that an account can send for another account.
  • Reading the balance of the account that you have permission to send tokens for
  • Owner is able to increase and decrease the approval at will, or revoke it completely
    • This is much harder than anticipated

11 - Pausing Token transfers (maybe a way to prevent the contract from being imported)

12 - Cloning the token to create a new token with the same distribution

13 - Restricted ownership (For accredited investors and such)

  • 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 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
  2. Deploy the ExampleToken definition
  3. You can use the get_balance.cdc or get_supply.cdc scripts to read the balance of a user's Vault or the total supply of all tokens, respectively.
  4. Use the setupAccount.cdc on any account to set up the account to be able to use FlowTokens.
  5. Use the transfer_tokens.cdc transaction file to send tokens from one user with a Vault in their account storage to another user with a Vault in their account storage.
  6. Use the mint_tokens.cdc transaction with the admin account to mint new tokens.
  7. Use the burn_tokens.cdc transaction with the admin account to burn tokens.
  8. Use the create_minter.cdc transaction to create a new MintandBurn resource and store it in a new Admin's account.

Fungible Token Switchboard

FungibleTokenSwitchboard.cdc, allows users to receive payments in different fungible tokens using a single &{FungibleToken.Receiver} placed in a standard receiver path /public/GenericFTReceiver.

How to use it

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 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_capability.cdc.
    transaction {
        let exampleTokenVaultCapabilty: Capability<&{FungibleToken.Receiver}>
        let switchboardRef:  &FungibleTokenSwitchboard.Switchboard
    
        prepare(signer: AuthAccount) {
          // Get the example token vault capability from the signer's account
          self.exampleTokenVaultCapability = 
            signer.getCapability<&{FungibleToken.Receiver}>
                                    (ExampleToken.ReceiverPublicPath)
          // Get a reference to the signers switchboard
          self.switchboardRef = signer.borrow<&FungibleTokenSwitchboard.Switchboard>
            (from: FungibleTokenSwitchboard.StoragePath) 
              ?? panic("Could not borrow reference to switchboard")
        }
    
        execute {
          // Add the capability to the switchboard using addNewVault method
          self.switchboardRef.addNewVault(capability: self.exampleTokenVaultCapability)
        }
    }

    This function will panic if is not possible to .borrow() a reference to a &{FungibleToken.Receiver} from the passed capability. It will also panic if there is already a capability stored for the same Type of resource exposed by the capability.

  2. Adding one or more capabilities using the paths where they are stored using addNewVaultsByPath(paths: [PublicPath], address: Address)

    • When using this method, an array of PublicPath objects should be passed along with the Address of the account from where the vaults' capabilities should be retrieved.
    transaction (address: Address) {
    
        let exampleTokenVaultPath: PublicPath
        let vaultPaths: [PublicPath]
        let switchboardRef:  &FungibleTokenSwitchboard.Switchboard
    
        prepare(signer: AuthAccount) {
          // Get the example token vault path from the contract
          self.exampleTokenVaultPath = ExampleToken.ReceiverPublicPath
          // And store it in the array of public paths that will be passed to the
          // switchboard method
          self.vaultPaths = []
          self.vaultPaths.append(self.exampleTokenVaultPath)
          // Get a reference to the signers switchboard
          self.switchboardRef = signer.borrow<&FungibleTokenSwitchboard.Switchboard>
            (from: FungibleTokenSwitchboard.StoragePath) 
              ?? panic("Could not borrow reference to switchboard")
        }
    
        execute {
          // Add the capability to the switchboard using addNewVault method
          self.switchboardRef.addNewVaultsByPath(paths: self.vaultPaths, 
                                                        address: address)
        }
    }

    This function won't panic, instead it will just not add to the @Switchboard any capability which can not be retrieved from any of the provided PublicPaths. It will also ignore any type of &{FungibleToken.Receiver} that is already present on the @Switchboard

  3. Adding a capability to a receiver specifying which type of token will be deposited there using addNewVaultWrapper(capability: Capability<&{FungibleToken.Receiver}>, type: Type). This method can be used to link a token forwarder or any other wrapper to the switchboard. Once the Forwarder has been properly created containing the capability to an actual @FungibleToken.Vault, this method can be used to link the @Forwarder to the switchboard to deposit the specified type of Fungible Token. In the template transaction switchboard/add_vault_wrapper_capability.cdc, we assume that the signer has a forwarder containing a capability to an @ExampleToken.Vault resource:

transaction {

  let tokenForwarderCapability: Capability<&{FungibleToken.Receiver}>
  let switchboardRef:  &FungibleTokenSwitchboard.Switchboard

  prepare(signer: AuthAccount) {

      // Get the token forwarder capability from the signer's account
      self.tokenForwarderCapability = 
          signer.getCapability<&{FungibleToken.Receiver}>
                              (ExampleToken.ReceiverPublicPath)
      
      // Check if the receiver capability exists
      assert(self.tokenForwarderCapability.check(), 
          message: "Signer does not have a working fungible token receiver capability")
      
      // Get a reference to the signers switchboard
      self.switchboardRef = signer.borrow<&FungibleTokenSwitchboard.Switchboard>
          (from: FungibleTokenSwitchboard.StoragePath) 
          ?? panic("Could not borrow reference to switchboard")
  
  }

  execute {

      // Add the capability to the switchboard using addNewVault method
      self.switchboardRef.addNewVaultWrapper(capability: self.tokenForwarderCapability, type: Type<@ExampleToken.Vault>())
  
  }

}

Removing a vault from the switchboard

If a user no longer wants to be able to receive deposits from a certain FT, or if they want to update the provided capability for one of them, they will need to remove the vault from the switchboard. This can be accomplished by using removeVault(capability: Capability<&{FungibleToken.Receiver}>). This can be observed in the template transaction transactions/switchboard/remove_vault_capability.cdc:

transaction {
   let exampleTokenVaultCapabilty: Capability<&{FungibleToken.Receiver}>
   let switchboardRef:  &FungibleTokenSwitchboard.Switchboard

   prepare(signer: AuthAccount) {
     // Get the example token vault capability from the signer's account
     self.exampleTokenVaultCapability = signer.getCapability
                   <&{FungibleToken.Receiver}>(ExampleToken.ReceiverPublicPath)
     // Get a reference to the signers switchboard  
     self.switchboardRef = signer.borrow<&FungibleTokenSwitchboard.Switchboard>
       (from: FungibleTokenSwitchboard.StoragePath) 
         ?? panic("Could not borrow reference to switchboard")

   }

   execute {
     // Remove the capability from the switchboard using the 
     // removeVault method
     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.

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. An example of how to do this can be found in the transaction template on this repo transactions/switchboard/transfer_tokens.cdc
transaction(to: Address, amount: UFix64) {
   // The Vault resource that holds the tokens that are being transferred
   let sentVault: @FungibleToken.Vault

   prepare(signer: AuthAccount) {

       // Get a reference to the signer's stored vault
       let vaultRef = signer.borrow<&ExampleToken.Vault>
                                   (from: ExampleToken.VaultStoragePath)
   		?? panic("Could not borrow reference to the owner's Vault!")

       // Withdraw tokens from the signer's stored vault
       self.sentVault <- vaultRef.withdraw(amount: amount)
   }

   execute {

       // Get the recipient's public account object
       let recipient = getAccount(to)

       // Get a reference to the recipient's Switchboard Receiver
       let switchboardRef = recipient.getCapability
           (FungibleTokenSwitchboard.ReceiverPublicPath)
           .borrow<&{FungibleToken.Receiver}>()
   		    ?? panic("Could not borrow receiver reference to switchboard!")

       // Deposit the withdrawn tokens in the recipient's switchboard receiver
       switchboardRef.deposit(from: <-self.sentVault)
   }
}
  1. 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:
transaction(to: Address, amount: UFix64) {
   // The reference to the vault from the payer's account
   let vaultRef: &ExampleToken.Vault
   // The Vault resource that holds the tokens that are being transferred
   let sentVault: @FungibleToken.Vault


   prepare(signer: AuthAccount) {

       // Get a reference to the signer's stored vault
       self.vaultRef = signer.borrow<&ExampleToken.Vault>(from: ExampleToken.VaultStoragePath)
   		?? panic("Could not borrow reference to the owner's Vault!")

       // Withdraw tokens from the signer's stored vault
       self.sentVault <- self.vaultRef.withdraw(amount: amount)
   }

   execute {

       // Get the recipient's public account object
       let recipient = getAccount(to)

       // Get a reference to the recipient's Switchboard Receiver
       let switchboardRef = recipient.getCapability(FungibleTokenSwitchboard.PublicPath)
           .borrow<&FungibleTokenSwitchboard.Switchboard{FungibleTokenSwitchboard.SwitchboardPublic}>()
   		?? panic("Could not borrow receiver reference to switchboard!")

       // Deposit the withdrawn tokens in the recipient's switchboard receiver,
       // then deposit the returned vault in the signer's vault
       self.vaultRef.deposit(from: <- switchboardRef.safeDeposit(from: <-self.sentVault))
   }
}

Running Automated Tests

You can find automated tests in the lib/go/test/token_test.go file. It uses the transaction templates that are contained in the lib/go/templates/transaction_templates.go file. Currently, these rely on a dependency from a private dapper labs repository to run, so external users will not be able to run them. We are working on making all of this public so anyone can run tests, but haven't completed this work yet.

License

The works in these folders are under the Unlicense:

More Repositories

1

flow-go

A fast, secure, and developer-friendly blockchain built to support the next generation of games, apps, and the digital assets that power them.
Go
532
star
2

cadence

Cadence, the resource-oriented smart contract programming language πŸƒβ€β™‚οΈ
Go
505
star
3

flow-nft

The non-fungible token standard on the Flow blockchain
Cadence
459
star
4

kitty-items

Kitty Items: CryptoKitties Sample App
JavaScript
408
star
5

flow

Flow is a fast, secure, and developer-friendly blockchain built to support the next generation of games, apps, and the digital assets that power them 🌊
Go
357
star
6

fcl-js

FCL (Flow Client Library) - The best tool for building JavaScript (browser & NodeJS) applications on Flow 🌊
JavaScript
318
star
7

flow-go-sdk

Tools for building Go applications on Flow 🌊
Go
211
star
8

flow-cli

The Flow CLI is a command-line interface that provides useful utilities for building Flow applications
Go
207
star
9

flow-playground

Flow Playground front-end app πŸ€Ήβ€β™‚οΈ
TypeScript
112
star
10

nft-storefront

A general-purpose Cadence contract for trading NFTs on Flow
Cadence
102
star
11

flow-core-contracts

Cadence smart contracts that define core functionality of the Flow protocol
Go
86
star
12

flow-emulator

The Flow Emulator is a lightweight tool that emulates the behaviour of the real Flow network
Go
84
star
13

freshmint

TypeScript
68
star
14

vscode-cadence

The Visual Studio Code extension for Cadence
TypeScript
52
star
15

fcl-dev-wallet

A Flow wallet for development purposes. To be used with the Flow Emulator.
Go
50
star
16

developer-grants

Grants for developers that contribute to the broader developer ecosystem
50
star
17

flip-fest

A backlog of all the available tasks to complete for Flow's FLIP Fest.
50
star
18

flow-js-testing

Testing framework to enable Cadence testing via a set of JavaScript methods and tools
JavaScript
46
star
19

atree

Atree provides scalable arrays and scalable ordered maps.
Go
39
star
20

nft-catalog

Cadence
37
star
21

flow-101-quest

Cadence
30
star
22

flips

Flow Improvement Proposals
25
star
23

cadence-tools

Developer tools for Cadence
Go
24
star
24

flow-cadut

Node based template generator to simplify interaction with Cadence files.
JavaScript
22
star
25

wallet-api

A REST API to create and manage Flow accounts
HTML
22
star
26

walletless-arcade-example

An example Flow App to demonstrate walletless onboarding and promote composable, secure, and smooth UX for on-chain games without the need for a traditional backend.
Cadence
21
star
27

monster-maker

Create a monster on Flow
TypeScript
18
star
28

hybrid-custody

Cadence suite enabling Hybrid Custody on Flow
Cadence
15
star
29

rosetta

Rosetta implementation for the Flow blockchain
Go
15
star
30

UnityFlowSDK

Flow SDK for Unity - build Unity games on the Flow blockchain
C#
13
star
31

flow-java-client-example

Java
12
star
32

wallet-extension-example

An example and guide showing how to build an FCL-compatible wallet extension on Flow.
JavaScript
12
star
33

fcl-discovery

JavaScript
11
star
34

flow-interaction-template-service

TypeScript
11
star
35

flow-playground-api

Flow Playground back-end app πŸ€Ήβ€β™‚οΈ
Go
11
star
36

linked-accounts

Cadence
11
star
37

ledger-app-flow

JavaScript
10
star
38

sc-eng-gaming

Showcasing how a Rock Paper Scissors game could be made #onFlow
Cadence
10
star
39

flow-batch-scan

Library for running batch scans of the flow network
Go
10
star
40

flow-evm-gateway

FlowEVM Gateway implements an Ethereum-equivalent JSON-RPC API for EVM clients to use
Go
9
star
41

cadence-libraries

Libraries for common programming utilities in the Cadence smart contract programming language
Go
9
star
42

flow-evm-bridge

Repository for contracts supporting bridge between Flow <> EVM
Cadence
9
star
43

sdks

Tips and resources for building Flow SDKs and client libraries πŸ”§
Cadence
9
star
44

developer-portal

Source code for developers.flow.com
TypeScript
8
star
45

docs

Flow Developer Portal. Discover the developer ecosystem and master the Flow blockchain
TypeScript
8
star
46

cadence-lang.org

The home of the Cadence website
MDX
8
star
47

cadence-cookbook

JavaScript
8
star
48

flow-multisig

JavaScript
8
star
49

OWBSummer2020Project

OWB (Open World Builders) bootcamp summer 2020 cohort capstone projects submission
CSS
8
star
50

Flow-Working-Groups

8
star
51

casestudies

Learn more about building on Flow from teams that have already launched successful projects
7
star
52

BFTune

Byzantine Fault Tolerance (BFT) Testing Framework for Flow
7
star
53

cadence-style-guide

The Flow Team guide on how to write better Cadence code
7
star
54

twg

Tokenomics Working Group
6
star
55

flowkit

Go
6
star
56

flow-interaction-template-tools

TypeScript
6
star
57

flow-kmm

Kotlin Multiplatform Mobile (KMM) library for building Android and iOS applications on the Flow blockchain
Objective-C
5
star
58

scaffold-flow

🌊 forkable Flow dev stack focused on fast product iterations
JavaScript
5
star
59

flow-issue-box

A public repository dedicated to collecting issues and feedback from external contributors. The Issue Box πŸ—³οΈ is similar to a backlog, where the issue is later triaged and assigned to the proper team.
5
star
60

ccf

Cadence Compact Format (CCF) is a binary data format and alternative to JSON-CDC
4
star
61

token-cold-storage

JavaScript
4
star
62

cddl

A CDDL implementation in Go
Go
4
star
63

Offers

Cadence
4
star
64

full-observer-node-example

An example demonstrating the use of the Flow unstaked consensus follower
Go
4
star
65

flow-account-api

Go
4
star
66

faucet

Cadence
4
star
67

contract-updater

Enabling delayed contract updates to a wrapped account at or beyond a specified block height
Cadence
4
star
68

flow-validator

Run a Flow node and help secure the network
4
star
69

flow-playground-tutorials

Repository to contain and test tutorials, which are deployed to Playground and used in docs
Cadence
3
star
70

flow-public-key-indexer

A observer service for indexing flow Accounts and by their associated Keys.
Go
3
star
71

flow-cadence-eth-utils

Cadence
3
star
72

flow-cadence-hrt

Write your Cadence tests with human readable TOML
JavaScript
3
star
73

random-coin-toss

An example repo demonstrating safe use of onchain randomness
Cadence
3
star
74

blindninja

Blind Ninja is a composability-first fully onchain game on Flow
JavaScript
3
star
75

waterhose

Waterhose listens to Flow events and publishes them to Kafka
2
star
76

fcl-auth-android

A Kotlin library for the Flow Client Library (FCL) that enables Flow wallet authentication on Android devices
Kotlin
2
star
77

service-account

Cadence
2
star
78

fcl-six

Stored Interactions (SIX) for FCL
JavaScript
2
star
79

flow-scaffold-list

Scaffolds for starting Flow apps
2
star
80

hybrid-custody-scaffold

Starter template for working with HybridCustody contract suite
Cadence
2
star
81

fcl-contracts

Cadence contracts used by the Flow Client Library (FCL)
Cadence
2
star
82

crypto

Assembly
2
star
83

dex

2
star
84

gwg

The Flow Governance Working Group (GWG) is an open-for-all forum that plays a pivotal role in shaping the Flow ecosystem with a focus on discussing and resolving governance issues.
2
star
85

next-docs-v0

next-docs
JavaScript
1
star
86

storage-fees-scripts

1
star
87

unity-flow-sdk-api-docs

HTML
1
star
88

fusd

Cadence source code for the FUSD stablecoin on Flow
Cadence
1
star
89

band-oracle-contracts

Contracts and related for integration with Band protocol Oracle Network
Cadence
1
star
90

cadence-1-migrator

Cadence
1
star
91

fcl-gcp-kms-web

JavaScript
1
star
92

fcl-next-scaffold

JavaScript
1
star
93

wallet-wg

Flow Wallet Working Group
1
star
94

minting-nfts-in-a-set

Cadence Cookbook Recipe: Minting NFTs in a Set
Cadence
1
star
95

create-a-marketplace

Cadence Cookbook Recipe: Create a Marketplace
Cadence
1
star
96

metadata-views

Cadence Cookbook Recipe: Metadata Views
Cadence
1
star
97

create-a-topshot-play

Cadence Cookbook Recipe: Create a TopShot Play
Cadence
1
star
98

collection-for-holding-nfts

Cadence Cookbook Recipe: Collection for Holding NFTs
Cadence
1
star
99

add-a-play-to-topshot-set

Cadence Cookbook Recipe: Add a Play to TopShot Set
Cadence
1
star
100

minting-a-moment-in-topshot-set

Cadence Cookbook Recipe: Minting a Moment in TopShot Set
Cadence
1
star