Repository: onflow/flow-cli
Pull request #188 (2021-04-16 13:22:07)

Release v18
## Release branch v18

### Features:
- Build, sign and send transaction commands #183 
- Resolve transactions and scripts arguments #161  
- Version check #171 

### Improvements:
- Account sequence number added #175 
- Add key weights to account creation #178 

### Bugfixes:
- Init reset bug #180 
- Emulator config path #187 

### Release Scheduled: 19.4.


Patch:
diff --git a/docs/account-add-contract.md b/docs/account-add-contract.md
index ccdfaa8c..e8065cbd 100644
--- a/docs/account-add-contract.md
+++ b/docs/account-add-contract.md
@@ -17,13 +17,16 @@ flow accounts add-contract <name> <filename>
 Contract 'FungibleToken' deployed to the account 0xf8d6e0586b0a20c7
 
 Address	 0xf8d6e0586b0a20c7
-Balance	 9999999999970000000
+Balance	 99999999999.70000000
 Keys	 1
 
 Key 0	Public Key		 640a5a359bf3536d15192f18d872d57c98a96cb871b92b70cecb0739c2d5c37b4be12548d3526933c2cda9b0b9c69412f45ffb6b85b6840d8569d969fe84e5b7
 	Weight			 1000
 	Signature Algorithm	 ECDSA_P256
 	Hash Algorithm		 SHA3_256
+	Revoked 		 false
+	Sequence Number 	 6
+	Index 			 0
 
 Contracts Deployed: 1
 Contract: 'FungibleToken'
@@ -69,6 +72,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`).
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/account-remove-contract.md b/docs/account-remove-contract.md
index 0d3b68fb..b38bc9d1 100644
--- a/docs/account-remove-contract.md
+++ b/docs/account-remove-contract.md
@@ -17,13 +17,16 @@ flow accounts remove-contract <name>
 Contract 'FungibleToken' removed from account '0xf8d6e0586b0a20c7'
 
 Address	 0xf8d6e0586b0a20c7
-Balance	 0
+Balance	 99999999999.70000000
 Keys	 1
 
 Key 0	Public Key		 640a5a359bf3536d15192f18d872d57c98a96cb871b92b70cecb0739c2d5c37b4be12548d3526933c2cda9b0b9c69412f45ffb6b85b6840d8569d969fe84e5b7
-Weight			 1000
-Signature Algorithm	 ECDSA_P256
-Hash Algorithm		 SHA3_256
+	Weight			 1000
+	Signature Algorithm	 ECDSA_P256
+	Hash Algorithm		 SHA3_256
+	Revoked 		 false
+	Sequence Number 	 6
+	Index 			 0
 
 Contracts Deployed: 0
 ```
@@ -61,6 +64,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/account-staking-info.md b/docs/account-staking-info.md
index 2392b4d2..c5109aec 100644
--- a/docs/account-staking-info.md
+++ b/docs/account-staking-info.md
@@ -47,7 +47,7 @@ Tokens Unstaking: 	 0.00000000
 ### Address
 
 - Name: `address`
