You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
8.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using ChainSafe.Gaming;
using ChainSafe.Gaming.Evm.Contracts.BuiltIn;
using ChainSafe.Gaming.Evm.Contracts.Extensions;
using ChainSafe.Gaming.MultiCall;
using ChainSafe.Gaming.UnityPackage;
using Nethereum.ABI.FunctionEncoding.Attributes;
using Nethereum.Contracts.QueryHandlers.MultiCall;
using Nethereum.Hex.HexConvertors.Extensions;
using Nethereum.RPC.Eth.DTOs;
using Newtonsoft.Json;
using Scripts.EVM.Token;
using UnityEngine;
public class EvmSample : MonoBehaviour, ISample
{
#region Fields
[field: SerializeField] public string Title { get; private set; }
[field: SerializeField, TextArea] public string Description { get; private set; }
public Type[] DependentServiceTypes => Array.Empty<Type>();
[Header("Change the fields below for testing purposes")]
#region Contract Send
[Header("Contract Send")]
[SerializeField] private string methodSend = "addTotal";
[SerializeField] private int increaseAmountSend = 1;
#endregion
#region Contract Call
[Header("Contract Call")]
[SerializeField] private string methodCall = "myTotal";
#endregion
#region Get Send Array
[Header("Array Calls")]
[SerializeField] private string methodArrayGet = "getStore";
[SerializeField] private string methodArraySend = "setStore";
[SerializeField]
private string[] stringArraySend =
{
"0xFb3aECf08940785D4fB3Ad87cDC6e1Ceb20e9aac",
"0x92d4040e4f3591e60644aaa483821d1bd87001e3"
};
#endregion
#region Sign Verify Sha3
[Header("Sign Verify SHA3 calls")]
[SerializeField] private string messageSign = "The right man in the wrong place can make all the difference in the world.";
[SerializeField] private string messageSignVerify = "A man chooses, a slave obeys.";
[SerializeField] private string messageSha = "Its dangerous to go alone, take this!";
#endregion
#region Send Transaction
[Header("Send Transaction Call")]
[SerializeField] private string toAddress = "0xdD4c825203f97984e7867F11eeCc813A036089D1";
[SerializeField] private string value = "12300000000000000";
#endregion
#region Registered Contract
[Header("Registered Contract Call")]
[SerializeField] private string registeredContractName = "CsTestErc20";
#endregion
#region ECDSA
[Header("ECDSA Calls")]
[SerializeField] private string ecdsaKey = "0x78dae1a22c7507a4ed30c06172e7614eb168d3546c13856340771e63ad3c0081";
[SerializeField] private string ecdsaMessage = "This is a test message";
[SerializeField] private string transactionHash = "0x123456789";
[SerializeField] private string chainId = "11155111";
#endregion
#region Multi Call
[Header("MutliCall")]
[SerializeField] private string Erc20Account = "0xd25b827D92b0fd656A1c829933e9b0b836d5C3e2";
#endregion
#region EventData
/// <summary>
/// Class for the event data that we're calling, this must match the solidity event i.e. event AmountIncreased(address indexed wallet, uint256 amount);
/// </summary>
[Event("AmountIncreased")]
private class AmountIncreasedEvent : IEventDTO
{
[Parameter("address", "wallet", 1, true)]
public string wallet { get; set; }
[Parameter("uint256", "amount", 2, false)]
public BigInteger amount { get; set; }
}
private string eventContract = "0x9832B82746a4316E9E3A5e6c7ea02451bdAC4546";
#endregion
#endregion
/// <summary>
/// Calls values from a contract
/// </summary>
public async Task<string> ContractCall()
{
object[] args =
{
Web3Unity.Instance.PublicAddress
};
var response = await Web3Unity.Instance.ContractCall(methodCall, ABI.ArrayTotal, ChainSafeContracts.ArrayTotal, args);
return BuildToString(response);
}
/// <summary>
/// Sends values to a contract
/// </summary>
public async Task<string> ContractSend()
{
object[] args =
{
increaseAmountSend
};
var response = await Web3Unity.Instance.ContractSend(methodSend, ABI.ArrayTotal, ChainSafeContracts.ArrayTotal, args);
return BuildToString(response);
}
/// <summary>
/// Gets the current block number
/// </summary>
public async Task<string> GetBlockNumber()
{
var blockNumber = await Web3Unity.Instance.GetBlockNumber();
return blockNumber.ToString();
}
/// <summary>
/// Gets the gas limit for a specific function
/// </summary>
public async Task<string> GetGasLimit()
{
object[] args =
{
increaseAmountSend
};
var gasLimit = await Web3Unity.Instance.GetGasLimit(ABI.ArrayTotal, ChainSafeContracts.ArrayTotal, methodSend, args);
return gasLimit.ToString();
}
/// <summary>
/// Gets the current gas price
/// </summary>
public async Task<string> GetGasPrice()
{
var gasPrice = await Web3Unity.Instance.GetGasPrice();
return gasPrice.ToString();
}
/// <summary>
/// Sends a transaction
/// </summary>
public async Task<string> SendTransaction()
{
var hash = await Web3Unity.Instance.SendTransaction(toAddress, BigInteger.Parse(value));
return hash;
}
/// <summary>
/// Signs a message, the result is specific to each user
/// </summary>
public async Task<string> SignMessage()
{
var signHash = await Web3Unity.Instance.SignMessage(messageSign);
return signHash;
}
/// <summary>
/// Gets events data from a transaction
/// </summary>
public async Task<string> EventTxData()
{
// Contract write
var amount = 1;
object[] args =
{
amount
};
var contract = Web3Unity.Web3.ContractBuilder.Build(ABI.ArrayTotal, eventContract);
var data = await contract.SendWithReceipt("addTotal", args);
// Quick pause to deal with chain congestion
await new WaitForSeconds(2);
// Event data from receipt
var logs = data.receipt.Logs.Select(jToken => JsonConvert.DeserializeObject<FilterLog>(jToken.ToString()));
var eventAbi = EventExtensions.GetEventABI<AmountIncreasedEvent>();
var eventLogs = logs
.Select(log => eventAbi.DecodeEvent<AmountIncreasedEvent>(log))
.Where(l => l != null).ToArray();
if (!eventLogs.Any())
{
Debug.Log("No event data");
}
else
{
Debug.Log("Event data found");
foreach (var eventLog in eventLogs)
{
var eventData = eventLog.Event;
Debug.Log($"Wallet from event data: {eventData.wallet}");
Debug.Log($"Amount from event data: {eventData.amount}");
}
}
return $"{nameof(EventTxData)} executed.";
}
/// <summary>
/// Makes multiple calls
/// </summary>
public async Task<string> MultiCall()
{
var erc20Contract = Web3Unity.Web3.ContractBuilder.Build(ABI.Erc20, ChainSafeContracts.Erc20);
var erc20BalanceOfCalldata = erc20Contract.Calldata(EthMethods.BalanceOf, new object[]
{
Erc20Account
});
var erc20TotalSupplyCalldata = erc20Contract.Calldata(EthMethods.TotalSupply, new object[]
{
});
var calls = new[]
{
new Call3Value()
{
Target = ChainSafeContracts.Erc20,
AllowFailure = true,
CallData = erc20BalanceOfCalldata.HexToByteArray(),
},
new Call3Value()
{
Target = ChainSafeContracts.Erc20,
AllowFailure = true,
CallData = erc20TotalSupplyCalldata.HexToByteArray(),
}
};
var multicallResultResponse = await Web3Unity.Web3.MultiCall().MultiCallAsync(calls);
Debug.Log(multicallResultResponse);
if (multicallResultResponse[0] != null && multicallResultResponse[0].Success)
{
var decodedBalanceOf = erc20Contract.Decode(EthMethods.BalanceOf, multicallResultResponse[0].ReturnData.ToHex());
Debug.Log($"decodedBalanceOf {((BigInteger)decodedBalanceOf[0]).ToString()}");
}
if (multicallResultResponse[1] != null && multicallResultResponse[1].Success)
{
var decodedTotalSupply = erc20Contract.Decode(EthMethods.TotalSupply, multicallResultResponse[1].ReturnData.ToHex());
Debug.Log($"decodedTotalSupply {((BigInteger)decodedTotalSupply[0]).ToString()}");
}
return $"{nameof(MultiCall)} executed.";
}
private static string BuildToString(IEnumerable<object> dynamicResponse)
{
return string.Join(",\n", dynamicResponse.Select(o => o.ToString()));
}
}