Build on Flow | Learn FCL - 13. How to Modify the State of the Chain by Signing Transactions with Wallets
Tags: javascript, tutorial, fcl, onflow
Published: 2022-07-25 16:49:00

## Overview

In this post we will learn:

- Signing roles - `payer`, `proposer` and `authorizers`
- What is a signing function and how to create one
- How to sign a transaction with one of your wallets
- How to sign a transaction with your private key

## Preface

Once we have our wallet or private keys, we can start signing transactions. Woohoo! 

For better understanding of how this works, you will need some extra knowledge.

The signing process on Flow requires 3 different parties to sign the transaction:

- `Proposer` - this is the account, which proposes to include changes done by transaction into the blockchain. Proposer role can be filled by any account on Flow blockchain.
- `Payer` is the account, who will pay the gas fees for transaction execution. Similar to `proposer` , this can be any account, who have enough FLOW tokens to cover the fee and is eager to do it.
- `Authorizers` - this is a list of accounts, who authorize any changes in their accounts, done by transaction they are signing. These should be accounts, that want to make said changes. If there is only a single account, it should still be a list of one.

> 💡All of those roles can be filled by the same account! You don’t need to have 3 “actors” to sign transaction 😅
> 

### Step 1 - Installation

Add `"@onflow/fcl": "1.0.0"` as your dependency

### Step 2 - Setup

Just like the last time we will import necessary methods and setup FCL. This time, though, we will extend our configuration with some new values to enable Wallet Discovery.