-- Valid Input: Flow account address
+- Valid Input: Flow account address.
 
 Flow [account address](https://docs.onflow.org/concepts/accounts-and-keys/) (prefixed with `0x` or not).
 
@@ -68,6 +68,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/account-update-contract.md b/docs/account-update-contract.md
index 4b7d780b..850706ef 100644
--- a/docs/account-update-contract.md
+++ b/docs/account-update-contract.md
@@ -17,13 +17,16 @@ flow accounts update-contract <name> <filename>
 Contract 'FungibleToken' updated on account '0xf8d6e0586b0a20c7'
 
 Address	 0xf8d6e0586b0a20c7
-Balance	 9999999999970000000
+Balance	 99999999999.70000000
 Keys	 1
 
 Key 0	Public Key		 640a5a359bf3536d15192f18d872d57c98a96cb871b92b70cecb0739c2d5c37b4be12548d3526933c2cda9b0b9c69412f45ffb6b85b6840d8569d969fe84e5b7
 	Weight			 1000
 	Signature Algorithm	 ECDSA_P256
 	Hash Algorithm		 SHA3_256
+	Revoked 		 false
+	Sequence Number 	 6
+	Index 			 0
 
 Contracts Deployed: 1
 Contract: 'FungibleToken'
@@ -67,6 +70,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/build-transactions.md b/docs/build-transactions.md
new file mode 100644
index 00000000..52510b80
--- /dev/null
+++ b/docs/build-transactions.md
@@ -0,0 +1,179 @@
+---
+title: Build a Transaction with the Flow CLI
+sidebar_title: Build a Transaction
+description: How to build a Flow transaction from the command line
+---
+
+The Flow CLI provides a command to build a transactions with options to specify
+authorizer accounts, payer account and proposer account. 
+
+The `build` command doesn't produce any signatures and instead
+is designed to be used with the `sign` and `send-signed` commands. 
+
+Use this functionality in the following order:
+1. Use this command (`build`) to build the transaction.
+2. Use the `sign` command to sign with all accounts specified in the build process.
+3. Use `send-signed` command to submit the signed transaction to the Flow network.
+
+```shell
+flow transactions build <code filename>
+```
+
+## Example Usage
+
+```shell
+> flow transactions build ./transaction.cdc \
+  --signer alice \
+  --proposer bob \
+  --payer charlie \
+  --arg "String:Meow" \
+  --filter payload --save built.rlp
+
+ID		e8c0a69952fbe50a66703985e220307c8d44b8fa36c76cbca03f8c43d0167847
+Payer		e03daebed8ca0615
+Authorizers	[f3fcd2c1a78f5eee]
+
+Proposal Key:	
+    Address	179b6b1cb6755e31
+    Index	0
+    Sequence	1
+
+No Payload Signatures
+
+No Envelope Signatures
+
+
+Arguments (1):
+    - Argument 0: {"type":"String","value":"Meow"}
+
+
+Code
+
+transaction(greeting: String) {
+  let guest: Address
+
+  prepare(authorizer: AuthAccount) {
+    self.guest = authorizer.address
+  }
+
+  execute {
+    log(greeting.concat(",").concat(self.guest.toString()))
+  }
+}
+
+
+Payload:
+f9013df90138b8d17472616e...73616374696f6e286eeec0c0
+```
+
+## Arguments
+
+### Code Filename
+
+- Name: `filename`
+- Valid inputs: Any filename and path valid on the system.
+
+The first argument is a path to a Cadence file containing the
+transaction to be executed.
+
+
+## Flags
+
+
+### Payer
+
+- Flag: `--payer`
+- Valid Inputs: Flow address or account name from configuration.
+- Default: service account
+
+Specify account address that will be paying for the transaction.
+Read more about payers [here](https://docs.onflow.org/concepts/accounts-and-keys/).
+
+### Proposer
+
+- Flag: `--proposer`
+- Valid inputs: Flow address or account name from configuration.
+- Default: service account
+
+Specify a name of the account that is proposing the transaction.
+Account must be defined in flow configuration.
+
+### Proposer Key Index
+
+- Flag: `--proposer-key-index`
+- Valid inputs: number of existing key index
+- Default: 0
+
+Specify key index for the proposer account.
+
+### Authorizer
+
+- Flag: `--authorizer`
+- Valid Inputs: Flow address or account name from configuration.
+- Default: service account
+
+Additional authorizer addresses to add to the transaction.
+Read more about authorizers [here](https://docs.onflow.org/concepts/accounts-and-keys/).
+
+### Host
+
+- Flag: `--host`
+- Valid inputs: an IP address or hostname.
+- Default: `127.0.0.1:3569` (Flow Emulator)
+
+Specify the hostname of the Access API that will be
+used to execute the commands.
+
+### Network
+
+- Flag: `--network`
+- Short Flag: `-n`
+- Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
+
+Specify which network you want the command to use for execution.
+
+### Filter
+
+- Flag: `--filter`
+- Short Flag: `-x`
+- Valid inputs: case-sensitive name of the result property.
+
+Specify any property name from the result you want to return as the only value.
+
+### Output
+
+- Flag: `--output`
+- Short Flag: `-o`
+- Valid inputs: `json`, `inline`
+
+Specify in which format you want to display the result.
+
+### Save
+
+- Flag: `--save`
+- Short Flag: `-s`
+- Valid inputs: valid filename
+
+Specify the filename where you want the result to be saved.
+
+### Log
+
+- Flag: `--log`
+- Short Flag: `-l`
+- Valid inputs: `none`, `error`, `debug`
+- Default: `info`
+
+Specify the log level. Control how much output you want to see while command execution.
+
+### Configuration
+
+- Flag: `--config-path`
+- Short Flag: `-f`
+- Valid inputs: valid filename
+
+Specify a filename for the configuration files, you can provide multiple configuration
+files by using `-f` flag multiple times.
+
+
+
diff --git a/docs/create-accounts.md b/docs/create-accounts.md
index 71b61817..5394f94f 100644
--- a/docs/create-accounts.md
+++ b/docs/create-accounts.md
@@ -47,7 +47,7 @@ In the above example, the `flow.json` file would look something like this:
 }
 ```
 
-## Options
+## Flags
     
 ### Public Key
 
@@ -57,6 +57,16 @@ In the above example, the `flow.json` file would look something like this:
 Specify the public key that will be added to the new account
 upon creation.
 
+### Key Weight
+
+- Flag: `--key-weight`
+- Valid inputs: number between 0 and 1000
+- Default: 1000
+
+Specify the weight of the public key being added to the new account. 
+
+When opting to use this flag, you must specify a `--key-weight` flag for each public `--key` flag provided.
+
 ### Public Key Signature Algorithm
     
 - Flag: `--sig-algo`
@@ -109,6 +119,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/deploy-project-contracts.md b/docs/deploy-project-contracts.md
index 497c2615..2e0aff74 100644
--- a/docs/deploy-project-contracts.md
+++ b/docs/deploy-project-contracts.md
@@ -121,6 +121,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/developer-updates/release-notes-v18.md b/docs/developer-updates/release-notes-v18.md
new file mode 100644
index 00000000..54b778a8
--- /dev/null
+++ b/docs/developer-updates/release-notes-v18.md
@@ -0,0 +1,192 @@
+## ⬆️ Install or Upgrade
+
+Follow the [Flow CLI installation guide](https://docs.onflow.org/flow-cli/install/) for instructions on how to install or upgrade the CLI.
+
+## ⭐ Features
+
+### Resolve Contract Imports in Scripts and Transactions
+This is a new feature that allows you to send transactions and scripts that reference 
+contracts deployed using the `project deploy` command. Imports are resolved 
+by matching contract source paths to their declarations in `flow.json`.
+
+For example:
+
+Example script: `get_supply.cdc`
+```
+import Kibble from "../../contracts/Kibble.cdc"
+
+pub fun main(): UFix64 {
+    let supply = Kibble.totalSupply
+    return supply
+}
+
+```
+
+Example command:
+```
+flow scripts execute ./get_supply.cdc
+```
+
+Note: Please make sure you first deploy the contract using `flow project deploy` 
+command and that contracts are correctly added to the flow configuration.
+
+
+### Build, Sign and Send Transactions
+New functionality allows you to build a transaction, sign it 
+and send signed to the network in separated steps. 
+
+#### Build Transaction
+Build new transaction and specify who will be the proposer, signer and payer account 
+or address. Example:
+
+```
+flow transactions build ./transaction.cdc --proposer alice --payer bob --authorizer bob --filter payload --save payload1.rlp
+```
+
+Check more about [this functionality in docs](https://docs.onflow.org/flow-cli/build-transactions/).
+
+#### Sign Transaction
+After using build command and saving payload to a file you should sign the transaction 
+with each account. Example:
+
+```
+flow transactions sign ./payload1.rlp --signer alice --filter payload --save payload2.rlp 
+```
+
+#### Send Signed Transaction
+When authorizer, payer and proposer sign the transaction it is ready to be 
+sent to the network. Anyone can execute the `send-signed` command. Example:
+
+```
+flow transactions send-signed ./payload3.rlp
+```
+
+### Version Check
+Automatically checks if a new version exists and outputs a warning in case there 
+is a newer version. Example:
+```
+⚠️  Version Warning: New version v0.18.0 of Flow CLI is available.
+Follow the Flow CLI installation guide for instructions on how to install or upgrade the CLI: https://docs.onflow.org/flow-cli/install
+```
+
+
+### Create Account With Multiple Keys and Weights
+Account creation can be done using multiple keys (`--key`) and new `--key-weight` 
+flag. Flag enables you to set key weight for each of the keys. Command example: 
+```
+accounts create \
+    --key ca8cc7...76f67 --key-weight 500 \
+    --key da8123...043ce --key-weight 500
+
+Address	 0x179b6b1cb6755e31
+Balance	 0.10000000
+Keys	 2
+
+Key 0	Public Key		 ca8cc7...76f67
+	Weight			 500
+	Signature Algorithm	 ECDSA_P256
+	Hash Algorithm		 SHA3_256
+	Revoked 		 false
+	Sequence Number 	 0
+	Index 			 0
+
+
+Key 1	Public Key		 da8123...043ce
+	Weight			 500
+	Signature Algorithm	 ECDSA_P256
+	Hash Algorithm		 SHA3_256
+	Revoked 		 false
+	Sequence Number 	 0
+	Index 			 1
+
+```
+
+## 🎉 Improvements
+
+### Account Response Improved
+Account response includes two new fields in key section: `Sequence Number` and `Index`.
+
+### Transaction Result Improved
+Transaction result displays more information about the transaction. New format example:
+
+```
+Status		✅ SEALED
+ID		b6430b35ba23849a8acb4fa1a4a1d5cce3ed4589111ecbb3984de1b6bd1ba39e
+Payer		a2c4941b5f3c7151
+Authorizers	[a2c4941b5f3c7151]
+
+Proposal Key:	
+    Address	a2c4941b5f3c7151
+    Index	0
+    Sequence	9
+
+No Payload Signatures
+
+Envelope Signature 0:
+    Address	a2c4941b5f3c7151
+    Signature	5391a6fed0fe...2742048166f9d5c925a8dcb78a6d8c710921d67
+    Key Index	0
+
+
+Events:	 None
+
+
+Arguments (1):
+    - Argument 0: {"type":"String","value":"Meow"}
+
+
+Code
+
+transaction(greeting: String) {
+  let guest: Address
+
+  prepare(authorizer: AuthAccount) {
+    self.guest = authorizer.address
+  }
+
+  execute {
+    log(greeting.concat(",").concat(self.guest.toString()))
+  }
+}
+
+
+Payload:
+f90184f90138...8a9462751237da2742048166f9d5c925a8dcb78a6d8c710921d67
+```
+
+Transaction error is now shown at the top of the result.
+```
+Transaction 0dd6294a7614bc0fbeb39b44a6e9f68e821225caa4baf4104a17dc1193d4f011 sealed
+
+Status: SEALED
+Execution Error: Execution failed:
+error: invalid move operation for non-resource
+  --> 0dd6294a7614bc0fbeb39b44a6e9f68e821225caa4baf4104a17dc1193d4f011:15:15
+   |
+15 |         useRes(<-result)
+   |                ^^^ unexpected `<-`
+
+error: mismatched types
+  --> 0dd6294a7614bc0fbeb39b44a6e9f68e821225caa4baf4104a17dc1193d4f011:15:15
+   |
+15 |         useRes(<-result)
+   |                ^^^^^^^^ expected `AnyResource`, got `&AnyResource`
+
+Events:
+  None
+```
+
+## 🐞 Bug Fixes
+
+### New Transaction ID Log
+While sending transaction was in progress output displayed wrong transaction ID.
+
+### Init Reset Fix
+Old configuration format caused an error saying to reset the 
+configuration using reset flag, but when ran it produced the same error again. 
+This bug was fixed.
+
+### Emulator Config Path
+When running emulator command `flow emulator` config flag `-f` was ignored. 
+This has been fixed, so you can provide a custom path to the config while running 
+the start emulator command.
diff --git a/docs/execute-scripts.md b/docs/execute-scripts.md
index 7f7e08bd..0e27d26e 100644
--- a/docs/execute-scripts.md
+++ b/docs/execute-scripts.md
@@ -70,6 +70,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/get-accounts.md b/docs/get-accounts.md
index afbd6a71..67c83ae1 100644
--- a/docs/get-accounts.md
+++ b/docs/get-accounts.md
@@ -19,13 +19,16 @@ flow accounts get 0xf8d6e0586b0a20c7
 ### Example response
 ```shell
 Address	 0xf8d6e0586b0a20c7
-Balance	 9999999999970000000
+Balance	 99999999999.70000000
 Keys	 1
 
-Key 0	Public Key		 858a7d978b25d61f348841a343f79131f4b9fab341dd8a476a6f4367c25510570bf69b795fc9c3d2b7191327d869bcf848508526a3c1cafd1af34f71c7765117
+Key 0	Public Key		 640a5a359bf3536d15192f18d872d57c98a96cb871b92b70cecb0739c2d5c37b4be12548d3526933c2cda9b0b9c69412f45ffb6b85b6840d8569d969fe84e5b7
 	Weight			 1000
 	Signature Algorithm	 ECDSA_P256
 	Hash Algorithm		 SHA3_256
+	Revoked 		 false
+	Sequence Number 	 6
+	Index 			 0
 
 Contracts Deployed: 2
 Contract: 'FlowServiceAccount'
@@ -34,6 +37,16 @@ Contract: 'FlowStorageFees'
 
 ```
 
+## Arguments
+
+### Address
+
+- Name: `address`
+- Valid Input: Flow account address
+
+Flow [account address](https://docs.onflow.org/concepts/accounts-and-keys/) (prefixed with `0x` or not).
+
+
 ## Flags
 
 ### Contracts
@@ -45,7 +58,6 @@ Display contracts deployed to the account.
 ### Code 
 ⚠️  No longer supported: use contracts flag instead.
 
-
 ### Host
 
 - Flag: `--host`
@@ -61,6 +73,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/get-blocks.md b/docs/get-blocks.md
index 55f77052..f8085609 100644
--- a/docs/get-blocks.md
+++ b/docs/get-blocks.md
@@ -103,6 +103,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/get-collections.md b/docs/get-collections.md
index 8ca29bb0..4ef0f809 100644
--- a/docs/get-collections.md
+++ b/docs/get-collections.md
@@ -55,6 +55,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/get-events.md b/docs/get-events.md
index 9040c214..63df08a5 100644
--- a/docs/get-events.md
+++ b/docs/get-events.md
@@ -88,6 +88,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/get-transactions.md b/docs/get-transactions.md
index 0cfe9a11..7cd04c9a 100644
--- a/docs/get-transactions.md
+++ b/docs/get-transactions.md
@@ -75,6 +75,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/send-signed-transactions.md b/docs/send-signed-transactions.md
new file mode 100644
index 00000000..a4cff5db
--- /dev/null
+++ b/docs/send-signed-transactions.md
@@ -0,0 +1,142 @@
+---
+title: Send Signed Transaction with the Flow CLI
+sidebar_title: Send Signed Transaction
+description: How to send a signed Flow transaction from the command line
+---
+
+The Flow CLI provides a command to send signed transactions to
+any Flow Access API.
+
+Use this functionality in the following order:
+1. Use this command (`build`) to build the transaction.
+2. Use the `sign` command to sign with all accounts specified in the build process.
+3. Use `send-signed` command to submit the signed transaction to the Flow network.
+
+```shell
+flow transactions send-signed <signed transaction filename>
+```
+
+## Example Usage
+
+```shell
+> flow transactions send-signed ./signed.rlp
+    
+Status		✅ SEALED
+ID		b6430b35ba23849a8acb4fa1a4a1d5cce3ed4589111ecbb3984de1b6bd1ba39e
+Payer		a2c4941b5f3c7151
+Authorizers	[a2c4941b5f3c7151]
+
+Proposal Key:	
+    Address	a2c4941b5f3c7151
+    Index	0
+    Sequence	9
+
+No Payload Signatures
+
+Envelope Signature 0:
+    Address	a2c4941b5f3c7151
+    Signature	5391a6fed0fe...2742048166f9d5c925a8dcb78a6d8c710921d67
+    Key Index	0
+
+
+Events:	 None
+
+
+Arguments (1):
+    - Argument 0: {"type":"String","value":"Meow"}
+
+
+Code
+
+transaction(greeting: String) {
+  let guest: Address
+
+  prepare(authorizer: AuthAccount) {
+    self.guest = authorizer.address
+  }
+
+  execute {
+    log(greeting.concat(",").concat(self.guest.toString()))
+  }
+}
+
+
+Payload:
+f90184f90138...8a9462751237da2742048166f9d5c925a8dcb78a6d8c710921d67
+
+```
+
+
+## Arguments
+
+### Signed Code Filename
+- Name: `signed transaction filename`
+- Valid inputs: Any filename and path valid on the system.
+
+The first argument is a path to a Cadence file containing the
+transaction to be executed.
+
+## Flags
+
+### Host
+
+- Flag: `--host`
+- Valid inputs: an IP address or hostname.
+- Default: `127.0.0.1:3569` (Flow Emulator)
+
+Specify the hostname of the Access API that will be
+used to execute the command. This flag overrides
+any host defined by the `--network` flag.
+
+### Network
+
+- Flag: `--network`
+- Short Flag: `-n`
+- Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
+
+Specify which network you want the command to use for execution.
+
+### Filter
+
+- Flag: `--filter`
+- Short Flag: `-x`
+- Valid inputs: a case-sensitive name of the result property.
+
+Specify any property name from the result you want to return as the only value.
+
+### Output
+
+- Flag: `--output`
+- Short Flag: `-o`
+- Valid inputs: `json`, `inline`
+
+Specify the format of the command results.
+
+### Save
+
+- Flag: `--save`
+- Short Flag: `-s`
+- Valid inputs: a path in the current filesystem.
+
+Specify the filename where you want the result to be saved
+
+### Log
+
+- Flag: `--log`
+- Short Flag: `-l`
+- Valid inputs: `none`, `error`, `debug`
+- Default: `info`
+
+Specify the log level. Control how much output you want to see during command execution.
+
+### Configuration
+
+- Flag: `--config-path`
+- Short Flag: `-f`
+- Valid inputs: a path in the current filesystem.
+- Default: `flow.json`
+
+Specify the path to the `flow.json` configuration file.
+You can use the `-f` flag multiple times to merge
+several configuration files.
diff --git a/docs/send-transactions.md b/docs/send-transactions.md
index 673f36d8..d06801dc 100644
--- a/docs/send-transactions.md
+++ b/docs/send-transactions.md
@@ -8,21 +8,59 @@ The Flow CLI provides a command to sign and send transactions to
 any Flow Access API.
 
 ```shell
-flow transactions send
+flow transactions send <code filename>
 ```
 
 ## Example Usage
 
 ```shell
-# Submit a transaction to Flow Testnet
-> flow transactions send <filename>
+> flow transactions send <code filename>
     --signer my-testnet-account \
     --host access.testnet.nodes.onflow.org:9000
     
-ID	 f23582ba17322405608c0d3da79312617f8d16e118afe63e764b5e68edc5f211
-Status	 SEALED
-Payer	 a2c4941b5f3c7151
-Events
+Status		✅ SEALED
+ID		b6430b35ba23849a8acb4fa1a4a1d5cce3ed4589111ecbb3984de1b6bd1ba39e
+Payer		a2c4941b5f3c7151
+Authorizers	[a2c4941b5f3c7151]
+
+Proposal Key:	
+    Address	a2c4941b5f3c7151
+    Index	0
+    Sequence	9
+
+No Payload Signatures
+
+Envelope Signature 0:
+    Address	a2c4941b5f3c7151
+    Signature	5391a6fed0fe...2742048166f9d5c925a8dcb78a6d8c710921d67
+    Key Index	0
+
+
+Events:	 None
+
+
+Arguments (1):
+    - Argument 0: {"type":"String","value":"Meow"}
+
+
+Code
+
+transaction(greeting: String) {
+  let guest: Address
+
+  prepare(authorizer: AuthAccount) {
+    self.guest = authorizer.address
+  }
+
+  execute {
+    log(greeting.concat(",").concat(self.guest.toString()))
+  }
+}
+
+
+Payload:
+f90184f90138...8a9462751237da2742048166f9d5c925a8dcb78a6d8c710921d67
+
 ```
 
 In the above example, the `flow.json` file would look something like this:
@@ -40,8 +78,8 @@ In the above example, the `flow.json` file would look something like this:
 
 ## Arguments
 
-### Filename
-- Name: `filename`
+### Code Filename
+- Name: `code filename`
 - Valid inputs: Any filename and path valid on the system.
 
 The first argument is a path to a Cadence file containing the
@@ -68,6 +106,23 @@ transaction to be executed.
 
 Specify the name of the account that will be used to sign the transaction.
 
+### Arguments
+
+- Flag: `--arg`
+- Valid inputs: argument in `Type:Value` format.
+
+Arguments passed to the Cadence transaction in `Type:Value` format.
+The `Type` must be the same as type in the transaction source code for that argument.
+
+### Arguments JSON
+
+- Flag: `--argsJSON`
+- Valid inputs: arguments in JSON-Cadence form.
+
+Arguments passed to the Cadence transaction in `Type:Value` format.
+The `Type` must be the same type as the corresponding parameter
+in the Cadence transaction code.
+
 ### Host
 
 - Flag: `--host`
@@ -83,6 +138,7 @@ any host defined by the `--network` flag.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/docs/sign-transaction.md b/docs/sign-transaction.md
new file mode 100644
index 00000000..294fd581
--- /dev/null
+++ b/docs/sign-transaction.md
@@ -0,0 +1,140 @@
+---
+title: Sign a Transaction with the Flow CLI
+sidebar_title: Sign a Transaction
+description: How to sign a Flow transaction from the command line
+---
+
+The Flow CLI provides a command to sign transactions with options to specify
+authorizer accounts, payer accounts and proposer accounts.
+
+Use this functionality in the following order:
+1. Use this command (`build`) to build the transaction.
+2. Use the `sign` command to sign with all accounts specified in the build process.
+3. Use `send-signed` command to submit the signed transaction to the Flow network.
+
+```shell
+flow transactions sign <built transaction filename>
+```
+
+## Example Usage
+
+```shell
+> flow transactions sign ./built.rlp --signer alice \
+  --filter payload --save signed.rlp
+
+Hash		b03b18a8d9d30ff7c9f0fdaa80fcaab242c2f36eedb687dd9b368326311fe376
+Payer		f8d6e0586b0a20c7
+Authorizers	[f8d6e0586b0a20c7]
+
+Proposal Key:	
+    Address	f8d6e0586b0a20c7
+    Index	0
+    Sequence	6
+
+No Envelope Signatures
+
+Payload Signature 0:
+    Address	f8d6e0586b0a20c7
+    Signature	b5b1dfed2a899037...164e1b224a7ac924018e7033b68b0df86769dd54
+    Key Index	0
+
+
+Arguments (1):
+    - Argument 0: {"type":"String","value":"Meow"}
+
+
+Code
+
+transaction(greeting: String) {
+  let guest: Address
+
+  prepare(authorizer: AuthAccount) {
+    self.guest = authorizer.address
+  }
+
+  execute {
+    log(greeting.concat(",").concat(self.guest.toString()))
+  }
+}
+
+
+Payload:
+f90184f...a199bfd9b837a11a0885f9104b54014750f5e3e5bfe4a5795968b0df86769dd54c0
+```
+
+## Arguments
+
+### Built Transaction Filename
+- Name: `built transaction filename`
+- Valid inputs: Any filename and path valid on the system.
+
+Specify the filename containing valid transaction payload that will be used for signing.
+To be used with the `flow transaction build` command.
+
+## Flags
+
+### Signer
+
+- Flag: `--signer`
+- Valid inputs: the name of an account defined in the configuration (`flow.json`)
+
+Specify the name of the account that will be used to sign the transaction.
+
+### Host
+- Flag: `--host`
+- Valid inputs: an IP address or hostname.
+- Default: `127.0.0.1:3569` (Flow Emulator)
+
+Specify the hostname of the Access API that will be
+used to execute the commands.
+
+### Network
+
+- Flag: `--network`
+- Short Flag: `-n`
+- Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
+
+Specify which network you want the command to use for execution.
+
+### Filter
+
+- Flag: `--filter`
+- Short Flag: `-x`
+- Valid inputs: case-sensitive name of the result property.
+
+Specify any property name from the result you want to return as the only value.
+
+### Output
+
+- Flag: `--output`
+- Short Flag: `-o`
+- Valid inputs: `json`, `inline`
+
+Specify in which format you want to display the result.
+
+### Save
+
+- Flag: `--save`
+- Short Flag: `-s`
+- Valid inputs: valid filename
+
+Specify the filename where you want the result to be saved.
+
+### Log
+
+- Flag: `--log`
+- Short Flag: `-l`
+- Valid inputs: `none`, `error`, `debug`
+- Default: `info`
+
+Specify the log level. Control how much output you want to see while command execution.
+
+### Configuration
+
+- Flag: `--conf`
+- Short Flag: `-f`
+- Valid inputs: valid filename
+
+Specify a filename for the configuration files, you can provide multiple configuration
+files by using `-f` flag multiple times.
diff --git a/docs/template.md b/docs/template.md
index 071693d4..525a1c8a 100644
--- a/docs/template.md
+++ b/docs/template.md
@@ -15,11 +15,9 @@ description:
 ## Example Usage
 
 ```shell
-{usage example}
+{usage example with response}
 ```
 
-### Example response
-
 ## Arguments
 
 ### {Argument 1}
@@ -66,6 +64,7 @@ used to execute the commands.
 - Flag: `--network`
 - Short Flag: `-n`
 - Valid inputs: the name of a network defined in the configuration (`flow.json`)
+- Default: `emulator`
 
 Specify which network you want the command to use for execution.
 
diff --git a/go.mod b/go.mod
index c59d773e..b1ce19c7 100644
--- a/go.mod
+++ b/go.mod
@@ -7,6 +7,7 @@ require (
 	github.com/fatih/color v1.7.0
 	github.com/gosuri/uilive v0.0.4
 	github.com/magiconair/properties v1.8.1 // indirect
+	github.com/manifoldco/promptui v0.8.0
 	github.com/onflow/cadence v0.14.4
 	github.com/onflow/cadence/languageserver v0.14.4
 	github.com/onflow/flow-core-contracts/lib/go/templates v0.6.0
diff --git a/go.sum b/go.sum
index b743a90c..7ec8efcb 100644
--- a/go.sum
+++ b/go.sum
@@ -125,8 +125,11 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
 github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
+github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -409,6 +412,8 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
+github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
 github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
@@ -581,12 +586,16 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
 github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
 github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs=
 github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
+github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
 github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
 github.com/m4ksio/wal v1.0.0/go.mod h1:S3UyatBTuMdoI5QTuz2DWb8Csd9568vYrFAmMI/bnMw=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
 github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
+github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
diff --git a/internal/accounts/accounts.go b/internal/accounts/accounts.go
index 2ff688c4..e98c6a33 100644
--- a/internal/accounts/accounts.go
+++ b/internal/accounts/accounts.go
@@ -53,7 +53,7 @@ type AccountResult struct {
 func (r *AccountResult) JSON() interface{} {
 	result := make(map[string]interface{})
 	result["address"] = r.Address
-	result["balance"] = r.Balance
+	result["balance"] = cadence.UFix64(r.Balance).String()
 
 	keys := make([]string, 0)
 	for _, key := range r.Keys {
@@ -96,6 +96,8 @@ func (r *AccountResult) String() string {
 		fmt.Fprintf(writer, "\tSignature Algorithm\t %s\n", key.SigAlgo)
 		fmt.Fprintf(writer, "\tHash Algorithm\t %s\n", key.HashAlgo)
 		fmt.Fprintf(writer, "\tRevoked \t %t\n", key.Revoked)
+		fmt.Fprintf(writer, "\tSequence Number \t %d\n", key.SequenceNumber)
+		fmt.Fprintf(writer, "\tIndex \t %d\n", key.Index)
 		fmt.Fprintf(writer, "\n")
 	}
 
@@ -123,5 +125,5 @@ func (r *AccountResult) Oneliner() string {
 		keys = append(keys, key.PublicKey.String())
 	}
 
-	return fmt.Sprintf("Address: 0x%s, Balance: %v, Public Keys: %s", r.Address, r.Balance, keys)
+	return fmt.Sprintf("Address: 0x%s, Balance: %s, Public Keys: %s", r.Address, cadence.UFix64(r.Balance), keys)
 }
diff --git a/internal/accounts/create.go b/internal/accounts/create.go
index 54c5ae75..feb5ecfb 100644
--- a/internal/accounts/create.go
+++ b/internal/accounts/create.go
@@ -30,6 +30,7 @@ import (
 type flagsCreate struct {
 	Signer    string   `default:"emulator-account" flag:"signer" info:"Account name from configuration used to sign the transaction"`
 	Keys      []string `flag:"key" info:"Public keys to attach to account"`
+	Weights   []int    `flag:"key-weight" info:"Weight for the key"`
 	SigAlgo   string   `default:"ECDSA_P256" flag:"sig-algo" info:"Signature algorithm used to generate the keys"`
 	HashAlgo  string   `default:"SHA3_256" flag:"hash-algo" info:"Hash used for the digest"`
 	Contracts []string `flag:"contract" info:"Contract to be deployed during account creation. <name:filename>"`
@@ -58,6 +59,7 @@ var CreateCommand = &command.Command{
 		account, err := services.Accounts.Create(
 			createFlags.Signer,
 			createFlags.Keys,
+			createFlags.Weights,
 			createFlags.SigAlgo,
 			createFlags.HashAlgo,
 			createFlags.Contracts,
diff --git a/internal/accounts/get.go b/internal/accounts/get.go
index 7a9309b3..26433c52 100644
--- a/internal/accounts/get.go
+++ b/internal/accounts/get.go
@@ -36,9 +36,10 @@ var getFlags = flagsGet{}
 
 var GetCommand = &command.Command{
 	Cmd: &cobra.Command{
-		Use:   "get <address>",
-		Short: "Gets an account by address",
-		Args:  cobra.ExactArgs(1),
+		Use:     "get <address>",
+		Short:   "Gets an account by address",
+		Example: "flow accounts get f8d6e0586b0a20c7",
+		Args:    cobra.ExactArgs(1),
 	},
 	Flags: &getFlags,
 	Run: func(
diff --git a/internal/accounts/staking-info.go b/internal/accounts/staking-info.go
index 88e00878..08487a44 100644
--- a/internal/accounts/staking-info.go
+++ b/internal/accounts/staking-info.go
@@ -37,9 +37,10 @@ var stakingFlags = flagsStakingInfo{}
 
 var StakingCommand = &command.Command{
 	Cmd: &cobra.Command{
-		Use:   "staking-info <address>",
-		Short: "Get account staking info",
-		Args:  cobra.ExactArgs(1),
+		Use:     "staking-info <address>",
+		Short:   "Get account staking info",
+		Example: "flow accounts staking-info f8d6e0586b0a20c7",
+		Args:    cobra.ExactArgs(1),
 	},
 	Flags: &stakingFlags,
 	Run: func(
diff --git a/internal/blocks/get.go b/internal/blocks/get.go
index ffe3aa86..f11e9957 100644
--- a/internal/blocks/get.go
+++ b/internal/blocks/get.go
@@ -39,9 +39,10 @@ var blockFlags = flagsBlocks{}
 
 var GetCommand = &command.Command{
 	Cmd: &cobra.Command{
-		Use:   "get <block_id|latest|block_height>",
-		Short: "Get block info",
-		Args:  cobra.ExactArgs(1),
+		Use:     "get <block_id|latest|block_height>",
+		Short:   "Get block info",
+		Example: "flow blocks get latest --network testnet",
+		Args:    cobra.ExactArgs(1),
 	},
 	Flags: &blockFlags,
 	Run: func(
diff --git a/internal/collections/get.go b/internal/collections/get.go
index 1bbbb392..ce2d18b3 100644
--- a/internal/collections/get.go
+++ b/internal/collections/get.go
@@ -31,9 +31,10 @@ var collectionFlags = flagsCollections{}
 
 var GetCommand = &command.Command{
 	Cmd: &cobra.Command{
-		Use:   "get <collection_id>",
-		Short: "Get collection info",
-		Args:  cobra.ExactArgs(1),
+		Use:     "get <collection_id>",
+		Short:   "Get collection info",
+		Example: "flow collections get 270d...9c31e",
+		Args:    cobra.ExactArgs(1),
 	},
 	Flags: &collectionFlags,
 	Run: func(
diff --git a/internal/command/command.go b/internal/command/command.go
index 2cf4cf64..fb2cd2d4 100644
--- a/internal/command/command.go
+++ b/internal/command/command.go
@@ -22,20 +22,23 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"io/ioutil"
+	"net/http"
 	"os"
 	"strings"
 
-	"github.com/onflow/flow-go-sdk/client"
-	"github.com/psiemens/sconfig"
-	"github.com/spf13/afero"
-	"github.com/spf13/cobra"
-
+	"github.com/onflow/flow-cli/build"
 	"github.com/onflow/flow-cli/pkg/flowcli/config"
 	"github.com/onflow/flow-cli/pkg/flowcli/gateway"
 	"github.com/onflow/flow-cli/pkg/flowcli/output"
 	"github.com/onflow/flow-cli/pkg/flowcli/project"
 	"github.com/onflow/flow-cli/pkg/flowcli/services"
 	"github.com/onflow/flow-cli/pkg/flowcli/util"
+
+	"github.com/onflow/flow-go-sdk/client"
+	"github.com/psiemens/sconfig"
+	"github.com/spf13/afero"
+	"github.com/spf13/cobra"
 )
 
 type RunCommand func(
@@ -58,6 +61,7 @@ type GlobalFlags struct {
 	Host       string
 	Log        string
 	Network    string
+	Yes        bool
 	ConfigPath []string
 }
 
@@ -74,73 +78,82 @@ const (
 	logLevelNone  = "none"
 )
 
-var flags = GlobalFlags{
+var Flags = GlobalFlags{
 	Filter:     "",
 	Format:     formatText,
 	Save:       "",
 	Host:       "",
+	Network:    config.DefaultEmulatorNetwork().Name,
 	Log:        logLevelInfo,
-	Network:    "",
+	Yes:        false,
 	ConfigPath: project.DefaultConfigPaths,
 }
 
 // InitFlags init all the global persistent flags
 func InitFlags(cmd *cobra.Command) {
 	cmd.PersistentFlags().StringVarP(
-		&flags.Filter,
+		&Flags.Filter,
 		"filter",
 		"x",
-		flags.Filter,
+		Flags.Filter,
 		"Filter result values by property name",
 	)
 
 	cmd.PersistentFlags().StringVarP(
-		&flags.Host,
+		&Flags.Host,
 		"host",
 		"",
-		flags.Host,
+		Flags.Host,
 		"Flow Access API host address",
 	)
 
 	cmd.PersistentFlags().StringVarP(
-		&flags.Format,
+		&Flags.Format,
 		"output",
 		"o",
-		flags.Format,
+		Flags.Format,
 		"Output format, options: \"text\", \"json\", \"inline\"",
 	)
 
 	cmd.PersistentFlags().StringVarP(
-		&flags.Save,
+		&Flags.Save,
 		"save",
 		"s",
-		flags.Save,
+		Flags.Save,
 		"Save result to a filename",
 	)
 
 	cmd.PersistentFlags().StringVarP(
-		&flags.Log,
+		&Flags.Log,
 		"log",
 		"l",
-		flags.Log,
+		Flags.Log,
 		"Log level, options: \"debug\", \"info\", \"error\", \"none\"",
 	)
 
 	cmd.PersistentFlags().StringSliceVarP(
-		&flags.ConfigPath,
+		&Flags.ConfigPath,
 		"config-path",
 		"f",
-		flags.ConfigPath,
+		Flags.ConfigPath,
 		"Path to flow configuration file",
 	)
 
 	cmd.PersistentFlags().StringVarP(
-		&flags.Network,
+		&Flags.Network,
 		"network",
 		"n",
-		flags.Network,
+		Flags.Network,
 		"Network from configuration file",
 	)
+
+	cmd.PersistentFlags().BoolVarP(
+		&Flags.Yes,
+		"yes",
+		"y",
+		Flags.Yes,
+		"Approve any prompts",
+	)
 }
 
 // AddToParent add new command to main parent cmd
@@ -150,32 +163,34 @@ func InitFlags(cmd *cobra.Command) {
 func (c Command) AddToParent(parent *cobra.Command) {
 	c.Cmd.Run = func(cmd *cobra.Command, args []string) {
 		// initialize project but ignore error since config can be missing
-		proj, err := project.Load(flags.ConfigPath)
+		proj, err := project.Load(Flags.ConfigPath)
 		// here we ignore if config does not exist as some commands don't require it
-		if !errors.Is(err, config.ErrDoesNotExist) {
+		if !errors.Is(err, config.ErrDoesNotExist) && cmd.CommandPath() != "flow init" { // ignore configs errors if we are doing init config
 			handleError("Config Error", err)
 		}
 
-		host, err := resolveHost(proj, flags.Host, flags.Network)
+		host, err := resolveHost(proj, Flags.Host, Flags.Network)
 		handleError("Host Error", err)
 
 		clientGateway, err := createGateway(host)
 		handleError("Gateway Error", err)
 
-		logger := createLogger(flags.Log, flags.Format)
+		logger := createLogger(Flags.Log, Flags.Format)
 
 		service := services.NewServices(clientGateway, proj, logger)
 
+		checkVersion(logger)
+
 		// run command
-		result, err := c.Run(cmd, args, flags, service)
+		result, err := c.Run(cmd, args, Flags, service)
 		handleError("Command Error", err)
 
 		// format output result
-		formattedResult, err := formatResult(result, flags.Filter, flags.Format)
+		formattedResult, err := formatResult(result, Flags.Filter, Flags.Format)
 		handleError("Result", err)
 
 		// output result
-		err = outputResult(formattedResult, flags.Save)
+		err = outputResult(formattedResult, Flags.Save, Flags.Format, Flags.Filter)
 		handleError("Output Error", err)
 	}
 
@@ -193,24 +208,30 @@ func createGateway(host string) (gateway.Gateway, error) {
 
 // resolveHost from the flags provided
 func resolveHost(proj *project.Project, hostFlag string, networkFlag string) (string, error) {
-	host := hostFlag
-	if networkFlag != "" && proj != nil {
+	// don't allow both network and host flag as the host might be different
+	if networkFlag != config.DefaultEmulatorNetwork().Name && hostFlag != "" {
+		return "", fmt.Errorf("shouldn't use both host and network flags, better to use network flag")
+	}
+
+	// host flag has highest priority
+	if hostFlag != "" {
+		return hostFlag, nil
+	}
+	// network flag with project initialized is next
+	if proj != nil {
 		check := proj.NetworkByName(networkFlag)
 		if check == nil {
-			return "", fmt.Errorf("provided network with name %s doesn't exists in condiguration", networkFlag)
+			return "", fmt.Errorf("network with name %s does not exist in configuration", networkFlag)
 		}
 
-		host = proj.NetworkByName(networkFlag).Host
-	} else if host == "" {
-		host = config.DefaultEmulatorNetwork().Host
+		return proj.NetworkByName(networkFlag).Host, nil
 	}
-
-	return host, nil
+	// default to emulator host
+	return config.DefaultEmulatorNetwork().Host, nil
 }
 
 // create logger utility
 func createLogger(logFlag string, formatFlag string) output.Logger {
-
 	// disable logging if we user want a specific format like JSON
 	// (more common they will not want also to have logs)
 	if formatFlag != formatText {
@@ -248,7 +269,7 @@ func formatResult(result Result, filterFlag string, formatFlag string) (string,
 		return fmt.Sprintf("%v", value), nil
 	}
 
-	switch formatFlag {
+	switch strings.ToLower(formatFlag) {
 	case formatJSON:
 		jsonRes, _ := json.Marshal(result.JSON())
 		return string(jsonRes), nil
@@ -260,7 +281,7 @@ func formatResult(result Result, filterFlag string, formatFlag string) (string,
 }
 
 // outputResult to selected media
-func outputResult(result string, saveFlag string) error {
+func outputResult(result string, saveFlag string, formatFlag string, filterFlag string) error {
 	if saveFlag != "" {
 		af := afero.Afero{
 			Fs: afero.NewOsFs(),
@@ -270,8 +291,11 @@ func outputResult(result string, saveFlag string) error {
 		return af.WriteFile(saveFlag, []byte(result), 0644)
 	}
 
-	// default normal output
-	fmt.Fprintf(os.Stdout, "%s\n", result)
+	if formatFlag == formatInline || filterFlag != "" {
+		fmt.Fprintf(os.Stdout, "%s", result)
+	} else { // default normal output
+		fmt.Fprintf(os.Stdout, "\n%s\n\n", result)
+	}
 	return nil
 }
 
@@ -289,7 +313,7 @@ func filterResultValue(result Result, filter string) (interface{}, error) {
 		possibleFilters = append(possibleFilters, key)
 	}
 
-	value := jsonResult[filter]
+	value := jsonResult[strings.ToLower(filter)]
 
 	if value == nil {
 		return nil, fmt.Errorf("value for filter: '%s' doesn't exists, possible values to filter by: %s", filter, possibleFilters)
@@ -319,7 +343,8 @@ func handleError(description string, err error) {
 		} else if strings.Contains(err.Error(), "NotFound desc =") {
 			fmt.Fprintf(os.Stderr, "❌ Not Found:%s \n", strings.Split(err.Error(), "NotFound desc =")[1])
 		} else if strings.Contains(err.Error(), "code = InvalidArgument desc = ") {
-			fmt.Fprintf(os.Stderr, "❌ Invalid argument: %s \n", strings.Split(err.Error(), "code = InvalidArgument desc = ")[1])
+			desc := strings.Split(err.Error(), "code = InvalidArgument desc = ")
+			fmt.Fprintf(os.Stderr, "❌ Invalid argument: %s \n", desc[len(desc)-1])
 			if strings.Contains(err.Error(), "is invalid for chain") {
 				fmt.Fprintf(os.Stderr, "🙏 Check you are connecting to the correct network or account address you use is correct.")
 			} else {
@@ -340,6 +365,26 @@ func handleError(description string, err error) {
 	os.Exit(1)
 }
 
+// checkVersion fetches latest version and compares it to local
+func checkVersion(logger output.Logger) {
+	resp, err := http.Get("https://raw.githubusercontent.com/onflow/flow-cli/master/version.txt")
+	if err != nil || resp.StatusCode >= 400 {
+		return
+	}
+
+	defer resp.Body.Close()
+	body, _ := ioutil.ReadAll(resp.Body)
+	latestVersion := strings.TrimSpace(string(body))
+
+	if latestVersion != build.Semver() {
+		logger.Info(fmt.Sprintf(
+			"\n⚠️  Version warning: a new version of Flow CLI is available (%s).\n"+
+				"Read the installation guide for upgrade instructions: https://docs.onflow.org/flow-cli/install",
+			strings.ReplaceAll(string(latestVersion), "\n", ""),
+		))
+	}
+}
+
 // bindFlags bind all the flags needed
 func bindFlags(command Command) {
 	err := sconfig.New(command.Flags).
diff --git a/internal/emulator/start.go b/internal/emulator/start.go
index 86990d52..c2795b7d 100644
--- a/internal/emulator/start.go
+++ b/internal/emulator/start.go
@@ -21,6 +21,8 @@ package emulator
 import (
 	"errors"
 
+	"github.com/onflow/flow-cli/internal/command"
+
 	emulator "github.com/onflow/flow-emulator"
 
 	"github.com/onflow/flow-emulator/cmd/emulator/start"
@@ -65,10 +67,10 @@ func ConfiguredServiceKey(
 			}
 		}
 	} else {
-		proj, err = project.Load(project.DefaultConfigPaths)
+		proj, err = project.Load(command.Flags.ConfigPath)
 		if err != nil {
 			if errors.Is(err, config.ErrDoesNotExist) {
-				util.Exitf(1, "🙏 Configuration is missing, initialize it with: 'flow project init' and then rerun this command.")
+				util.Exitf(1, "🙏 Configuration is missing, initialize it with: 'flow init' and then rerun this command.")
 			} else {
 				util.Exitf(1, err.Error())
 			}
diff --git a/internal/events/events.go b/internal/events/events.go
index 30373388..341303be 100644
--- a/internal/events/events.go
+++ b/internal/events/events.go
@@ -111,10 +111,10 @@ func eventsString(writer io.Writer, events []flow.Event) {
 }
 
 func eventString(writer io.Writer, event flow.Event) {
-	fmt.Fprintf(writer, "\n\t Index\t %v\n", event.EventIndex)
-	fmt.Fprintf(writer, "\t Type\t %s\n", event.Type)
-	fmt.Fprintf(writer, "\t Tx ID\t %s\n", event.TransactionID)
-	fmt.Fprintf(writer, "\t Values\n")
+	fmt.Fprintf(writer, "\n    Index\t%d\n", event.EventIndex)
+	fmt.Fprintf(writer, "    Type\t%s\n", event.Type)
+	fmt.Fprintf(writer, "    Tx ID\t%s\n", event.TransactionID)
+	fmt.Fprintf(writer, "    Values\n")
 
 	for i, field := range event.Value.EventType.Fields {
 		value := event.Value.Fields[i]
@@ -132,8 +132,8 @@ func printField(writer io.Writer, field cadence.Field, value cadence.Value) {
 		typeInfo = "Address"
 	}
 
-	fmt.Fprintf(writer, "\t\t")
-	fmt.Fprintf(writer, " %s (%s)\t", field.Identifier, typeInfo)
+	fmt.Fprintf(writer, "\t\t-")
+	fmt.Fprintf(writer, " %s (%s):\t", field.Identifier, typeInfo)
 	// Try the two most obvious cases
 	if address, ok := v.([8]byte); ok {
 		fmt.Fprintf(writer, "%x", address)
diff --git a/internal/keys/keys.go b/internal/keys/keys.go
index 8c271934..43016dc9 100644
--- a/internal/keys/keys.go
+++ b/internal/keys/keys.go
@@ -49,8 +49,8 @@ type KeyResult struct {
 // JSON convert result to JSON
 func (k *KeyResult) JSON() interface{} {
 	result := make(map[string]string)
-	result["private"] = hex.EncodeToString(k.privateKey.PublicKey().Encode())
-	result["public"] = hex.EncodeToString(k.privateKey.Encode())
+	result["public"] = hex.EncodeToString(k.privateKey.PublicKey().Encode())
+	result["private"] = hex.EncodeToString(k.privateKey.Encode())
 
 	return result
 }
diff --git a/internal/project/deploy.go b/internal/project/deploy.go
index 87a8034b..a3ef04da 100644
--- a/internal/project/deploy.go
+++ b/internal/project/deploy.go
@@ -34,8 +34,9 @@ var deployFlags = flagsDeploy{}
 
 var DeployCommand = &command.Command{
 	Cmd: &cobra.Command{
-		Use:   "deploy",
-		Short: "Deploy Cadence contracts",
+		Use:     "deploy",
+		Short:   "Deploy Cadence contracts",
+		Example: "flow project deploy --network testnet",
 	},
 	Flags: &deployFlags,
 	Run: func(
diff --git a/internal/project/init.go b/internal/project/init.go
index 1cf28f44..33d6d710 100644
--- a/internal/project/init.go
+++ b/internal/project/init.go
@@ -32,8 +32,9 @@ var initFlag = config.FlagsInit{}
 
 var InitCommand = &command.Command{
 	Cmd: &cobra.Command{
-		Use:   "init",
-		Short: "Initialize a new configuration",
+		Use:     "init",
+		Short:   "Initialize a new configuration",
+		Example: "flow project init",
 	},
 	Flags: &initFlag,
 	Run: func(
diff --git a/internal/scripts/execute.go b/internal/scripts/execute.go
index ecb97fb3..655a91d2 100644
--- a/internal/scripts/execute.go
+++ b/internal/scripts/execute.go
@@ -72,6 +72,7 @@ var ExecuteCommand = &command.Command{
 			filename,
 			scriptFlags.Arg,
 			scriptFlags.ArgsJSON,
+			globalFlags.Network,
 		)
 		if err != nil {
 			return nil, err
diff --git a/internal/transactions/build.go b/internal/transactions/build.go
new file mode 100644
index 00000000..39e87128
--- /dev/null
+++ b/internal/transactions/build.go
@@ -0,0 +1,73 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package transactions
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/onflow/flow-cli/internal/command"
+	"github.com/onflow/flow-cli/pkg/flowcli/services"
+)
+
+type flagsBuild struct {
+	ArgsJSON         string   `default:"" flag:"args-json" info:"arguments in JSON-Cadence format"`
+	Args             []string `default:"" flag:"arg" info:"argument in Type:Value format"`
+	Proposer         string   `default:"emulator-account" flag:"proposer" info:"transaction proposer"`
+	ProposerKeyIndex int      `default:"0" flag:"proposer-key-index" info:"proposer key index"`
+	Payer            string   `default:"emulator-account" flag:"payer" info:"transaction payer"`
+	Authorizer       []string `default:"emulator-account" flag:"authorizer" info:"transaction authorizer"`
+}
+
+var buildFlags = flagsBuild{}
+
+var BuildCommand = &command.Command{
+	Cmd: &cobra.Command{
+		Use:     "build <code filename>",
+		Short:   "Build an unsigned transaction",
+		Example: "flow transactions build ./transaction.cdc --proposer alice --authorizer alice --payer bob",
+		Args:    cobra.ExactArgs(1),
+	},
+	Flags: &buildFlags,
+	Run: func(
+		cmd *cobra.Command,
+		args []string,
+		globalFlags command.GlobalFlags,
+		services *services.Services,
+	) (command.Result, error) {
+
+		globalFlags.Filter = "payload"
+
+		build, err := services.Transactions.Build(
+			buildFlags.Proposer,
+			buildFlags.Authorizer,
+			buildFlags.Payer,
+			buildFlags.ProposerKeyIndex,
+			args[0], // code filename
+			buildFlags.Args,
+			buildFlags.ArgsJSON,
+			globalFlags.Network,
+		)
+		if err != nil {
+			return nil, err
+		}
+
+		return &TransactionResult{
+			tx: build.FlowTransaction(),
+		}, nil
+	},
+}
diff --git a/internal/transactions/get.go b/internal/transactions/get.go
index 4563651e..60dc5b4f 100644
--- a/internal/transactions/get.go
+++ b/internal/transactions/get.go
@@ -39,6 +39,7 @@ var GetCommand = &command.Command{
 		Use:     "get <tx_id>",
 		Aliases: []string{"status"},
 		Short:   "Get the transaction by ID",
+		Example: "flow transactions get 07a8...b433",
 		Args:    cobra.ExactArgs(1),
 	},
 	Flags: &getFlags,
diff --git a/internal/transactions/send-signed.go b/internal/transactions/send-signed.go
new file mode 100644
index 00000000..0dbac74d
--- /dev/null
+++ b/internal/transactions/send-signed.go
@@ -0,0 +1,60 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package transactions
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/onflow/flow-cli/internal/command"
+	"github.com/onflow/flow-cli/pkg/flowcli/services"
+)
+
+type flagsSendSigned struct {
+}
+
+var sendSignedFlags = flagsSendSigned{}
+
+var SendSignedCommand = &command.Command{
+	Cmd: &cobra.Command{
+		Use:     "send-signed <signed transaction filename>",
+		Short:   "Send signed transaction",
+		Args:    cobra.ExactArgs(1),
+		Example: `flow transactions send-signed signed.rlp`,
+	},
+	Flags: &sendSignedFlags,
+	Run: func(
+		cmd *cobra.Command,
+		args []string,
+		globalFlags command.GlobalFlags,
+		services *services.Services,
+	) (command.Result, error) {
+
+		tx, result, err := services.Transactions.SendSigned(
+			args[0], // signed filename
+		)
+		if err != nil {
+			return nil, err
+		}
+
+		return &TransactionResult{
+			result: result,
+			tx:     tx,
+		}, nil
+	},
+}
diff --git a/internal/transactions/send.go b/internal/transactions/send.go
index 71c8f816..6a462397 100644
--- a/internal/transactions/send.go
+++ b/internal/transactions/send.go
@@ -40,7 +40,7 @@ var sendFlags = flagsSend{}
 
 var SendCommand = &command.Command{
 	Cmd: &cobra.Command{
-		Use:     "send <filename>",
+		Use:     "send <code filename>",
 		Short:   "Send a transaction",
 		Args:    cobra.MaximumNArgs(1),
 		Example: `flow transactions send tx.cdc --arg String:"Hello world"`,
@@ -70,8 +70,6 @@ var SendCommand = &command.Command{
 		} else if sendFlags.Code != "" {
 			fmt.Println("⚠️  DEPRECATION WARNING: use filename as a command argument <filename>")
 			filename = sendFlags.Code
-		} else {
-			return nil, fmt.Errorf("provide a valide filename command argument")
 		}
 
 		tx, result, err := services.Transactions.Send(
@@ -79,6 +77,7 @@ var SendCommand = &command.Command{
 			sendFlags.Signer,
 			sendFlags.Arg,
 			sendFlags.ArgsJSON,
+			globalFlags.Network,
 		)
 		if err != nil {
 			return nil, err
diff --git a/internal/transactions/sign.go b/internal/transactions/sign.go
new file mode 100644
index 00000000..407ccc77
--- /dev/null
+++ b/internal/transactions/sign.go
@@ -0,0 +1,62 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package transactions
+
+import (
+	"github.com/spf13/cobra"
+
+	"github.com/onflow/flow-cli/internal/command"
+	"github.com/onflow/flow-cli/pkg/flowcli/services"
+)
+
+type flagsSign struct {
+	Signer string `default:"emulator-account" flag:"signer" info:"name of the account used to sign"`
+}
+
+var signFlags = flagsSign{}
+
+var SignCommand = &command.Command{
+	Cmd: &cobra.Command{
+		Use:     "sign <built transaction filename>",
+		Short:   "Sign built transaction",
+		Example: "flow transactions sign ./built.rlp --signer alice",
+		Args:    cobra.ExactArgs(1),
+	},
+	Flags: &signFlags,
+	Run: func(
+		cmd *cobra.Command,
+		args []string,
+		globalFlags command.GlobalFlags,
+		services *services.Services,
+	) (command.Result, error) {
+
+		signed, err := services.Transactions.Sign(
+			args[0], // transaction payload
+			signFlags.Signer,
+			globalFlags.Yes,
+		)
+		if err != nil {
+			return nil, err
+		}
+
+		return &TransactionResult{
+			tx: signed.FlowTransaction(),
+		}, nil
+	},
+}
diff --git a/internal/transactions/transactions.go b/internal/transactions/transactions.go
index e2a9ae2b..299ea8d6 100644
--- a/internal/transactions/transactions.go
+++ b/internal/transactions/transactions.go
@@ -23,10 +23,10 @@ import (
 	"fmt"
 	"text/tabwriter"
 
+	"github.com/onflow/flow-cli/internal/events"
+
 	"github.com/onflow/flow-go-sdk"
 	"github.com/spf13/cobra"
-
-	"github.com/onflow/flow-cli/internal/events"
 )
 
 var Cmd = &cobra.Command{
@@ -38,6 +38,9 @@ var Cmd = &cobra.Command{
 func init() {
 	GetCommand.AddToParent(Cmd)
 	SendCommand.AddToParent(Cmd)
+	SignCommand.AddToParent(Cmd)
+	BuildCommand.AddToParent(Cmd)
+	SendSignedCommand.AddToParent(Cmd)
 }
 
 // TransactionResult represent result from all account commands
@@ -51,10 +54,14 @@ type TransactionResult struct {
 func (r *TransactionResult) JSON() interface{} {
 	result := make(map[string]string)
 	result["id"] = r.tx.ID().String()
-	result["status"] = r.result.Status.String()
+	result["payload"] = fmt.Sprintf("%x", r.tx.Encode())
+	result["authorizers"] = fmt.Sprintf("%s", r.tx.Authorizers)
+	result["payer"] = r.tx.Payer.String()
 
 	if r.result != nil {
 		result["events"] = fmt.Sprintf("%s", r.result.Events)
+		result["status"] = r.result.Status.String()
+		result["error"] = r.result.Error.Error()
 	}
 
 	return result
@@ -65,19 +72,77 @@ func (r *TransactionResult) String() string {
 	var b bytes.Buffer
 	writer := tabwriter.NewWriter(&b, 0, 8, 1, '\t', tabwriter.AlignRight)
 
-	fmt.Fprintf(writer, "ID\t %s\n", r.tx.ID())
-	fmt.Fprintf(writer, "Status\t %s\n", r.result.Status)
-	fmt.Fprintf(writer, "Payer\t %s\n", r.tx.Payer.Hex())
+	if r.result != nil {
+		if r.result.Error != nil {
+			fmt.Fprintf(writer, "❌ Transaction Error \n%s\n\n\n", r.result.Error.Error())
+		}
+
+		statusBadge := ""
+		if r.result.Status == flow.TransactionStatusSealed {
+			statusBadge = "✅"
+		}
+		fmt.Fprintf(writer, "Status\t%s %s\n", statusBadge, r.result.Status)
+	}
+
+	fmt.Fprintf(writer, "ID\t%s\n", r.tx.ID())
+	fmt.Fprintf(writer, "Payer\t%s\n", r.tx.Payer.Hex())
+	fmt.Fprintf(writer, "Authorizers\t%s\n", r.tx.Authorizers)
+
+	fmt.Fprintf(writer,
+		"\nProposal Key:\t\n    Address\t%s\n    Index\t%v\n    Sequence\t%v\n",
+		r.tx.ProposalKey.Address, r.tx.ProposalKey.KeyIndex, r.tx.ProposalKey.SequenceNumber,
+	)
+
+	if len(r.tx.PayloadSignatures) == 0 {
+		fmt.Fprintf(writer, "\nNo Payload Signatures\n")
+	}
+
+	if len(r.tx.EnvelopeSignatures) == 0 {
+		fmt.Fprintf(writer, "\nNo Envelope Signatures\n")
+	}
+
+	for i, e := range r.tx.PayloadSignatures {
+		fmt.Fprintf(writer, "\nPayload Signature %v:\n", i)
+		fmt.Fprintf(writer, "    Address\t%s\n", e.Address)
+		fmt.Fprintf(writer, "    Signature\t%x\n", e.Signature)
+		fmt.Fprintf(writer, "    Key Index\t%d\n", e.KeyIndex)
+	}
+
+	for i, e := range r.tx.EnvelopeSignatures {
+		fmt.Fprintf(writer, "\nEnvelope Signature %v:\n", i)
+		fmt.Fprintf(writer, "    Address\t%s\n", e.Address)
+		fmt.Fprintf(writer, "    Signature\t%x\n", e.Signature)
+		fmt.Fprintf(writer, "    Key Index\t%d\n", e.KeyIndex)
+	}
+
+	if r.result != nil {
+		e := events.EventResult{
+			Events: r.result.Events,
+		}
 
-	events := events.EventResult{
-		Events: r.result.Events,
+		eventsOutput := e.String()
+		if eventsOutput == "" {
+			eventsOutput = "None"
+		}
+
+		fmt.Fprintf(writer, "\n\nEvents:\t %s\n", eventsOutput)
 	}
-	fmt.Fprintf(writer, "Events\t %s\n", events.String())
 
-	if r.code {
-		fmt.Fprintf(writer, "Code\n\n%s\n", r.tx.Script)
+	if r.tx.Script != nil {
+		if len(r.tx.Arguments) == 0 {
+			fmt.Fprintf(writer, "\n\nArguments\tNo arguments\n")
+		} else {
+			fmt.Fprintf(writer, "\n\nArguments (%d):\n", len(r.tx.Arguments))
+			for i, argument := range r.tx.Arguments {
+				fmt.Fprintf(writer, "    - Argument %d: %s\n", i, argument)
+			}
+		}
+
+		fmt.Fprintf(writer, "\nCode\n\n%s\n", r.tx.Script)
 	}
 
+	fmt.Fprintf(writer, "\n\nPayload:\n%x", r.tx.Encode())
+
 	writer.Flush()
 	return b.String()
 }
diff --git a/pkg/flowcli/arguments.go b/pkg/flowcli/arguments.go
index b175a72c..ced0d14f 100644
--- a/pkg/flowcli/arguments.go
+++ b/pkg/flowcli/arguments.go
@@ -75,6 +75,8 @@ func ParseArgumentsCommaSplit(input []string) ([]cadence.Value, error) {
 			)
 		}
 
+		argInput = sanitizeAddressArg(argInput)
+
 		args = append(args, map[string]string{
 			"value": argInput[1],
 			"type":  argInput[0],
@@ -86,6 +88,15 @@ func ParseArgumentsCommaSplit(input []string) ([]cadence.Value, error) {
 	return cadenceArgs, err
 }
 
+// sanitizeAddressArg sanitize address and make sure it has 0x prefix
+func sanitizeAddressArg(argInput []string) []string {
+	if argInput[0] == "Address" && !strings.Contains(argInput[1], "0x") {
+		argInput[1] = fmt.Sprintf("0x%s", argInput[1])
+	}
+
+	return argInput
+}
+
 func ParseArguments(args []string, argsJSON string) (scriptArgs []cadence.Value, err error) {
 	if argsJSON != "" {
 		scriptArgs, err = ParseArgumentsJSON(argsJSON)
diff --git a/pkg/flowcli/config/config.go b/pkg/flowcli/config/config.go
index 07ed99a9..9b92e442 100644
--- a/pkg/flowcli/config/config.go
+++ b/pkg/flowcli/config/config.go
@@ -163,7 +163,7 @@ func (c *Contract) IsAlias() bool {
 }
 
 // GetByNameAndNetwork get contract array for account and network
-func (c *Contracts) GetByNameAndNetwork(name string, network string) Contract {
+func (c *Contracts) GetByNameAndNetwork(name string, network string) *Contract {
 	contracts := make(Contracts, 0)
 
 	for _, contract := range *c {
@@ -176,15 +176,18 @@ func (c *Contracts) GetByNameAndNetwork(name string, network string) Contract {
 	// and replace only name and source with existing
 	if len(contracts) == 0 {
 		cName := c.GetByName(name)
+		if cName == nil {
+			return nil
+		}
 
-		return Contract{
+		return &Contract{
 			Name:    cName.Name,
 			Network: network,
 			Source:  cName.Source,
 		}
 	}
 
-	return contracts[0]
+	return &contracts[0]
 }
 
 // TODO: this filtering can cause error if not found, better to refactor to returning
diff --git a/pkg/flowcli/contracts/contracts.go b/pkg/flowcli/contracts/contracts.go
index 4325ea58..d861054f 100644
--- a/pkg/flowcli/contracts/contracts.go
+++ b/pkg/flowcli/contracts/contracts.go
@@ -20,7 +20,6 @@ package contracts
 
 import (
 	"fmt"
-	"io/ioutil"
 	"path"
 	"strings"
 
@@ -133,106 +132,10 @@ func (c *Contract) addAlias(location string, target flow.Address) {
 	c.aliases[location] = target
 }
 
-type Loader interface {
-	Load(source string) (string, error)
-	Normalize(base, relative string) string
-}
-
-type FilesystemLoader struct{}
-
-func (f FilesystemLoader) Load(source string) (string, error) {
-	codeBytes, err := ioutil.ReadFile(source)
-	if err != nil {
-		return "", err
-	}
-
-	return string(codeBytes), nil
-}
-
-func (f FilesystemLoader) Normalize(base, relative string) string {
-	return absolutePath(base, relative)
-}
-
 func absolutePath(basePath, relativePath string) string {
 	return path.Join(path.Dir(basePath), relativePath)
 }
 
-type Preprocessor struct {
-	loader            Loader
-	aliases           map[string]string
-	contracts         []*Contract
-	contractsBySource map[string]*Contract
-}
-
-func NewPreprocessor(loader Loader, aliases map[string]string) *Preprocessor {
-	return &Preprocessor{
-		loader:            loader,
-		aliases:           aliases,
-		contracts:         make([]*Contract, 0),
-		contractsBySource: make(map[string]*Contract),
-	}
-}
-
-func (p *Preprocessor) AddContractSource(
-	contractName,
-	contractSource string,
-	target flow.Address,
-) error {
-	contractCode, err := p.loader.Load(contractSource)
-	if err != nil {
-		return err
-	}
-
-	c, err := newContract(
-		len(p.contracts),
-		contractName,
-		contractSource,
-		contractCode,
-		target,
-	)
-	if err != nil {
-		return err
-	}
-
-	p.contracts = append(p.contracts, c)
-	p.contractsBySource[c.source] = c
-
-	return nil
-}
-
-func (p *Preprocessor) ResolveImports() error {
-	for _, c := range p.contracts {
-		for _, location := range c.imports() {
-			importPath := p.loader.Normalize(c.source, location)
-			importAlias, isAlias := p.aliases[importPath]
-			importContract, isContract := p.contractsBySource[importPath]
-
-			if isContract {
-				c.addDependency(location, importContract)
-			} else if isAlias {
-				c.addAlias(location, flow.HexToAddress(importAlias))
-			} else {
-				return fmt.Errorf("Import from %s could not be found: %s, make sure import path is correct.", c.name, importPath)
-			}
-		}
-	}
-
-	return nil
-}
-
-func (p *Preprocessor) ContractBySource(contractSource string) *Contract {
-	return p.contractsBySource[contractSource]
-}
-
-func (p *Preprocessor) ContractDeploymentOrder() ([]*Contract, error) {
-	sorted, err := sortByDeploymentOrder(p.contracts)
-	if err != nil {
-		return nil, err
-	}
-
-	return sorted, nil
-}
-
 type CyclicImportError struct {
 	Cycles [][]*Contract
 }
diff --git a/pkg/flowcli/contracts/loader.go b/pkg/flowcli/contracts/loader.go
new file mode 100644
index 00000000..89e79963
--- /dev/null
+++ b/pkg/flowcli/contracts/loader.go
@@ -0,0 +1,41 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package contracts
+
+import "io/ioutil"
+
+type Loader interface {
+	Load(source string) (string, error)
+	Normalize(base, relative string) string
+}
+
+type FilesystemLoader struct{}
+
+func (f FilesystemLoader) Load(source string) (string, error) {
+	codeBytes, err := ioutil.ReadFile(source)
+	if err != nil {
+		return "", err
+	}
+
+	return string(codeBytes), nil
+}
+
+func (f FilesystemLoader) Normalize(base, relative string) string {
+	return absolutePath(base, relative)
+}
diff --git a/pkg/flowcli/contracts/preprocessor.go b/pkg/flowcli/contracts/preprocessor.go
new file mode 100644
index 00000000..ba52186b
--- /dev/null
+++ b/pkg/flowcli/contracts/preprocessor.go
@@ -0,0 +1,103 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package contracts
+
+import (
+	"fmt"
+
+	"github.com/onflow/flow-cli/pkg/flowcli/project"
+
+	"github.com/onflow/flow-go-sdk"
+)
+
+type Preprocessor struct {
+	loader            Loader
+	aliases           project.Aliases
+	contracts         []*Contract
+	contractsBySource map[string]*Contract
+}
+
+func NewPreprocessor(loader Loader, aliases project.Aliases) *Preprocessor {
+	return &Preprocessor{
+		loader:            loader,
+		aliases:           aliases,
+		contracts:         make([]*Contract, 0),
+		contractsBySource: make(map[string]*Contract),
+	}
+}
+
+func (p *Preprocessor) AddContractSource(
+	contractName,
+	contractSource string,
+	target flow.Address,
+) error {
+	contractCode, err := p.loader.Load(contractSource)
+	if err != nil {
+		return err
+	}
+
+	c, err := newContract(
+		len(p.contracts),
+		contractName,
+		contractSource,
+		contractCode,
+		target,
+	)
+	if err != nil {
+		return err
+	}
+
+	p.contracts = append(p.contracts, c)
+	p.contractsBySource[c.source] = c
+
+	return nil
+}
+
+func (p *Preprocessor) ResolveImports() error {
+	for _, c := range p.contracts {
+		for _, location := range c.imports() {
+			importPath := p.loader.Normalize(c.source, location)
+			importAlias, isAlias := p.aliases[importPath]
+			importContract, isContract := p.contractsBySource[importPath]
+
+			if isContract {
+				c.addDependency(location, importContract)
+			} else if isAlias {
+				c.addAlias(location, flow.HexToAddress(importAlias))
+			} else {
+				return fmt.Errorf("Import from %s could not be found: %s, make sure import path is correct.", c.name, importPath)
+			}
+		}
+	}
+
+	return nil
+}
+
+func (p *Preprocessor) ContractBySource(contractSource string) *Contract {
+	return p.contractsBySource[contractSource]
+}
+
+func (p *Preprocessor) ContractDeploymentOrder() ([]*Contract, error) {
+	sorted, err := sortByDeploymentOrder(p.contracts)
+	if err != nil {
+		return nil, err
+	}
+
+	return sorted, nil
+}
diff --git a/pkg/flowcli/contracts/resolver.go b/pkg/flowcli/contracts/resolver.go
new file mode 100644
index 00000000..3963e611
--- /dev/null
+++ b/pkg/flowcli/contracts/resolver.go
@@ -0,0 +1,122 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package contracts
+
+import (
+	"fmt"
+	"path"
+	"strings"
+
+	"github.com/onflow/cadence/runtime/ast"
+	"github.com/onflow/cadence/runtime/common"
+	"github.com/onflow/cadence/runtime/parser2"
+	"github.com/onflow/flow-go-sdk"
+
+	"github.com/onflow/flow-cli/pkg/flowcli/project"
+)
+
+// Resolver handles resolving imports in Cadence code
+type Resolver struct {
+	code    []byte
+	program *ast.Program
+}
+
+// NewResolver creates a new resolver
+func NewResolver(code []byte) (*Resolver, error) {
+	program, err := parser2.ParseProgram(string(code))
+	if err != nil {
+		return nil, err
+	}
+
+	return &Resolver{
+		code:    code,
+		program: program,
+	}, nil
+}
+
+// ResolveImports resolves imports in code to addresses
+//
+// resolving is done based on code file path and is resolved to
+// addresses defined in configuration for contracts or their aliases
+//
+func (r *Resolver) ResolveImports(
+	codePath string,
+	contracts []project.Contract,
+	aliases project.Aliases,
+) ([]byte, error) {
+	imports := r.getFileImports()
+	sourceTarget := r.getSourceTarget(contracts, aliases)
+
+	for _, imp := range imports {
+		target := sourceTarget[absolutePath(codePath, imp)]
+		if target != "" {
+			r.code = r.replaceImport(imp, target)
+		} else {
+			return nil, fmt.Errorf("import %s could not be resolved from the configuration", imp)
+		}
+	}
+
+	return r.code, nil
+}
+
+// replaceImport replaces import from path to address
+func (r *Resolver) replaceImport(from string, to string) []byte {
+	return []byte(strings.Replace(
+		string(r.code),
+		fmt.Sprintf(`"%s"`, from),
+		fmt.Sprintf("0x%s", to),
+		1,
+	))
+}
+
+// getSourceTarget return a map with contract paths as keys and addresses as values
+func (r *Resolver) getSourceTarget(
+	contracts []project.Contract,
+	aliases project.Aliases,
+) map[string]string {
+	sourceTarget := make(map[string]string)
+	for _, contract := range contracts {
+		sourceTarget[path.Clean(contract.Source)] = contract.Target.String()
+	}
+
+	for source, target := range aliases {
+		sourceTarget[path.Clean(source)] = flow.HexToAddress(target).String()
+	}
+
+	return sourceTarget
+}
+
+// HasFileImports checks if there is a file import statement present in Cadence code
+func (r *Resolver) HasFileImports() bool {
+	return len(r.getFileImports()) > 0
+}
+
+// getFileImports returns all cadence file imports from Cadence code as an array
+func (r *Resolver) getFileImports() []string {
+	imports := make([]string, 0)
+
+	for _, importDeclaration := range r.program.ImportDeclarations() {
+		_, ok := importDeclaration.Location.(common.AddressLocation)
+		if !ok {
+			imports = append(imports, importDeclaration.Location.String())
+		}
+	}
+
+	return imports
+}
diff --git a/pkg/flowcli/gateway/emulator.go b/pkg/flowcli/gateway/emulator.go
index 57b0d519..135ff1dd 100644
--- a/pkg/flowcli/gateway/emulator.go
+++ b/pkg/flowcli/gateway/emulator.go
@@ -51,7 +51,7 @@ func (g *EmulatorGateway) GetAccount(address flow.Address) (*flow.Account, error
 	return g.emulator.GetAccount(address)
 }
 
-func (g *EmulatorGateway) SendTransaction(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
+func (g *EmulatorGateway) SendSignedTransaction(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
 	return nil, fmt.Errorf("Not Supported Yet")
 }
 
diff --git a/pkg/flowcli/gateway/gateway.go b/pkg/flowcli/gateway/gateway.go
index 35baec85..e26ea793 100644
--- a/pkg/flowcli/gateway/gateway.go
+++ b/pkg/flowcli/gateway/gateway.go
@@ -28,7 +28,7 @@ import (
 
 type Gateway interface {
 	GetAccount(flow.Address) (*flow.Account, error)
-	SendTransaction(*flow.Transaction, *project.Account) (*flow.Transaction, error)
+	SendSignedTransaction(*project.Transaction) (*flow.Transaction, error)
 	GetTransactionResult(*flow.Transaction, bool) (*flow.TransactionResult, error)
 	GetTransaction(flow.Identifier) (*flow.Transaction, error)
 	ExecuteScript([]byte, []cadence.Value) (cadence.Value, error)
diff --git a/pkg/flowcli/gateway/grpc.go b/pkg/flowcli/gateway/grpc.go
index 4fae9ac4..a73838b2 100644
--- a/pkg/flowcli/gateway/grpc.go
+++ b/pkg/flowcli/gateway/grpc.go
@@ -62,37 +62,11 @@ func (g *GrpcGateway) GetAccount(address flow.Address) (*flow.Account, error) {
 	return account, nil
 }
 
-// TODO: replace with txsender - much nicer implemented
-// SendTransaction sends a transaction to Flow through the Access API.
-func (g *GrpcGateway) SendTransaction(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
-	account, err := g.GetAccount(signer.Address())
-	if err != nil {
-		return nil, fmt.Errorf("failed to get account with address %s: %w", signer.Address(), err)
-	}
-
-	// Default 0, i.e. first key
-	accountKey := account.Keys[0]
-
-	sealed, err := g.client.GetLatestBlockHeader(g.ctx, true)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get latest sealed block: %w", err)
-	}
-
-	tx.SetReferenceBlockID(sealed.ID).
-		SetProposalKey(signer.Address(), accountKey.Index, accountKey.SequenceNumber).
-		SetPayer(signer.Address())
-
-	sig, err := signer.DefaultKey().Signer(g.ctx)
-	if err != nil {
-		return nil, err
-	}
-
-	err = tx.SignEnvelope(signer.Address(), accountKey.Index, sig)
-	if err != nil {
-		return nil, fmt.Errorf("failed to sign transaction: %w", err)
-	}
+// SendSignedTransaction sends a transaction to flow that is already prepared and signed
+func (g *GrpcGateway) SendSignedTransaction(transaction *project.Transaction) (*flow.Transaction, error) {
+	tx := transaction.FlowTransaction()
 
-	err = g.client.SendTransaction(g.ctx, *tx)
+	err := g.client.SendTransaction(g.ctx, *tx)
 	if err != nil {
 		return nil, fmt.Errorf("failed to submit transaction: %w", err)
 	}
diff --git a/pkg/flowcli/output/logger.go b/pkg/flowcli/output/logger.go
index 5af4c1c3..cba9a6c7 100644
--- a/pkg/flowcli/output/logger.go
+++ b/pkg/flowcli/output/logger.go
@@ -36,7 +36,7 @@ type Logger interface {
 	Info(string)
 	Error(string)
 	StartProgress(string)
-	StopProgress(string)
+	StopProgress()
 }
 
 // NewStdoutLogger returns a new stdout logger.
@@ -78,20 +78,20 @@ func (s *StdoutLogger) StartProgress(msg string) {
 	}
 
 	if s.spinner != nil {
-		s.spinner.Stop("")
+		s.spinner.Stop()
 	}
 
 	s.spinner = NewSpinner(msg, "")
 	s.spinner.Start()
 }
 
-func (s *StdoutLogger) StopProgress(msg string) {
+func (s *StdoutLogger) StopProgress() {
 	if s.level == NoneLog {
 		return
 	}
 
 	if s.spinner != nil {
-		s.spinner.Stop(msg)
+		s.spinner.Stop()
 		s.spinner = nil
 	}
 }
diff --git a/pkg/flowcli/output/prompt.go b/pkg/flowcli/output/prompt.go
new file mode 100644
index 00000000..efe94623
--- /dev/null
+++ b/pkg/flowcli/output/prompt.go
@@ -0,0 +1,93 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package output
+
+import (
+	"fmt"
+
+	"github.com/gosuri/uilive"
+	"github.com/manifoldco/promptui"
+
+	"github.com/onflow/flow-cli/pkg/flowcli/project"
+)
+
+func ApproveTransactionPrompt(transaction *project.Transaction) bool {
+	writer := uilive.New()
+	tx := transaction.FlowTransaction()
+
+	fmt.Fprintf(writer, "\n")
+	fmt.Fprintf(writer, "ID\t%s\n", tx.ID())
+	fmt.Fprintf(writer, "Payer\t%s\n", tx.Payer.Hex())
+	fmt.Fprintf(writer, "Authorizers\t%s\n", tx.Authorizers)
+
+	fmt.Fprintf(writer,
+		"\nProposal Key:\t\n    Address\t%s\n    Index\t%v\n    Sequence\t%v\n",
+		tx.ProposalKey.Address, tx.ProposalKey.KeyIndex, tx.ProposalKey.SequenceNumber,
+	)
+
+	if len(tx.PayloadSignatures) == 0 {
+		fmt.Fprintf(writer, "\nNo Payload Signatures\n")
+	}
+
+	if len(tx.EnvelopeSignatures) == 0 {
+		fmt.Fprintf(writer, "\nNo Envelope Signatures\n")
+	}
+
+	for i, e := range tx.PayloadSignatures {
+		fmt.Fprintf(writer, "\nPayload Signature %v:\n", i)
+		fmt.Fprintf(writer, "    Address\t%s\n", e.Address)
+		fmt.Fprintf(writer, "    Signature\t%x\n", e.Signature)
+		fmt.Fprintf(writer, "    Key Index\t%d\n", e.KeyIndex)
+	}
+
+	for i, e := range tx.EnvelopeSignatures {
+		fmt.Fprintf(writer, "\nEnvelope Signature %v:\n", i)
+		fmt.Fprintf(writer, "    Address\t%s\n", e.Address)
+		fmt.Fprintf(writer, "    Signature\t%x\n", e.Signature)
+		fmt.Fprintf(writer, "    Key Index\t%d\n", e.KeyIndex)
+	}
+
+	if tx.Script != nil {
+		if len(tx.Arguments) == 0 {
+			fmt.Fprintf(writer, "\n\nArguments\tNo arguments\n")
+		} else {
+			fmt.Fprintf(writer, "\n\nArguments (%d):\n", len(tx.Arguments))
+			for i, argument := range tx.Arguments {
+				fmt.Fprintf(writer, "    - Argument %d: %s\n", i, argument)
+			}
+		}
+
+		fmt.Fprintf(writer, "\nCode\n\n%s\n", tx.Script)
+	}
+
+	fmt.Fprintf(writer, "\n\n")
+	writer.Flush()
+
+	prompt := promptui.Select{
+		Label: "⚠️  Do you want to sign this transaction?",
+		Items: []string{"No", "Yes"},
+	}
+
+	_, result, _ := prompt.Run()
+
+	fmt.Fprintf(writer, "\r\r")
+	writer.Flush()
+
+	return result == "Yes"
+}
diff --git a/pkg/flowcli/output/spinner.go b/pkg/flowcli/output/spinner.go
index e67e0e65..700f511d 100644
--- a/pkg/flowcli/output/spinner.go
+++ b/pkg/flowcli/output/spinner.go
@@ -54,8 +54,8 @@ func (s *Spinner) run() {
 
 	for {
 		select {
-		case message := <-s.done:
-			_, _ = fmt.Fprintln(writer, message)
+		case <-s.done:
+			_, _ = fmt.Fprintf(writer, "\r")
 			_ = writer.Flush()
 			close(s.done)
 			return
@@ -73,7 +73,7 @@ func (s *Spinner) run() {
 	}
 }
 
-func (s *Spinner) Stop(message string) {
-	s.done <- message
-	<-s.done
+func (s *Spinner) Stop() {
+	s.done <- ""
+	time.Sleep(50 * time.Millisecond)
 }
diff --git a/pkg/flowcli/project/keys.go b/pkg/flowcli/project/keys.go
index 2b7d63a7..313bd101 100644
--- a/pkg/flowcli/project/keys.go
+++ b/pkg/flowcli/project/keys.go
@@ -23,6 +23,8 @@ import (
 	"encoding/hex"
 	"fmt"
 
+	"github.com/onflow/flow-cli/pkg/flowcli/util"
+
 	"github.com/onflow/flow-go-sdk"
 	"github.com/onflow/flow-go-sdk/crypto"
 	"github.com/onflow/flow-go-sdk/crypto/cloudkms"
@@ -37,6 +39,7 @@ type AccountKey interface {
 	HashAlgo() crypto.HashAlgorithm
 	Signer(ctx context.Context) (crypto.Signer, error)
 	ToConfig() config.AccountKey
+	Validate() error
 }
 
 func NewAccountKey(accountKeyConf config.AccountKey) (AccountKey, error) {
@@ -82,6 +85,10 @@ func (a *baseAccountKey) Index() int {
 	return a.index
 }
 
+func (a *baseAccountKey) Validate() error {
+	return nil
+}
+
 type KmsAccountKey struct {
 	*baseAccountKey
 	kmsKey cloudkms.Key
@@ -117,6 +124,11 @@ func (a *KmsAccountKey) Signer(ctx context.Context) (crypto.Signer, error) {
 	return accountKMSSigner, nil
 }
 
+func (a *KmsAccountKey) Validate() error {
+	resourceID := a.ToConfig().Context[config.KMSContextField]
+	return util.GcloudApplicationSignin(resourceID)
+}
+
 func newKmsAccountKey(key config.AccountKey) (AccountKey, error) {
 	accountKMSKey, err := cloudkms.KeyFromResourceID(key.Context[config.KMSContextField])
 	if err != nil {
diff --git a/pkg/flowcli/project/project.go b/pkg/flowcli/project/project.go
index a99b8928..582f6751 100644
--- a/pkg/flowcli/project/project.go
+++ b/pkg/flowcli/project/project.go
@@ -23,6 +23,8 @@ import (
 	"fmt"
 	"path"
 
+	"github.com/onflow/flow-cli/pkg/flowcli/util"
+
 	"github.com/onflow/flow-go-sdk"
 	"github.com/onflow/flow-go-sdk/crypto"
 	"github.com/spf13/afero"
@@ -30,7 +32,6 @@ import (
 
 	"github.com/onflow/flow-cli/pkg/flowcli/config"
 	"github.com/onflow/flow-cli/pkg/flowcli/config/json"
-	"github.com/onflow/flow-cli/pkg/flowcli/util"
 )
 
 var (
@@ -130,7 +131,10 @@ func newProject(conf *config.Config, composer *config.Loader) (*Project, error)
 // The CLI currently does not allow the same contract to be deployed to multiple
 // accounts in the same network.
 func (p *Project) ContractConflictExists(network string) bool {
-	contracts := p.ContractsByNetwork(network)
+	contracts, err := p.ContractsByNetwork(network)
+	if err != nil {
+		return false
+	}
 
 	uniq := funk.Uniq(
 		funk.Map(contracts, func(c Contract) string {
@@ -170,16 +174,22 @@ func (p *Project) SetEmulatorServiceKey(privateKey crypto.PrivateKey) {
 }
 
 // ContractsByNetwork returns all contracts for a network.
-func (p *Project) ContractsByNetwork(network string) []Contract {
+func (p *Project) ContractsByNetwork(network string) ([]Contract, error) {
 	contracts := make([]Contract, 0)
 
 	// get deployments for the specified network
 	for _, deploy := range p.conf.Deployments.GetByNetwork(network) {
 		account := p.AccountByName(deploy.Account)
+		if account == nil {
+			return nil, fmt.Errorf("could not find account with name %s in the configuration", deploy.Account)
+		}
 
 		// go through each contract in this deployment
 		for _, contractName := range deploy.Contracts {
 			c := p.conf.Contracts.GetByNameAndNetwork(contractName, network)
+			if c == nil {
+				return nil, fmt.Errorf("could not find contract with name name %s in the configuration", contractName)
+			}
 
 			contract := Contract{
 				Name:   c.Name,
@@ -191,7 +201,7 @@ func (p *Project) ContractsByNetwork(network string) []Contract {
 		}
 	}
 
-	return contracts
+	return contracts, nil
 }
 
 // AccountNamesForNetwork returns all configured account names for a network.
@@ -245,9 +255,11 @@ func (p *Project) AccountByName(name string) *Account {
 	return account
 }
 
+type Aliases map[string]string
+
 // AliasesForNetwork returns all deployment aliases for a network.
-func (p *Project) AliasesForNetwork(network string) map[string]string {
-	aliases := make(map[string]string)
+func (p *Project) AliasesForNetwork(network string) Aliases {
+	aliases := make(Aliases)
 
 	// get all contracts for selected network and if any has an address as target make it an alias
 	for _, contract := range p.conf.Contracts.GetByNetwork(network) {
diff --git a/pkg/flowcli/project/transaction.go b/pkg/flowcli/project/transaction.go
new file mode 100644
index 00000000..98edf191
--- /dev/null
+++ b/pkg/flowcli/project/transaction.go
@@ -0,0 +1,283 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package project
+
+import (
+	"context"
+	"encoding/hex"
+	"fmt"
+	"io/ioutil"
+	"strings"
+
+	"github.com/onflow/flow-go-sdk/templates"
+
+	"github.com/onflow/flow-cli/pkg/flowcli"
+
+	"github.com/onflow/cadence"
+	"github.com/onflow/flow-go-sdk"
+
+	"github.com/onflow/flow-cli/pkg/flowcli/util"
+)
+
+const (
+	defaultGasLimit = 1000
+)
+
+// NewTransaction create new instance of transaction
+func NewTransaction() *Transaction {
+	return &Transaction{
+		tx: flow.NewTransaction(),
+	}
+}
+
+// NewTransactionFromPayload build transaction from payload
+func NewTransactionFromPayload(filename string) (*Transaction, error) {
+	partialTxHex, err := ioutil.ReadFile(filename)
+	if err != nil {
+		return nil, fmt.Errorf("failed to read partial transaction from %s: %v", filename, err)
+	}
+
+	partialTxBytes, err := hex.DecodeString(string(partialTxHex))
+	if err != nil {
+		return nil, fmt.Errorf("failed to decode partial transaction from %s: %v", filename, err)
+	}
+
+	decodedTx, err := flow.DecodeTransaction(partialTxBytes)
+	if err != nil {
+		return nil, fmt.Errorf("failed to decode transaction from %s: %v", filename, err)
+	}
+
+	tx := &Transaction{
+		tx: decodedTx,
+	}
+
+	return tx, nil
+}
+
+// NewUpdateAccountContractTransaction update account contract
+func NewUpdateAccountContractTransaction(signer *Account, name string, source string) (*Transaction, error) {
+	contract := templates.Contract{
+		Name:   name,
+		Source: source,
+	}
+
+	return newTransactionFromTemplate(
+		templates.UpdateAccountContract(signer.Address(), contract),
+		signer,
+	)
+}
+
+// NewAddAccountContractTransaction add new contract to the account
+func NewAddAccountContractTransaction(signer *Account, name string, source string) (*Transaction, error) {
+	contract := templates.Contract{
+		Name:   name,
+		Source: source,
+	}
+
+	return newTransactionFromTemplate(
+		templates.AddAccountContract(signer.Address(), contract),
+		signer,
+	)
+}
+
+// NewRemoveAccountContractTransaction creates new transaction to remove contract
+func NewRemoveAccountContractTransaction(signer *Account, name string) (*Transaction, error) {
+	return newTransactionFromTemplate(
+		templates.RemoveAccountContract(signer.Address(), name),
+		signer,
+	)
+}
+
+// NewCreateAccountTransaction creates new transaction for account
+func NewCreateAccountTransaction(
+	signer *Account,
+	keys []*flow.AccountKey,
+	contractArgs []string,
+) (*Transaction, error) {
+
+	contracts := make([]templates.Contract, 0)
+	for _, contract := range contractArgs {
+		contractFlagContent := strings.SplitN(contract, ":", 2)
+		if len(contractFlagContent) != 2 {
+			return nil, fmt.Errorf("wrong format for contract. Correct format is name:path, but got: %s", contract)
+		}
+
+		contractSource, err := util.LoadFile(contractFlagContent[1])
+		if err != nil {
+			return nil, err
+		}
+
+		contracts = append(contracts, templates.Contract{
+			Name:   contractFlagContent[0],
+			Source: string(contractSource),
+		})
+	}
+
+	return newTransactionFromTemplate(
+		templates.CreateAccount(keys, contracts, signer.Address()),
+		signer,
+	)
+}
+
+func newTransactionFromTemplate(templateTx *flow.Transaction, signer *Account) (*Transaction, error) {
+	tx := &Transaction{tx: templateTx}
+
+	err := tx.SetSigner(signer)
+	if err != nil {
+		return nil, err
+	}
+	tx.SetPayer(signer.Address())
+
+	return tx, nil
+}
+
+// Transaction builder of flow transactions
+type Transaction struct {
+	signer   *Account
+	proposer *flow.Account
+	tx       *flow.Transaction
+}
+
+// Signer get signer
+func (t *Transaction) Signer() *Account {
+	return t.signer
+}
+
+// Proposer get proposer
+func (t *Transaction) Proposer() *flow.Account {
+	return t.proposer
+}
+
+// FlowTransaction get flow transaction
+func (t *Transaction) FlowTransaction() *flow.Transaction {
+	return t.tx
+}
+
+func (t *Transaction) SetScriptWithArgs(script []byte, args []string, argsJSON string) error {
+	t.tx.SetScript(script)
+	return t.AddRawArguments(args, argsJSON)
+}
+
+// SetSigner sets the signer for transaction
+func (t *Transaction) SetSigner(account *Account) error {
+	err := account.DefaultKey().Validate()
+	if err != nil {
+		return err
+	}
+
+	t.signer = account
+	return nil
+}
+
+// SetProposer sets the proposer for transaction
+func (t *Transaction) SetProposer(proposer *flow.Account, keyIndex int) *Transaction {
+	t.proposer = proposer
+	proposerKey := proposer.Keys[keyIndex]
+
+	t.tx.SetProposalKey(
+		proposer.Address,
+		proposerKey.Index,
+		proposerKey.SequenceNumber,
+	)
+
+	return t
+}
+
+// SetPayer sets the payer for transaction
+func (t *Transaction) SetPayer(address flow.Address) *Transaction {
+	t.tx.SetPayer(address)
+	return t
+}
+
+// SetBlockReference sets block reference for transaction
+func (t *Transaction) SetBlockReference(block *flow.Block) *Transaction {
+	t.tx.SetReferenceBlockID(block.ID)
+	return t
+}
+
+// SetDefaultGasLimit set the default gas limit for transaction
+func (t *Transaction) SetDefaultGasLimit() *Transaction {
+	t.tx.SetGasLimit(defaultGasLimit)
+	return t
+}
+
+// AddRawArguments add raw arguments to tx
+func (t *Transaction) AddRawArguments(args []string, argsJSON string) error {
+	txArguments, err := flowcli.ParseArguments(args, argsJSON)
+	if err != nil {
+		return err
+	}
+
+	return t.AddArguments(txArguments)
+}
+
+// AddArguments add array of cadence arguments
+func (t *Transaction) AddArguments(args []cadence.Value) error {
+	for _, arg := range args {
+		err := t.AddArgument(arg)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// AddArgument add cadence typed argument
+func (t *Transaction) AddArgument(arg cadence.Value) error {
+	return t.tx.AddArgument(arg)
+}
+
+// AddAuthorizers add group of authorizers
+func (t *Transaction) AddAuthorizers(authorizers []flow.Address) *Transaction {
+	for _, authorizer := range authorizers {
+		t.tx.AddAuthorizer(authorizer)
+	}
+
+	return t
+}
+
+// Sign signs transaction using signer account
+func (t *Transaction) Sign() (*Transaction, error) {
+	keyIndex := t.signer.DefaultKey().Index()
+	signer, err := t.signer.DefaultKey().Signer(context.Background())
+	if err != nil {
+		return nil, err
+	}
+
+	if t.shouldSignEnvelope() {
+		err = t.tx.SignEnvelope(t.signer.address, keyIndex, signer)
+		if err != nil {
+			return nil, fmt.Errorf("failed to sign transaction: %s", err)
+		}
+	} else {
+		err = t.tx.SignPayload(t.signer.address, keyIndex, signer)
+		if err != nil {
+			return nil, fmt.Errorf("failed to sign transaction: %s", err)
+		}
+	}
+
+	return t, nil
+}
+
+// shouldSignEnvelope checks if signer should sign envelope or payload
+func (t *Transaction) shouldSignEnvelope() bool {
+	// if signer is payer
+	return t.signer.address == t.tx.Payer // todo discuss
+}
diff --git a/pkg/flowcli/services/accounts.go b/pkg/flowcli/services/accounts.go
index 632f643c..5c1a6a5b 100644
--- a/pkg/flowcli/services/accounts.go
+++ b/pkg/flowcli/services/accounts.go
@@ -19,22 +19,19 @@
 package services
 
 import (
-	"context"
 	"fmt"
 	"strings"
 
-	"github.com/onflow/cadence"
-	tmpl "github.com/onflow/flow-core-contracts/lib/go/templates"
-	"github.com/onflow/flow-go-sdk"
-	"github.com/onflow/flow-go-sdk/crypto"
-	"github.com/onflow/flow-go-sdk/templates"
-
 	"github.com/onflow/flow-cli/pkg/flowcli"
-	"github.com/onflow/flow-cli/pkg/flowcli/config"
 	"github.com/onflow/flow-cli/pkg/flowcli/gateway"
 	"github.com/onflow/flow-cli/pkg/flowcli/output"
 	"github.com/onflow/flow-cli/pkg/flowcli/project"
 	"github.com/onflow/flow-cli/pkg/flowcli/util"
+
+	"github.com/onflow/cadence"
+	tmpl "github.com/onflow/flow-core-contracts/lib/go/templates"
+	"github.com/onflow/flow-go-sdk"
+	"github.com/onflow/flow-go-sdk/crypto"
 )
 
 // Accounts is a service that handles all account-related interactions.
@@ -64,104 +61,15 @@ func (a *Accounts) Get(address string) (*flow.Account, error) {
 	flowAddress := flow.HexToAddress(address)
 
 	account, err := a.gateway.GetAccount(flowAddress)
-	a.logger.StopProgress("")
+	a.logger.StopProgress()
 
 	return account, err
 }
 
-func (a *Accounts) Add(
-	name string,
-	accountAddress string,
-	signatureAlgorithm string,
-	hashingAlgorithm string,
-	keyIndex int,
-	keyHex string,
-	overwrite bool,
-	path []string,
-) (*project.Account, error) {
-	if a.project == nil {
-		return nil, fmt.Errorf("missing configuration, initialize it: flow init")
-	}
-
-	existingAccount := a.project.AccountByName(name)
-	if existingAccount != nil && !overwrite {
-		return nil, fmt.Errorf("account with name [%s] already exists in the config, use `overwrite` if you want to overwrite it", name)
-	}
-
-	sigAlgo, hashAlgo, err := util.ConvertSigAndHashAlgo(signatureAlgorithm, hashingAlgorithm)
-	if err != nil {
-		return nil, err
-	}
-
-	if keyIndex < 0 {
-		return nil, fmt.Errorf("key index must be positive number")
-	}
-
-	address := flow.HexToAddress(accountAddress)
-	chainID, err := util.GetAddressNetwork(address)
-	if err != nil {
-		return nil, err
-	}
-
-	confAccount := config.Account{
-		Name:    name,
-		Address: address,
-		ChainID: chainID,
-	}
-
-	accountKey := config.AccountKey{
-		Index:    keyIndex,
-		SigAlgo:  sigAlgo,
-		HashAlgo: hashAlgo,
-	}
-
-	// TODO: discuss refactor to accounts
-	if keyHex != "" {
-		_, err := crypto.DecodePrivateKeyHex(sigAlgo, keyHex)
-		if err != nil {
-			return nil, fmt.Errorf("key hex could not be parsed")
-		}
-
-		accountKey.Type = config.KeyTypeHex
-		accountKey.Context = make(map[string]string)
-		accountKey.Context[config.PrivateKeyField] = keyHex
-
-	} else {
-		return nil, fmt.Errorf("private key must be provided")
-	}
-
-	confAccount.Keys = []config.AccountKey{accountKey}
-
-	account, err := project.AccountFromConfig(confAccount)
-	if err != nil {
-		return nil, err
-	}
-	// TODO: refactor context
-	sig, err := account.DefaultKey().Signer(context.Background())
-	if err != nil {
-		return nil, err
-	}
-
-	_, err = sig.Sign([]byte("test"))
-	if err != nil {
-		return nil, fmt.Errorf("could not sign with the new key")
-	}
-
-	a.project.AddOrUpdateAccount(account)
-
-	err = a.project.Save(path[0]) // only allow saving to one config for now
-	if err != nil {
-		return nil, err
-	}
-
-	a.logger.Info("Account added to configuration\n")
-
-	return account, nil
-}
-
 // StakingInfo returns the staking information for an account.
 func (a *Accounts) StakingInfo(accountAddress string) (*cadence.Value, *cadence.Value, error) {
 	a.logger.StartProgress(fmt.Sprintf("Fetching info for %s...", accountAddress))
+	defer a.logger.StopProgress()
 
 	address := flow.HexToAddress(accountAddress)
 
@@ -193,7 +101,7 @@ func (a *Accounts) StakingInfo(accountAddress string) (*cadence.Value, *cadence.
 		return nil, nil, fmt.Errorf("error getting delegation info: %s", err.Error())
 	}
 
-	a.logger.StopProgress("")
+	a.logger.StopProgress()
 
 	return &stakingValue, &delegationValue, nil
 }
@@ -206,6 +114,7 @@ func (a *Accounts) StakingInfo(accountAddress string) (*cadence.Value, *cadence.
 func (a *Accounts) Create(
 	signerName string,
 	keys []string,
+	keyWeights []int,
 	signatureAlgorithm string,
 	hashingAlgorithm string,
 	contracts []string,
@@ -214,12 +123,22 @@ func (a *Accounts) Create(
 		return nil, fmt.Errorf("missing configuration, initialize it: flow init")
 	}
 
+	// if more than one key is provided and at least one weight is specified, make sure there isn't a missmatch
+	if len(keys) > 1 && len(keyWeights) > 0 && len(keys) != len(keyWeights) {
+		return nil, fmt.Errorf(
+			"number of keys and weights provided must match, number of provided keys: %d, number of provided key weights: %d",
+			len(keys),
+			len(keyWeights),
+		)
+	}
+
 	signer := a.project.AccountByName(signerName)
 	if signer == nil {
 		return nil, fmt.Errorf("signer account: [%s] doesn't exists in configuration", signerName)
 	}
 
 	a.logger.StartProgress("Creating account...")
+	defer a.logger.StopProgress()
 
 	accountKeys := make([]*flow.AccountKey, len(keys))
 
@@ -241,46 +160,41 @@ func (a *Accounts) Create(
 			)
 		}
 
+		weight := flow.AccountKeyWeightThreshold
+		if len(keyWeights) > i {
+			weight = keyWeights[i]
+
+			if weight > flow.AccountKeyWeightThreshold || weight <= 0 {
+				return nil, fmt.Errorf("invalid key weight, valid range (0 - 1000)")
+			}
+		}
+
 		accountKeys[i] = &flow.AccountKey{
 			PublicKey: publicKey,
 			SigAlgo:   sigAlgo,
 			HashAlgo:  hashAlgo,
-			Weight:    flow.AccountKeyWeightThreshold,
+			Weight:    weight,
 		}
 	}
 
-	var contractTemplates []templates.Contract
-
-	for _, contract := range contracts {
-		contractFlagContent := strings.SplitN(contract, ":", 2)
-		if len(contractFlagContent) != 2 {
-			return nil, fmt.Errorf("wrong format for contract. Correct format is name:path, but got: %s", contract)
-		}
-		contractName := contractFlagContent[0]
-		contractPath := contractFlagContent[1]
-
-		contractSource, err := util.LoadFile(contractPath)
-		if err != nil {
-			return nil, err
-		}
+	tx, err := project.NewCreateAccountTransaction(signer, accountKeys, contracts)
+	if err != nil {
+		return nil, err
+	}
 
-		contractTemplates = append(contractTemplates,
-			templates.Contract{
-				Name:   contractName,
-				Source: string(contractSource),
-			},
-		)
+	tx, err = a.prepareTransaction(tx, signer)
+	if err != nil {
+		return nil, err
 	}
 
-	tx := templates.CreateAccount(accountKeys, contractTemplates, signer.Address())
-	tx, err = a.gateway.SendTransaction(tx, signer)
+	sentTx, err := a.gateway.SendSignedTransaction(tx)
 	if err != nil {
 		return nil, err
 	}
 
 	a.logger.StartProgress("Waiting for transaction to be sealed...")
 
-	result, err := a.gateway.GetTransactionResult(tx, true)
+	result, err := a.gateway.GetTransactionResult(sentTx, true)
 	if err != nil {
 		return nil, err
 	}
@@ -296,7 +210,7 @@ func (a *Accounts) Create(
 		return nil, fmt.Errorf("new account address couldn't be fetched")
 	}
 
-	a.logger.StopProgress("")
+	a.logger.StopProgress()
 
 	return a.gateway.GetAccount(*newAccountAddress)
 }
@@ -375,43 +289,42 @@ func (a *Accounts) addContract(
 			account.Address(),
 		),
 	)
+	defer a.logger.StopProgress()
 
-	if account.DefaultKey().Type() == config.KeyTypeGoogleKMS {
-		a.logger.StartProgress("Connecting to KMS...")
-		resourceID := account.DefaultKey().ToConfig().Context[config.KMSContextField]
-		err := util.GcloudApplicationSignin(resourceID)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	tx := templates.AddAccountContract(
-		account.Address(),
-		templates.Contract{
-			Name:   contractName,
-			Source: string(contractSource),
-		},
+	tx, err := project.NewAddAccountContractTransaction(
+		account,
+		contractName,
+		string(contractSource),
 	)
+	if err != nil {
+		return nil, err
+	}
 
 	// if we are updating contract
 	if updateExisting {
-		tx = templates.UpdateAccountContract(
-			account.Address(),
-			templates.Contract{
-				Name:   contractName,
-				Source: string(contractSource),
-			},
+		tx, err = project.NewUpdateAccountContractTransaction(
+			account,
+			contractName,
+			string(contractSource),
 		)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	tx, err = a.prepareTransaction(tx, account)
+	if err != nil {
+		return nil, err
 	}
 
 	// send transaction with contract
-	tx, err := a.gateway.SendTransaction(tx, account)
+	sentTx, err := a.gateway.SendSignedTransaction(tx)
 	if err != nil {
 		return nil, err
 	}
 
 	// we wait for transaction to be sealed
-	trx, err := a.gateway.GetTransactionResult(tx, true)
+	trx, err := a.gateway.GetTransactionResult(sentTx, true)
 	if err != nil {
 		return nil, err
 	}
@@ -423,7 +336,7 @@ func (a *Accounts) addContract(
 
 	update, err := a.gateway.GetAccount(account.Address())
 
-	a.logger.StopProgress("")
+	a.logger.StopProgress()
 
 	if updateExisting {
 		a.logger.Info(fmt.Sprintf(
@@ -455,14 +368,24 @@ func (a *Accounts) RemoveContract(
 	a.logger.StartProgress(
 		fmt.Sprintf("Removing Contract %s from %s...", contractName, account.Address()),
 	)
+	defer a.logger.StopProgress()
 
-	tx := templates.RemoveAccountContract(account.Address(), contractName)
-	tx, err := a.gateway.SendTransaction(tx, account)
+	tx, err := project.NewRemoveAccountContractTransaction(account, contractName)
 	if err != nil {
 		return nil, err
 	}
 
-	txr, err := a.gateway.GetTransactionResult(tx, true)
+	tx, err = a.prepareTransaction(tx, account)
+	if err != nil {
+		return nil, err
+	}
+
+	sentTx, err := a.gateway.SendSignedTransaction(tx)
+	if err != nil {
+		return nil, err
+	}
+
+	txr, err := a.gateway.GetTransactionResult(sentTx, true)
 	if err != nil {
 		return nil, err
 	}
@@ -471,12 +394,39 @@ func (a *Accounts) RemoveContract(
 		return nil, txr.Error
 	}
 
-	a.logger.StopProgress("")
+	a.logger.StopProgress()
 	a.logger.Info(fmt.Sprintf("Contract %s removed from account %s\n", contractName, account.Address()))
 
 	return a.gateway.GetAccount(account.Address())
 }
 
+// prepareTransaction prepares transaction for sending with data from network
+func (a *Accounts) prepareTransaction(
+	tx *project.Transaction,
+	account *project.Account,
+) (*project.Transaction, error) {
+
+	block, err := a.gateway.GetLatestBlock()
+	if err != nil {
+		return nil, err
+	}
+
+	proposer, err := a.gateway.GetAccount(account.Address())
+	if err != nil {
+		return nil, err
+	}
+
+	tx.SetBlockReference(block).
+		SetProposer(proposer, 0)
+
+	tx, err = tx.Sign()
+	if err != nil {
+		return nil, err
+	}
+
+	return tx, nil
+}
+
 // AccountFromAddressAndKey get account from address and private key
 func accountFromAddressAndKey(address string, accountPrivateKey string) (*project.Account, error) {
 	privateKey, err := crypto.DecodePrivateKeyHex(crypto.ECDSA_P256, accountPrivateKey)
diff --git a/pkg/flowcli/services/blocks.go b/pkg/flowcli/services/blocks.go
index b9126241..01dda605 100644
--- a/pkg/flowcli/services/blocks.go
+++ b/pkg/flowcli/services/blocks.go
@@ -62,6 +62,7 @@ func (e *Blocks) GetBlock(
 	verbose bool,
 ) (*flow.Block, []client.BlockEvents, []*flow.Collection, error) {
 	e.logger.StartProgress("Fetching Block...")
+	defer e.logger.StopProgress()
 
 	// smart parsing of query
 	var err error
@@ -103,7 +104,7 @@ func (e *Blocks) GetBlock(
 		}
 	}
 
-	e.logger.StopProgress("")
+	e.logger.StopProgress()
 
 	return block, events, collections, err
 }
diff --git a/pkg/flowcli/services/events.go b/pkg/flowcli/services/events.go
index 3a4607d8..7e49eec8 100644
--- a/pkg/flowcli/services/events.go
+++ b/pkg/flowcli/services/events.go
@@ -61,6 +61,7 @@ func (e *Events) Get(name string, start string, end string) ([]client.BlockEvent
 	}
 
 	e.logger.StartProgress("Fetching Events...")
+	defer e.logger.StopProgress()
 
 	var endHeight uint64
 	if end == "" {
@@ -93,6 +94,6 @@ func (e *Events) Get(name string, start string, end string) ([]client.BlockEvent
 		return nil, err
 	}
 
-	e.logger.StopProgress("")
+	e.logger.StopProgress()
 	return events, nil
 }
diff --git a/pkg/flowcli/services/project.go b/pkg/flowcli/services/project.go
index 1dacecd0..230286f9 100644
--- a/pkg/flowcli/services/project.go
+++ b/pkg/flowcli/services/project.go
@@ -22,9 +22,7 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/onflow/flow-go-sdk"
 	"github.com/onflow/flow-go-sdk/crypto"
-	"github.com/onflow/flow-go-sdk/templates"
 
 	"github.com/onflow/flow-cli/pkg/flowcli/contracts"
 	"github.com/onflow/flow-cli/pkg/flowcli/gateway"
@@ -59,39 +57,38 @@ func (p *Project) Init(
 	serviceKeyHashAlgo string,
 	servicePrivateKey string,
 ) (*project.Project, error) {
-	if !project.Exists(project.DefaultConfigPath) || reset {
-
-		sigAlgo, hashAlgo, err := util.ConvertSigAndHashAlgo(serviceKeySigAlgo, serviceKeyHashAlgo)
-		if err != nil {
-			return nil, err
-		}
-
-		proj, err := project.Init(sigAlgo, hashAlgo)
-		if err != nil {
-			return nil, err
-		}
+	if project.Exists(project.DefaultConfigPath) && !reset {
+		return nil, fmt.Errorf(
+			"configuration already exists at: %s, if you want to reset configuration use the reset flag",
+			project.DefaultConfigPath,
+		)
+	}
 
-		if len(servicePrivateKey) > 0 {
-			serviceKey, err := crypto.DecodePrivateKeyHex(sigAlgo, servicePrivateKey)
-			if err != nil {
-				return nil, fmt.Errorf("could not decode private key for a service account, provided private key: %s", servicePrivateKey)
-			}
+	sigAlgo, hashAlgo, err := util.ConvertSigAndHashAlgo(serviceKeySigAlgo, serviceKeyHashAlgo)
+	if err != nil {
+		return nil, err
+	}
 
-			proj.SetEmulatorServiceKey(serviceKey)
-		}
+	proj, err := project.Init(sigAlgo, hashAlgo)
+	if err != nil {
+		return nil, err
+	}
 
-		err = proj.Save(project.DefaultConfigPath)
+	if len(servicePrivateKey) > 0 {
+		serviceKey, err := crypto.DecodePrivateKeyHex(sigAlgo, servicePrivateKey)
 		if err != nil {
-			return nil, err
+			return nil, fmt.Errorf("could not decode private key for a service account, provided private key: %s", servicePrivateKey)
 		}
 
-		return proj, nil
+		proj.SetEmulatorServiceKey(serviceKey)
 	}
 
-	return nil, fmt.Errorf(
-		"configuration already exists at: %s, if you want to reset configuration use the reset flag",
-		project.DefaultConfigPath,
-	)
+	err = proj.Save(project.DefaultConfigPath)
+	if err != nil {
+		return nil, err
+	}
+
+	return proj, nil
 }
 
 func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, error) {
@@ -112,7 +109,12 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er
 		p.project.AliasesForNetwork(network),
 	)
 
-	for _, contract := range p.project.ContractsByNetwork(network) {
+	contractsNetwork, err := p.project.ContractsByNetwork(network)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, contract := range contractsNetwork {
 		err := processor.AddContractSource(
 			contract.Name,
 			contract.Source,
@@ -123,7 +125,7 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er
 		}
 	}
 
-	err := processor.ResolveImports()
+	err = processor.ResolveImports()
 	if err != nil {
 		return nil, err
 	}
@@ -138,6 +140,12 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er
 		len(orderedContracts),
 		strings.Join(p.project.AccountNamesForNetwork(network), ","),
 	))
+	defer p.logger.StopProgress()
+
+	block, err := p.gateway.GetLatestBlock()
+	if err != nil {
+		return nil, err
+	}
 
 	deployErr := false
 	for _, contract := range orderedContracts {
@@ -152,7 +160,10 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er
 			return nil, fmt.Errorf("failed to fetch information for account %s with error %s", targetAccount.Address(), err.Error())
 		}
 
-		var tx *flow.Transaction
+		tx, err := project.NewAddAccountContractTransaction(targetAccount, contract.Name(), contract.TranspiledCode())
+		if err != nil {
+			return nil, err
+		}
 
 		_, exists := targetAccountInfo.Contracts[contract.Name()]
 		if exists {
@@ -166,12 +177,21 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er
 				continue
 			}
 
-			tx = prepareUpdateContractTransaction(targetAccount.Address(), contract)
-		} else {
-			tx = prepareAddContractTransaction(targetAccount.Address(), contract)
+			tx, err = project.NewUpdateAccountContractTransaction(targetAccount, contract.Name(), contract.TranspiledCode())
+			if err != nil {
+				return nil, err
+			}
 		}
 
-		tx, err = p.gateway.SendTransaction(tx, targetAccount)
+		tx.SetBlockReference(block).
+			SetProposer(targetAccountInfo, 0)
+
+		tx, err = tx.Sign()
+		if err != nil {
+			return nil, err
+		}
+
+		sentTx, err := p.gateway.SendSignedTransaction(tx)
 		if err != nil {
 			p.logger.Error(err.Error())
 			deployErr = true
@@ -181,20 +201,17 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er
 			fmt.Sprintf("%s deploying...", util.Bold(contract.Name())),
 		)
 
-		result, err := p.gateway.GetTransactionResult(tx, true)
+		result, err := p.gateway.GetTransactionResult(sentTx, true)
 		if err != nil {
 			p.logger.Error(err.Error())
 			deployErr = true
 		}
 
 		if result.Error == nil && !deployErr {
-			p.logger.StopProgress(
-				fmt.Sprintf("%s -> 0x%s", util.Green(contract.Name()), contract.Target()),
-			)
+			p.logger.StopProgress()
+			fmt.Printf("%s -> 0x%s\n", util.Green(contract.Name()), contract.Target())
 		} else {
-			p.logger.StopProgress(
-				fmt.Sprintf("%s error", util.Red(contract.Name())),
-			)
+			p.logger.StopProgress()
 			p.logger.Error(
 				fmt.Sprintf("%s error: %s", contract.Name(), result.Error),
 			)
@@ -211,29 +228,3 @@ func (p *Project) Deploy(network string, update bool) ([]*contracts.Contract, er
 
 	return orderedContracts, nil
 }
-
-func prepareUpdateContractTransaction(
-	targetAccount flow.Address,
-	contract *contracts.Contract,
-) *flow.Transaction {
-	return templates.UpdateAccountContract(
-		targetAccount,
-		templates.Contract{
-			Name:   contract.Name(),
-			Source: contract.TranspiledCode(),
-		},
-	)
-}
-
-func prepareAddContractTransaction(
-	targetAccount flow.Address,
-	contract *contracts.Contract,
-) *flow.Transaction {
-	return templates.AddAccountContract(
-		targetAccount,
-		templates.Contract{
-			Name:   contract.Name(),
-			Source: contract.TranspiledCode(),
-		},
-	)
-}
diff --git a/pkg/flowcli/services/scripts.go b/pkg/flowcli/services/scripts.go
index c2f6973f..9aa72d5c 100644
--- a/pkg/flowcli/services/scripts.go
+++ b/pkg/flowcli/services/scripts.go
@@ -19,9 +19,12 @@
 package services
 
 import (
+	"fmt"
+
 	"github.com/onflow/cadence"
 
 	"github.com/onflow/flow-cli/pkg/flowcli"
+	"github.com/onflow/flow-cli/pkg/flowcli/contracts"
 	"github.com/onflow/flow-cli/pkg/flowcli/gateway"
 	"github.com/onflow/flow-cli/pkg/flowcli/output"
 	"github.com/onflow/flow-cli/pkg/flowcli/project"
@@ -49,25 +52,56 @@ func NewScripts(
 }
 
 // Execute executes a Cadence script from a file.
-func (s *Scripts) Execute(scriptFilename string, args []string, argsJSON string) (cadence.Value, error) {
-	script, err := util.LoadFile(scriptFilename)
+func (s *Scripts) Execute(scriptPath string, args []string, argsJSON string, network string) (cadence.Value, error) {
+	script, err := util.LoadFile(scriptPath)
 	if err != nil {
 		return nil, err
 	}
 
-	return s.execute(script, args, argsJSON)
+	return s.execute(script, args, argsJSON, scriptPath, network)
 }
 
 // Execute executes a Cadence script from a source code string.
 func (s *Scripts) ExecuteWithCode(code []byte, args []string, argsJSON string) (cadence.Value, error) {
-	return s.execute(code, args, argsJSON)
+	return s.execute(code, args, argsJSON, "", "")
 }
 
-func (s *Scripts) execute(code []byte, args []string, argsJSON string) (cadence.Value, error) {
+func (s *Scripts) execute(code []byte, args []string, argsJSON string, scriptPath string, network string) (cadence.Value, error) {
 	scriptArgs, err := flowcli.ParseArguments(args, argsJSON)
 	if err != nil {
 		return nil, err
 	}
 
+	resolver, err := contracts.NewResolver(code)
+	if err != nil {
+		return nil, err
+	}
+
+	if resolver.HasFileImports() {
+		if s.project == nil {
+			return nil, fmt.Errorf("missing configuration, initialize it: flow init")
+		}
+		if network == "" {
+			return nil, fmt.Errorf("missing network, specify which network to use to resolve imports in script code")
+		}
+		if scriptPath == "" { // when used as lib with code we don't support imports
+			return nil, fmt.Errorf("resolving imports in scripts not supported")
+		}
+
+		contractsNetwork, err := s.project.ContractsByNetwork(network)
+		if err != nil {
+			return nil, err
+		}
+
+		code, err = resolver.ResolveImports(
+			scriptPath,
+			contractsNetwork,
+			s.project.AliasesForNetwork(network),
+		)
+		if err != nil {
+			return nil, err
+		}
+	}
+
 	return s.gateway.ExecuteScript(code, scriptArgs)
 }
diff --git a/pkg/flowcli/services/transactions.go b/pkg/flowcli/services/transactions.go
index 2cd1ee8f..4b1f14c5 100644
--- a/pkg/flowcli/services/transactions.go
+++ b/pkg/flowcli/services/transactions.go
@@ -22,11 +22,11 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/onflow/flow-cli/pkg/flowcli/contracts"
+
 	"github.com/onflow/flow-go-sdk"
 	"github.com/onflow/flow-go-sdk/crypto"
 
-	"github.com/onflow/flow-cli/pkg/flowcli"
-	"github.com/onflow/flow-cli/pkg/flowcli/config"
 	"github.com/onflow/flow-cli/pkg/flowcli/gateway"
 	"github.com/onflow/flow-cli/pkg/flowcli/output"
 	"github.com/onflow/flow-cli/pkg/flowcli/project"
@@ -53,140 +53,300 @@ func NewTransactions(
 	}
 }
 
-// Send sends a transaction from a file.
-func (t *Transactions) Send(
-	transactionFilename string,
-	signerName string,
-	args []string,
-	argsJSON string,
+// GetStatus of transaction
+func (t *Transactions) GetStatus(
+	transactionID string,
+	waitSeal bool,
 ) (*flow.Transaction, *flow.TransactionResult, error) {
-	if t.project == nil {
-		return nil, nil, fmt.Errorf("missing configuration, initialize it: flow init")
-	}
+	txID := flow.HexToID(
+		strings.ReplaceAll(transactionID, "0x", ""),
+	)
 
-	signer := t.project.AccountByName(signerName)
-	if signer == nil {
-		return nil, nil, fmt.Errorf("signer account: [%s] doesn't exists in configuration", signerName)
-	}
+	t.logger.StartProgress("Fetching Transaction...")
 
-	code, err := util.LoadFile(transactionFilename)
+	tx, err := t.gateway.GetTransaction(txID)
 	if err != nil {
 		return nil, nil, err
 	}
 
-	return t.send(code, signer, args, argsJSON)
+	if waitSeal {
+		t.logger.StartProgress("Waiting for transaction to be sealed...")
+	}
+
+	result, err := t.gateway.GetTransactionResult(tx, waitSeal)
+
+	t.logger.StopProgress()
+
+	return tx, result, err
 }
 
-// SendForAddress send transaction for address and private key, code passed via filename
-func (t *Transactions) SendForAddress(
-	transactionFilename string,
-	signerAddress string,
-	signerPrivateKey string,
+// Build builds a transaction with specified payer, proposer and authorizer
+func (t *Transactions) Build(
+	proposer string,
+	authorizer []string,
+	payer string,
+	proposerKeyIndex int,
+	codeFilename string,
 	args []string,
 	argsJSON string,
-) (*flow.Transaction, *flow.TransactionResult, error) {
-	code, err := util.LoadFile(transactionFilename)
+	network string,
+) (*project.Transaction, error) {
+	proposerAddress, err := getAddressFromStringOrConfig(proposer, t.project)
 	if err != nil {
-		return nil, nil, err
+		return nil, err
+	}
+
+	payerAddress, err := getAddressFromStringOrConfig(payer, t.project)
+	if err != nil {
+		return nil, err
+	}
+
+	authorizerAddresses := make([]flow.Address, 0)
+	for _, a := range authorizer {
+		authorizerAddress, err := getAddressFromStringOrConfig(a, t.project)
+		if err != nil {
+			return nil, err
+		}
+		authorizerAddresses = append(authorizerAddresses, authorizerAddress)
+	}
+
+	latestBlock, err := t.gateway.GetLatestBlock()
+	if err != nil {
+		return nil, fmt.Errorf("failed to get latest sealed block: %w", err)
+	}
+
+	proposerAccount, err := t.gateway.GetAccount(proposerAddress)
+	if err != nil {
+		return nil, err
 	}
 
-	return t.SendForAddressWithCode(code, signerAddress, signerPrivateKey, args, argsJSON)
+	tx := project.NewTransaction().
+		SetPayer(payerAddress).
+		SetProposer(proposerAccount, proposerKeyIndex).
+		AddAuthorizers(authorizerAddresses).
+		SetDefaultGasLimit().
+		SetBlockReference(latestBlock)
+
+	code, err := util.LoadFile(codeFilename)
+	if err != nil {
+		return nil, err
+	}
+
+	resolver, err := contracts.NewResolver(code)
+	if err != nil {
+		return nil, err
+	}
+
+	if resolver.HasFileImports() {
+		if network == "" {
+			return nil, fmt.Errorf("missing network, specify which network to use to resolve imports in transaction code")
+		}
+		if codeFilename == "" { // when used as lib with code we don't support imports
+			return nil, fmt.Errorf("resolving imports in transactions not supported")
+		}
+
+		contractsNetwork, err := t.project.ContractsByNetwork(network)
+		if err != nil {
+			return nil, err
+		}
+
+		code, err = resolver.ResolveImports(
+			codeFilename,
+			contractsNetwork,
+			t.project.AliasesForNetwork(network),
+		)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	err = tx.SetScriptWithArgs(code, args, argsJSON)
+	if err != nil {
+		return nil, err
+	}
+
+	return tx, nil
 }
 
-// SendForAddressWithCode send transaction for address and private key, code passed via byte array
-func (t *Transactions) SendForAddressWithCode(
-	code []byte,
-	signerAddress string,
-	signerPrivateKey string,
-	args []string,
-	argsJSON string,
+// Sign transaction
+func (t *Transactions) Sign(
+	payloadFilename string,
+	signerName string,
+	approveSigning bool,
+) (*project.Transaction, error) {
+	if t.project == nil {
+		return nil, fmt.Errorf("missing configuration, initialize it: flow project init")
+	}
+
+	// get the signer account
+	signerAccount := t.project.AccountByName(signerName)
+	if signerAccount == nil {
+		return nil, fmt.Errorf("signer account: [%s] doesn't exists in configuration", signerName)
+	}
+
+	tx, err := project.NewTransactionFromPayload(payloadFilename)
+	if err != nil {
+		return nil, err
+	}
+
+	err = tx.SetSigner(signerAccount)
+	if err != nil {
+		return nil, err
+	}
+
+	if approveSigning {
+		return tx.Sign()
+	}
+
+	if !output.ApproveTransactionPrompt(tx) {
+		return nil, fmt.Errorf("transaction was not approved for signing")
+	}
+
+	return tx.Sign()
+}
+
+// SendSigned sends the transaction that is already signed
+func (t *Transactions) SendSigned(
+	signedFilename string,
 ) (*flow.Transaction, *flow.TransactionResult, error) {
-	address := flow.HexToAddress(signerAddress)
+	tx, err := project.NewTransactionFromPayload(signedFilename)
+	if err != nil {
+		return nil, nil, err
+	}
 
-	privateKey, err := crypto.DecodePrivateKeyHex(crypto.ECDSA_P256, signerPrivateKey)
+	sentTx, err := t.gateway.SendSignedTransaction(tx)
 	if err != nil {
-		return nil, nil, fmt.Errorf("private key is not correct")
+		return nil, nil, err
 	}
 
-	account := project.AccountFromAddressAndKey(address, privateKey)
+	res, err := t.gateway.GetTransactionResult(sentTx, true)
+	if err != nil {
+		return nil, nil, err
+	}
 
-	return t.send(code, account, args, argsJSON)
+	return sentTx, res, nil
 }
 
-func (t *Transactions) send(
-	code []byte,
-	signer *project.Account,
+// Send sends a transaction from a file.
+func (t *Transactions) Send(
+	transactionFilename string,
+	signerName string,
 	args []string,
 	argsJSON string,
+	network string,
 ) (*flow.Transaction, *flow.TransactionResult, error) {
-
-	// if google kms account then sign in
-	// TODO discuss refactor - move to account
-	if signer.DefaultKey().Type() == config.KeyTypeGoogleKMS {
-		resourceID := signer.DefaultKey().ToConfig().Context[config.KMSContextField]
-		err := util.GcloudApplicationSignin(resourceID)
-		if err != nil {
-			return nil, nil, err
-		}
+	if t.project == nil {
+		return nil, nil, fmt.Errorf("missing configuration, initialize it: flow project init")
 	}
 
-	t.logger.StartProgress("Sending transaction...")
+	signerAccount := t.project.AccountByName(signerName)
+	if signerAccount == nil {
+		return nil, nil, fmt.Errorf("signer account: [%s] doesn't exists in configuration", signerName)
+	}
 
-	tx := flow.NewTransaction().
-		SetScript(code).
-		AddAuthorizer(signer.Address())
+	tx, err := t.Build(
+		signerName,
+		[]string{signerName},
+		signerName,
+		0, // default 0 key
+		transactionFilename,
+		args,
+		argsJSON,
+		network,
+	)
+	if err != nil {
+		return nil, nil, err
+	}
 
-	transactionArguments, err := flowcli.ParseArguments(args, argsJSON)
+	err = tx.SetSigner(signerAccount)
 	if err != nil {
 		return nil, nil, err
 	}
 
-	for _, arg := range transactionArguments {
-		err := tx.AddArgument(arg)
-		if err != nil {
-			return nil, nil, fmt.Errorf("failed to add %s argument to a transaction", arg)
-		}
+	signed, err := tx.Sign()
+	if err != nil {
+		return nil, nil, err
 	}
 
-	t.logger.Info(fmt.Sprintf("Sending transaction with ID %s", tx.ID()))
+	t.logger.StartProgress(fmt.Sprintf("Sending Transaction with ID: %s", signed.FlowTransaction().ID()))
+	defer t.logger.StopProgress()
 
-	tx, err = t.gateway.SendTransaction(tx, signer)
+	sentTx, err := t.gateway.SendSignedTransaction(signed)
 	if err != nil {
 		return nil, nil, err
 	}
 
 	t.logger.StartProgress("Waiting for transaction to be sealed...")
 
-	res, err := t.gateway.GetTransactionResult(tx, true)
+	res, err := t.gateway.GetTransactionResult(sentTx, true)
 
-	t.logger.StopProgress("")
+	t.logger.StopProgress()
 
-	return tx, res, err
+	return sentTx, res, err
 }
 
-// GetStatus of transaction
-func (t *Transactions) GetStatus(
-	transactionID string,
-	waitSeal bool,
+// SendForAddressWithCode send transaction for address and private key specified with code
+func (t *Transactions) SendForAddressWithCode(
+	code []byte,
+	signerAddress string,
+	signerPrivateKey string,
+	args []string,
+	argsJSON string,
 ) (*flow.Transaction, *flow.TransactionResult, error) {
-	txID := flow.HexToID(
-		strings.ReplaceAll(transactionID, "0x", ""),
-	)
+	address := flow.HexToAddress(signerAddress)
 
-	t.logger.StartProgress("Fetching Transaction...")
+	privateKey, err := crypto.DecodePrivateKeyHex(crypto.ECDSA_P256, signerPrivateKey)
+	if err != nil {
+		return nil, nil, fmt.Errorf("private key is not correct")
+	}
 
-	tx, err := t.gateway.GetTransaction(txID)
+	signer := project.AccountFromAddressAndKey(address, privateKey)
+
+	tx := project.NewTransaction()
+	err = tx.SetSigner(signer)
 	if err != nil {
 		return nil, nil, err
 	}
 
-	if waitSeal {
-		t.logger.StartProgress("Waiting for transaction to be sealed...")
+	err = tx.SetScriptWithArgs(code, args, argsJSON)
+	if err != nil {
+		return nil, nil, err
 	}
 
-	result, err := t.gateway.GetTransactionResult(tx, waitSeal)
+	tx, err = tx.Sign()
+	if err != nil {
+		return nil, nil, err
+	}
 
-	t.logger.StopProgress("")
+	t.logger.StartProgress("Sending transaction...")
+	defer t.logger.StopProgress()
 
-	return tx, result, err
+	sentTx, err := t.gateway.SendSignedTransaction(tx)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	t.logger.StartProgress("Waiting for transaction to be sealed...")
+
+	res, err := t.gateway.GetTransactionResult(sentTx, true)
+
+	t.logger.StopProgress()
+	return sentTx, res, err
+}
+
+// getAddressFromStringOrConfig try to parse value as address or as an account from the config
+func getAddressFromStringOrConfig(value string, project *project.Project) (flow.Address, error) {
+	address, isValid := util.ParseAddress(value)
+
+	if isValid {
+		return address, nil
+	} else if project != nil {
+		account := project.AccountByName(value)
+		if account == nil {
+			return flow.EmptyAddress, fmt.Errorf("account could not be found")
+		}
+		return account.Address(), nil
+	} else {
+		return flow.EmptyAddress, fmt.Errorf("could not parse address or account name from config, missing configuration")
+	}
 }
diff --git a/pkg/flowcli/util/utilities.go b/pkg/flowcli/util/utilities.go
index da14ec42..ab46ea7b 100644
--- a/pkg/flowcli/util/utilities.go
+++ b/pkg/flowcli/util/utilities.go
@@ -30,7 +30,7 @@ import (
 
 var Green = color.New(color.FgGreen, color.Bold).SprintfFunc()
 var Red = color.New(color.FgRed, color.Bold).SprintfFunc()
-var Bold = color.New(color.Bold).SprintfFunc()
+var Bold = color.New(color.FgCyan).SprintfFunc()
 
 // LoadFile loads a file by filename.
 func LoadFile(filename string) ([]byte, error) {
@@ -104,3 +104,21 @@ func GetAddressNetwork(address flow.Address) (flow.ChainID, error) {
 
 	return "", fmt.Errorf("address not valid for any known chain: %s", address)
 }
+
+func ContainsString(s []string, e string) bool {
+	for _, a := range s {
+		if a == e {
+			return true
+		}
+	}
+	return false
+}
+
+func ParseAddress(value string) (flow.Address, bool) {
+	address := flow.HexToAddress(value)
+
+	// valid on any chain
+	return address, address.IsValid(flow.Mainnet) ||
+		address.IsValid(flow.Testnet) ||
+		address.IsValid(flow.Emulator)
+}


Test patch:
diff --git a/pkg/flowcli/contracts/resolver_test.go b/pkg/flowcli/contracts/resolver_test.go
new file mode 100644
index 00000000..d769d572
--- /dev/null
+++ b/pkg/flowcli/contracts/resolver_test.go
@@ -0,0 +1,134 @@
+/*
+ * Flow CLI
+ *
+ * Copyright 2019-2021 Dapper Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package contracts
+
+import (
+	"regexp"
+	"testing"
+
+	"github.com/onflow/flow-go-sdk"
+	"github.com/stretchr/testify/assert"
+
+	"github.com/onflow/flow-cli/pkg/flowcli/project"
+)
+
+func cleanCode(code []byte) string {
+	space := regexp.MustCompile(`\s+`)
+	return space.ReplaceAllString(string(code), " ")
+}
+
+func TestResolver(t *testing.T) {
+
+	contracts := []project.Contract{{
+		Name:   "Kibble",
+		Source: "./tests/Kibble.cdc",
+		Target: flow.HexToAddress("0x1"),
+	}, {
+		Name:   "FT",
+		Source: "./tests/FT.cdc",
+		Target: flow.HexToAddress("0x2"),
+	}}
+
+	aliases := map[string]string{
+		"./tests/NFT.cdc": flow.HexToAddress("0x4").String(),
+	}
+
+	paths := []string{
+		"./tests/foo.cdc",
+		"./scripts/bar/foo.cdc",
+		"./scripts/bar/foo.cdc",
+	}
+
+	scripts := [][]byte{
+		[]byte(`
+			import Kibble from "./Kibble.cdc"
+      import FT from "./FT.cdc"
+			pub fun main() {}
+    `), []byte(`
+			import Kibble from "../../tests/Kibble.cdc"
+      import FT from "../../tests/FT.cdc"
+			pub fun main() {}
+    `), []byte(`
+			import Kibble from "../../tests/Kibble.cdc"
+      import NFT from "../../tests/NFT.cdc"
+			pub fun main() {}
+    `),
+	}
+
+	resolved := [][]byte{
+		[]byte(`
+			import Kibble from 0x0000000000000001 
+			import FT from 0x0000000000000002 
+			pub fun main() {}
+    `), []byte(`
+			import Kibble from 0x0000000000000001 
+			import FT from 0x0000000000000002 
+			pub fun main() {}
+    `), []byte(`
+			import Kibble from 0x0000000000000001 
+			import NFT from 0x0000000000000004 
+			pub fun main() {}
+    `),
+	}
+
+	t.Run("Import exists", func(t *testing.T) {
+		resolver, err := NewResolver([]byte(`
+      import Kibble from "./Kibble.cdc"
+      pub fun main() {}
+    `))
+		assert.NoError(t, err)
+		assert.True(t, resolver.HasFileImports())
+	})
+
+	t.Run("Import doesn't exists", func(t *testing.T) {
+		resolver, err := NewResolver([]byte(`
+      pub fun main() {}
+    `))
+		assert.NoError(t, err)
+		assert.False(t, resolver.HasFileImports())
+
+		resolver, err = NewResolver([]byte(`
+			import Foo from 0xf8d6e0586b0a20c7
+      pub fun main() {}
+    `))
+		assert.NoError(t, err)
+		assert.False(t, resolver.HasFileImports())
+	})
+
+	t.Run("Parse imports", func(t *testing.T) {
+		resolver, err := NewResolver(scripts[0])
+		assert.NoError(t, err)
+		assert.Equal(t, resolver.getFileImports(), []string{
+			"./Kibble.cdc", "./FT.cdc",
+		})
+	})
+
+	t.Run("Resolve imports", func(t *testing.T) {
+		for i, script := range scripts {
+			resolver, err := NewResolver(script)
+			assert.NoError(t, err)
+
+			code, err := resolver.ResolveImports(paths[i], contracts, aliases)
+
+			assert.NoError(t, err)
+			assert.Equal(t, cleanCode(code), cleanCode(resolved[i]))
+		}
+	})
+
+}
diff --git a/pkg/flowcli/project/project_test.go b/pkg/flowcli/project/project_test.go
index a89af259..5b6f401c 100644
--- a/pkg/flowcli/project/project_test.go
+++ b/pkg/flowcli/project/project_test.go
@@ -318,7 +318,7 @@ Project Tests
 func Test_GetContractsByNameSimple(t *testing.T) {
 	p := generateSimpleProject()
 
-	contracts := p.ContractsByNetwork("emulator")
+	contracts, _ := p.ContractsByNetwork("emulator")
 
 	assert.Len(t, contracts, 1)
 	assert.Equal(t, contracts[0].Name, "NonFungibleToken")
@@ -360,7 +360,7 @@ func Test_HostSimple(t *testing.T) {
 func Test_GetContractsByNameComplex(t *testing.T) {
 	p := generateComplexProject()
 
-	contracts := p.ContractsByNetwork("emulator")
+	contracts, _ := p.ContractsByNetwork("emulator")
 
 	assert.Equal(t, 7, len(contracts))
 
@@ -452,7 +452,7 @@ func Test_GetAliases(t *testing.T) {
 	p := generateAliasesProject()
 
 	aliases := p.AliasesForNetwork("emulator")
-	contracts := p.ContractsByNetwork("emulator")
+	contracts, _ := p.ContractsByNetwork("emulator")
 
 	assert.Len(t, aliases, 1)
 	assert.Equal(t, aliases["../hungry-kitties/cadence/contracts/FungibleToken.cdc"], "ee82856bf20e2aa6")
@@ -464,10 +464,10 @@ func Test_GetAliasesComplex(t *testing.T) {
 	p := generateAliasesComplexProject()
 
 	aEmulator := p.AliasesForNetwork("emulator")
-	cEmulator := p.ContractsByNetwork("emulator")
+	cEmulator, _ := p.ContractsByNetwork("emulator")
 
 	aTestnet := p.AliasesForNetwork("testnet")
-	cTestnet := p.ContractsByNetwork("testnet")
+	cTestnet, _ := p.ContractsByNetwork("testnet")
 
 	assert.Len(t, cEmulator, 1)
 	assert.Equal(t, cEmulator[0].Name, "NonFungibleToken")
diff --git a/pkg/flowcli/services/accounts_test.go b/pkg/flowcli/services/accounts_test.go
index 2a7f0b14..486e61d4 100644
--- a/pkg/flowcli/services/accounts_test.go
+++ b/pkg/flowcli/services/accounts_test.go
@@ -43,16 +43,24 @@ func TestAccounts(t *testing.T) {
 
 	mock := &tests.MockGateway{}
 
+	mock.GetLatestBlockMock = func() (*flow.Block, error) {
+		return tests.NewBlock(), nil
+	}
+
+	mock.GetTransactionResultMock = func(tx *flow.Transaction) (*flow.TransactionResult, error) {
+		return tests.NewTransactionResult(nil), nil
+	}
+
+	mock.GetAccountMock = func(address flow.Address) (*flow.Account, error) {
+		return tests.NewAccountWithAddress(address.String()), nil
+	}
+
 	proj, err := project.Init(crypto.ECDSA_P256, crypto.SHA3_256)
 	assert.NoError(t, err)
 
 	accounts := NewAccounts(mock, proj, output.NewStdoutLogger(output.NoneLog))
 
 	t.Run("Get an Account", func(t *testing.T) {
-		mock.GetAccountMock = func(address flow.Address) (*flow.Account, error) {
-			return tests.NewAccountWithAddress(address.String()), nil
-		}
-
 		account, err := accounts.Get(serviceAddress)
 
 		assert.NoError(t, err)
@@ -62,9 +70,9 @@ func TestAccounts(t *testing.T) {
 	t.Run("Create an Account", func(t *testing.T) {
 		newAddress := "192440c99cb17282"
 
-		mock.SendTransactionMock = func(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
-			assert.Equal(t, tx.Authorizers[0].String(), serviceAddress)
-			assert.Equal(t, signer.Address().String(), serviceAddress)
+		mock.SendSignedTransactionMock = func(tx *project.Transaction) (*flow.Transaction, error) {
+			assert.Equal(t, tx.FlowTransaction().Authorizers[0].String(), serviceAddress)
+			assert.Equal(t, tx.Signer().Address().String(), serviceAddress)
 
 			return tests.NewTransaction(), nil
 		}
@@ -73,13 +81,15 @@ func TestAccounts(t *testing.T) {
 			return tests.NewAccountCreateResult(newAddress), nil
 		}
 
+		compareAddress := serviceAddress
 		mock.GetAccountMock = func(address flow.Address) (*flow.Account, error) {
-			assert.Equal(t, address.String(), newAddress)
+			assert.Equal(t, address.String(), compareAddress)
+			compareAddress = newAddress
 
-			return tests.NewAccountWithAddress(newAddress), nil
+			return tests.NewAccountWithAddress(address.String()), nil
 		}
 
-		a, err := accounts.Create(serviceName, []string{pubKey}, sigAlgo, hashAlgo, nil)
+		a, err := accounts.Create(serviceName, []string{pubKey}, []int{1000}, sigAlgo, hashAlgo, nil)
 
 		assert.NotNil(t, a)
 		assert.NoError(t, err)
@@ -89,10 +99,10 @@ func TestAccounts(t *testing.T) {
 	t.Run("Create an Account with Contract", func(t *testing.T) {
 		newAddress := "192440c99cb17282"
 
-		mock.SendTransactionMock = func(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
-			assert.Equal(t, tx.Authorizers[0].String(), serviceAddress)
-			assert.Equal(t, signer.Address().String(), serviceAddress)
-			assert.True(t, strings.Contains(string(tx.Script), "acct.contracts.add"))
+		mock.SendSignedTransactionMock = func(tx *project.Transaction) (*flow.Transaction, error) {
+			assert.Equal(t, tx.FlowTransaction().Authorizers[0].String(), serviceAddress)
+			assert.Equal(t, tx.Signer().Address().String(), serviceAddress)
+			assert.True(t, strings.Contains(string(tx.FlowTransaction().Script), "acct.contracts.add"))
 
 			return tests.NewTransaction(), nil
 		}
@@ -102,12 +112,10 @@ func TestAccounts(t *testing.T) {
 		}
 
 		mock.GetAccountMock = func(address flow.Address) (*flow.Account, error) {
-			assert.Equal(t, address.String(), newAddress)
-
-			return tests.NewAccountWithAddress(newAddress), nil
+			return tests.NewAccountWithAddress(address.String()), nil
 		}
 
-		a, err := accounts.Create(serviceName, []string{pubKey}, sigAlgo, hashAlgo, []string{"Hello:../../../tests/Hello.cdc"})
+		a, err := accounts.Create(serviceName, []string{pubKey}, []int{1000}, sigAlgo, hashAlgo, []string{"Hello:../../../tests/Hello.cdc"})
 
 		assert.NotNil(t, a)
 		assert.NoError(t, err)
@@ -115,22 +123,14 @@ func TestAccounts(t *testing.T) {
 	})
 
 	t.Run("Contract Add for Account", func(t *testing.T) {
-		mock.SendTransactionMock = func(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
-			assert.Equal(t, tx.Authorizers[0].String(), serviceAddress)
-			assert.Equal(t, signer.Address().String(), serviceAddress)
-			assert.True(t, strings.Contains(string(tx.Script), "signer.contracts.add"))
+		mock.SendSignedTransactionMock = func(tx *project.Transaction) (*flow.Transaction, error) {
+			assert.Equal(t, tx.FlowTransaction().Authorizers[0].String(), serviceAddress)
+			assert.Equal(t, tx.Signer().Address().String(), serviceAddress)
+			assert.True(t, strings.Contains(string(tx.FlowTransaction().Script), "signer.contracts.add"))
 
 			return tests.NewTransaction(), nil
 		}
 
-		mock.GetTransactionResultMock = func(tx *flow.Transaction) (*flow.TransactionResult, error) {
-			return tests.NewTransactionResult(nil), nil
-		}
-
-		mock.GetAccountMock = func(address flow.Address) (*flow.Account, error) {
-			return tests.NewAccountWithAddress(address.String()), nil
-		}
-
 		a, err := accounts.AddContract(serviceName, "Hello", "../../../tests/Hello.cdc", false)
 
 		assert.NotNil(t, a)
@@ -139,22 +139,14 @@ func TestAccounts(t *testing.T) {
 	})
 
 	t.Run("Contract Update for Account", func(t *testing.T) {
-		mock.SendTransactionMock = func(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
-			assert.Equal(t, tx.Authorizers[0].String(), serviceAddress)
-			assert.Equal(t, signer.Address().String(), serviceAddress)
-			assert.True(t, strings.Contains(string(tx.Script), "signer.contracts.update__experimental"))
+		mock.SendSignedTransactionMock = func(tx *project.Transaction) (*flow.Transaction, error) {
+			assert.Equal(t, tx.FlowTransaction().Authorizers[0].String(), serviceAddress)
+			assert.Equal(t, tx.Signer().Address().String(), serviceAddress)
+			assert.True(t, strings.Contains(string(tx.FlowTransaction().Script), "signer.contracts.update__experimental"))
 
 			return tests.NewTransaction(), nil
 		}
 
-		mock.GetTransactionResultMock = func(tx *flow.Transaction) (*flow.TransactionResult, error) {
-			return tests.NewTransactionResult(nil), nil
-		}
-
-		mock.GetAccountMock = func(address flow.Address) (*flow.Account, error) {
-			return tests.NewAccountWithAddress(address.String()), nil
-		}
-
 		account, err := accounts.AddContract(serviceName, "Hello", "../../../tests/Hello.cdc", true)
 
 		assert.NotNil(t, account)
@@ -163,22 +155,14 @@ func TestAccounts(t *testing.T) {
 	})
 
 	t.Run("Contract Remove for Account", func(t *testing.T) {
-		mock.SendTransactionMock = func(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
-			assert.Equal(t, tx.Authorizers[0].String(), serviceAddress)
-			assert.Equal(t, signer.Address().String(), serviceAddress)
-			assert.True(t, strings.Contains(string(tx.Script), "signer.contracts.remove"))
+		mock.SendSignedTransactionMock = func(tx *project.Transaction) (*flow.Transaction, error) {
+			assert.Equal(t, tx.FlowTransaction().Authorizers[0].String(), serviceAddress)
+			assert.Equal(t, tx.Signer().Address().String(), serviceAddress)
+			assert.True(t, strings.Contains(string(tx.FlowTransaction().Script), "signer.contracts.remove"))
 
 			return tests.NewTransaction(), nil
 		}
 
-		mock.GetTransactionResultMock = func(tx *flow.Transaction) (*flow.TransactionResult, error) {
-			return tests.NewTransactionResult(nil), nil
-		}
-
-		mock.GetAccountMock = func(address flow.Address) (*flow.Account, error) {
-			return tests.NewAccountWithAddress(address.String()), nil
-		}
-
 		account, err := accounts.RemoveContract("Hello", serviceName)
 
 		assert.NotNil(t, account)
diff --git a/pkg/flowcli/services/scripts_test.go b/pkg/flowcli/services/scripts_test.go
index 47c6778f..e72b1d39 100644
--- a/pkg/flowcli/services/scripts_test.go
+++ b/pkg/flowcli/services/scripts_test.go
@@ -45,7 +45,7 @@ func TestScripts(t *testing.T) {
 			return arguments[0], nil
 		}
 
-		_, err := scripts.Execute("../../../tests/script.cdc", []string{"String:Foo"}, "")
+		_, err := scripts.Execute("../../../tests/script.cdc", []string{"String:Foo"}, "", "")
 
 		assert.NoError(t, err)
 	})
diff --git a/pkg/flowcli/services/transactions_test.go b/pkg/flowcli/services/transactions_test.go
index 4893822a..46ee3daf 100644
--- a/pkg/flowcli/services/transactions_test.go
+++ b/pkg/flowcli/services/transactions_test.go
@@ -33,6 +33,18 @@ import (
 func TestTransactions(t *testing.T) {
 	mock := &tests.MockGateway{}
 
+	mock.SendSignedTransactionMock = func(tx *project.Transaction) (*flow.Transaction, error) {
+		return tx.FlowTransaction(), nil
+	}
+
+	mock.GetLatestBlockMock = func() (*flow.Block, error) {
+		return tests.NewBlock(), nil
+	}
+
+	mock.GetAccountMock = func(address flow.Address) (*flow.Account, error) {
+		return tests.NewAccountWithAddress(address.String()), nil
+	}
+
 	proj, err := project.Init(crypto.ECDSA_P256, crypto.SHA3_256)
 	assert.NoError(t, err)
 
@@ -67,18 +79,24 @@ func TestTransactions(t *testing.T) {
 			return tests.NewTransactionResult(nil), nil
 		}
 
-		mock.SendTransactionMock = func(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
+		mock.SendSignedTransactionMock = func(tx *project.Transaction) (*flow.Transaction, error) {
 			called++
-			arg, err := tx.Argument(0)
+			arg, err := tx.FlowTransaction().Argument(0)
 
 			assert.NoError(t, err)
 			assert.Equal(t, arg.String(), "\"Bar\"")
-			assert.Equal(t, signer.Address().String(), serviceAddress)
-			assert.Equal(t, len(string(tx.Script)), 209)
+			assert.Equal(t, tx.Signer().Address().String(), serviceAddress)
+			assert.Equal(t, len(string(tx.FlowTransaction().Script)), 209)
 			return tests.NewTransaction(), nil
 		}
 
-		_, _, err := transactions.Send("../../../tests/transaction.cdc", serviceName, []string{"String:Bar"}, "")
+		_, _, err := transactions.Send(
+			"../../../tests/transaction.cdc",
+			serviceName,
+			[]string{"String:Bar"},
+			"",
+			"",
+		)
 
 		assert.NoError(t, err)
 		assert.Equal(t, called, 2)
@@ -92,10 +110,10 @@ func TestTransactions(t *testing.T) {
 			return tests.NewTransactionResult(nil), nil
 		}
 
-		mock.SendTransactionMock = func(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
+		mock.SendSignedTransactionMock = func(tx *project.Transaction) (*flow.Transaction, error) {
 			called++
-			assert.Equal(t, signer.Address().String(), serviceAddress)
-			assert.Equal(t, len(string(tx.Script)), 209)
+			assert.Equal(t, tx.Signer().Address().String(), serviceAddress)
+			assert.Equal(t, len(string(tx.FlowTransaction().Script)), 209)
 			return tests.NewTransaction(), nil
 		}
 
@@ -104,6 +122,7 @@ func TestTransactions(t *testing.T) {
 			serviceName,
 			nil,
 			"[{\"type\": \"String\", \"value\": \"Bar\"}]",
+			"",
 		)
 
 		assert.NoError(t, err)
@@ -111,17 +130,35 @@ func TestTransactions(t *testing.T) {
 	})
 
 	t.Run("Send Transaction Fails wrong args", func(t *testing.T) {
-		_, _, err := transactions.Send("../../../tests/transaction.cdc", serviceName, []string{"Bar"}, "")
+		_, _, err := transactions.Send(
+			"../../../tests/transaction.cdc",
+			serviceName,
+			[]string{"Bar"},
+			"",
+			"",
+		)
 		assert.Equal(t, err.Error(), "argument not passed in correct format, correct format is: Type:Value, got Bar")
 	})
 
 	t.Run("Send Transaction Fails wrong filename", func(t *testing.T) {
-		_, _, err := transactions.Send("nooo.cdc", serviceName, []string{"Bar"}, "")
+		_, _, err := transactions.Send(
+			"nooo.cdc",
+			serviceName,
+			[]string{"Bar"},
+			"",
+			"",
+		)
 		assert.Equal(t, err.Error(), "Failed to load file: nooo.cdc")
 	})
 
 	t.Run("Send Transaction Fails wrong args", func(t *testing.T) {
-		_, _, err := transactions.Send("../../../tests/transaction.cdc", serviceName, nil, "[{\"Bar\":\"No\"}]")
+		_, _, err := transactions.Send(
+			"../../../tests/transaction.cdc",
+			serviceName,
+			nil,
+			"[{\"Bar\":\"No\"}]",
+			"",
+		)
 		assert.Equal(t, err.Error(), "failed to decode value: invalid JSON Cadence structure")
 	})
 }
diff --git a/tests/e2e_test.go b/tests/e2e_test.go
index ed0d6db3..ee6d1940 100644
--- a/tests/e2e_test.go
+++ b/tests/e2e_test.go
@@ -71,6 +71,7 @@ func TestAccount(t *testing.T) {
 		account, err := accounts.Create(
 			emulatorAccount,
 			keys,
+			[]int{1000},
 			"ECDSA_P256",
 			"SHA3_256",
 			[]string{},
@@ -207,14 +208,19 @@ func TestScripts(t *testing.T) {
 	scripts := services.NewScripts(gateway, project, logger)
 
 	t.Run("Test Script", func(t *testing.T) {
-		val, err := scripts.Execute("./script.cdc", []string{"String:Mr G"}, "")
+		val, err := scripts.Execute("./script.cdc", []string{"String:Mr G"}, "", "")
 
 		assert.NoError(t, err)
 		assert.Equal(t, val.String(), `"Hello Mr G"`)
 	})
 
 	t.Run("Test Script JSON args", func(t *testing.T) {
-		val, err := scripts.Execute("./script.cdc", []string{}, "[{\"type\": \"String\", \"value\": \"Mr G\"}]")
+		val, err := scripts.Execute(
+			"./script.cdc",
+			[]string{},
+			"[{\"type\": \"String\", \"value\": \"Mr G\"}]",
+			"",
+		)
 
 		assert.NoError(t, err)
 		assert.Equal(t, val.String(), `"Hello Mr G"`)
@@ -236,18 +242,28 @@ func TestTransactions(t *testing.T) {
 	var txID1 flow.Identifier
 
 	t.Run("Test Transactions", func(t *testing.T) {
-		tx, tr, err := transactions.Send("./transaction.cdc", emulatorAccount, []string{"String:Hello"}, "")
+		tx, tr, err := transactions.Send(
+			"./transaction.cdc",
+			emulatorAccount, []string{"String:Hello"}, "",
+			"",
+		)
 		txID1 = tx.ID()
 
+		assert.NoError(t, tr.Error)
 		assert.NoError(t, err)
 		assert.Equal(t, tx.Payer.String(), serviceAddress)
 		assert.Equal(t, tr.Status.String(), "SEALED")
 	})
 
 	t.Run("Test Failed Transactions", func(t *testing.T) {
-		tx, tr, err := transactions.Send("./transactionErr.cdc", emulatorAccount, []string{}, "")
+		tx, tr, err := transactions.Send(
+			"./transactionErr.cdc",
+			emulatorAccount, []string{}, "",
+			"",
+		)
 
 		assert.NoError(t, err)
+		assert.NotNil(t, tr.Error)
 		assert.Equal(t, tx.Payer.String(), serviceAddress)
 		assert.Equal(t, tr.Status.String(), "SEALED")
 		require.Greater(t, len(tr.Error.Error()), 100)
diff --git a/tests/mockGateway.go b/tests/mockGateway.go
index 0a4a08be..a1b4ff01 100644
--- a/tests/mockGateway.go
+++ b/tests/mockGateway.go
@@ -28,16 +28,18 @@ import (
 )
 
 type MockGateway struct {
-	GetAccountMock           func(address flow.Address) (*flow.Account, error)
-	SendTransactionMock      func(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error)
-	GetTransactionResultMock func(tx *flow.Transaction) (*flow.TransactionResult, error)
-	GetTransactionMock       func(id flow.Identifier) (*flow.Transaction, error)
-	ExecuteScriptMock        func(script []byte, arguments []cadence.Value) (cadence.Value, error)
-	GetLatestBlockMock       func() (*flow.Block, error)
-	GetEventsMock            func(string, uint64, uint64) ([]client.BlockEvents, error)
-	GetCollectionMock        func(id flow.Identifier) (*flow.Collection, error)
-	GetBlockByHeightMock     func(uint64) (*flow.Block, error)
-	GetBlockByIDMock         func(flow.Identifier) (*flow.Block, error)
+	GetAccountMock                func(address flow.Address) (*flow.Account, error)
+	SendTransactionMock           func(tx *project.Transaction) (*flow.Transaction, error)
+	PrepareTransactionPayloadMock func(tx *project.Transaction) (*project.Transaction, error)
+	SendSignedTransactionMock     func(tx *project.Transaction) (*flow.Transaction, error)
+	GetTransactionResultMock      func(tx *flow.Transaction) (*flow.TransactionResult, error)
+	GetTransactionMock            func(id flow.Identifier) (*flow.Transaction, error)
+	ExecuteScriptMock             func(script []byte, arguments []cadence.Value) (cadence.Value, error)
+	GetLatestBlockMock            func() (*flow.Block, error)
+	GetEventsMock                 func(string, uint64, uint64) ([]client.BlockEvents, error)
+	GetCollectionMock             func(id flow.Identifier) (*flow.Collection, error)
+	GetBlockByHeightMock          func(uint64) (*flow.Block, error)
+	GetBlockByIDMock              func(flow.Identifier) (*flow.Block, error)
 }
 
 func NewMockGateway() gateway.Gateway {
@@ -48,8 +50,8 @@ func (g *MockGateway) GetAccount(address flow.Address) (*flow.Account, error) {
 	return g.GetAccountMock(address)
 }
 
-func (g *MockGateway) SendTransaction(tx *flow.Transaction, signer *project.Account) (*flow.Transaction, error) {
-	return g.SendTransactionMock(tx, signer)
+func (g *MockGateway) SendSignedTransaction(tx *project.Transaction) (*flow.Transaction, error) {
+	return g.SendSignedTransactionMock(tx)
 }
 
 func (g *MockGateway) GetTransactionResult(tx *flow.Transaction, waitSeal bool) (*flow.TransactionResult, error) {
diff --git a/tests/transaction3Auths.cdc b/tests/transaction3Auths.cdc
new file mode 100644
index 00000000..e7042162
--- /dev/null
+++ b/tests/transaction3Auths.cdc
@@ -0,0 +1,11 @@
+transaction(greeting: String) {
+  let guest: Address
+
+  prepare(authorizer1: AuthAccount, authorizer2: AuthAccount, authorizer3: AuthAccount) {
+    self.guest = authorizer1.address
+  }
+
+  execute {
+    log(greeting.concat(",").concat(self.guest.toString()))
+  }
+}
\ No newline at end of file