Skip to main content
Version: Next

Accounts

Every account can be accessed through two types, PublicAccount and AuthAccount.

PublicAccount

Public Account objects have the type PublicAccount, which represents the publicly available portion of an account.


_88
access(all) struct PublicAccount {
_88
_88
/// The address of the account.
_88
access(all) let address: Address
_88
_88
/// The FLOW balance of the default vault of this account.
_88
access(all) let balance: UFix64
_88
_88
/// The FLOW balance of the default vault of this account that is available to be moved.
_88
access(all) let availableBalance: UFix64
_88
_88
/// The current amount of storage used by the account in bytes.
_88
access(all) let storageUsed: UInt64
_88
_88
/// The storage capacity of the account in bytes.
_88
access(all) let storageCapacity: UInt64
_88
_88
/// The contracts deployed to the account.
_88
access(all) let contracts: PublicAccount.Contracts
_88
_88
/// The keys assigned to the account.
_88
access(all) let keys: PublicAccount.Keys
_88
_88
/// The capabilities of the account.
_88
pub let capabilities: PublicAccount.Capabilities
_88
_88
/// All public paths of this account.
_88
access(all) let publicPaths: [PublicPath]
_88
_88
/// Iterate over all the public paths of an account.
_88
/// passing each path and type in turn to the provided callback function.
_88
///
_88
/// The callback function takes two arguments:
_88
/// 1. The path of the stored object
_88
/// 2. The runtime type of that object
_88
///
_88
/// Iteration is stopped early if the callback function returns `false`.
_88
///
_88
/// The order of iteration, as well as the behavior of adding or removing objects from storage during iteration,
_88
/// is undefined.
_88
access(all) fun forEachPublic(_ function: fun(PublicPath, Type): Bool)
_88
_88
access(all) struct Contracts {
_88
_88
/// The names of all contracts deployed in the account.
_88
access(all) let names: [String]
_88
_88
/// Returns the deployed contract for the contract/contract interface with the given name in the account, if any.
_88
///
_88
/// Returns nil if no contract/contract interface with the given name exists in the account.
_88
access(all) fun get(name: String): DeployedContract?
_88
_88
/// Returns a reference of the given type to the contract with the given name in the account, if any.
_88
///
_88
/// Returns nil if no contract with the given name exists in the account,
_88
/// or if the contract does not conform to the given type.
_88
access(all) fun borrow<T: &Any>(name: String): T?
_88
}
_88
_88
access(all) struct Keys {
_88
_88
/// Returns the key at the given index, if it exists, or nil otherwise.
_88
///
_88
/// Revoked keys are always returned, but they have `isRevoked` field set to true.
_88
access(all) fun get(keyIndex: Int): AccountKey?
_88
_88
/// Iterate over all unrevoked keys in this account,
_88
/// passing each key in turn to the provided function.
_88
///
_88
/// Iteration is stopped early if the function returns `false`.
_88
/// The order of iteration is undefined.
_88
access(all) fun forEach(_ function: fun(AccountKey): Bool)
_88
_88
/// The total number of unrevoked keys in this account.
_88
access(all) let count: UInt64
_88
}
_88
_88
pub struct Capabilities {
_88
/// get returns the storage capability at the given path, if one was stored there.
_88
pub fun get<T: &Any>(_ path: PublicPath): Capability<T>?
_88
_88
/// borrow gets the storage capability at the given path, and borrows the capability if it exists.
_88
///
_88
/// Returns nil if the capability does not exist or cannot be borrowed using the given type.
_88
/// The function is equivalent to `get(path)?.borrow()`.
_88
pub fun borrow<T: &Any>(_ path: PublicPath): T?
_88
}
_88
}

Any code can get the PublicAccount for an account address using the built-in getAccount function:


_10
fun getAccount(_ address: Address): PublicAccount

AuthAccount

Authorized Account object have the type AuthAccount, which represents the authorized portion of an account.

Access to an AuthAccount means having full access to its storage, public keys, and code.

Only signed transactions can get the AuthAccount for an account. For each signer of the transaction that signs as an authorizer, the corresponding AuthAccount object is passed to the prepare phase of the transaction.


