Skip to main content
Version: Next

Keys

Accounts have keys associated with them. When a key is added to an account, the key can be used to sign a transaction, which in turn gets access the account and can perform write operations on it.

An account exposes its keys through the keys field, which has the type Account.Keys.

Account.Keys

access(all)
struct Keys {

/// The total number of unrevoked keys in this account.
access(all)
let count: UInt64

/// Returns the key at the given index, if it exists, or nil otherwise.
///
/// Revoked keys are always returned, but they have `isRevoked` field set to true.
access(all)
view fun get(keyIndex: Int): AccountKey?

/// Iterate over all unrevoked keys in this account,
/// passing each key in turn to the provided function.
///
/// Iteration is stopped early if the function returns `false`.
///
/// The order of iteration is undefined.
access(all)
fun forEach(_ function: fun(AccountKey): Bool)

/// Adds a new key with the given hashing algorithm and a weight.
///
/// Returns the added key.
access(Keys | AddKey)
fun add(
publicKey: PublicKey,
hashAlgorithm: HashAlgorithm,
weight: UFix64
): AccountKey

/// Marks the key at the given index revoked, but does not delete it.
///
/// Returns the revoked key if it exists, or nil otherwise.
access(Keys | RevokeKey)
fun revoke(keyIndex: Int): AccountKey?
}

entitlement Keys

entitlement AddKey
entitlement RevokeKey

Account key

An account key has the following structure:

access(all)
struct AccountKey {

const accountKeyHashAlgorithmFieldDocString = ``
const accountKeyWeightFieldDocString = ``
const accountKeyIsRevokedFieldDocString = ``

/// The index of the account key.
access(all)
let keyIndex: Int

/// The public key of the account key.
let publicKey: PublicKey

/// The hash algorithm used by the public key.
let hashAlgorithm: HashAlgorithm

/// The weight assigned to the account key,
/// with a maximum of 1000.0
let weight: UFix64

/// The flag indicating whether the key is revoked.
let isRevoked: Bool
}

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

Refer to the hash algorithms section for more details on supported hash algorithms.

Getting an account key

The functions keys.get and keys.forEach allow retrieving the keys of an account.

The get function allows retrieving a key with a specific index. The function returns the key if it exists, and nil otherwise.

access(all)
view fun get(keyIndex: Int): AccountKey?

The forEach function allows iterating over all keys of an account.

access(all)
fun forEach(_ function: fun(AccountKey): Bool)

For each key of the account, the forEach function calls the given callback, passing the key to it. When the callback function returns true the iteration continues, and when it returns false, iteration stops.

warning

The keys.get and keys.forEach functions include revoked keys, which have the isRevoked field set to true.

access(all)
fun main() {
let account = getAccount(0x42)

// Get the third key from the account.
let thirdKey = account.keys.get(keyIndex: 2)
// ...

// Iterate over all keys of the account.
account.keys.forEach(fun (key: AccountKey): Bool {
// ...
return true
})
}

Adding an account key

The function keys.add allows a key to access an account.

access(Keys | AddKey)
fun add(
publicKey: PublicKey,
hashAlgorithm: HashAlgorithm,
weight: UFix64
): AccountKey

Calling the add function requires access to an account via a reference which is authorized with the coarse-grained Keys entitlement (auth(Keys) &Account), or the fine-grained AddKey entitlement (auth(AddKey) &Account).

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

transaction(publicKey: [UInt8]) {
prepare(signer: auth(AddKey) &Account) {
let key = PublicKey(
publicKey: publicKey,
signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
)

signer.keys.add(
publicKey: key,
hashAlgorithm: HashAlgorithm.SHA3_256,
weight: 10.0
)
}
}

A more complex transaction, which creates an account, has the signer of the transaction pay for the account creation, and authorizes one key to access the account, could look like:

transaction(publicKey: [UInt8]) {
prepare(signer: auth(BorrowValue) &Account) {
let key = PublicKey(
publicKey: publicKey,
signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
)

let account = Account(payer: signer)

account.keys.add(
publicKey: key,
hashAlgorithm: HashAlgorithm.SHA3_256,
weight: 10.0
)
}
}

Revoking an account key

The revoke function revokes a key from accessing an account. The function only marks the key at the given index as revoked, but never deletes it.

access(Keys | RevokeKey)
fun revoke(keyIndex: Int): AccountKey?

Calling the revoke function requires access to an account via a reference which is authorized with the coarse-grained Keys entitlement (auth(Keys) &Account), or the fine-grained RevokeKey entitlement (auth(RevokeKey) &Account).

For example, to revoke the third key of the account which signed the transaction:

transaction {
prepare(signer: auth(RevokeKey) &Account) {
let revokedKey = signer.keys.revoke(keyIndex: 2)
// ...
}
}