# Graffle Flow SDK

The Graffle Flow SDK is a C# SDK that abstracts away the gRPC calls to interact with the Flow blockchain.\
\
<https://github.com/Graffle/flow-c-sharp-graffle-sdk>

#### Create client:

```
var flowClientFactory = new FlowClientFactory(nodeName);
var flowClient = flowClientFactory.CreateFlowClient();
```

#### Get latest block:

```
var latestBlock = flowClient.GetLatestBlockAsync();
```

#### Get latest sealed block:

```
var latestBlock = await flowClient.GetLatestBlockAsync(true);
```

#### Search a block range for a specific event:

```
    var eventId = "A.c1e4f4f4c4257510.Market.MomentPurchased";
    ulong startBlock = 22037959;
    ulong endBlock = 22037961;
    var eventsResponse = await flowClient.GetEventsForHeightRangeAsync(eventId, startBlock, endBlock);
```

#### Execute script at block id:

```
    var latestBlockResponse = await this.flowClient.GetLatestBlockAsync(true);

    var helloWorldScript = @"
        pub fun main(): String {
            return ""Hello World""
        }               
    ";
    
    var scriptBytes = Encoding.ASCII.GetBytes(helloWorldScript);
    
    var scriptResponse = await flowClient.ExecuteScriptAtBlockIdAsync(latestBlockResponse.Id.HashToByteString(), scriptBytes, new List<FlowValueType>());
    var metaDataJson = Encoding.Default.GetString(scriptResponse.Value.ToByteArray());
    var result = StringType.FromJson(metaDataJson);
```

#### Execute script at block height:

```
    var latestBlockResponse = await this.flowClient.GetLatestBlockAsync(true);

    var helloWorldScript = @"
        pub fun main(): String {
            return ""Hello World""
        }               
    ";
    
    var scriptBytes = Encoding.ASCII.GetBytes(helloWorldScript);
    
    var scriptResponse = await flowClient.ExecuteScriptAtBlockIdAsync(latestBlockResponse.Height, scriptBytes, new List<FlowValueType>());
    var metaDataJson = Encoding.Default.GetString(scriptResponse.Value.ToByteArray());
    var result = StringType.FromJson(metaDataJson);
```

#### Get block at height

```
    var blockResponse = await flowClient.GetBlockByHeightAsync(blockHeight);
```

#### Get a transaction within a block

```
    var block = await flowClient.GetBlockByHeightAsync(blockHeight);
    var collectionId = block.CollectionGuarantees.FirstOrDefault().CollectionId;
    var collection = await flowClient.GetCollectionById(collectionId.HashToByteString());
    var transactionId = collection.TransactionIds.FirstOrDefault();
    var transactionResult = await flowClient.GetTransactionResult(transactionId.HashToByteString());
    var transaction = await flowClient.GetTransactionAsync(transactionId.HashToByteString());  
```

#### Get account at block height

```
    var account = await flowClient.GetAccountAsync(addressHex, blockHeight)
```

#### Get collection by Id

```
    var collection = await flowClient.GetCollectionById(collectionId.HashToByteString());
```

#### Create a new account

```
//example given using emulator account, load real account from flow.json for working with MainNet or TestNet
    var emulatorAccount = await flowClient.GetAccountFromConfigAsync("emulator-account");

    var emulatorAccountKey = emulatorAccount.Keys[0];

    var flowAccountKey = Flow.Entities.AccountKey.GenerateRandomEcdsaKey(SignatureAlgorithm.ECDSA_P256, HashAlgorithm.SHA3_256);
    var newFlowAccountKeys = new List<Flow.Entities.AccountKey> { flowAccountKey };

    var latestBlock = await flowClient.GetLatestBlockAsync();
    var emulatorAddress = new FlowAddress(emulatorAccount.Address);

    var transaction = AccountTransactions.CreateAccount(newFlowAccountKeys, emulatorAddress);

    transaction.Payer = emulatorAddress;
    transaction.ProposalKey = new FlowProposalKey
    {
        Address = emulatorAddress,
        KeyId = emulatorAccountKey.Index,
        SequenceNumber = emulatorAccountKey.SequenceNumber
    };
    transaction.ReferenceBlockId = latestBlock.Id;

    // sign and submit the transaction
    transaction = FlowTransaction.AddEnvelopeSignature(transaction, emulatorAddress, emulatorAccountKey.Index, emulatorAccountKey.Signer);

    var response = await flowClient.SendTransactionAsync(transaction);

    // wait for seal
    var sealedResponse = await flowClient.WaitForSealAsync(response);

    var createdEvent = sealedResponse.Events.FirstOrDefault(x => x.Type == "flow.AccountCreated");

    string addressHex = createdEvent.EventComposite.Data.FirstOrDefault().Value.Substring(2);

    var address = new FlowAddress(addressHex);

    var latestBlock2 = await flowClient.GetLatestBlockAsync();
    var account = await flowClient.GetAccountAsync(addressHex, latestBlock2.Height);

    account.Keys = FlowAccountKey.UpdateFlowAccountKeys(newFlowAccountKeys.Select(x => new FlowAccountKey(x)).ToList(), account.Keys.ToList());
```

#### Send transaction

```
    var emulatorAccount = await flowClient.GetAccountFromConfigAsync("emulator-account");
    var emulatorAddress = new FlowAddress(emulatorAccount.Address);
    var emulatorAccountKey = emulatorAccount.Keys[0];

    var latestBlock = await flowClient.GetLatestBlockAsync();
    var transaction = new FlowTransaction
    {
        Script = new FlowScript("transaction {}"),
        ReferenceBlockId = latestBlock.Id,
        Payer = emulatorAddress,
        ProposalKey = new FlowProposalKey
        {
            Address = emulatorAddress,
            KeyId = emulatorAccountKey.Index,
            SequenceNumber = emulatorAccountKey.SequenceNumber
        }
    };

    transaction = FlowTransaction.AddEnvelopeSignature(transaction, emulatorAddress, emulatorAccountKey.Index, emulatorAccountKey.Signer);

    var response = await flowClient.SendTransactionAsync(transaction);

    // wait for seal
    var sealedResponse = await flowClient.WaitForSealAsync(response);

```

####


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.graffle.io/graffle-docs/open-source/graffle-flow-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