_354
access(all) struct AuthAccount {
_354
_354
/// The address of the account.
_354
access(all) let address: Address
_354
_354
/// The FLOW balance of the default vault of this account.
_354
access(all) let balance: UFix64
_354
_354
/// The FLOW balance of the default vault of this account that is available to be moved.
_354
access(all) let availableBalance: UFix64
_354
_354
/// The current amount of storage used by the account in bytes.
_354
access(all) let storageUsed: UInt64
_354
_354
/// The storage capacity of the account in bytes.
_354
access(all) let storageCapacity: UInt64
_354
_354
/// The contracts deployed to the account.
_354
access(all) let contracts: AuthAccount.Contracts
_354
_354
/// The keys assigned to the account.
_354
access(all) let keys: AuthAccount.Keys
_354
_354
/// The inbox allows bootstrapping (sending and receiving) capabilities.
_354
access(all) let inbox: AuthAccount.Inbox
_354
_354
/// The capabilities of the account.
_354
pub let capabilities: AuthAccount.Capabilities
_354
_354
/// All public paths of this account.
_354
access(all) let publicPaths: [PublicPath]
_354
_354
/// All private paths of this account.
_354
access(all) let privatePaths: [PrivatePath]
_354
_354
/// All storage paths of this account.
_354
access(all) let storagePaths: [StoragePath]
_354
_354
/// Saves the given object into the account's storage at the given path.
_354
///
_354
/// Resources are moved into storage, and structures are copied.
_354
///
_354
/// If there is already an object stored under the given path, the program aborts.
_354
///
_354
/// The path must be a storage path, i.e., only the domain `storage` is allowed.
_354
access(all) fun save<T: Storable>(_ value: T, to: StoragePath)
_354
_354
/// Reads the type of an object from the account's storage which is stored under the given path,
_354
/// or nil if no object is stored under the given path.
_354
///
_354
/// If there is an object stored, the type of the object is returned without modifying the stored object.
_354
///
_354
/// The path must be a storage path, i.e., only the domain `storage` is allowed.
_354
access(all) fun type(at: StoragePath): Type?
_354
_354
/// Loads an object from the account's storage which is stored under the given path,
_354
/// or nil if no object is stored under the given path.
_354
///
_354
/// If there is an object stored,
_354
/// the stored resource or structure is moved out of storage and returned as an optional.
_354
///
_354
/// When the function returns, the storage no longer contains an object under the given path.
_354
///
_354
/// The given type must be a supertype of the type of the loaded object.
_354
/// If it is not, the function panics.
_354
///
_354
/// The given type must not necessarily be exactly the same as the type of the loaded object.
_354
///
_354
/// The path must be a storage path, i.e., only the domain `storage` is allowed.
_354
access(all) fun load<T: Storable>(from: StoragePath): T?
_354
_354
/// Returns a copy of a structure stored in account storage under the given path,
_354
/// without removing it from storage,
_354
/// or nil if no object is stored under the given path.
_354
///
_354
/// If there is a structure stored, it is copied.
_354
/// The structure stays stored in storage after the function returns.
_354
///
_354
/// The given type must be a supertype of the type of the copied structure.
_354
/// If it is not, the function panics.
_354
///
_354
/// The given type must not necessarily be exactly the same as the type of the copied structure.
_354
///
_354
/// The path must be a storage path, i.e., only the domain `storage` is allowed.
_354
access(all) fun copy<T: AnyStruct>(from: StoragePath): T?
_354
_354
/// Returns a reference to an object in storage without removing it from storage.
_354
///
_354
/// If no object is stored under the given path, the function returns nil.
_354
/// If there is an object stored, a reference is returned as an optional,
_354
/// provided it can be borrowed using the given type.
_354
/// If the stored object cannot be borrowed using the given type, the function panics.
_354
///
_354
/// The given type must not necessarily be exactly the same as the type of the borrowed object.
_354
///
_354
/// The path must be a storage path, i.e., only the domain `storage` is allowed
_354
access(all) fun borrow<T: &Any>(from: StoragePath): T?
_354
_354
/// Returns true if the object in account storage under the given path satisfies the given type,
_354
/// i.e. could be borrowed using the given type.
_354
///
_354
/// The given type must not necessarily be exactly the same as the type of the borrowed object.
_354
///
_354
/// The path must be a storage path, i.e., only the domain `storage` is allowed.
_354
access(all) fun check<T: Any>(from: StoragePath): Bool
_354
_354
/// Iterate over all the public paths of an account,
_354
/// passing each path and type in turn to the provided callback function.
_354
///
_354
/// The callback function takes two arguments:
_354
/// 1. The path of the stored object
_354
/// 2. The runtime type of that object
_354
///
_354
/// Iteration is stopped early if the callback function returns `false`.
_354
///
_354
/// The order of iteration is undefined.
_354
///
_354
/// If an object is stored under a new public path,
_354
/// or an existing object is removed from a public path,
_354
/// then the callback must stop iteration by returning false.
_354
/// Otherwise, iteration aborts.
_354
///
_354
access(all) fun forEachPublic(_ function: fun(PublicPath, Type): Bool)
_354
_354
/// Iterate over all the private paths of an account,
_354
/// passing each path and type in turn to the provided callback function.
_354
///
_354
/// The callback function takes two arguments:
_354
/// 1. The path of the stored object
_354
/// 2. The runtime type of that object
_354
///
_354
/// Iteration is stopped early if the callback function returns `false`.
_354
///
_354
/// The order of iteration is undefined.
_354
///
_354
/// If an object is stored under a new private path,
_354
/// or an existing object is removed from a private path,
_354
/// then the callback must stop iteration by returning false.
_354
/// Otherwise, iteration aborts.
_354
access(all) fun forEachPrivate(_ function: fun(PrivatePath, Type): Bool)
_354
_354
/// Iterate over all the stored paths of an account,
_354
/// passing each path and type in turn to the provided callback function.
_354
///
_354
/// The callback function takes two arguments:
_354
/// 1. The path of the stored object
_354
/// 2. The runtime type of that object
_354
///
_354
/// Iteration is stopped early if the callback function returns `false`.
_354
///
_354
/// If an object is stored under a new storage path,
_354
/// or an existing object is removed from a storage path,
_354
/// then the callback must stop iteration by returning false.
_354
/// Otherwise, iteration aborts.
_354
access(all) fun forEachStored(_ function: fun(StoragePath, Type): Bool)
_354
_354
access(all) struct Contracts {
_354
_354
/// The names of all contracts deployed in the account.
_354
access(all) let names: [String]
_354
_354
/// Adds the given contract to the account.
_354
///
_354
/// The `code` parameter is the UTF-8 encoded representation of the source code.
_354
/// The code must contain exactly one contract or contract interface,
_354
/// which must have the same name as the `name` parameter.
_354
///
_354
/// All additional arguments that are given are passed further to the initializer
_354
/// of the contract that is being deployed.
_354
///
_354
/// The function fails if a contract/contract interface with the given name already exists in the account,
_354
/// if the given code does not declare exactly one contract or contract interface,
_354
/// or if the given name does not match the name of the contract/contract interface declaration in the code.
_354
///
_354
/// Returns the deployed contract.
_354
access(all) fun add(
_354
name: String,
_354
code: [UInt8]
_354
): DeployedContract
_354
_354
/// **Experimental**
_354
///
_354
/// Updates the code for the contract/contract interface in the account.
_354
///
_354
/// The `code` parameter is the UTF-8 encoded representation of the source code.
_354
/// The code must contain exactly one contract or contract interface,
_354
/// which must have the same name as the `name` parameter.
_354
///
_354
/// Does **not** run the initializer of the contract/contract interface again.
_354
/// The contract instance in the world state stays as is.
_354
///
_354
/// Fails if no contract/contract interface with the given name exists in the account,
_354
/// if the given code does not declare exactly one contract or contract interface,
_354
/// or if the given name does not match the name of the contract/contract interface declaration in the code.
_354
///
_354
/// Returns the deployed contract for the updated contract.
_354
access(all) fun update__experimental(name: String, code: [UInt8]): DeployedContract
_354
_354
/// Returns the deployed contract for the contract/contract interface with the given name in the account, if any.
_354
///
_354
/// Returns nil if no contract/contract interface with the given name exists in the account.
_354
access(all) fun get(name: String): DeployedContract?
_354
_354
/// Removes the contract/contract interface from the account which has the given name, if any.
_354
///
_354
/// Returns the removed deployed contract, if any.
_354
///
_354
/// Returns nil if no contract/contract interface with the given name exists in the account.
_354
access(all) fun remove(name: String): DeployedContract?
_354
_354
/// Returns a reference of the given type to the contract with the given name in the account, if any.
_354
///
_354
/// Returns nil if no contract with the given name exists in the account,
_354
/// or if the contract does not conform to the given type.
_354
access(all) fun borrow<T: &Any>(name: String): T?
_354
}
_354
_354
access(all) struct Keys {
_354
_354
/// Adds a new key with the given hashing algorithm and a weight.
_354
///
_354
/// Returns the added key.
_354
access(all) fun add(
_354
publicKey: PublicKey,
_354
hashAlgorithm: HashAlgorithm,
_354
weight: UFix64
_354
): AccountKey
_354
_354
/// Returns the key at the given index, if it exists, or nil otherwise.
_354
///
_354
/// Revoked keys are always returned, but they have `isRevoked` field set to true.
_354
access(all) fun get(keyIndex: Int): AccountKey?
_354
_354
/// Marks the key at the given index revoked, but does not delete it.
_354
///
_354
/// Returns the revoked key if it exists, or nil otherwise.
_354
access(all) fun revoke(keyIndex: Int): AccountKey?
_354
_354
/// Iterate over all unrevoked keys in this account,
_354
/// passing each key in turn to the provided function.
_354
///
_354
/// Iteration is stopped early if the function returns `false`.
_354
///
_354
/// The order of iteration is undefined.
_354
access(all) fun forEach(_ function: fun(AccountKey): Bool)
_354
_354
/// The total number of unrevoked keys in this account.
_354
access(all) let count: UInt64
_354
}
_354
_354
access(all) struct Inbox {
_354
_354
/// Publishes a new Capability under the given name,
_354
/// to be claimed by the specified recipient.
_354
access(all) fun publish(_ value: Capability, name: String, recipient: Address)
_354
_354
/// Unpublishes a Capability previously published by this account.
_354
///
_354
/// Returns `nil` if no Capability is published under the given name.
_354
///
_354
/// Errors if the Capability under that name does not match the provided type.
_354
access(all) fun unpublish<T: &Any>(_ name: String): Capability<T>?
_354
_354
/// Claims a Capability previously published by the specified provider.
_354
///
_354
/// Returns `nil` if no Capability is published under the given name,
_354
/// or if this account is not its intended recipient.
_354
///
_354
/// Errors if the Capability under that name does not match the provided type.
_354
access(all) fun claim<T: &Any>(_ name: String, provider: Address): Capability<T>?
_354
}
_354
_354
pub struct Capabilities {
_354
_354
/// The storage capabilities of the account.
_354
pub let storage: AuthAccount.StorageCapabilities
_354
_354
/// The account capabilities of the account.
_354
pub let account: AuthAccount.AccountCapabilities
_354
_354
/// Returns the capability at the given public path.
_354
/// Returns nil if the capability does not exist,
_354
/// or if the given type is not a supertype of the capability's borrow type.
_354
pub fun get<T: &Any>(_ path: PublicPath): Capability<T>?
_354
_354
/// Borrows the capability at the given public path.
_354
/// Returns nil if the capability does not exist, or cannot be borrowed using the given type.
_354
/// The function is equivalent to `get(path)?.borrow()`.
_354
pub fun borrow<T: &Any>(_ path: PublicPath): T?
_354
_354
/// Publish the capability at the given public path.
_354
///
_354
/// If there is already a capability published under the given path, the program aborts.
_354
///
_354
/// The path must be a public path, i.e., only the domain `public` is allowed.
_354
pub fun publish(_ capability: Capability, at: PublicPath)
_354
_354
/// Unpublish the capability published at the given path.
_354
///
_354
/// Returns the capability if one was published at the path.
_354
/// Returns nil if no capability was published at the path.
_354
pub fun unpublish(_ path: PublicPath): Capability?
_354
}
_354
_354
pub struct StorageCapabilities {
_354
_354
/// Get the storage capability controller for the capability with the specified ID.
_354
///
_354
/// Returns nil if the ID does not reference an existing storage capability.
_354
pub fun getController(byCapabilityID: UInt64): &StorageCapabilityController?
_354
_354
/// Get all storage capability controllers for capabilities that target this storage path
_354
pub fun getControllers(forPath: StoragePath): [&StorageCapabilityController]
_354
_354
/// Iterate over all storage capability controllers for capabilities that target this storage path,
_354
/// passing a reference to each controller to the provided callback function.
_354
///
_354
/// Iteration is stopped early if the callback function returns `false`.
_354
///
_354
/// If a new storage capability controller is issued for the path,
_354
/// an existing storage capability controller for the path is deleted,
_354
/// or a storage capability controller is retargeted from or to the path,
_354
/// then the callback must stop iteration by returning false.
_354
/// Otherwise, iteration aborts.
_354
pub fun forEachController(forPath: StoragePath, _ function: fun(&StorageCapabilityController): Bool)
_354
_354
/// Issue/create a new storage capability.
_354
pub fun issue<T: &Any>(_ path: StoragePath): Capability<T>
_354
}
_354
_354
pub struct AccountCapabilities {
_354
/// Get capability controller for capability with the specified ID.
_354
///
_354
/// Returns nil if the ID does not reference an existing account capability.
_354
pub fun getController(byCapabilityID: UInt64): &AccountCapabilityController?
_354
_354
/// Get all capability controllers for all account capabilities.
_354
pub fun getControllers(): [&AccountCapabilityController]
_354
_354
/// Iterate over all account capability controllers for all account capabilities,
_354
/// passing a reference to each controller to the provided callback function.
_354
///
_354
/// Iteration is stopped early if the callback function returns `false`.
_354
///
_354
/// If a new account capability controller is issued for the account,
_354
/// or an existing account capability controller for the account is deleted,
_354
/// then the callback must stop iteration by returning false.
_354
/// Otherwise, iteration aborts.
_354
pub fun forEachController(_ function: (&AccountCapabilityController): Bool)
_354
_354
/// Issue/create a new account capability.
_354
pub fun issue<T: &AuthAccount>(): Capability<T>
_354
}
_354
}

