Skip to content

Commit fa83ec3

Browse files
Serhii Yolkinenlight
authored andcommitted
Code cleanup (loomnetwork#37)
* Emit compiler error if scripting runtime is not set to 4.6 * Renamed "build" folder to ".build" to avoid it being imported by Unity * Cleanup and refactor IRpcClient and friends * Exposed more private stuff in Contract and DAppChainClient * Renamed ReSharper settings to match new folder name * Updated README * Fix member order
1 parent b0519c1 commit fa83ec3

24 files changed

+568
-443
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ corresponding methods in `Assets/authSample.cs`, these must be pressed in the co
5959
return the key/value it stored.
6060
4. You can press the `Call GetMsg` button to send a simple query to the `BluePrint` contract.
6161

62+
## Building the SDK
63+
64+
`BuildScripts` folder contains scripts for building loom-unity-sdk.unitypackage for Windows and macOS. Scripts use the `UNITY_PATH` environment variable to determine the Unity executable path, if it is set; alternatively, the path can be passed as an argument. As a fallback, standard Unity installation directory might be used.
65+
The package is built to `Assets\~NonVersioned\loom-unity-sdk.unitypackage`.
66+
6267
## Dependencies
6368

6469
For ease of use all necessary prebuilt dependencies are located in the `Assets/Plugins` directory in

UnityProject/Assets/LoomSDK/Source/Editor/CheckProject.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
using UnityEditor;
1+
#if !NET_4_6
2+
#error Loom SDK requires .NET 4.6. Please go to Build Settings -> Player Settings -> Configuration and set Scripting Runtime Version to .NET 4.6
3+
#endif
4+
5+
using UnityEditor;
26
using UnityEditor.Build;
37

48
namespace Loom.Client.Unity.Editor.Internal

UnityProject/Assets/LoomSDK/Source/Runtime/Contract.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public async Task CallAsync(string method, IMessage args)
6464
Method = method,
6565
Args = args.ToByteString()
6666
};
67-
var result = await this.client.QueryAsync<byte[]>(this.Address, query, this.Caller, VMType.Plugin);
67+
var result = await this.Client.QueryAsync<byte[]>(this.Address, query, this.Caller, VMType.Plugin);
6868
if (result != null)
6969
{
7070
T msg = new T();
@@ -97,7 +97,7 @@ protected override ChainEventArgs TransformChainEvent(RawChainEventArgs e) {
9797
/// <returns>The return value of the smart contract method.</returns>
9898
private async Task<T> CallAsync<T>(Transaction tx) where T : IMessage, new()
9999
{
100-
var result = await this.client.CommitTxAsync(tx);
100+
var result = await this.Client.CommitTxAsync(tx);
101101
if (result != null && result.DeliverTx.Data != null && result.DeliverTx.Data.Length != 0)
102102
{
103103
var resp = new Response();

UnityProject/Assets/LoomSDK/Source/Runtime/ContractBase.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ namespace Loom.Client {
1111
/// into and querying that contract.
1212
/// </summary>
1313
public abstract class ContractBase<TChainEvent> {
14-
protected readonly DAppChainClient client;
1514
protected event EventHandler<TChainEvent> eventReceived;
1615

16+
/// <summary>
17+
/// Client that writes to and reads from a Loom DAppChain.
18+
/// </summary>
19+
public DAppChainClient Client { get; }
20+
1721
/// <summary>
1822
/// Smart contract address.
1923
/// </summary>
@@ -32,7 +36,7 @@ public abstract class ContractBase<TChainEvent> {
3236
/// <param name="callerAddr">Address of the caller, generated from the public key of the transaction signer.</param>
3337
protected ContractBase(DAppChainClient client, Address contractAddr, Address callerAddr)
3438
{
35-
this.client = client;
39+
this.Client = client;
3640
this.Address = contractAddr;
3741
this.Caller = callerAddr;
3842
}
@@ -48,25 +52,21 @@ public event EventHandler<TChainEvent> EventReceived
4852
this.eventReceived += value;
4953
if (isFirstSub)
5054
{
51-
this.client.ChainEventReceived += this.NotifyContractEventReceived;
55+
this.Client.ChainEventReceived += NotifyContractEventReceived;
5256
}
5357
}
5458
remove
5559
{
5660
this.eventReceived -= value;
5761
if (this.eventReceived == null)
5862
{
59-
this.client.ChainEventReceived -= this.NotifyContractEventReceived;
63+
this.Client.ChainEventReceived -= NotifyContractEventReceived;
6064
}
6165
}
6266
}
6367

64-
protected void InvokeChainEvent(object sender, RawChainEventArgs e)
65-
{
66-
if (this.eventReceived != null)
67-
{
68-
this.eventReceived(this, TransformChainEvent(e));
69-
}
68+
protected void InvokeChainEvent(object sender, RawChainEventArgs e) {
69+
this.eventReceived?.Invoke(this, TransformChainEvent(e));
7070
}
7171

7272
protected abstract TChainEvent TransformChainEvent(RawChainEventArgs e);
@@ -87,7 +87,7 @@ protected virtual void NotifyContractEventReceived(object sender, RawChainEventA
8787
/// <returns>Nothing.</returns>
8888
internal async Task CallAsync(Transaction tx)
8989
{
90-
await this.client.CommitTxAsync(tx);
90+
await this.Client.CommitTxAsync(tx);
9191
}
9292

9393
internal Transaction CreateContractMethodCallTx(string hexData, VMType vmType) {

UnityProject/Assets/LoomSDK/Source/Runtime/CryptoUtils.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ public static byte[] RandomBytes(uint length)
3030
public static byte[] GeneratePrivateKey(byte[] privateKeySeed)
3131
{
3232
if (privateKeySeed == null)
33-
throw new ArgumentNullException("privateKeySeed");
33+
throw new ArgumentNullException(nameof(privateKeySeed));
3434

3535
if (privateKeySeed.Length != 32)
36-
throw new ArgumentException("Expected a 32-byte array", "privateKeySeed");
36+
throw new ArgumentException("Expected a 32-byte array", nameof(privateKeySeed));
3737

3838
byte[] publicKey32;
3939
byte[] privateKey64;
@@ -61,7 +61,7 @@ public static byte[] PublicKeyFromPrivateKey(byte[] privateKey)
6161
{
6262
if (privateKey.Length != 64)
6363
{
64-
throw new ArgumentException("Expected 64-byte array", "privateKey");
64+
throw new ArgumentException("Expected 64-byte array", nameof(privateKey));
6565
}
6666

6767
var publicKey = new byte[32];

UnityProject/Assets/LoomSDK/Source/Runtime/DAppChainClient.cs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ public class DAppChainClient : IDisposable
2121
{
2222
private const string LogTag = "Loom.DAppChainClient";
2323

24-
private Dictionary<EventHandler<RawChainEventArgs>, EventHandler<JsonRpcEventData>> eventSubs;
24+
private readonly Dictionary<EventHandler<RawChainEventArgs>, EventHandler<JsonRpcEventData>> eventSubs =
25+
new Dictionary<EventHandler<RawChainEventArgs>, EventHandler<JsonRpcEventData>>();
2526

2627
private IRpcClient writeClient;
2728
private IRpcClient readClient;
29+
private ILogger logger = NullLogger.Instance;
2830

2931
/// <summary>
3032
/// Middleware to apply when committing transactions.
@@ -34,13 +36,25 @@ public class DAppChainClient : IDisposable
3436
/// <summary>
3537
/// Logger to be used for logging, defaults to <see cref="NullLogger"/>.
3638
/// </summary>
37-
public ILogger Logger { get; set; }
39+
public ILogger Logger {
40+
get {
41+
return logger;
42+
}
43+
set {
44+
if (value == null)
45+
{
46+
value = NullLogger.Instance;
47+
}
48+
49+
this.logger = value;
50+
}
51+
}
3852

3953
/// <summary>
4054
/// Maximum number of times a tx should be resent after being rejected because of a bad nonce.
4155
/// Defaults to 5.
4256
/// </summary>
43-
public int NonceRetries { get; set; }
57+
public int NonceRetries { get; set; } = 5;
4458

4559
/// <summary>
4660
/// Events emitted by the DAppChain.
@@ -64,11 +78,8 @@ public event EventHandler<RawChainEventArgs> ChainEventReceived
6478
/// <param name="readClient">RPC client to use for querying DAppChain state.</param>
6579
public DAppChainClient(IRpcClient writeClient, IRpcClient readClient)
6680
{
67-
this.eventSubs = new Dictionary<EventHandler<RawChainEventArgs>, EventHandler<JsonRpcEventData>>();
6881
this.writeClient = writeClient;
6982
this.readClient = readClient;
70-
this.Logger = NullLogger.Instance;
71-
this.NonceRetries = 5;
7283
}
7384

7485
public void Dispose()
@@ -122,7 +133,6 @@ public async Task<Address> ResolveContractAddressAsync(string contractName)
122133
/// <exception cref="InvalidTxNonceException">Thrown if transaction is rejected due to a bad nonce after <see cref="NonceRetries"/> attempts.</exception>
123134
internal async Task<BroadcastTxResult> CommitTxAsync(IMessage tx)
124135
{
125-
BroadcastTxResult result = null;
126136
int badNonceCount = 0;
127137
do
128138
{
@@ -143,13 +153,9 @@ internal async Task<BroadcastTxResult> CommitTxAsync(IMessage tx)
143153
#else
144154
await Task.Delay(TimeSpan.FromSeconds(delay));
145155
#endif
146-
} while ((this.NonceRetries != 0) && (badNonceCount <= this.NonceRetries));
156+
} while (this.NonceRetries != 0 && badNonceCount <= this.NonceRetries);
147157

148-
if (badNonceCount > 0)
149-
{
150-
throw new InvalidTxNonceException(1, "sequence number does not match");
151-
}
152-
return result;
158+
throw new InvalidTxNonceException(1, "sequence number does not match");
153159
}
154160

155161
/// <summary>
@@ -260,13 +266,13 @@ private async void UnsubReadClient(EventHandler<RawChainEventArgs> handler)
260266
}
261267
}
262268

263-
private class NonceParams
269+
private struct NonceParams
264270
{
265271
[JsonProperty("key")]
266272
public string Key;
267273
}
268274

269-
private class ResolveParams
275+
private struct ResolveParams
270276
{
271277
[JsonProperty("name")]
272278
public string ContractName;

UnityProject/Assets/LoomSDK/Source/Runtime/EvmContract.cs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public EvmContract(DAppChainClient client, Address contractAddr, Address callerA
3333
this.topicToEventName = new Dictionary<string, string>();
3434
foreach (EventABI eventAbi in this.contractBuilder.ContractABI.Events)
3535
{
36-
this.topicToEventName.Add(eventAbi.Sha33Signature, eventAbi.Name);
36+
this.topicToEventName.Add("0x" + eventAbi.Sha33Signature, eventAbi.Name);
3737
}
3838
}
3939

@@ -380,13 +380,7 @@ public async Task<TReturn> StaticCallSimpleTypeOutputAsync<TInput, TReturn>(TInp
380380
protected override EvmChainEventArgs TransformChainEvent(RawChainEventArgs e)
381381
{
382382
if (e.Topics == null)
383-
throw new ArgumentNullException("topics");
384-
385-
for (int i = 0; i < e.Topics.Length; i++)
386-
{
387-
// Remove 0x
388-
e.Topics[i] = e.Topics[i].Substring(2);
389-
}
383+
throw new ArgumentNullException(nameof(e.Topics));
390384

391385
// First topic is the signature of event itself
392386
string eventName;
@@ -407,7 +401,7 @@ protected override EvmChainEventArgs TransformChainEvent(RawChainEventArgs e)
407401

408402
private async Task<byte[]> StaticCallAsyncByteArray(string callInput)
409403
{
410-
return await this.client.QueryAsync<byte[]>(this.Address, CryptoUtils.HexStringToBytes(callInput), this.Caller, Protobuf::VMType.Evm);
404+
return await this.Client.QueryAsync<byte[]>(this.Address, CryptoUtils.HexStringToBytes(callInput), this.Caller, Protobuf::VMType.Evm);
411405
}
412406

413407
private async Task StaticCallAsync(string callInput)
@@ -426,7 +420,7 @@ private async Task<TReturn> StaticCallAsync<TReturn>(string callInput, FunctionB
426420
private async Task<BroadcastTxResult> CallAsyncBrodcastTxResult(string callInput)
427421
{
428422
var tx = this.CreateContractMethodCallTx(callInput, Protobuf::VMType.Evm);
429-
return await this.client.CommitTxAsync(tx);
423+
return await this.Client.CommitTxAsync(tx);
430424
}
431425

432426
private async Task CallAsync(string callInput)
@@ -437,7 +431,7 @@ private async Task CallAsync(string callInput)
437431
private async Task<TReturn> CallAsync<TReturn>(string callInput, FunctionBuilderBase functionBuilder, Func<FunctionBuilderBase, string, TReturn> decodeFunc)
438432
{
439433
var tx = this.CreateContractMethodCallTx(callInput, Protobuf::VMType.Evm);
440-
var result = await this.client.CommitTxAsync(tx);
434+
var result = await this.Client.CommitTxAsync(tx);
441435
var validResult = result?.DeliverTx.Data != null && result.DeliverTx.Data.Length != 0;
442436
return validResult ? decodeFunc(functionBuilder, CryptoUtils.BytesToHexString(result.DeliverTx.Data)) : default(TReturn);
443437
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Loom.Client;
7+
using UnityEngine;
8+
9+
namespace Loom.Client
10+
{
11+
public interface ILogProducer {
12+
/// <summary>
13+
/// Logger to be used for logging, defaults to <see cref="NullLogger"/>.
14+
/// </summary>
15+
ILogger Logger { get; set; }
16+
}
17+
}

UnityProject/Assets/LoomSDK/Source/Runtime/ILogProducer.cs.meta

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using UnityEngine;
7+
8+
namespace Loom.Client.Internal
9+
{
10+
internal abstract class BaseRpcClient : IRpcClient, ILogProducer
11+
{
12+
private ILogger logger = NullLogger.Instance;
13+
private RpcConnectionState? lastConnectionState;
14+
15+
protected bool disposed = false;
16+
17+
/// <summary>
18+
/// Logger to be used for logging, defaults to <see cref="NullLogger"/>.
19+
/// </summary>
20+
public virtual ILogger Logger {
21+
get {
22+
return logger;
23+
}
24+
set {
25+
if (value == null)
26+
{
27+
value = NullLogger.Instance;
28+
}
29+
30+
this.logger = value;
31+
}
32+
}
33+
34+
public void Dispose()
35+
{
36+
Dispose(true);
37+
GC.SuppressFinalize(this);
38+
}
39+
40+
public virtual event RpcClientConnectionStateChangedHandler ConnectionStateChanged;
41+
public abstract RpcConnectionState ConnectionState { get; }
42+
public abstract Task<TResult> SendAsync<TResult, TArgs>(string method, TArgs args);
43+
public abstract Task DisconnectAsync();
44+
public abstract Task SubscribeAsync(EventHandler<JsonRpcEventData> handler);
45+
public abstract Task UnsubscribeAsync(EventHandler<JsonRpcEventData> handler);
46+
47+
protected abstract void Dispose(bool disposing);
48+
49+
protected void NotifyConnectionStateChanged()
50+
{
51+
RpcConnectionState state = ConnectionState;
52+
if (this.lastConnectionState != null && this.lastConnectionState == state)
53+
return;
54+
55+
this.lastConnectionState = state;
56+
ConnectionStateChanged?.Invoke(this, state);
57+
}
58+
59+
~BaseRpcClient()
60+
{
61+
Dispose(false);
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)