{"id":19610854,"url":"https://github.com/onflow/flow-ft","last_synced_at":"2026-02-02T08:38:28.658Z","repository":{"id":37526919,"uuid":"257023041","full_name":"onflow/flow-ft","owner":"onflow","description":"The Fungible Token standard on the Flow Blockchain ","archived":false,"fork":false,"pushed_at":"2026-01-13T22:23:20.000Z","size":3420,"stargazers_count":139,"open_issues_count":2,"forks_count":51,"subscribers_count":41,"default_branch":"master","last_synced_at":"2026-01-14T00:44:31.820Z","etag":null,"topics":["blockchain","fungible-tokens","linear-types","onflow","smart-contracts"],"latest_commit_sha":null,"homepage":"https://onflow.org","language":"Cadence","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/onflow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-04-19T14:39:48.000Z","updated_at":"2026-01-13T22:21:58.000Z","dependencies_parsed_at":"2023-09-26T20:36:33.244Z","dependency_job_id":"aca9cf9e-ff7a-4bfd-a8ee-bdf4ef2189c9","html_url":"https://github.com/onflow/flow-ft","commit_stats":{"total_commits":153,"total_committers":21,"mean_commits":7.285714285714286,"dds":0.6405228758169934,"last_synced_commit":"35ba90f3212a36f7b6d7e115ff3fe4eac4289471"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/onflow/flow-ft","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-ft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-ft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-ft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-ft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onflow","download_url":"https://codeload.github.com/onflow/flow-ft/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-ft/sbom","scorecard":{"id":707272,"data":{"date":"2025-08-11","repo":{"name":"github.com/onflow/flow-ft","commit":"e27c9b72a795d52c0c8f918d7ae2667f5b935b39"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.1,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":9,"reason":"Found 10/11 approved changesets -- score normalized to 9","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/onflow/flow-ft/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/onflow/flow-ft/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/onflow/flow-ft/ci.yml/master?enable=pin","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: The Unlicense: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":7,"reason":"3 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2024-2819 / GHSA-4xc9-8hmq-j652","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T07:02:24.624Z","repository_id":37526919,"created_at":"2025-08-22T07:02:24.624Z","updated_at":"2025-08-22T07:02:24.624Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29008255,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-02T08:20:25.892Z","status":"ssl_error","status_checked_at":"2026-02-02T08:20:04.345Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","fungible-tokens","linear-types","onflow","smart-contracts"],"created_at":"2024-11-11T10:34:05.418Z","updated_at":"2026-02-02T08:38:28.643Z","avatar_url":"https://github.com/onflow.png","language":"Cadence","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fungible Token Standard\n\nThis is a description of the Flow standard for fungible token contracts. \nIt is meant to contain the minimum requirements to implement a safe, secure, easy to understand,\nand easy to use fungible token contract.\nIt also includes an example implementation to show how a \nconcrete smart contract would actually implement the interface.\n\nThe version of the contracts in the `master` branch is the\nCadence 1.0 version of the contracts and is not the same\nas the ones that are currently deployed to testnet and mainnet.\nSee the `cadence-0.42` branch for the currently deployed versions.\n\n## What is Flow?\n\nFlow is a new blockchain for open worlds. Read more about it [here](https://www.flow.com/).\n\n## What is Cadence?\n\nCadence is a new Resource-oriented programming language \nfor developing smart contracts for the Flow Blockchain.\nRead more about it [here](https://developers.flow.com/) and see its implementation [here](https://github.com/onflow/cadence)\n\nWe recommend that anyone who is reading this should have already\ncompleted the [Cadence Tutorials](https://cadence-lang.org/docs/tutorial/first-steps) \nso they can build a basic understanding of the programming language.\n\nResource-oriented programming, and by extension Cadence, \nis the perfect programming environment for currencies, because users are able\nto store their tokens directly in their accounts and transact\npeer-to-peer. Please see the [blog post about resources](https://medium.com/dapperlabs/resource-oriented-programming-bee4d69c8f8e)\nto understand why they are perfect for digital assets.\n\n## Import Addresses\n\nThe `FungibleToken`, `FungibleTokenMetadataViews`, and `FungibleTokenSwitchboard` contracts are already deployed\non various networks. You can import them in your contracts from these addresses.\nThere is no need to deploy them yourself.\n\n| Network           | Contract Address     |\n| ----------------- | -------------------- |\n| Emulator          | `0xee82856bf20e2aa6` |\n| Testnet           | `0x9a0766d93b6608b7` |\n| Sandboxnet        | `0xe20612a0776ca4bf` |\n| Mainnet           | `0xf233dcee88fe0abe` |\n\nThe `Burner` contract is also deployed to these addresses, but should only be used in Cadence 1.0 `FungibleToken` implementations of the standard.\n\n## Basics of the Standard:\n\nThe code for the standard is in [`contracts/FungibleToken.cdc`](contracts/FungibleToken.cdc). An example implementation of the standard that simulates what a simple token would be like is in [`contracts/ExampleToken.cdc`](contracts/FungibleToken.cdc). \n\nThe exact smart contract that is used for the official Flow Network Token (`FlowToken`) is in [the `flow-core-contracts` repository](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowToken.cdc).\n\nExample 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.\n\nThe standard consists of a contract interface called `FungibleToken` that defines important\nfunctionality for token implementations. Contracts are expected to define a resource\nthat implement the `FungibleToken.Vault` resource interface.\nA `Vault` represents the tokens that an account owns. Each account that owns tokens\nwill have a `Vault` stored in its account storage. \nUsers call functions on each other's `Vault`s to send and receive tokens.  \n\nThe standard uses 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.\n\n## Core Features (All contained in the main FungibleToken interface)\n\n### `Balance` Interface\n\nSpecifies that the implementing type must have a `UFix64` `balance` field.\n  - `access(all) var balance: UFix64`\n\n### `Provider` Interface\nDefines a [`withdraw ` function](contracts/FungibleToken.cdc#L95) for withdrawing a specific amount of tokens as *amount*.\n  - `access(all) fun withdraw(amount: UFix64): @{FungibleToken.Vault}`\n      - Conditions\n          - the returned Vault's balance must equal the amount withdrawn\n          - The amount withdrawn must be less than or equal to the balance\n          - The resulting balance must equal the initial balance - amount\n  - Users can give other accounts a persistent Capability\n  or ephemeral reference to their `Vault` cast as a `Provider`\n  to allow them to withdraw and send tokens for them. \n  A contract can define any custom logic to govern the amount of tokens\n  that can be withdrawn at a time with a `Provider`. \n  This can mimic the `approve`, `transferFrom` functionality of ERC20.\n- [`FungibleToken.Withdrawn` event](contracts/FungibleToken.cdc#L50)\n    - Event that is emitted automatically to indicate how much was withdrawn\n    and from what account the `Vault` is stored in.\n      If the `Vault` is not in account storage when the event is emitted,\n      `from` will be `nil`.\n    - Contracts do not have to emit their own events,\n    the standard events will automatically be emitted from the interface contract with values identifying the relevant `Vault`.\n\nDefines [an `isAvailableToWithdraw()` function](contracts/FungibleToken.cdc#L95)\nto ask a `Provider` if the specified number of tokens can be withdrawn from the implementing type.\n\n### `Receiver` Interface\nDefines functionality to depositing fungible tokens into a resource object.\n- [`deposit()` function](contracts/FungibleToken.cdc#L119):\n  - `access(all) fun deposit(from: @{FungibleToken.Vault})`\n  - Conditions\n      - `from` balance must be non-zero\n      - The resulting balance must be equal to the initial balance + the balance of `from`\n  - It is important that if you are making your own implementation of the fungible token interface that\n  you cast the input to `deposit` as the type of your token.\n  `let vault \u003c- from as! @ExampleToken.Vault`\n  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 incrementing the receiving `Vault`'s balance.\n- deposit event\n    - [`FungibleToken.Deposited` event](contracts/FungibleToken.cdc#L53) from the standard\n    that indicates how much was deposited and to what account the `Vault` is stored in.\n      - If the `Vault` is not in account storage when the event is emitted,\n        `to` will be `nil`.\n      - This event is emitted from the interface contract automatically on any deposit,\n        so projects do not need to define and emit their own events.\n\nDefines Functionality for Getting Supported Vault Types\n- Some resource types can accept multiple different vault types in their deposit functions,\n  so the `getSupportedVaultTypes()` and `isSupportedVaultType()` functions allow callers\n  to query a resource that implements `Receiver` to see if the `Receiver` accepts\n  their desired `Vault` type in its deposit function.\n\nUsers could create custom `Receiver`s to trigger special code when transfers to them happen,\nlike forwarding the tokens to another account, splitting them up, and much more.\n\n### `Vault` Interface\n[Interface](contracts/FungibleToken.cdc#L134) that inherits from `Provider`, `Receiver`, `Balance`, `ViewResolver.Resolver`,\nand `Burner.Burnable` and provides additional pre and post conditions.\n\nThe `ViewResolver.Resolver` interface defines functionality for retrieving metadata\nabout a particular resource object. [Fungible Token metadata](README.md#ft-metadata) is described below.\n\nSee the comments in [the `Burner` contract](contracts/Burner.cdc) for context about it.\nBasically, it defines functionality for tokens to have custom logic when those tokens\nare destroyed.\n\n### Creating an empty Vault resource\nDefines functionality in the contract to create a new empty vault of\nof the contract's defined type.\n- `access(all) fun createEmptyVault(vaultType: Type): @{FungibleToken.Vault}`\n- Defined in the contract \n- To create an empty `Vault`, the caller calls the function and provides the Vault Type\n  that they want. They get a vault back and can store it in their storage.\n- Conditions:\n    - the balance of the returned Vault must be 0\n\n\n## Comparison to Similar Standards in Ethereum\n\nThis spec covers much of the same ground that a spec like ERC-20 covers, but without most of the downsides.  \n\n- 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.\n- 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`\n- 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.\n- The `approve`, `transferFrom` pattern is not included, so double spends are not permitted\n- Transfers can trigger actions because users can define custom `Receivers` to execute certain code when a token is sent.\n- Cadence integer types protect against overflow and underflow, so a `SafeMath`-equivalent library is not needed.\n\n## FT Metadata\n\nFT Metadata is represented in a flexible and modular way using both\nthe [standard proposed in FLIP-0636](https://github.com/onflow/flips/blob/main/application/20210916-nft-metadata.md)\nand the [standard proposed in FLIP-1087](https://github.com/onflow/flips/blob/main/application/20220811-fungible-tokens-metadata.md).\n\n[A guide for NFT metadata](https://developers.flow.com/build/advanced-concepts/metadata-views)\nis provided on the docs site. Many of the concepts described there also apply\nto fungible tokens, so it is useful to read for any Cadence developer.\n\nWhen writing an FT contract interface, your contract will implement\nthe `FungibleToken` contract interface which already inherits\nfrom [the `ViewResolver` contract interface](https://github.com/onflow/flow-nft/blob/master/contracts/ViewResolver.cdc),\nso you will be required to implement the metadata functions.\nAdditionally, your `Vault` will also implement the `ViewResolver.Resolver` by default,\nwhich allows your `Vault` resource to implement one or more metadata types called views.\n\nViews do not specify or require how to store your metadata, they only specify\nthe format to query and return them, so projects can still be flexible with how they store their data.\n\n### Fungible token Metadata Views\n\nThe [FungibleTokenMetadataViews contract](contracts/FungibleTokenMetadataViews.cdc) defines four new views that can used to communicate any fungible token information:\n\n1. `FTView`: A view that wraps the two other views that actually contain the data.\n2. `FTDisplay`: The view that contains all the information that will be needed\nby other dApps to display the fungible token: name, symbol, description, external URL, logos and links to social media.\n3. `FTVaultData`: The view that can be used by other dApps to interact programmatically\nwith the fungible token, providing the information about the public and storage paths\nused by default by the token, the public linked types for exposing capabilities\nand the function for creating new empty vaults.\nYou 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)\n4. `TotalSupply`: Specifies the total supply of the given token.\n\n### How to implement metadata\n\nThe [Example Token contract](contracts/ExampleToken.cdc) shows how to implement metadata views for fungible tokens.\n\n### How to read metadata\n\nIn 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).\n\nLatter 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:\n\n\n\n## Bonus Features\n\nThe following features could each be defined as a separate standard. 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.\n\n- Scoped Provider \nThis refers to restricting a `Provider` capability to only be able to withdraw a specific amount of tokens from someone else's `Vault`\nThis is currently being worked on.\n\n- Pausing Token transfers (maybe a way to prevent the contract from being imported)\n- Cloning the token to create a new token with the same distribution\n- Restricted ownership (For accredited investors and such)\n- allowlisting\n- denylisting\n\n# How to use the Fungible Token contract\n\nTo use the Flow Token contract as is, you need to follow these steps:\n\n1. If you are using any network or the playground, there is no need to deploy\nthe `FungibleToken` definition to accounts yourself.\nIt is a pre-deployed interface in the emulator, testnet, mainnet,\nand playground and you can import definition from those accounts:\n    - `0xee82856bf20e2aa6` on emulator\n    - `0x9a0766d93b6608b7` on testnet/crescendo\n    - `0xf233dcee88fe0abe` on mainnet\n2. Deploy the `ExampleToken` definition, making sure to import the `FungibleToken` interface.\n3. You can use the `get_balance.cdc` or `get_supply.cdc` scripts to read the \n   balance of a user's `Vault` or the total supply of all tokens, respectively.\n4. Use the `setup_account.cdc` on any account to set up the account to be able to\n   use `ExampleToken`.\n5. Use the `transfer_tokens.cdc` transaction file to send tokens from one user with\n   a `Vault` in their account storage to another user with a `Vault` in their account storage.\n6. Use the `mint_tokens.cdc` transaction with the admin account to mint new tokens.\n7. Use the `burn_tokens.cdc` transaction with the admin account to burn tokens.\n8. Use the `create_minter.cdc` transaction to create a new MintandBurn resource\n   and store it in a new Admin's account.\n\n# Fungible Token Switchboard\n\n`FungibleTokenSwitchboard.cdc`, allows users to receive payments in different fungible tokens using a single `\u0026{FungibleToken.Receiver}` placed in a standard receiver path `/public/GenericFTReceiver`.\n\n ## How to use it\n\n 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.\n \n This can be accomplished by executing the transaction found in this repository `transactions/switchboard/setup_account.cdc`.\n This transaction will create and save a Switchboard resource to the signer's account,\n and it also will create the needed public capabilities to access it.\n After setting up their switchboard, in order to make it support receiving a certain token,\n users will need to add the desired token's receiver capability to their switchboard resource.\n \n ## Adding a new vault to the switchboard\n When a user wants to receive a new fungible token through their switchboard,\n they will need to add a new public capability linked to said FT\n to their switchboard resource. This can be accomplished in two different ways:\n \n 1. Adding a single capability using `addNewVault(capability: Capability\u003c\u0026{FungibleToken.Receiver}\u003e)`\n    * Before calling this method on a transaction you should first retrieve the capability to the token's vault you are\n    willing to add to the switchboard, as is done in the template transaction [`transactions/switchboard/add_vault_capability.cdc`](./transactions/switchboard/add_vault_capability.cdc).\n\n    This function will panic if is not possible to `.borrow()` a reference\n    to a `\u0026{FungibleToken.Receiver}` from the passed capability.\n\n 2. Adding one or more capabilities using the paths where they are stored using `addNewVaultsByPath(paths: [PublicPath], address: Address)`. This is shown in\n    the [`batch_add_vault_wrapper_capabilities.cdc` transaction](./transactions/switchboard/batch_add_vault_wrapper_capabilities.cdc)\n    * 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.\n\n    This function won't panic, instead it will just not add to the `@Switchboard`\n    any capability which can not be retrieved from any of the provided `PublicPath`s.\n    It will also ignore any type of `\u0026{FungibleToken.Receiver}` that is already present on the `@Switchboard`\n\n  3. Adding a capability to a receiver specifying which type of token will be deposited there \n  using `addNewVaultWrapper(capability: Capability\u003c\u0026{FungibleToken.Receiver}\u003e, type: Type)`. \n  This method can be used to link a token forwarder or any other wrapper to the switchboard. \n  Once the `Forwarder` has been properly created containing the capability to an actual `@FungibleToken.Vault`,\n  this method can be used to link the `@Forwarder` to the switchboard to deposit the specified type of Fungible Token.\n  In [the template transaction  `switchboard/add_vault_wrapper_capability.cdc`](./transactions/switchboard/add_vault_wrapper_capability.cdc),\n  we assume that the signer has a forwarder containing a capability to an `@ExampleToken.Vault` resource:\n\n ## Removing a vault from the switchboard\n If a user no longer wants to be able to receive deposits from a certain FT,\n or if they want to update the provided capability for one of them,\n they will need to remove the vault from the switchboard.\n This can be accomplished by using `removeVault(capability: Capability\u003c\u0026{FungibleToken.Receiver}\u003e)`. \nThis can be observed in [the template transaction `transactions/switchboard/remove_vault_capability.cdc`](./transactions/switchboard/remove_vault_capability.cdc):\n\n This function will panic if is not possible to `.borrow()` a reference to a `\u0026{FungibleToken.Receiver}` from the passed capability.\n\n ## Transferring tokens through the switchboard\n The Fungible Token Switchboard provides two different ways of depositing tokens to it,\n using the `deposit(from: @{FungibleToken.Vault})` method enforced by\n the `{FungibleToken.Receiver}` or using the `safeDeposit(from: @FungibleToken.Vault): @FungibleToken`:\n\n 1. Using the first method will be just the same as depositing to `\u0026{FungibleToken.Receiver}`.\n The path for the Switchboard receiver is defined in `FungibleTokenSwitchboard.ReceiverPublicPath`,\n the generic receiver path `/public/GenericFTReceiver` that can also be obtained from the NFT MetadataViews contract.\n An example of how to do this can be found in the transaction template on this repo [`transactions/switchboard/transfer_tokens.cdc`](./transactions/switchboard/transfer_tokens.cdc).\n\n 2. The `safeDeposit(from: @FungibleToken.Vault): @FungibleToken` works in a similar way,\n with the difference that it will not panic if the desired FT Vault\n can not be obtained from the Switchboard. The method will return the passed vault,\n empty if the funds were deposited successfully or still containing the funds\n if the transfer of the funds was not possible. Keep in mind that \n when using this method on a transaction you will always have to deal\n with the returned resource. An example of this can be found on [`transactions/switchboard/safe_transfer_tokens.cdc`](./transactions/switchboard/safe_transfer_tokens.cdc):\n\n# Running Automated Tests\n\nThere are two sets of tests in the repo, Cadence tests and Go tests.\nThe Cadence tests are much more straightforward and are all written in Cadence,\nso we recommend following those.\n\n## Cadence Testing Framework\n\nThe Cadence tests are located in the `tests/` repository. They are written in Cadence\nand can be run directly from the command line using the Flow CLI.\nMake sure you are using [the latest Cadence 1.0 CLI verion](https://forum.flow.com/t/update-on-cadence-1-0/5197/10).\n```\nflow test --cover --covercode=\"contracts\" tests/*.cdc\n```\n\n## Go tests\n\nYou can find automated tests in the `lib/go/test/token_test.go` file.\nIt uses the transaction templates that are contained in the\n`lib/go/templates/transaction_templates.go` file. You can run them by navigating\nto the `lib/go/test/` directory and running `go test -v`.\nIf you make changes to the contracts or transactions in between running tests,\nyou will need to run `make generate` from the `lib/go/` directory\nto generate the assets used in the tests.\n\n## License \n\nThe works in these folders are under the [Unlicense](https://github.com/onflow/flow-ft/blob/master/LICENSE):\n\n- [/contracts](https://github.com/onflow/flow-ft/blob/master/contracts/)\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonflow%2Fflow-ft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonflow%2Fflow-ft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonflow%2Fflow-ft/lists"}