A script can get the AuthAccount for an account address using the built-in getAuthAccount function:


_10
fun getAuthAccount(_ address: Address): AuthAccount

This AuthAccount object can perform all operations associated with authorized accounts, and as such this function is only available in scripts, which discard their changes upon completion. Attempting to use this function outside of a script will cause a type error.

Account Creation

Accounts can be created by calling the AuthAccount constructor and passing the account that should pay for the account creation for the payer parameter.

The payer must have enough funds to be able to create an account. If the account does not have the required funds, the program aborts.


_10
transaction() {
_10
prepare(signer: AuthAccount) {
_10
let account = AuthAccount(payer: signer)
_10
}
_10
}

Account Keys

An account (both PublicAccount and AuthAccount) has keys associated with it. An account key has the following structure.


_10
struct AccountKey {
_10
let keyIndex: Int
_10
let publicKey: PublicKey
_10
let hashAlgorithm: HashAlgorithm
_10
let weight: UFix64
_10
let isRevoked: Bool
_10
}

Refer to the PublicKey section for more details on the creation and validity of public keys.

Account Key API

Account key API provides a set of functions to manage account keys.

Add Account Keys

To authorize access to the account, keys can be added using the add() function. Keys can only be added to an AuthAccount.

For example, to create an account and have the signer of the transaction pay for the account creation, and authorize one key to access the account:


