-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathStarknetInterop.cs
More file actions
235 lines (195 loc) · 8.65 KB
/
StarknetInterop.cs
File metadata and controls
235 lines (195 loc) · 8.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using AOT;
using bottlenoselabs.C2CS.Runtime;
using Newtonsoft.Json;
using Debug = UnityEngine.Debug;
using dojo_bindings;
using System.Text.RegularExpressions;
namespace Dojo.Starknet
{
public class StarknetInterop
{
[DllImport("__Internal")]
public static extern IntPtr NewProvider(CString nodeUrl);
[DllImport("__Internal")]
public static extern IntPtr NewAccount(IntPtr provider, CString privateKey, CString address, Action<IntPtr> cb);
public class NewAccountHelper
{
public static TaskCompletionSource<IntPtr> Tcs;
[MonoPInvokeCallback(typeof(Action<IntPtr>))]
public static void Callback(IntPtr result)
{
Tcs.SetResult(result);
}
}
public static Task<IntPtr> NewAccountAsync(IntPtr provider, SigningKey privateKey, FieldElement address)
{
NewAccountHelper.Tcs = new TaskCompletionSource<IntPtr>();
NewAccount(provider, new CString(privateKey.Inner.Hex()), new CString(address.Hex()), NewAccountHelper.Callback);
return NewAccountHelper.Tcs.Task;
}
[DllImport("__Internal")]
public static extern string AccountAddress(IntPtr account);
[DllImport("__Internal")]
public static extern string AccountChainId(IntPtr account);
[DllImport("__Internal")]
public static extern void AccountExecuteRaw(IntPtr account, CString calls, Action<string> cb);
public class AccountExecuteRawHelper
{
public static TaskCompletionSource<FieldElement> Tcs;
[MonoPInvokeCallback(typeof(Action<string>))]
public static void Callback(string result)
{
try
{
var message = JsonConvert.DeserializeObject<CallbackMessage>(result);
if (message.Success)
Tcs.SetResult(new FieldElement(message.Result));
else
Tcs.SetException(new Exception(message.Error));
}
catch (Exception ex)
{
Tcs.SetException(ex);
}
}
}
private class CallbackMessage
{
public bool Success { get; set; }
public string Result { get; set; }
public string Error { get; set; }
}
struct SerializedCall
{
public SerializedCall(FieldElement to, string selector, FieldElement[] calldata)
{
this.to = to.Hex();
this.selector = selector;
this.calldata = calldata.Select(f => f.Hex()).ToArray();
}
// hex string of address
public string to;
// the unhashed selector
public string selector;
// array of hex strings
public string[] calldata;
}
class SerializedBlockId
{
public static object Serialize(dojo.BlockId blockId)
{
return blockId.tag switch
{
dojo.BlockId_Tag.Hash => new BlockIdHash { Hash = new FieldElement(blockId.hash).Hex() },
dojo.BlockId_Tag.Number => new BlockIdNumber { Number = blockId.number.ToString() },
dojo.BlockId_Tag.BlockTag_ => new BlockIdTag
{
BlockTag = blockId.block_tag switch
{
dojo.BlockTag.Latest => "Latest",
dojo.BlockTag.Pending => "Pending",
_ => throw new Exception("Unknown block tag")
}
},
_ => throw new Exception("Unknown block id type")
};
}
public struct BlockIdHash
{
public string Hash;
}
public struct BlockIdNumber
{
public string Number;
}
public struct BlockIdTag
{
public string BlockTag;
}
}
public static Task<FieldElement> AccountExecuteRawAsync(IntPtr account, dojo.Call[] calls)
{
AccountExecuteRawHelper.Tcs = new TaskCompletionSource<FieldElement>();
AccountExecuteRaw(account, new CString(JsonConvert.SerializeObject(calls.Select(call => new SerializedCall(new FieldElement(call.to), call.selector, call.calldata.ToArray().Select(f => new FieldElement(f)).ToArray())).ToArray())), AccountExecuteRawHelper.Callback);
return AccountExecuteRawHelper.Tcs.Task;
}
[DllImport("__Internal")]
public static extern void AccountDeployBurner(IntPtr account, CString privateKey, Action<IntPtr> cb);
public class AccountDeployBurnerHelper
{
public static TaskCompletionSource<IntPtr> Tcs;
[MonoPInvokeCallback(typeof(Action<IntPtr>))]
public static void Callback(IntPtr result)
{
Tcs.SetResult(result);
}
}
public static Task<IntPtr> AccountDeployBurnerAsync(IntPtr account, SigningKey signingKey)
{
AccountDeployBurnerHelper.Tcs = new TaskCompletionSource<IntPtr>();
AccountDeployBurner(account, new CString(signingKey.Inner.Hex()), AccountDeployBurnerHelper.Callback);
return AccountDeployBurnerHelper.Tcs.Task;
}
[DllImport("__Internal")]
public static extern void Call(IntPtr provider, CString call, CString blockId, Action<string> cb);
public class CallHelper
{
public static TaskCompletionSource<FieldElement[]> Tcs;
[MonoPInvokeCallback(typeof(Action<FieldElement[]>))]
public static void Callback(string result)
{
Tcs.SetResult(JsonConvert.DeserializeObject<string[]>(result).Select(f => new FieldElement(f)).ToArray());
}
}
public static Task<FieldElement[]> CallAsync(IntPtr provider, dojo.Call call, dojo.BlockId blockId)
{
WaitForTransactionHelper.Tcs = new TaskCompletionSource<bool>();
var serializedCall = new SerializedCall(new FieldElement(call.to), call.selector, call.calldata.ToArray().Select(f => new FieldElement(f)).ToArray());
object serializedBlockId = SerializedBlockId.Serialize(blockId);
Call(provider, new CString(JsonConvert.SerializeObject(serializedCall)), new CString(JsonConvert.SerializeObject(serializedBlockId)), CallHelper.Callback);
return CallHelper.Tcs.Task;
}
[DllImport("__Internal")]
public static extern void WaitForTransaction(IntPtr provider, CString transactionHash, Action<bool> cb);
public class WaitForTransactionHelper
{
public static TaskCompletionSource<bool> Tcs;
[MonoPInvokeCallback(typeof(Action<bool>))]
public static void Callback(bool result)
{
Tcs.SetResult(result);
}
}
public static Task<bool> WaitForTransactionAsync(IntPtr provider, FieldElement transactionHash)
{
WaitForTransactionHelper.Tcs = new TaskCompletionSource<bool>();
WaitForTransaction(provider, new CString(transactionHash.Hex()), WaitForTransactionHelper.Callback);
return WaitForTransactionHelper.Tcs.Task;
}
[DllImport("__Internal")]
public static extern string NewSigningKey();
[DllImport("__Internal")]
public static extern string Sign(CString privateKey, CString hash);
[DllImport("__Internal")]
public static extern string NewVerifyingKey(CString privateKey);
[DllImport("__Internal")]
public static extern bool Verify(CString publicKey, CString hash, CString r, CString s);
[DllImport("__Internal")]
private static extern string SerializeByteArray(CString byteArray);
public static FieldElement[] SerializeByteArray(string byteArray)
{
return JsonConvert.DeserializeObject<string[]>(SerializeByteArray(new CString(byteArray))).Select(f => new FieldElement(f)).ToArray();
}
[DllImport("__Internal")]
private static extern string DeserializeByteArray(CString felts);
public static string DeserializeByteArray(FieldElement[] felts)
{
return DeserializeByteArray(new CString(JsonConvert.SerializeObject(felts.Select(f => f.Hex()).ToArray())));
}
}
}