Ethereum Unity3D Boilerplate Questions

Good question and one I do not have a great answer to. The answer is, it depends on what you want to do with the random number. Nothing in software is every truly random.

If you want to randomly display objects in your gameā€™s worldspace you can get by with any random number generator. If you are drawing cards for a multiplayer game you want something not in the client (you could use a cloud function). If you are securing something or trying to generate secure keys you need a solution that cryptographically sound.

The SDK does not specifically offer this as there are other options already available.

For simple sudo randomness you can always use System.Random. However this is unsecure and not really random.

You may find references to RNGCryptoServiceProvider but this is obsolete.

BouncyCastle (used by Nethererum and Wallet Connect has a random number generator but there is some question about it being a software only solution. It is closer to random than plain System.Random.

.NET provides the RandomNumberGenerator. This is supposed to be cryptographically sound but is platform based. Implementations provided for this abstract class are marked with the UnsupportedOsPlatformsAttribute meaning it may not compile for some platforms.

Software only solutions are sudo random but not truly random. Truly random number generation depends on the introducing entropy which is usually provided by a hardware component.

Since Unity generates device specific builds you will need to explore how to implement secure random number generation for every build target you want to deploy to. iOS and Android both have good security.

You have sparked some curiosity in me to see what I else I can find for Unity on this topic.

Regards,

David

In Unity, we use the Random.Range(x,y) and Random.value methods which generate pseudorandom numbers, but my question wasnā€™t exactly that. Provable provides a service for generating a random number from a provably random source. I was wondering if Moralis also had something similar, but Iā€™ll rely on simple HTTP requests for this I suppose.

1 Like

Whatā€™s the way to send an array of bytes over to a Cloud Function? How will that array be treated in JS, as a regular array or a typed UInt8Array?

1 Like

Sorry for the diversion but can someone please take a look at Moralis Cloud Code and Typescript? I have received no responses or even indications about this.

1 Like

I would think serializing an deserializing a normal array using JSON.serialize should would. You could also convert the array to a Base63 string. I will try.

Sorry some has not gotten back to you, I will take a look.

Regards,

David

1 Like

@vivraan,

From your other post:

I am going to need to try to contact someone else about this.

1 Like

Iā€™m trying to use a Moralis Object to save a highscore and then return a list of highscores; Iā€™m having trouble getting the data to actually save though. I think it might be because the SessionToken is null inside of SaveAsyncā€¦ everything else seems to work - I am able to get the user, do blockchain transactions etc. Do you have any idea what may be causing the SessionToken to be null?

Hereā€™s my code:


public class MyScores : MoralisObject
{
    public string Name;
    public float Seconds;
}

async void SaveScore(float time)
    {
        var user = await MoralisInterface.GetUserAsync();
        var addr = user.authData["moralisEth"]["id"].ToString();
        var ens = MoralisInterface.GetClient().Web3Api.Resolve.ResolveAddress(addr);
        var score = MoralisInterface.GetClient().Create<MyScores>();
        score.Name = !string.IsNullOrEmpty(ens.Name) ? ens.Name : addr;
        score.Seconds = time;
        await score.SaveAsync();
        Debug.Log("SavedScore");
    }
1 Like

Mea Culpa, looks like I broke this with the last release. I pasted your code into the empty demo and had the same result. Looks like it is not session but ClassName that is not set.

I will open a Issue in GitHub and include this fix in the next release which should be in a couple of days.

This is the fix I am going to post. I think handling at this level instead of outside of the base class will make sure these are always populated properly.

Find Moralis / MoralisDotNet / Platform / MoralisObject.cs. Update the default constructor to:

public MoralisObject()
        {
            this.ClassName = this.GetType().Name;//  String.Empty;
            this.objectId = null; // String.Empty;
            this.createdAt = DateTime.Now;
            this.updatedAt = DateTime.Now;
            this.ACL = new MoralisAcl();
            this.IsDirty = false;
            this.SessionToken = string.Empty;
            this.ObjectService = null;
        }

Regards,

David

Thanks David that seems to have resolved the issue of saving my objects!
Iā€™m having another one now thoughā€¦
I am trying to query for the top 10 scores in that list using:

        var query = MoralisInterface.GetClient().Query<MyScores>()
            .OrderBy("Seconds")
            .Limit(10);
        var results = await query.FindAsync();

Based on the docs here (Queries - Moralis) I think this should work? In unity however Iā€™m getting an error thrown in MoralisService.BuildQueryString because itā€™s trying to serialize a ā€œwhereā€ parameter that wasnā€™t specified (tries to convert it to a string)?

I messed around trying to fix it by removing where the ā€œwhereā€ parameter gets set in MoralisQuery.BuildParameters which allowed the query to go through to the server, but I am still not getting any response

Another issue: I removed the public read right permissions in my scores table and set ā€œAuthenticatedā€ to read/write and when I try to query the scores i get a ā€œPermission denied, user needs to be authenticated.ā€ even though the user is authenticated.

In either case though, when there was an error, FindAsync never returns

1 Like

I will be adding another unity test for this one :slight_smile:

For now find Moralis / MoralisDotNet / Platform / Queries / MoralisQuery.cs.

Find the BuildParameters method. For the first conditional:

            if (Filters != null)
                result["where"] = JsonSerializer.Serialize(Filters);//PointerOrLocalIdEncoder.Instance.Encode(Filters, Services);
            else
                result["where"] = new object();

remove the else statement so the first conditional statement should now be:

            if (Filters != null)
                result["where"] = JsonSerializer.Serialize(Filters);//PointerOrLocalIdEncoder.Instance.Encode(Filters, Services);

Hope that helps,

David

Yup it partially fixes it; The query goes through but it still doesnā€™t return any rows of data from the server for some reason. Do you see anything wrong with that query?

No. I used it against a table in my DB and it returned all 6 rows (just the table was Hero and I ordered by Level).

Make sure names are the same case and the table exists and has rows. I cannot think of anything else that would cause your code to fail.

Figured it outā€¦ the save was setting the ACL as ā€œMaster Key Onlyā€ - I need to add Public Read permission to retrieve them in my game

1 Like

Whatā€™s the method of converting to a base64 in the SDK currently? Iā€™ll try a normal array of bytes.

1 Like

For C# or JS (this is a function in the language, not the SDK)?

1 Like

C# in this case.

In my use case, Iā€™ve encrypted the private key to a wallet as a Moralis Server Config var. The wrapping key is provided in the code and the initialisation vector is supplied by the client. Every time the requested Cloud Function is called, the PK is decrypted, the wallet is added, a transaction is created and signed, and then it is removed.

The IV is meant to be an array of bytes (byte[] in C# or UInt8Array in JS).

Btw can I use crypto.subtle in Moralis Cloud Code?

1 Like

I was able to pass in the array as an array. I had forgotten but internally the Moralis SDK serializes byte[] values as Base64 automatically since the Parse server expects this.

This C# code:

byte[] testArray = { 4, 92, 3, 42, 28, 59, 31, 13 };
IDictionary<string, object> pars = new Dictionary<string, object>();
pars.Add("arr1", testArray);

CloudFunctionResult cfResp = await moralis.Cloud.RunAsync<CloudFunctionResult>("myFunction", pars);

byte[] ba1 = JsonConvert.DeserializeObject<byte[]>(cfResp.a1) as byte[];

Calls the Cloud Function below with a byte[] and processes the result to a byte[].

Moralis.Cloud.define("myFunction", async (request) => {
    var a1 = request.params.arr1;
    var sar = [];
    atob(a1).split("").map(function(c) { sar.push(c.charCodeAt(0));});
    sar = sar.sort();
  	var resp = {a1: JSON.stringify(sar)}; 
  	return resp;
}, {
	fields : ['arr1']
});

and here is the result object:

    public class CloudFunctionResult
    {
        public string a1;
    }

Hope this helps,

David

1 Like

Hi @dgoodrich
Iā€™m getting this error while building WebGL build from unity 2021.2.5f. I followed instructions on Github and created a new project with importing the package.

Iā€™m familiar with atob() as it converts from base64 to a regular string, but Iā€™ll need to encode the resulting string then, since it will not be a printable string.

1 Like

Hi. Current stable version of Unity is 2020.3.27. However I will pull the version you indicated and give it a try. It may be a few hours before I get back on this ā€¦