_16
transaction(publicKey: [UInt8]) {
_16
prepare(signer: AuthAccount) {
_16
let key = PublicKey(
_16
publicKey: publicKey,
_16
signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
_16
)
_16
_16
let account = AuthAccount(payer: signer)
_16
_16
account.keys.add(
_16
publicKey: key,
_16
hashAlgorithm: HashAlgorithm.SHA3_256,
_16
weight: 10.0
_16
)
_16
}
_16
}

To add a public key to an existing account, which signed the transaction:


_14
transaction(publicKey: [UInt8]) {
_14
prepare(signer: AuthAccount) {
_14
let key = PublicKey(
_14
publicKey: publicKey,
_14
signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
_14
)
_14
_14
signer.keys.add(
_14
publicKey: key,
_14
hashAlgorithm: HashAlgorithm.SHA3_256,
_14
weight: 10.0
_14
)
_14
}
_14
}

Get Account Keys

Keys that are added to an account can be retrieved using get() function, using the index of the key. Revoked keys are always returned, but they have isRevoked field set to true. Returns nil if there is no key available at the given index. Keys can be retrieved from both PublicAccout and AuthAccount.


_10
transaction() {
_10
prepare(signer: AuthAccount) {
_10
// Get a key from an auth account.
_10
let keyA = signer.keys.get(keyIndex: 2)
_10
_10
// Get a key from the public aacount.
_10
let publicAccount = getAccount(0x42)
_10
let keyB = publicAccount.keys.get(keyIndex: 2)
_10
}
_10
}

