Preface
One of the problems you might encounter, when you need to sign with a lot of transactions is inability to sign more than single transaction by account in single block. This happens because Proposer
role is used to provide a nounce
, which will be updated on account key only after transaction is sealed.
The solution - we need to add more keys 🔑✨!
Overview
After you go through the code in this article you will know:
- how to discover public keys on account using Flow View Source
- how to add new
PublicKey
with set weight
Wallet Limitations
While Blocto
or Lilico
will not allow you to use key with different index - other than 0 - in some cases it’s still valuable to add public key you can use programmatically to automate some tasks. The key with full weight will give you access to the account storage and ability to manipulate it.
Investigation
Before we continue, let’s check our current account on Flow View Source - 0x5593df7d286bcdb8
😅 Considering how many times Codesandbox has been run, you probably will see multiple keys here, when you read it.
You should see at least a single key with weight
equal to 1000 (full weight).
Step 1 - Installation
💡You can go and fork your work from previous article as it will be mostly the same :)
Add "@onflow/fcl"
, elliptic
and sha3
packages as your dependencies.
Step 2 - Create a signer
You can copy/paste the content of signer.js
file from previous article or follow the instructions and make a new one.
Step 3 - Configure FCL
We are not gonna use wallets in this example - consider this as homework assignment 😉 - so our config only needs access node url:
config({ "accessNode.api": "https://rest-testnet.onflow.org" });
Step 4 - Implement addPublicKey
Let’s make a new function called addPublicKey
, which will:
- accept
PublicKey
as a string, - prepare transaction to pass public key and
weight
as arguments - sign and send aforementioned transaction to network
The process is similar to how we were cooking transactions in previous article:
const addPublicKey = async (publicKey) => {
const cadence = `
transaction(publicKey: String, weight: UFix64) {
prepare(signer: AuthAccount) {
let bytes = publicKey.decodeHex()
let key = PublicKey(
publicKey: bytes,
signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
)
var clampledWeight = weight
// weight should be in range 0 to 1000
if(clampledWeight > 1000.0){
clampledWeight = 1000.0
}
signer.keys.add(
publicKey: key,
hashAlgorithm: HashAlgorithm.SHA3_256,
weight: clampledWeight
)
}
}
`;
// List of arguments
const weight = (0).toFixed(1) // zero weight keys are perfectly fine for Proposer role
const args = (arg, t) => [
arg(publicKey, t.String),
arg(weight, t.UFix64)
];
// Roles
const proposer = signer;
const payer = signer;
const authorizations = [signer];
// Execution limit
const limit = 1000
// "mutate" method will return us transaction id
const txId = await mutate({
proposer, payer, authorizations,
cadence, args, limit
});
// Then we subscribe to status updates and return, when it's sealed
return tx(txId).onceSealed();
};
Step 5 - Implement revokePublicKey
Another function we would like to prepare is revokePublicKey
. It will prepare and submit transaction, which will revoke the key on account:
const revokePublicKey = async (keyIndex) => {
const cadence = `
transaction(keyIndex: Int){
prepare(signer: AuthAccount){
signer.keys.revoke(keyIndex:keyIndex)
}
}
`;
const args = (arg, t) => [arg(keyIndex.toString(), t.Int)];
const proposer = signer;
const payer = signer;
const authorizations = [signer];
const limit = 1000;
// "mutate" method will return us transaction id
const txId = await mutate({
cadence, args, limit,
proposer, payer, authorizations
});
// Then we subscribe to status updates and return, when it's sealed
return tx(txId).onceSealed();
};
Finally -
Let's add an IIFE at the end of the file and populate it with methods we have just defined:
(async () => {
console.clear();
// PublicKey doesn't need to be unique, so we are gonna use exactly the same one
// that already exist on account. This way we can control it with the same private key.
const key =
"790a6849decbc179e9904f7f601fbd629f1687f371484998ceb8c587303e05ae4f859c7aa91f8493642de1039039d2da9650b4b7d9d44d2486e7a2adabf602bc";
// Uncomment this block to add public key
/*
const txDetails = await addPublicKey(key);
console.log({ txDetails });
*/
// Uncomment this block to revoke key
/*
const txDetails = await revokePublicKey(2);
console.log({ txDetails });
*/
})();
When the dust settles, your console should have the output, showcasing that transaction succesfully updated your account:
txDetails: {
blockId: "b9ddfac94c968864ca369ec890e8025c0144375f334bd0e2ddea1965b175fc82",
status: 4,
statusString: "SEALED",
statusCode: 0,
errorMessage: "",
events: Array(4),
0: Object {
type: "flow.AccountKeyAdded"
transactionId: "fa2640f428a3317b656196ef7f069a744b2455569e492f8112d37abca31e273d"
transactionIndex: 0
eventIndex: 0
data: Object
},
1: Object,
2: Object,
3: Object,
}
Checking Flow View Source will show there are now multiple keys that can be used:
If you uncomment the revokePublicKey
usage block and wait for execution, you will be able to see that key is marked as revoked.
💡 Please note, that keys are not
removed
, butrevoked
- you won’t be able to use this key index on this account anymore 🤷♂️
Hope you’ve found this article useful. And if you have gone through it with us - you’ve grown stronger! 💪
Until next time 👋
Resources
- Full Source Code - https://codesandbox.io/s/dev-to-15-add-public-key-cvfho2
- Cadence Docs - Add Key - https://docs.onflow.org/cadence/language/accounts/#add-account-keys
- Cadence Docs - Revoke Key - https://docs.onflow.org/cadence/language/accounts/#revoke-account-keys
Other resources you might find useful:
- Flow Docs Site - https://docs.onflow.org/ - More detailed information about Flow blockchain and how to interact with it
- Flow Portal - https://flow.com/ - your entry point to Flow
- FCL JS - https://github.com/onflow/fcl-js - Source code and ability to contribute to the FCL JS library
- Cadence - https://docs.onflow.org/cadence/ - Introduction to Cadence
- Codesandbox - https://codesandbox.io - An amazing in-browser IDE enabling quick prototyping
Top comments (0)