{"id":37043649,"url":"https://github.com/tyronbrand/flow.net","last_synced_at":"2026-01-14T05:01:13.657Z","repository":{"id":37035706,"uuid":"413790328","full_name":"tyronbrand/flow.net","owner":"tyronbrand","description":"Tools for building .Net applications on Flow","archived":false,"fork":false,"pushed_at":"2023-06-22T18:24:10.000Z","size":1008,"stargazers_count":18,"open_issues_count":0,"forks_count":8,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-11-21T11:05:31.480Z","etag":null,"topics":["blockchain","flow-blockchain","onflow","sdk"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tyronbrand.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-05T11:31:34.000Z","updated_at":"2025-06-11T09:07:35.000Z","dependencies_parsed_at":"2023-01-23T22:01:38.839Z","dependency_job_id":null,"html_url":"https://github.com/tyronbrand/flow.net","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/tyronbrand/flow.net","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyronbrand%2Fflow.net","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyronbrand%2Fflow.net/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyronbrand%2Fflow.net/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyronbrand%2Fflow.net/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tyronbrand","download_url":"https://codeload.github.com/tyronbrand/flow.net/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyronbrand%2Fflow.net/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28410074,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","flow-blockchain","onflow","sdk"],"created_at":"2026-01-14T05:01:12.507Z","updated_at":"2026-01-14T05:01:13.610Z","avatar_url":"https://github.com/tyronbrand.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cbr /\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"#\"\u003e\n    \u003cimg src=\"https://tyronbrand.github.io/flow.net/flowdotnetfull.png\" alt=\"Logo\" width=\"500\" height=\"auto\"\u003e\n  \u003c/a\u003e\n  \u003cp align=\"center\"\u003e \u003cbr /\u003e\n    \u003ca href=\"https://github.com/tyronbrand/flow.net\"\u003e\u003cstrong\u003eView on GitHub »\u003c/strong\u003e\u003c/a\u003e \u003cbr /\u003e\u003cbr /\u003e\n    \u003ca href=\"https://docs.onflow.org/sdk-guidelines/\"\u003eSDK Specifications\u003c/a\u003e ·\n    \u003ca href=\"https://github.com/tyronbrand/flow.net/blob/main/CONTRIBUTING.md\"\u003eContribute\u003c/a\u003e ·\n    \u003ca href=\"https://github.com/tyronbrand/flow.net/issues\"\u003eReport a Bug\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\u003cbr /\u003e\n\n## Overview \n\nThis reference documents all the methods available in the Flow.Net SDK, and explains in detail how these methods work.\n\nThe library client specifications can be found here:\n\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/index.html)\n\n## Getting Started\n\n### Installing\n\n### [Package Manager Console](#tab/install-with-pmconsole)\nRun following command in VS Package Manager Console:  \n```\nInstall-Package Flow.Net.Sdk\n```\n\n### [Command Line](#tab/install-with-cli)\nRun following command in command line:  \n```\ndotnet add package Flow.Net.Sdk\n```\n***\n\n## Connect\nThe library uses HTTP or gRPC APIs to communicate with the access nodes and it must be configured with correct access node API URL. \n\nYou can check more examples for creating clients in the examples:\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\" /\u003e](https://github.com/tyronbrand/flow.net/blob/b91a5648ea404701ba591c87b1a4aaacdf260d58/examples/Flow.Net.Examples/Program.cs#L14)**\n\n### Basic Example:\n```csharp\n// HTTP client\nvar flowHttpClient = new FlowHttpClient(new HttpClient(), new FlowClientOptions { ServerUrl = Sdk.Client.Http.ServerUrl.EmulatorHost });\n\n// gRPC client\nvar flowGrpcClient = new FlowGrpcClient(new FlowGrpcClientOptions { ServerUrl = Sdk.Client.Grpc.ServerUrl.EmulatorHost })\n```\n\n## Querying the Flow Network\nAfter you have established a connection with an access node, you can query the Flow network to retrieve data about blocks, accounts, events and transactions. We will explore how to retrieve each of these entities in the sections below.\n\n### Get Blocks\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Client.IFlowClient.html#Flow_Net_Sdk_Core_Client_IFlowClient_GetLatestBlockAsync_System_Boolean_)\n\nQuery the network for block by id, height or get the latest block.\n\n📖 **Block ID** is SHA3-256 hash of the entire block payload. This hash is stored as an ID field on any block response object (ie. response from `GetLatestBlock`). \n\n📖 **Block height** expresses the height of the block on the chain. The latest block height increases by one for every valid block produced.\n\n#### Examples\n\nThis example depicts ways to get the latest block as well as any other block by height or ID:\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/BlockExamples/BlockExample.cs)**\n```csharp\nprivate async Task Demo()\n{\n    // get the latest sealed block\n    var latestBlock = await FlowClient.GetLatestBlockAsync();\n    PrintResult(latestBlock);\n\n    // get the block by ID\n    var blockByIdResult = await FlowClient.GetBlockByIdAsync(latestBlock.Header.Id);\n    PrintResult(blockByIdResult);\n\n    // get block by height\n    var blockByHeightResult = await FlowClient.GetBlockByHeightAsync(latestBlock.Header.Height);\n    PrintResult(blockByHeightResult);\n}\n\nprivate void PrintResult(FlowBlock flowBlock)\n{\n    Console.WriteLine($\"ID: {flowBlock.Header.Id}\");\n    Console.WriteLine($\"height: {flowBlock.Header.Height}\");\n    Console.WriteLine($\"timestamp: {flowBlock.Header.Timestamp}\\n\");            \n}\n```\n\nExample output:\n```bash\nID: 7bc42fe85d32ca513769a74f97f7e1a7bad6c9407f0d934c2aa645ef9cf613c7\nheight: 0\ntimestamp: 19/12/2018 22:32:30 +00:00\n\nID: 7bc42fe85d32ca513769a74f97f7e1a7bad6c9407f0d934c2aa645ef9cf613c7\nheight: 0\ntimestamp: 19/12/2018 22:32:30 +00:00\n\nID: 7bc42fe85d32ca513769a74f97f7e1a7bad6c9407f0d934c2aa645ef9cf613c7\nheight: 0\ntimestamp: 19/12/2018 22:32:30 +00:00\n```\n\n### Get Account\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Client.IFlowClient.html#Flow_Net_Sdk_Core_Client_IFlowClient_GetAccountAtLatestBlockAsync_System_String_)\n\nRetrieve any account from Flow network's latest block or from a specified block height.\n\n📖 **Account address** is a unique account identifier. Be mindful about the `0x` prefix, you should use the prefix as a default representation but be careful and safely handle user inputs without the prefix.\n\nAn account includes the following data:\n- Address: the account address.\n- Balance: balance of the account.\n- Contracts: list of contracts deployed to the account.\n- Keys: list of keys associated with the account.\n\n#### Examples\nExample depicts ways to get an account at the latest block and at a specific block height:\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/AccountExamples/GetAccountExample.cs)**\n```csharp\nprivate async Task Demo()\n{\n    // get account from the latest block\n    var address = new FlowAddress(\"f8d6e0586b0a20c7\");\n    var account = await FlowClient.GetAccountAtLatestBlockAsync(address.Address);\n    PrintResult(account);\n\n    // get account from the block by height 0\n    account = await FlowClient.GetAccountAtBlockHeightAsync(address.Address, 0);\n    PrintResult(account);\n}\n\nprivate void PrintResult(FlowAccount flowAccount)\n{\n    Console.WriteLine($\"Address: {flowAccount.Address.Address}\");\n    Console.WriteLine($\"Balance: {flowAccount.Balance}\");\n    Console.WriteLine($\"Contracts: {flowAccount.Contracts.Count}\");\n    Console.WriteLine($\"Keys: {flowAccount.Keys.Count}\\n\");\n}\n```\n\nExample output:\n```bash\nAddress: f8d6e0586b0a20c7\nBalance: 999999999999700000\nContracts: 2\nKeys: 1\n\nAddress: f8d6e0586b0a20c7\nBalance: 999999999999700000\nContracts: 2\nKeys: 1\n```\n\n### Get Transactions\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Client.IFlowClient.html#Flow_Net_Sdk_Core_Client_IFlowClient_GetTransactionAsync_System_String_)\n\nRetrieve transactions from the network by providing a transaction ID. After a transaction has been submitted, you can also get the transaction result to check the status.\n\n📖 **Transaction ID** is a hash of the encoded transaction payload and can be calculated before submitting the transaction to the network.\n\n⚠️ The transaction ID provided must be from the current spork.\n\n📖 **Transaction status** represents the state of transaction in the blockchain. Status can change until is finalized.\n\n| Status      | Final | Description |\n| ----------- | ----------- | ----------- |\n|   UNKNOWN    |    ❌   |   The transaction has not yet been seen by the network  |\n|   PENDING    |    ❌   |   The transaction has not yet been included in a block   |\n|   FINALIZED    |   ❌     |  The transaction has been included in a block   |\n|   EXECUTED    |   ❌    |   The transaction has been executed but the result has not yet been sealed  |\n|   SEALED    |    ✅    |   The transaction has been executed and the result is sealed in a block  |\n|   EXPIRED    |   ✅     |  The transaction reference block is outdated before being executed    |\n\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/TransactionExamples/GetTransactionExample.cs)**\n```csharp\nprivate async Task Demo(string transactionId)\n{\n    var tx = await FlowClient.GetTransactionAsync(transactionId);\n    PrintTransaction(tx);\n\n    var txr = await FlowClient.GetTransactionResultAsync(transactionId);\n    PrintTransactionResult(txr);\n}\n\nprivate void PrintTransaction(FlowTransactionBase tx)\n{\n    Console.WriteLine($\"ReferenceBlockId: {tx.ReferenceBlockId}\");\n    Console.WriteLine($\"Payer: {tx.Payer.Address}\");\n    Console.WriteLine(\"Authorizers: [{0}]\", string.Join(\", \", tx.Authorizers.Select(s =\u003e s.Address).ToArray()));\n    Console.WriteLine($\"Proposer: {tx.ProposalKey.Address.Address}\");\n}\n\nprivate void PrintTransactionResult(FlowTransactionResult txr)\n{\n    Console.WriteLine($\"Status: {txr.Status}\");\n    Console.WriteLine($\"Error: {txr.ErrorMessage}\\n\");\n}\n```\n\nExample output:\n```bash\nReferenceBlockId: a31c341a905dcfd16d8c0be0ebec389222572ff6dd2957bd944f55ee80c4dca9\nPayer: f8d6e0586b0a20c7\nAuthorizers: []\nProposer: f8d6e0586b0a20c7\nStatus: Sealed\nError:\n```\n\n### Get Events\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Client.IFlowClient.html#Flow_Net_Sdk_Core_Client_IFlowClient_GetEventsForBlockIdsAsync_System_String_System_Collections_Generic_IEnumerable_System_String__)\n\nRetrieve events by a given type in a specified block height range or through a list of block IDs.\n\n📖 **Event type** is a string that follow a standard format:\n```\nA.{contract address}.{contract name}.{event name}\n```\n\nPlease read more about [events in the documentation](https://docs.onflow.org/core-contracts/flow-token/). The exception to this standard are \ncore events, and you should read more about them in [this document](https://docs.onflow.org/cadence/language/core-events/).\n\n📖 **Block height range** expresses the height of the start and end block in the chain.\n\n#### Examples\nExample depicts ways to get events within block range or by block IDs:\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/EventExamples/GetEventsExample.cs)**\n```csharp\nprivate async Task Demo(FlowAccount flowAccount, ByteString flowTransactionId)\n{\n    // Query for account creation events by type\n    var eventsForHeightRange = await FlowClient.GetEventsForHeightRangeAsync(\"flow.AccountCreated\", 0, 100);\n    PrintEvents(eventsForHeightRange);\n\n    // Query for our custom event by type\n    var customType = $\"A.{flowAccount.Address.HexValue}.EventDemo.Add\";\n    var customEventsForHeightRange = await FlowClient.GetEventsForHeightRangeAsync(customType, 0, 100);\n    PrintEvents(customEventsForHeightRange);\n\n    // Get events directly from transaction result\n    var txResult = await FlowClient.GetTransactionResultAsync(flowTransactionId);\n    PrintEvent(txResult.Events);\n}\n\nprivate void PrintEvents(IEnumerable\u003cFlowBlockEvent\u003e flowBlockEvents)\n{\n    foreach(var blockEvent in flowBlockEvents)\n        PrintEvent(blockEvent.Events);\n}\n\nprivate void PrintEvent(IEnumerable\u003cFlowEvent\u003e flowEvents)\n{\n    foreach(var @event in flowEvents)\n    {\n        Console.WriteLine($\"Type: {@event.Type}\");\n        Console.WriteLine($\"Values: {@event.Payload.Encode()}\");\n        Console.WriteLine($\"Transaction ID: {@event.TransactionId.FromByteStringToHex()} \\n\");\n    }\n}\n```\n\nExample output:\n```bash\nType: flow.AccountCreated\nValues: {\"type\":\"Event\",\"value\":{\"id\":\"flow.AccountCreated\",\"fields\":[{\"name\":\"address\",\"value\":{\"type\":\"Address\",\"value\":\"0x01cf0e2f2f715450\"}}]}}\nTransaction ID: 6edf928c88717fdaefe0849e014d7d4f7931471cdb6ae9329f992d4751844099\n\nType: A.01cf0e2f2f715450.EventDemo.Add\nValues: {\"type\":\"Event\",\"value\":{\"id\":\"A.01cf0e2f2f715450.EventDemo.Add\",\"fields\":[{\"name\":\"x\",\"value\":{\"type\":\"Int\",\"value\":\"2\"}},{\"name\":\"y\",\"value\":{\"type\":\"Int\",\"value\":\"3\"}},{\"name\":\"sum\",\"value\":{\"type\":\"Int\",\"value\":\"5\"}}]}}\nTransaction ID: 72ae51dbfcda12fdda9b97cf3e8df54980111c4b4bb7f0f86f9113420f21bece\n\nType: A.01cf0e2f2f715450.EventDemo.Add\nValues: {\"type\":\"Event\",\"value\":{\"id\":\"A.01cf0e2f2f715450.EventDemo.Add\",\"fields\":[{\"name\":\"x\",\"value\":{\"type\":\"Int\",\"value\":\"2\"}},{\"name\":\"y\",\"value\":{\"type\":\"Int\",\"value\":\"3\"}},{\"name\":\"sum\",\"value\":{\"type\":\"Int\",\"value\":\"5\"}}]}}\nTransaction ID: 72ae51dbfcda12fdda9b97cf3e8df54980111c4b4bb7f0f86f9113420f21bece\n```\n\n### Get Collections\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Client.IFlowClient.html#Flow_Net_Sdk_Core_Client_IFlowClient_GetCollectionAsync_System_String_)\n\nRetrieve a batch of transactions that have been included in the same block, known as ***collections***. \nCollections are used to improve consensus throughput by increasing the number of transactions per block and they act as a link between a block and a transaction.\n\n📖 **Collection ID** is SHA3-256 hash of the collection payload.\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/CollectionExamples/GetCollectionExample.cs)**\n```csharp\nprivate async Task Demo(FlowCollectionGuarantee flowCollectionGuarantee)\n{\n    // get collection by ID\n    var collection = await FlowClient.GetCollectionByIdAsync(flowCollectionGuarantee.CollectionId);\n    PrintCollection(collection);\n}\n\nprivate void PrintCollection(FlowCollectionResponse flowCollection)\n{\n    Console.WriteLine($\"ID: {flowCollection.Id.FromByteStringToHex()}\");\n    Console.WriteLine(\"Transactions: [{0}]\", string.Join(\", \", flowCollection.TransactionIds.Select(s =\u003e s.FromByteStringToHex()).ToArray()));\n}\n```\n\nExample output:\n```bash\nID: 31a5c134b24fb556069575fa3acdfbdf6a0b4faf072df85c32ad476cba308468\nTransactions: [6edf928c88717fdaefe0849e014d7d4f7931471cdb6ae9329f992d4751844099]\n```\n\n### Execute Scripts\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Client.IFlowClient.html#Flow_Net_Sdk_Core_Client_IFlowClient_ExecuteScriptAtLatestBlockAsync_Flow_Net_Sdk_Core_Models_FlowScript_)\n\nScripts allow you to write arbitrary non-mutating Cadence code on the Flow blockchain and return data. You can learn more about [Cadence and scripts here](https://docs.onflow.org/cadence/language/), but we are now only interested in executing the script code and getting back the data.\n\nWe can execute a script using the latest state of the Flow blockchain or we can choose to execute the script at a specific time in history defined by a block height or block ID.\n\n📖 **Block ID** is SHA3-256 hash of the entire block payload, but you can get that value from the block response properties.\n\n📖 **Block height** expresses the height of the block in the chain.\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/ScriptExamples/ScriptExample.cs)**\n```csharp\nprivate async Task Demo()\n{\n    // simple script\n    var script = @\"\npub fun main(a: Int): Int {\n    return a + 10\n}\";\n\n    var arguments = new List\u003cICadence\u003e\n    {\n        new CadenceNumber(CadenceNumberType.Int, \"5\")\n    };\n\n    var response = await FlowClient.ExecuteScriptAtLatestBlockAsync(\n        new FlowScript\n        {\n            Script = script,\n            Arguments = arguments\n        });\n    Console.WriteLine($\"Value: {response.As\u003cCadenceNumber\u003e().Value}\");\n\n    // complex script\n    var complexScript = @\"\npub struct User {\n    pub var balance: UFix64\n    pub var address: Address\n    pub var name: String\n\n    init(name: String, address: Address, balance: UFix64) {\n        self.name = name\n        self.address = address\n        self.balance = balance\n    }\n}\n    pub fun main(name: String): User {\n    return User(\n        name: name,\n        address: 0x1,\n        balance: 10.0\n    )\n}\";\n\n    var complexArguments = new List\u003cICadence\u003e\n    {\n        new CadenceString(\"Dete\")\n    };\n    var complexResponse = await FlowClient.ExecuteScriptAtLatestBlockAsync(\n        new FlowScript\n        {\n            Script = complexScript,\n            Arguments = complexArguments\n        });\n    PrintComplexScript(complexResponse);\n}\n\npublic class User\n{\n    public decimal Balance { get; set; }\n    public string Address { get; set; }\n    public string Name { get; set; }\n}\n\nprivate void PrintComplexScript(ICadence cadenceResponse)\n{\n    var user = new User\n    {\n        Name = cadenceResponse.As\u003cCadenceComposite\u003e().CompositeFieldAs\u003cCadenceString\u003e(\"name\").Value,\n        Address = cadenceResponse.As\u003cCadenceComposite\u003e().CompositeFieldAs\u003cCadenceAddress\u003e(\"address\").Value,\n        Balance = decimal.Parse(cadenceResponse.As\u003cCadenceComposite\u003e().CompositeFieldAs\u003cCadenceNumber\u003e(\"balance\").Value)\n    };\n\n    Console.WriteLine($\"Name: {user.Name}\");\n    Console.WriteLine($\"Address: {user.Address}\");\n    Console.WriteLine($\"Balance: {user.Balance}\");\n}\n```\n\nExample output:\n```bash\nValue: 15\nName: Dete\nAddress: 0000000000000001\nBalance: 10.00000000\n```\n\n## Mutate Flow Network\nFlow, like most blockchains, allows anybody to submit a transaction that mutates the shared global chain state. A transaction is an object that holds a payload, which describes the state mutation, and one or more authorizations that permit the transaction to mutate the state owned by specific accounts.\n\nTransaction data is composed and signed with help of the SDK. The signed payload of transaction then gets submitted to the access node API. If a transaction is invalid or the correct number of authorizing signatures are not provided, it gets rejected. \n\nExecuting a transaction requires couple of steps:\n- [Building a transaction](#build-transactions).\n- [Signing a transaction](#sign-transactions).\n- [Sending a transaction](#send-transactions).\n\n## Transactions\nA transaction is nothing more than a signed set of data that includes script code which are instructions on how to mutate the network state and properties that define and limit it's execution. All these properties are explained bellow. \n\n📖 **Script** field is the portion of the transaction that describes the state mutation logic. On Flow, transaction logic is written in [Cadence](https://docs.onflow.org/cadence/). Here is an example transaction script:\n```\ntransaction(greeting: String) {\n  execute {\n    log(greeting.concat(\", World!\"))\n  }\n}\n```\n\n📖 **Arguments**. A transaction can accept zero or more arguments that are passed into the Cadence script. The arguments on the transaction must match the number and order declared in the Cadence script. Sample script from above accepts a single `String` argument.\n\n📖 **[Proposal key](https://docs.onflow.org/concepts/transaction-signing/#proposal-key)** must be provided to act as a sequence number and prevent reply and other potential attacks.\n\nEach account key maintains a separate transaction sequence counter; the key that lends its sequence number to a transaction is called the proposal key.\n\nA proposal key contains three fields:\n- Account address\n- Key index\n- Sequence number\n\nA transaction is only valid if its declared sequence number matches the current on-chain sequence number for that key. The sequence number increments by one after the transaction is executed.\n\n📖 **[Payer](https://docs.onflow.org/concepts/transaction-signing/#signer-roles)** is the account that pays the fees for the transaction. A transaction must specify exactly one payer. The payer is only responsible for paying the network and gas fees; the transaction is not authorized to access resources or code stored in the payer account.\n\n📖 **[Authorizers](https://docs.onflow.org/concepts/transaction-signing/#signer-roles)** are accounts that authorize a transaction to read and mutate their resources. A transaction can specify zero or more authorizers, depending on how many accounts the transaction needs to access.\n\nThe number of authorizers on the transaction must match the number of AuthAccount parameters declared in the prepare statement of the Cadence script.\n\nExample transaction with multiple authorizers:\n```\ntransaction {\n  prepare(authorizer1: AuthAccount, authorizer2: AuthAccount) { }\n}\n```\n\n📖 **Gas limit** is the limit on the amount of computation a transaction requires, and it will abort if it exceeds its gas limit.\nCadence uses metering to measure the number of operations per transaction. You can read more about it in the [Cadence documentation](/cadence).\n\nThe gas limit depends on the complexity of the transaction script. Until dedicated gas estimation tooling exists, it's best to use the emulator to test complex transactions and determine a safe limit.\n\n📖 **Reference block** specifies an expiration window (measured in blocks) during which a transaction is considered valid by the network.\nA transaction will be rejected if it is submitted past its expiry block. Flow calculates transaction expiry using the _reference block_ field on a transaction.\nA transaction expires after `600` blocks are committed on top of the reference block, which takes about 10 minutes at average Mainnet block rates.\n\n### Build Transactions\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Models.FlowTransaction.html)\n\nBuilding a transaction involves setting the required properties explained above and producing a transaction object. \n\nHere we define a simple transaction script that will be used to execute on the network and serve as a good learning example.\n\n```\ntransaction(greeting: String) {\n\n  let guest: Address\n\n  prepare(authorizer: AuthAccount) {\n    self.guest = authorizer.address\n  }\n\n  execute {\n    log(greeting.concat(\",\").concat(guest.toString()))\n  }\n}\n```\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/TransactionExamples/CreateTransactionExample.cs)**\n```csharp\nprivate async Task Demo()\n{\n    // reading script from folder\n    var script = Utilities.ReadCadenceScript(\"greeting\");\n\n    var proposerAddress = new FlowAddress(\"9a0766d93b6608b7\");\n    uint proposerKeyIndex = 3;\n\n    var payerAddress = new FlowAddress(\"631e88ae7f1d7c20\");\n    var authorizerAddress = new FlowAddress(\"7aad92e5a0715d21\");\n\n    // Establish a connection with an access node\n    var accessAPIHost = \"\";\n    var flowClient = new FlowHttpClient(new HttpClient(), accessAPIHost);\n\n    // Get the latest sealed block to use as a reference block\n    var latestBlock = await flowClient.GetLatestBlockHeaderAsync();\n\n    // Get the latest account info for this address\n    var proposerAccount = await flowClient.GetAccountAtLatestBlockAsync(proposerAddress.Address);\n\n    // Get the latest sequence number for this key\n    var proposerKey = proposerAccount.Keys.FirstOrDefault(w =\u003e w.Index == proposerKeyIndex);\n    var sequenceNumber = proposerKey.SequenceNumber;\n\n    var tx = new FlowTransaction\n    {\n        Script = script,\n        GasLimit = 100,\n        ProposalKey = new FlowProposalKey\n        {\n            Address = proposerAddress,\n            KeyId = proposerKeyIndex,\n            SequenceNumber = sequenceNumber\n        },\n        Payer = payerAddress,\n        ReferenceBlockId = latestBlock.Id\n    };\n\n    // Add authorizer\n    tx.Authorizers.Add(authorizerAddress);\n\n    // Add argument            \n    tx.Arguments.Add(new CadenceString(\"Hello\"));\n}\n```\n\nAfter you have successfully [built a transaction](#build-transactions) the next step in the process is to sign it.\n\n### Sign Transactions\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Models.FlowTransactionExtensions.html#Flow_Net_Sdk_Models_FlowTransactionExtensions_AddEnvelopeSignature_Flow_Net_Sdk_Models_FlowTransaction_Google_Protobuf_ByteString_System_UInt32_Flow_Net_Sdk_Crypto_ISigner_)\n\nFlow introduces new concepts that allow for more flexibility when creating and signing transactions.\nBefore trying the examples below, we recommend that you read through the [transaction signature documentation](https://docs.onflow.org/concepts/accounts-and-keys/).\n\nAfter you have successfully [built a transaction](#build-transactions) the next step in the process is to sign it. Flow transactions have envelope and payload signatures, and you should learn about each in the [signature documentation](https://docs.onflow.org/concepts/accounts-and-keys/#anatomy-of-a-transaction).\n\nQuick example of building a transaction:\n```csharp\nvar proposerAccount = new FlowAccount();\nvar proposerKey = proposerAccount.Keys.FirstOrDefault(w =\u003e w.Index == 1);\n\nvar tx = new FlowTransaction\n{\n    Script = \"transaction { execute { log(\\\"Hello, World!\\\") } }\",\n    GasLimit = 100,\n    ProposalKey = new FlowProposalKey\n    {\n        Address = proposerAccount.Address,\n        KeyId = proposerKey.Index,\n        SequenceNumber = proposerKey.SequenceNumber\n    },\n    Payer = proposerAccount.Address\n};\n```\n\nSignatures can be generated more securely using keys stored in a hardware device such as an [HSM](https://en.wikipedia.org/wiki/Hardware_security_module). The `ISigner` interface is intended to be flexible enough to support a variety of signer implementations and is not limited to in-memory implementations.\n\nSimple signature example:\n```csharp\n// construct a signer from your private key and configured signature/hash algorithms\nvar signer = Sdk.Core.Crypto.Ecdsa.Utilities.CreateSigner(\"privateKey\", SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256);\n\nFlowTransaction.AddEnvelopeSignature(tx, proposerAccount.Address, proposerKey.Index, signer);\n```\n\nFlow supports great flexibility when it comes to transaction signing, we can define multiple authorizers (multi-sig transactions) and have different payer account than proposer. We will explore advanced signing scenarios bellow.\n\n### [Single party, single signature](https://docs.onflow.org/concepts/transaction-signing/#single-party-single-signature)\n\n- Proposer, payer and authorizer are the same account (`0x01`).\n- Only the envelope must be signed.\n- Proposal key must have full signing weight.\n\n| Account | Key ID | Weight |\n| ------- | ------ | ------ |\n| `0x01`  | 1      | 1.0    |\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/TransactionExamples/SinglePartySingleSignatureExample.cs)**\n```csharp\n// generate key\nvar flowAccountKey = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256);\n// create account with key\nvar account1 = await CreateAccountAsync(new List\u003cFlowAccountKey\u003e { flowAccountKey });\n// select key\nvar account1Key = account1.Keys.FirstOrDefault();\n\n// get the latest sealed block to use as a reference block\nvar latestBlock = await FlowClient.GetLatestBlockAsync();\n\nvar tx = new FlowTransaction\n{\n    Script = \"transaction {prepare(signer: AuthAccount) { log(signer.address) }}\",\n    GasLimit = 100,\n    Payer = account1.Address,\n    ProposalKey = new FlowProposalKey\n    {\n        Address = account1.Address,\n        KeyId = account1Key.Index,\n        SequenceNumber = account1Key.SequenceNumber\n    },\n    ReferenceBlockId = latestBlock.Header.Id,\n};\n\n// authorizers\ntx.Authorizers.Add(account1.Address);\n\n// account 1 signs the envelope with key 1\ntx = FlowTransaction.AddEnvelopeSignature(tx, account1.Address, account1Key.Index, account1Key.Signer);\n\n// send transaction\nvar txResponse = await FlowClient.SendTransactionAsync(tx);\n```\n\n### [Single party, multiple signatures](https://docs.onflow.org/concepts/transaction-signing/#single-party-multiple-signatures)\n\n- Proposer, payer and authorizer are the same account (`0x01`).\n- Only the envelope must be signed.\n- Each key has weight 0.5, so two signatures are required.\n\n| Account | Key ID | Weight |\n| ------- | ------ | ------ |\n| `0x01`  | 1      | 0.5    |\n| `0x01`  | 2      | 0.5    |\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/TransactionExamples/SinglePartyMultiSignatureExample.cs)**\n```csharp\n// generate key 1 for account1\nvar flowAccountKey1 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256, 500);\n// generate key 2 for account1\nvar flowAccountKey2 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256, 500);\n\n// create account with keys\nvar account1 = await CreateAccountAsync(new List\u003cFlowAccountKey\u003e { flowAccountKey1, flowAccountKey2 });\n\n// select keys\nvar account1Key1 = account1.Keys[0];\nvar account1Key2 = account1.Keys[1];\n\n// get the latest sealed block to use as a reference block\nvar latestBlock = await FlowClient.GetLatestBlockAsync();\n\nvar tx = new FlowTransaction\n{\n    Script = \"transaction {prepare(signer: AuthAccount) { log(signer.address) }}\",\n    GasLimit = 9999,\n    Payer = account1.Address,\n    ProposalKey = new FlowProposalKey\n    {\n        Address = account1.Address,\n        KeyId = account1Key1.Index,\n        SequenceNumber = account1Key1.SequenceNumber\n    },\n    ReferenceBlockId = latestBlock.Header.Id\n};\n\n// authorizers\ntx.Authorizers.Add(account1.Address);\n\n// account 1 signs the envelope with key 1\ntx = FlowTransaction.AddEnvelopeSignature(tx, account1.Address, account1Key1.Index, account1Key1.Signer);\n\n// account 1 signs the envelope with key 2\ntx = FlowTransaction.AddEnvelopeSignature(tx, account1.Address, account1Key2.Index, account1Key2.Signer);\n\n// send transaction\nvar txResponse = await FlowClient.SendTransactionAsync(tx);\n```\n\n### [Multiple parties](https://docs.onflow.org/concepts/transaction-signing/#multiple-parties)\n\n- Proposer and authorizer are the same account (`0x01`).\n- Payer is a separate account (`0x02`).\n- Account `0x01` signs the payload.\n- Account `0x02` signs the envelope.\n    - Account `0x02` must sign last since it is the payer.\n\n| Account | Key ID | Weight |\n| ------- | ------ | ------ |\n| `0x01`  | 1      | 1.0    |\n| `0x02`  | 3      | 1.0    |\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/TransactionExamples/MultiPartySingleSignatureExample.cs)**\n```csharp\n// generate key for account1\nvar flowAccountKey1 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256);\n// create account1\nvar account1 = await CreateAccountAsync(new List\u003cFlowAccountKey\u003e { flowAccountKey1 });\n// select account1 key\nvar account1Key = account1.Keys.FirstOrDefault();\n\n// generate key for account2\nvar flowAccountKey2 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256);\n// create account2\nvar account2 = await CreateAccountAsync(new List\u003cFlowAccountKey\u003e { flowAccountKey2 });\n// select account2 key\nvar account2Key = account2.Keys.FirstOrDefault();\n\n// get the latest sealed block to use as a reference block\nvar latestBlock = await FlowClient.GetLatestBlockAsync();\n\nvar tx = new FlowTransaction\n{\n    Script = \"transaction {prepare(signer: AuthAccount) { log(signer.address) }}\",\n    GasLimit = 9999,\n    Payer = account2.Address,\n    ProposalKey = new FlowProposalKey\n    {\n        Address = account1.Address,\n        KeyId = account1Key.Index,\n        SequenceNumber = account1Key.SequenceNumber\n    },\n    ReferenceBlockId = latestBlock.Header.Id,\n};\n\n// authorizers\ntx.Authorizers.Add(account1.Address);\n\n// account 1 signs the payload with key 1\ntx = FlowTransaction.AddPayloadSignature(tx, account1.Address, account1Key.Index, account1Key.Signer);\n\n// account 2 signs the envelope\ntx = FlowTransaction.AddEnvelopeSignature(tx, account2.Address, account2Key.Index, account2Key.Signer);\n\n// send transaction\nvar txResponse = await FlowClient.SendTransactionAsync(tx);\n```\n\n### [Multiple parties, two authorizers](https://docs.onflow.org/concepts/transaction-signing/#multiple-parties)\n\n- Proposer and authorizer are the same account (`0x01`).\n- Payer is a separate account (`0x02`).\n- Account `0x01` signs the payload.\n- Account `0x02` signs the envelope.\n    - Account `0x02` must sign last since it is the payer.\n- Account `0x02` is also an authorizer to show how to include two AuthAccounts into an transaction\n\n| Account | Key ID | Weight |\n| ------- | ------ | ------ |\n| `0x01`  | 1      | 1.0    |\n| `0x02`  | 3      | 1.0    |\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/TransactionExamples/MultiPartyTwoAuthorizersExample.cs)**\n```csharp\n// generate key for account1\nvar flowAccountKey1 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256);\n// create account1\nvar account1 = await CreateAccountAsync(new List\u003cFlowAccountKey\u003e { flowAccountKey1 });\n// select account1 key\nvar account1Key = account1.Keys.FirstOrDefault();\n\n// generate key for account2\nvar flowAccountKey2 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256);\n// create account2\nvar account2 = await CreateAccountAsync(new List\u003cFlowAccountKey\u003e { flowAccountKey2 });\n// select account2 key\nvar account2Key = account2.Keys.FirstOrDefault();\n\n// get the latest sealed block to use as a reference block\nvar latestBlock = await FlowClient.GetLatestBlockAsync();\n\nvar tx = new FlowTransaction\n{\n    Script = @\"\ntransaction { \n    prepare(signer1: AuthAccount, signer2: AuthAccount) { \n        log(signer1.address) \n        log(signer2.address)\n    }\n}\",\n    GasLimit = 9999,\n    Payer = account2.Address,\n    ProposalKey = new FlowProposalKey\n    {\n        Address = account1.Address,\n        KeyId = account1Key.Index,\n        SequenceNumber = account1Key.SequenceNumber\n    },\n    ReferenceBlockId = latestBlock.Header.Id\n};\n\n// authorizers\ntx.Authorizers.Add(account1.Address);\ntx.Authorizers.Add(account2.Address);\n\n// account 1 signs the payload with key 1\ntx = FlowTransaction.AddPayloadSignature(tx, account1.Address, account1Key.Index, account1Key.Signer);\n\n// account 2 signs the envelope\ntx = FlowTransaction.AddEnvelopeSignature(tx, account2.Address, account2Key.Index, account2Key.Signer);\n\n// send transaction\nvar txResponse = await FlowClient.SendTransactionAsync(tx);\n```\n\n### [Multiple parties, multiple signatures](https://docs.onflow.org/concepts/transaction-signing/#multiple-parties)\n\n- Proposer and authorizer are the same account (`0x01`).\n- Payer is a separate account (`0x02`).\n- Account `0x01` signs the payload.\n- Account `0x02` signs the envelope.\n    - Account `0x02` must sign last since it is the payer.\n- Both accounts must sign twice (once with each of their keys).\n\n| Account | Key ID | Weight |\n| ------- | ------ | ------ |\n| `0x01`  | 1      | 0.5    |\n| `0x01`  | 2      | 0.5    |\n| `0x02`  | 3      | 0.5    |\n| `0x02`  | 4      | 0.5    |\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/TransactionExamples/MultiPartyMultiSignatureExample.cs)**\n```csharp\n// generate key 1 for account1\nvar flowAccount1Key1 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA2_256, 500);\n// generate key 2 for account1\nvar flowAccount1Key2 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA2_256, 500);\n// create account1\nvar account1 = await CreateAccountAsync(new List\u003cFlowAccountKey\u003e { flowAccount1Key1, flowAccount1Key2 });\n\n// generate key 1 for account2\nvar flowAccount2Key3 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256, 500);\n// generate key 2 for account2\nvar flowAccount2Key4 = FlowAccountKey.GenerateRandomEcdsaKey(SignatureAlgo.ECDSA_P256, HashAlgo.SHA3_256, 500);\n// create account2\nvar account2 = await CreateAccountAsync(new List\u003cFlowAccountKey\u003e { flowAccount2Key3, flowAccount2Key4 });\n\n// get the latest sealed block to use as a reference block\nvar latestBlock = await FlowClient.GetLatestBlockAsync();\n\nvar tx = new FlowTransaction\n{\n    Script = \"transaction {prepare(signer: AuthAccount) { log(signer.address) }}\",\n    GasLimit = 9999,\n    Payer = account2.Address,\n    ProposalKey = new FlowProposalKey\n    {\n        Address = account1.Address,\n        KeyId = account1.Keys[0].Index,\n        SequenceNumber = account1.Keys[0].SequenceNumber\n    },\n    ReferenceBlockId = latestBlock.Header.Id\n};\n\n// authorizers\ntx.Authorizers.Add(account1.Address);\n\n// account 1 signs the payload with key 1\ntx = FlowTransaction.AddPayloadSignature(tx, account1.Address, account1.Keys[0].Index, account1.Keys[0].Signer);\n\n// account 1 signs the payload with key 2\ntx = FlowTransaction.AddPayloadSignature(tx, account1.Address, account1.Keys[1].Index, account1.Keys[1].Signer);\n\n// account 2 signs the envelope with key 3\ntx = FlowTransaction.AddEnvelopeSignature(tx, account2.Address, account2.Keys[0].Index, account2.Keys[0].Signer);\n\n// account 2 signs the envelope with key 3\ntx = FlowTransaction.AddEnvelopeSignature(tx, account2.Address, account2.Keys[1].Index, account2.Keys[1].Signer);\n\n// send transaction\nvar txResponse = await FlowClient.SendTransactionAsync(tx);\n```\n\n### Send Transactions\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Client.IFlowClient.html#Flow_Net_Sdk_Core_Client_IFlowClient_SendTransactionAsync_Flow_Net_Sdk_Core_Models_FlowTransaction_)\n\nAfter a transaction has been [built](#build-transactions) and [signed](#sign-transactions), it can be sent to the Flow blockchain where it will be executed. If sending was successful you can then [retrieve the transaction result](#get-transactions).\n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/TransactionExamples/MultiPartyMultiSignatureExample.cs)**\n```csharp\n// send transaction\nvar txResponse = await FlowClient.SendTransactionAsync(tx);\n```\n\n### Create Accounts\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Templates.AccountTemplates.html#Flow_Net_Sdk_Core_Templates_AccountTemplates_CreateAccount_System_Collections_Generic_IEnumerable_Flow_Net_Sdk_Core_Models_FlowAccountKey__Flow_Net_Sdk_Core_Models_FlowAddress_System_Collections_Generic_IEnumerable_Flow_Net_Sdk_Core_Models_FlowContract__)\n\nOn Flow, account creation happens inside a transaction. Because the network allows for a many-to-many relationship between public keys and accounts, it's not possible to derive a new account address from a public key offline. \n\nThe Flow VM uses a deterministic address generation algorithm to assigen account addresses on chain. You can find more details about address generation in the [accounts \u0026 keys documentation](https://docs.onflow.org/concepts/accounts-and-keys/).\n\n#### Public Key\nFlow uses ECDSA key pairs to control access to user accounts. Each key pair can be used in combination with the SHA2-256 or SHA3-256 hashing algorithms.\n\n⚠️ You'll need to authorize at least one public key to control your new account.\n\nFlow represents ECDSA public keys in raw form without additional metadata. Each key is a single byte slice containing a concatenation of its X and Y components in big-endian byte form.\n\nA Flow account can contain zero (not possible to control) or more public keys, referred to as account keys. Read more about [accounts in the documentation](https://docs.onflow.org/concepts/accounts-and-keys/#accounts).\n\nAn account key contains the following data:\n- Raw public key (described above)\n- Signature algorithm\n- Hash algorithm\n- Weight (integer between 0-1000)\n\nAccount creation happens inside a transaction, which means that somebody must pay to submit that transaction to the network. We'll call this person the account creator. Make sure you have read [sending a transaction section](#send-transactions) first. \n\n**[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/try.svg\" width=\"130\"\u003e](https://github.com/tyronbrand/flow.net/tree/main/examples/Flow.Net.Examples/ExampleBase.cs)**\n```csharp\n// read flow.json\nvar config = Utilities.ReadConfig();\n// get account from config\nvar accountConfig = config.Accounts[\"emulator-account\"];\n// get service account at latest block\nvar serviceAccount = await FlowClient.GetAccountAtLatestBlockAsync(accountConfig.Address);\n// add a Signer with the serviceAccount and the accountConfig\nserviceAccount = Utilities.AddSignerFromConfigAccount(accountConfig, serviceAccount);\n\n// creator key to use\nvar serviceAccountKey = serviceAccount.Keys.FirstOrDefault();\n\n// use template to create a transaction\nvar tx = AccountTemplates.CreateAccount(newFlowAccountKeys, serviceAccount.Address);\n\n// set the transaction payer and proposal key\ntx.Payer = serviceAccount.Address;\ntx.ProposalKey = new FlowProposalKey\n{\n    Address = serviceAccount.Address,\n    KeyId = serviceAccountKey.Index,\n    SequenceNumber = serviceAccountKey.SequenceNumber\n};\n\n// get the latest sealed block to use as a reference block\nvar latestBlock = await FlowClient.GetLatestBlockAsync();\ntx.ReferenceBlockId = latestBlock.Header.Id;\n\n// sign and submit the transaction\ntx = FlowTransaction.AddEnvelopeSignature(tx, serviceAccount.Address, serviceAccountKey.Index, serviceAccountKey.Signer);\n\nvar response = await FlowClient.SendTransactionAsync(tx);\n```\n\nAfter the account creation transaction has been submitted you can retrieve the new account address by [getting the transaction result](#get-transactions). \n\nThe new account address will be emitted in a system-level `flow.AccountCreated` event.\n\n```csharp\n var result = await GetTransactionResultAsync(transactionResponse.Id);\n\nif (result.Status == TransactionStatus.Sealed)\n{\n    var newAccountAddress = sealedResponse.Events.AccountCreatedAddress();\n\n    // get new account details\n    var newAccount = await FlowClient.GetAccountAtLatestBlockAsync(newAccountAddress);\n    newAccount.Keys = FlowAccountKey.UpdateFlowAccountKeys(newFlowAccountKeys, newAccount.Keys);\n    return newAccount;\n}\n```\n\n### Generate Keys\n[\u003cimg src=\"https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg\" width=\"130\"\u003e](https://tyronbrand.github.io/flow.net/api/Flow.Net.Sdk.Core.Crypto.Ecdsa.Utilities.html)\n\nFlow uses [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) signatures to control access to user accounts. Each key pair can be used in combination with the `SHA2-256` or `SHA3-256` hashing algorithms.\n\nHere's how to generate an ECDSA private key for the P-256 (secp256r1) curve.\n\n```csharp\nvar newKeys = Sdk.Core.Crypto.Ecdsa.Utilities.GenerateKeyPair(SignatureAlgo.ECDSA_P256);\nvar publicKey = Sdk.Core.Crypto.Ecdsa.Utilities.DecodePublicKeyToHex(newKeys);\nvar privateKey = Sdk.Core.Crypto.Ecdsa.Utilities.DecodePrivateKeyToHex(newKeys);\n```\n\nThe example above uses an ECDSA key pair on the P-256 (secp256r1) elliptic curve. Flow also supports the secp256k1 curve used by Bitcoin and Ethereum. Read more about [supported algorithms here](https://docs.onflow.org/concepts/accounts-and-keys/#supported-signature--hash-algorithms).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyronbrand%2Fflow.net","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftyronbrand%2Fflow.net","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyronbrand%2Fflow.net/lists"}