Revoke Account Keys

Keys that have been added to an account can be revoked using revoke() function. Revoke function only marks the key at the given index as revoked, but never deletes it. Keys can only be revoked from an AuthAccount.


_10
transaction() {
_10
prepare(signer: AuthAccount) {
_10
// Get a key from an auth account.
_10
let keyA = signer.keys.revoke(keyIndex: 2)
_10
}
_10
}

Account Inbox

Accounts also possess an Inbox that can be used to make Capabilities available to specific accounts. The functions in this Inbox provide a convenient means to "bootstrap" Capabilities, setting up an initial connection between two accounts that will later allow them to transfer data or permissions through a Capability.

Publishing a Capability

An account (the provider) that would like to provide a Capability to another account (the recipient) can do so using the publish function:


_10
fun publish(_ value: Capability, name: String, recipient: Address)

This publishes the specified Capability using the provided string as an identifier, to be later claimed by the recipient. Note, however, that until the recipient does claim this Capability, it is stored on the provider's account, and contributes towards their Account Storage total.

Calling this function emits an event, InboxValuePublished, that includes the address of both the provider and the recipient, as well as the name and the type of the published Capability. Refer to the Core Events section for more details on this event.

Claiming a Capability

The intended recipient of a Capability can claim that Capability from the provider using the claim function:


