Skip to content

Commit

Permalink
Add view function examples
Browse files Browse the repository at this point in the history
  • Loading branch information
GhostWalker562 committed Oct 15, 2024
1 parent 4afac37 commit 13dcba9
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 17 deletions.
64 changes: 64 additions & 0 deletions Aptos.Examples/ComplexViewFunctionExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Aptos.Examples;

public class ComplexViewFunctionExample
{
[JsonConverter(typeof(CurrentEpochProposalCountsConverter))]
public class CurrentEpochProposalCounts(ulong successfulProposals, ulong failedProposals)
{
public ulong? SuccessfulProposals = successfulProposals;

public ulong? FailedProposals = failedProposals;
}

public class CurrentEpochProposalCountsConverter : JsonConverter<CurrentEpochProposalCounts>
{
public override bool CanWrite => false;

public override CurrentEpochProposalCounts? ReadJson(
JsonReader reader,
Type objectType,
CurrentEpochProposalCounts? existingValue,
bool hasExistingValue,
JsonSerializer serializer
)
{
// Load the result of the View function which would be ["100", "100"] since the return type is (u64,u64).
// We then deserialize the return value into a CurrentEpochProposalCounts.
var jArrayObject = JArray.Load(reader);
return new CurrentEpochProposalCounts(
ulong.Parse(jArrayObject[0].ToString()),
ulong.Parse(jArrayObject[0].ToString())
);
}

public override void WriteJson(
JsonWriter writer,
CurrentEpochProposalCounts? value,
JsonSerializer serializer
) => throw new NotImplementedException();
}

public static async Task Run()
{
var aptos = new AptosClient(new AptosConfig(Networks.Devnet));

// Complex typed view function - We will deserialize the return value into a custom class by using a JsonConverter.
// This is only recommended if the return type is complex and cannot be easily deserialized
// using the default deserializer (multiple return types).
var proposals = await aptos.View<CurrentEpochProposalCounts>(
new GenerateViewFunctionPayloadData(
function: "0x1::stake::get_current_epoch_proposal_counts",
functionArguments: [(ulong)0]
)
);

Console.WriteLine(
$"Successful Proposals: {proposals.SuccessfulProposals} and Failed Proposals: {proposals.FailedProposals}"
);
}
}
92 changes: 75 additions & 17 deletions Aptos.Examples/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ public class RunExample
{
private static readonly Func<Task>[] exampleArray =
{
ViewFunctionExample.Run,
ComplexViewFunctionExample.Run,
SimpleTransferKeylessExample.Run,
SimpleTransferEd25519Example.Run,
SimpleTransferSingleKeyExample.Run,
Expand All @@ -17,27 +19,73 @@ public class RunExample
PlaygroundExample.Run,
};

private const int ExamplesPerPage = 5;

public static async Task Main()
{
DisplayAsciiArt();
int selectedIndex = 0;

int currentPage = 0;
int totalPages = (int)Math.Ceiling(exampleArray.Length / (double)ExamplesPerPage);
string errorMessage = string.Empty;

while (true)
{
DisplayMenu(selectedIndex, errorMessage);
// Ensure the selectedIndex stays within the current page's bounds
selectedIndex = Math.Clamp(
selectedIndex,
currentPage * ExamplesPerPage,
Math.Min((currentPage + 1) * ExamplesPerPage - 1, exampleArray.Length - 1)
);

DisplayMenu(selectedIndex, currentPage, totalPages, errorMessage);

ConsoleKeyInfo keyInfo = Console.ReadKey(intercept: true);

if (keyInfo.Key == ConsoleKey.UpArrow)
{
selectedIndex = (selectedIndex == 0) ? exampleArray.Length - 1 : selectedIndex - 1;
if (selectedIndex == currentPage * ExamplesPerPage) // First item on the current page
{
// Move to the previous page and set the selected index to the last item on that page
currentPage = (currentPage == 0) ? totalPages - 1 : currentPage - 1;
selectedIndex = Math.Min(
(currentPage + 1) * ExamplesPerPage - 1,
exampleArray.Length - 1
); // Wrap to last item of the previous page
}
else
{
selectedIndex--; // Move up within the current page
}
errorMessage = string.Empty; // Clear error on valid navigation
}
else if (keyInfo.Key == ConsoleKey.DownArrow)
{
selectedIndex = (selectedIndex == exampleArray.Length - 1) ? 0 : selectedIndex + 1;
if (
selectedIndex
== Math.Min((currentPage + 1) * ExamplesPerPage - 1, exampleArray.Length - 1)
) // Last item on the current page
{
// Move to the next page and set the selected index to the first item on that page
currentPage = (currentPage == totalPages - 1) ? 0 : currentPage + 1;
selectedIndex = currentPage * ExamplesPerPage; // Wrap to the first item of the next page
}
else
{
selectedIndex++; // Move down within the current page
}
errorMessage = string.Empty; // Clear error on valid navigation
}
else if (keyInfo.Key == ConsoleKey.LeftArrow)
{
currentPage = (currentPage == 0) ? totalPages - 1 : currentPage - 1;
selectedIndex = currentPage * ExamplesPerPage;
errorMessage = string.Empty; // Clear error on valid navigation
}
else if (keyInfo.Key == ConsoleKey.RightArrow)
{
currentPage = (currentPage == totalPages - 1) ? 0 : currentPage + 1;
selectedIndex = currentPage * ExamplesPerPage;
errorMessage = string.Empty; // Clear error on valid navigation
}
else if (keyInfo.Key == ConsoleKey.Enter)
Expand All @@ -52,14 +100,12 @@ public static async Task Main()
}
else if (char.IsDigit(keyInfo.KeyChar))
{
// Check if the typed number is valid and within the array range
if (
int.TryParse(keyInfo.KeyChar.ToString(), out int inputIndex)
&& inputIndex > 0
&& inputIndex <= exampleArray.Length
)
int digit = int.Parse(keyInfo.KeyChar.ToString());
int exampleIndex = currentPage * ExamplesPerPage + (digit - 1);

if (digit > 0 && exampleIndex < exampleArray.Length)
{
var selectedExample = exampleArray[inputIndex - 1];
var selectedExample = exampleArray[exampleIndex];
Console.WriteLine(
$"\nThe {selectedExample.Method.DeclaringType.Name} example was selected...\n"
);
Expand All @@ -80,33 +126,46 @@ public static async Task Main()
}
}

private static void DisplayMenu(int selectedIndex, string errorMessage)
private static void DisplayMenu(
int selectedIndex,
int currentPage,
int totalPages,
string errorMessage
)
{
Console.Clear();
DisplayAsciiArt();

Console.WriteLine(
"Use arrow keys to navigate and press Enter or type a number to choose an example:"
"Use arrow keys to navigate, press Enter to choose an example, and Left/Right to switch pages."
);
for (int i = 0; i < exampleArray.Length; i++)

int start = currentPage * ExamplesPerPage;
int end = Math.Min(start + ExamplesPerPage, exampleArray.Length);

for (int i = start; i < end; i++)
{
var name = Regex.Replace(
exampleArray[i].Method.DeclaringType?.Name,
"(?<!^)([A-Z])",
" $1"
);
int displayNumber = i - (currentPage * ExamplesPerPage) + 1; // Reset number per page

if (i == selectedIndex)
{
Console.ForegroundColor = ConsoleColor.Yellow; // Highlight the selected option
Console.WriteLine($"> {i + 1}. {name}");
Console.WriteLine($"> {displayNumber}. {name}");
Console.ResetColor();
}
else
{
Console.WriteLine($" {i + 1}. {name}");
Console.WriteLine($" {displayNumber}. {name}");
}
}

Console.WriteLine($"\nPage {currentPage + 1}/{totalPages}");

// Show error message if any
if (!string.IsNullOrEmpty(errorMessage))
{
Expand All @@ -118,7 +177,6 @@ private static void DisplayMenu(int selectedIndex, string errorMessage)

private static void DisplayAsciiArt()
{
// Color codes for fun output
string cyan = "\u001b[36m";
string yellow = "\u001b[33m";
string reset = "\u001b[0m";
Expand Down
46 changes: 46 additions & 0 deletions Aptos.Examples/ViewFunctionExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Aptos.Examples;

public class ViewFunctionExample
{
public class Option<T>(List<T> vec)
{
[JsonProperty("vec")]
public List<T> Vec = vec;
}

public static async Task Run()
{
var aptos = new AptosClient(new AptosConfig(Networks.Devnet));

// Regular view function
var values = await aptos.View(
new GenerateViewFunctionPayloadData(
function: "0x1::coin::name",
functionArguments: [],
typeArguments: ["0x1::aptos_coin::AptosCoin"]
)
);
// Returns an array of return values. In this array, we will get "["Aptos Coin]"
Console.WriteLine($"Coin name: {JsonConvert.SerializeObject(values)}");

// Typed view function - If you know the type of the return values, you can pass
// the type arguments to the view function to get the correct
// return values. You can create your own deserializable values
// to pass into this function. Its important to make sure that
// the return type is a List.
var typedValues = await aptos.View<List<Option<String>>>(
new GenerateViewFunctionPayloadData(
function: "0x1::coin::supply",
functionArguments: [],
typeArguments: ["0x1::aptos_coin::AptosCoin"]
)
);
// Returns an array of return values. In this array, we will get "[{"vec":["18447254572092493002"]}]"
Console.WriteLine($"Coin supply: {JsonConvert.SerializeObject(typedValues)}");
}
}
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,30 @@ var pendingTransaction = client.Transaction.SignAndSubmitTransaction(account, tr
var committedTransaction = await client.Transaction.WaitForTransaction(pendingTransaction);
```

### Smart Contract View Functions

Call view functions to query smart contracts.

```csharp
using Aptos;

// 1. Initialize the Aptos client
var config = new AptosConfig(Networks.Mainnet);
var client = new AptosClient(config);

// 2. Call a view function
var result = await client.Contract.View(
new GenerateViewFunctionPayloadData(
function: "0x1::coin::name",
functionArguments: [],
typeArguments: ["0x1::aptos_coin::AptosCoin"]
)
);

// 3. Parse the return values
Console.WriteLine(result[0]);
```

## Installation

The SDK is published onto [NuGet](https://www.nuget.org/packages/Aptos/) where you can install it using the following command:
Expand Down

0 comments on commit 13dcba9

Please sign in to comment.