> `FCL Wallet Discovery` allows you to connect to all known and registered wallets at once! If you are coming from Ethereum, you can think about it as Flow variant of [WalletConnect](https://walletconnect.com/) sans multichain support 😅
> 

Note that we are using slightly different way to specify config by passing in object instead of calling multiple `.put` calls:

```jsx
// Import methods from FCL
import { query, config } from "@onflow/fcl";

// Configure FCL
config({
	// Use Testnet Access Node
  "accessNode.api": "https://rest-testnet.onflow.org",
  // We will also specify the network as some of the FCL parts need it to properly do it's work
  "flow.network": "testnet",
	// This will be the title of our DApp
  "app.detail.title": "Meow DApp",
	// This is just a kitten photo, we will use for the icon
  "app.detail.icon": "https://placekitten.com/g/200/200",
	// Next two will define where Wallet Discovery is located
  "discovery.wallet": "https://fcl-discovery.onflow.org/testnet/authn",
  "discovery.authn.endpoint":
    "https://fcl-discovery.onflow.org/api/testnet/authn",

	// We will also set alias for the contract we will use in this example
	"0xBasic": "0xafabe20e55e9ceb6"
});
```

You can read more information about those and other configuration keys on FCL [documentation page](https://github.com/onflow/fcl-js/blob/master/docs/reference/configure-fcl.mdx#common-configuration-keys)

### Step 3 - Get Current Chain State

We’ve deployed a [Basic contract](https://flow-view-source.com/testnet/account/0xafabe20e55e9ceb6/contract/Basic) at `0xafabe20e55e9ceb6`. If you click on that link it will lead you to Flow View Source. You can see there is a single public variable `counter`, that we can read and a couple of methods to modify it. Let’s use the knowledge from previous articles and read it.

```jsx
const readCounter = async () => {
  const cadence = `
    import Basic from 0xBasic

    pub fun main():UInt{
      return Basic.counter
    }
  `;
  const counter = await query({ cadence });
  console.log({ counter });
};
```

This simple query looks exactly like what we’ve built before, except this time we are using `0xBasic` alias for the address. FCL will use the value we set in the config - `0xafabe20e55e9ceb6` - and replace it. We are doing it this way, cause we will make calls to the contract from our  transaction as well. So we have this value nice and handy in one place and we don’t need to constantly reference it or memorize it 😉 

You should see some output in your console, similar to this (number can be different, as there are multiple users, who would want to alter it):

```jsx
{counter: "19"}
```

### Step 4 - Modify Counter

We will use method `mutate` provided by FCL package to modify the state of the chain. In its most basic form `mutate` is very similar to `query`, but it’s using some hidden mechanisms in order to sign the transaction (we will demystify them in later article). 

Let’s define another method `shiftCounter`, which we will be using to modify the value of the `counter`. If you go back to the `Basic` [contract](https://flow-view-source.com/testnet/account/0xafabe20e55e9ceb6/contract/Basic) you will see that it defines two methods. We will use `incrementCounterBy(_ step: UInt8)`

We will need to pass `UInt8` value as an argument to the transaction - we do it the same way we’ve [done previously](https://dev.to/onflow/build-on-flow-learn-fcl-2-pass-arguments-to-scripts-393f) using the `query` method.

```jsx
const shiftCounter = async (value) => {
	// Our Cadence code. Notice we are using alias here as well
  const cadence = `
    import Basic from 0xBasic

    transaction(shift: UInt8){
      prepare(signer: AuthAccount){
        Basic.incrementCounterBy(shift)
      }
    }
  `;

	// List of arguments
  const args = (arg, t) => [
		// We need to pass UInt8 value, but it should be a string, remember? :)
		arg(value.toString(), t.UInt8)
	];
  
	// "mutate" method will return us transaction id
	const txId = await mutate({
    cadence,
    args,
    limit: 999
  });

  // We will use transaction id in order to "subscribe" to it's state change and get the details
  // of the transaction
  const txDetails = await tx(txId).onceSealed();
	return txDetails
};
```

Wait, but what about those roles we’ve mentioned above. You see, `mutate` will populate all of them with the current authenticated user…

![https://c.tenor.com/d-bHBk4UYs4AAAAC/who.gif](https://c.tenor.com/d-bHBk4UYs4AAAAC/who.gif)

That’s part of the FCL and Wallet Discovery magic 🎇. If you don’t specify any role in that `mutate` method it will ask you to connect to the wallet and then use selected account as current user. Then it will use all the necessary params to fill in the roles in that interaction. Pretty cool, ha? 😎

### Finally

Let's add an IIFE at the end of the file and populate it with methods we have just defined:

```jsx
(async () => {
  console.clear();
  // You can [un]comment this line to toggle Wallet Discovery
  unauthenticate();

	// Let's read value, currently set on contract 
  await readCounter();

  // Let's modify the state now
  const txDetails = await shiftCounter(13);
  console.log({ txDetails });

	// Now we can check that value is actually changed
  await readCounter();
})();
```

When the code on the page will execute it will present you a popup, allowing to choose which wallet to use.

> ⚠️ You need to have Lilico installed in order for it to appear in the list. Consult one of [our previous articles](https://dev.to/onflow/build-on-flow-learn-fcl-11-how-to-install-and-create-a-new-testnet-account-with-lillico-18i) for details how to install and setup [Lilico](https://lilico.app/).
> 
![Pick Wallet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wc81d4zwpwsfyca9w0k2.png)
 
If you were to choose `Lilico`, you will be presented with following flow. First it will ask you to connect wallet to our dapp:
![Connect Lilico](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ys5aidi8g0e8su2j2214.png)

Then ask for confirmation. You can expand/collapse script pane to check the code of the transaction.

> 💡 Actually, you should ALWAYS check what you are signing. Even on Testnet. It’s a good habit, that will help you make your interaction with Flow more secure 😉
> 
![Lilico - Approve](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ckrj5avioam3u4bzw865.png)

[Blocto](https://dev.to/onflow/build-on-flow-learn-fcl-10-how-to-create-a-new-testnet-account-with-blocto-wallet-4lda) will guide your through a similar process:
![Use Blocto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ovx8la1k5csdgmnc27vq.png)

And it also has a way to check the transaction code:
![Blocto - Confirm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/om4yqp9is88r2oesyxku.png)

After all said and done you should see the following in your console (numbers might change):

```jsx
{ counter: "234" }
{ txDetails: Object }
{ counter: "247" }
```

Expanding `txDetails` will give your more information about the transaction:

```jsx
blockId: "ad7605f10f9846dd1c5603723b1d12995a3152b19a1ca24e47a3a2e28cee0641"
status: 4
statusString: "SEALED"
statusCode: 0
errorMessage: ""
events: Array(3)
```

![https://media.giphy.com/media/3o7btNa0RUYa5E7iiQ/giphy.gif](https://media.giphy.com/media/3o7btNa0RUYa5E7iiQ/giphy.gif)

Until next time! 👋 

## Resources

- **Full Source Code** - [https://codesandbox.io/s/dev-to-part-13-modify-chain-state-1oy1l7](https://codesandbox.io/s/dev-to-part-13-modify-chain-state-1oy1l7?file=/index.html)
- **FCL - `mutate` method -** [https://docs.onflow.org/fcl/reference/api/#mutate](https://docs.onflow.org/fcl/reference/api/#mutate)
- **Cadence - Transactions -** [https://docs.onflow.org/cadence/language/transactions/](https://docs.onflow.org/cadence/language/transactions/)
- **Lilico Wallet** - [https://lilico.app/](https://lilico.app/)

Other resources you might find useful:

- **Flow Docs Site** - [https://docs.onflow.org/](https://docs.onflow.org/) - More detailed information about Flow blockchain and how to interact with it
- **Flow Portal** - [https://flow.com/](https://flow.com/) - your entry point to Flow
- **FCL JS** - [https://github.com/onflow/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/](https://docs.onflow.org/cadence/) - Introduction to Cadence
- **Codesandbox** - [https://codesandbox.io](https://codesandbox.io/) - An amazing in-browser IDE enabling quick prototyping