_10
fun claim<T: &Any>(_ name: String, provider: Address): Capability<T>?

This looks up the specified name in the provider's inbox, returning it to the recipient if it is present, conforms to the provided type argument, and is intended for the calling recipient. If the provider has no Capability stored under the provided name, or if the calling recipient is not the intended recipient of the Capability, the function returns nil. If the borrow type of the Capability is not a subtype of the provided type argument, the function will error at runtime.

Upon successful completion of the claim function, the claimed Capability is removed from the provider's inbox. Note that this means a given Capability can only be claimed once.

Calling this function emits an event, InboxValueClaimed, that includes the address of both the provider and the recipient, as well as the name of the claimed Capability. Refer to the Core Events section for more details on this event.

Unpublishing a Capability

If the provider of a Capability no longer wishes for it to be published for some reason (e.g. they no longer wish to pay for its storage costs), they can unpublish it using the unpublish function:


_10
fun unpublish<T: &Any>(_ name: String): Capability<T>?

This looks up the specified name in the provider's inbox, returning it to the provider if it is present and conforms to the provided type argument. If the provider has no Capability stored under the provided name, the function returns nil. If the borrow type of the Capability is not a subtype of the provided type argument, the function will error at runtime.

Upon successful completion of the unpublish function, the unpublished Capability is removed from the provider's inbox.

Calling this function emits an event, InboxValueUnpublished, that includes the address of the provider, and the name of the claimed Capability. Refer to the Core Events section for more details on this event.

Account Storage

All accounts have storage. Both resources and structures can be stored in account storage.

Paths

Objects are stored under paths. Paths consist of a domain and an identifier.

Paths start with the character /, followed by the domain, the path separator /, and finally the identifier. For example, the path /storage/test has the domain storage and the identifier test.

There are only three valid domains: storage, private, and public.

Objects in storage are always stored in the storage domain.

Paths in the storage domain have type StoragePath, in the private domain PrivatePath, and in the public domain PublicPath.

PrivatePath and PublicPath are subtypes of CapabilityPath.

Both StoragePath and CapabilityPath are subtypes of Path.

Path
CapabilityPathStoragePath
PrivatePathPublicPath

Path Functions


_10
fun toString(): String

Returns the string representation of the path.


_10
let storagePath = /storage/path
_10
_10
storagePath.toString() // is "/storage/path"

There are also utilities to produce paths from strings:


_10
fun PublicPath(identifier: string): PublicPath?
_10
fun PrivatePath(identifier: string): PrivatePath?
_10
fun StoragePath(identifier: string): StoragePath?

Each of these functions take an identifier and produce a path of the appropriate domain:


_10
let pathID = "foo"
_10
let path = PublicPath(identifier: pathID) // is /public/foo

Account Storage API

Account storage is accessed through the following functions of AuthAccount. This means that any code that has access to the authorized account has access to all its stored objects.


_10
fun save<T>(_ value: T, to: StoragePath)

Saves an object to account storage. Resources are moved into storage, and structures are copied.

T is the type parameter for the object type. It can be inferred from the argument's type.

If there is already an object stored under the given path, the program aborts.

The path must be a storage path, i.e., only the domain storage is allowed.


_10
fun type(at: StoragePath): Type?

Reads the type of an object from the account's storage which is stored under the given path, or nil if no object is stored under the given path.

If there is an object stored, the type of the object is returned without modifying the stored object.

The path must be a storage path, i.e., only the domain storage is allowed


_10
fun load<T>(from: StoragePath): T?

Loads an object from account storage. If no object is stored under the given path, the function returns nil. If there is an object stored, the stored resource or structure is moved out of storage and returned as an optional. When the function returns, the storage no longer contains an object under the given path.

T is the type parameter for the object type. A type argument for the parameter must be provided explicitly.

The type T must be a supertype of the type of the loaded object. If it is not, execution will abort with an error. The given type does not necessarily need to be exactly the same as the type of the loaded object.

The path must be a storage path, i.e., only the domain storage is allowed.


_10
fun copy<T: AnyStruct>(from: StoragePath): T?

Returns a copy of a structure stored in account storage, without removing it from storage.

If no structure is stored under the given path, the function returns nil. If there is a structure stored, it is copied. The structure stays stored in storage after the function returns.

T is the type parameter for the structure type. A type argument for the parameter must be provided explicitly.

The type T must be a supertype of the type of the copied structure. If it is not, execution will abort with an error. The given type does not necessarily need to be exactly the same as the type of the copied structure.

The path must be a storage path, i.e., only the domain storage is allowed.


_80
// Declare a resource named `Counter`.
_80
//
_80
resource Counter {
_80
access(all) var count: Int
_80
_80
access(all) init(count: Int) {
_80
self.count = count
_80
}
_80
}
_80
_80
// In this example an authorized account is available through the constant `authAccount`.
_80
_80
// Create a new instance of the resource type `Counter`
_80
// and save it in the storage of the account.
_80
//
_80
// The path `/storage/counter` is used to refer to the stored value.
_80
// Its identifier `counter` was chosen freely and could be something else.
_80
//
_80
authAccount.save(<-create Counter(count: 42), to: /storage/counter)
_80
_80
// Run-time error: Storage already contains an object under path `/storage/counter`
_80
//
_80
authAccount.save(<-create Counter(count: 123), to: /storage/counter)
_80
_80
// Load the `Counter` resource from storage path `/storage/counter`.
_80
//
_80
// The new constant `counter` has the type `Counter?`, i.e., it is an optional,
_80
// and its value is the counter resource, that was saved at the beginning
_80
// of the example.
_80
//
_80
let counter <- authAccount.load<@Counter>(from: /storage/counter)
_80
_80
// The storage is now empty, there is no longer an object stored
_80
// under the path `/storage/counter`.
_80
_80
// Load the `Counter` resource again from storage path `/storage/counter`.
_80
//
_80
// The new constant `counter2` has the type `Counter?` and is `nil`,
_80
// as nothing is stored under the path `/storage/counter` anymore,
_80
// because the previous load moved the counter out of storage.
_80
//
_80
let counter2 <- authAccount.load<@Counter>(from: /storage/counter)
_80
_80
// Create another new instance of the resource type `Counter`
_80
// and save it in the storage of the account.
_80
//
_80
// The path `/storage/otherCounter` is used to refer to the stored value.
_80
//
_80
authAccount.save(<-create Counter(count: 123), to: /storage/otherCounter)
_80
_80
// Load the `Vault` resource from storage path `/storage/otherCounter`.
_80
//
_80
// The new constant `vault` has the type `Vault?` and its value is `nil`,
_80
// as there is a resource with type `Counter` stored under the path,
_80
// which is not a subtype of the requested type `Vault`.
_80
//
_80
let vault <- authAccount.load<@Vault>(from: /storage/otherCounter)
_80
_80
// The storage still stores a `Counter` resource under the path `/storage/otherCounter`.
_80
_80
// Save the string "Hello, World" in storage
_80
// under the path `/storage/helloWorldMessage`.
_80
_80
authAccount.save("Hello, world!", to: /storage/helloWorldMessage)
_80
_80
// Copy the stored message from storage.
_80
//
_80
// After the copy, the storage still stores the string under the path.
_80
// Unlike `load`, `copy` does not remove the object from storage.
_80
//
_80
let message = authAccount.copy<String>(from: /storage/helloWorldMessage)
_80
_80
// Create a new instance of the resource type `Vault`
_80
// and save it in the storage of the account.
_80
//
_80
authAccount.save(<-createEmptyVault(), to: /storage/vault)
_80
_80
// Invalid: Cannot copy a resource, as this would allow arbitrary duplication.
_80
//
_80
let vault <- authAccount.copy<@Vault>(from: /storage/vault)

As it is convenient to work with objects in storage without having to move them out of storage, as it is necessary for resources, it is also possible to create references to objects in storage: This is possible using the borrow function of an AuthAccount:


_10
fun borrow<T: &Any>(from: StoragePath): T?

Returns a reference to an object in storage without removing it from storage. If no object is stored under the given path, the function returns nil. If there is an object stored, a reference is returned as an optional.

T is the type parameter for the object type. A type argument for the parameter must be provided explicitly. The type argument must be a reference to any type (&Any; Any is the supertype of all types). It must be possible to create the given reference type T for the stored / borrowed object. If it is not, execution will abort with an error. The given type does not necessarily need to be exactly the same as the type of the borrowed object.

The path must be a storage path, i.e., only the domain storage is allowed.


_63
// Declare a resource interface named `HasCount`, that has a field `count`
_63
//
_63
resource interface HasCount {
_63
count: Int
_63
}
_63
_63
// Declare a resource named `Counter` that conforms to `HasCount`
_63
//
_63
resource Counter: HasCount {
_63
access(all) var count: Int
_63
_63
access(all) init(count: Int) {
_63
self.count = count
_63
}
_63
}
_63
_63
// In this example an authorized account is available through the constant `authAccount`.
_63
_63
// Create a new instance of the resource type `Counter`
_63
// and save it in the storage of the account.
_63
//
_63
// The path `/storage/counter` is used to refer to the stored value.
_63
// Its identifier `counter` was chosen freely and could be something else.
_63
//
_63
authAccount.save(<-create Counter(count: 42), to: /storage/counter)
_63
_63
// Create a reference to the object stored under path `/storage/counter`,
_63
// typed as `&Counter`.
_63
//
_63
// `counterRef` has type `&Counter?` and is a valid reference, i.e. non-`nil`,
_63
// because the borrow succeeded:
_63
//
_63
// There is an object stored under path `/storage/counter`
_63
// and it has type `Counter`, so it can be borrowed as `&Counter`
_63
//
_63
let counterRef = authAccount.borrow<&Counter>(from: /storage/counter)
_63
_63
counterRef?.count // is `42`
_63
_63
// Create a reference to the object stored under path `/storage/counter`,
_63
// typed as `&{HasCount}`.
_63
//
_63
// `hasCountRef` is non-`nil`, as there is an object stored under path `/storage/counter`,
_63
// and the stored value of type `Counter` conforms to the requested type `{HasCount}`:
_63
// the type `Counter` implements the intersection type's interface `HasCount`
_63
_63
let hasCountRef = authAccount.borrow<&{HasCount}>(from: /storage/counter)
_63
_63
// Create a reference to the object stored under path `/storage/counter`,
_63
// typed as `&{SomethingElse}`.
_63
//
_63
// `otherRef` is `nil`, as there is an object stored under path `/storage/counter`,
_63
// but the stored value of type `Counter` does not conform to the requested type `{Other}`:
_63
// the type `Counter` does not implement the intersection type's interface `Other`
_63
_63
let otherRef = authAccount.borrow<&{Other}>(from: /storage/counter)
_63
_63
// Create a reference to the object stored under path `/storage/nonExistent`,
_63
// typed as `&{HasCount}`.
_63
//
_63
// `nonExistentRef` is `nil`, as there is nothing stored under path `/storage/nonExistent`
_63
//
_63
let nonExistentRef = authAccount.borrow<&{HasCount}>(from: /storage/nonExistent)

Storage Iteration

It is possible to iterate over an account's storage using the following iteration functions:


_10
fun forEachPublic(_ function: fun(PublicPath, Type): Bool)
_10
fun forEachPrivate(_ function: fun(PrivatePath, Type): Bool)
_10
fun forEachStored(_ function: fun(StoragePath, Type): Bool)

Each of these iterates over every element in the specified domain (public, private, and storage), applying the function argument to each. The first argument of the function is the path of the element, and the second is its runtime type. In the case of the private and public path iteration functions, this is the runtime type of the capability linked at that path. The Bool return value determines whether iteration continues; true will proceed to the next stored element, while false will terminate iteration. The specific order in which the objects are iterated over is undefined, as is the behavior when a path is added or removed from storage.

warning

The order of iteration is undefined. Do not rely on any particular behaviour.

Saving to or removing from storage during iteration can cause the order in which values are stored to change arbitrarily.

Continuing to iterate after such an operation will cause Cadence to panic and abort execution. In order to avoid such errors, we recommend not modifying storage during iteration. If you do, return false from the iteration callback to cause iteration to end after the mutation like so:


_13
account.save(1, to: /storage/foo1)
_13
account.save(2, to: /storage/foo2)
_13
account.save(3, to: /storage/foo3)
_13
account.save("qux", to: /storage/foo4)
_13
_13
account.forEachStored(fun (path: StoragePath, type: Type): Bool {
_13
if type == Type<String>() {
_13
account.save("bar", to: /storage/foo5)
_13
// returning false here ends iteration after storage is modified, preventing a panic
_13
return false
_13
}
_13
return true
_13
})

info

The iteration will skip any broken elements in the storage. An element could be broken due to invalid types associated with the stored value. e.g: A value belongs to type T of a contract with syntax/semantic errors.

Storage limit

An account's storage is limited by its storage capacity.

An account's storage used is the sum of the size of all the data that is stored in an account (in MB). An account's storage capacity is a value that is calculated from the amount of FLOW that is stored in the account's main FLOW token vault.

At the end of every transaction, the storage used is compared to the storage capacity. For all accounts involved in the transaction, if the account's storage used is greater than its storage capacity, the transaction will fail.

An account's storage used and storage capacity can be checked using the storageUsed and storageCapacity fields. The fields represent current values of storage which means this would be true:


_10
let storageUsedBefore = authAccount.storageUsed
_10
authAccount.save(<-create Counter(count: 123), to: /storage/counter)
_10
let storageUsedAfter = authAccount.storageUsed
_10
_10
let storageUsedChanged = storageUsedBefore != storageUsedAfter // is true