Skip to content

Commit 270b610

Browse files
✨ Add Solflare deeplink wallet implementation (#192)
1 parent 07f11e2 commit 270b610

15 files changed

+233
-42
lines changed

Runtime/Plugins/Web3AuthSDK/Web3Auth.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,20 @@ public void setOptions(Web3AuthOptions web3AuthOptions)
9898
if (this.web3AuthOptions.loginConfig != null)
9999
this.initParams["loginConfig"] = JsonConvert.SerializeObject(this.web3AuthOptions.loginConfig);
100100

101-
this.initParams["network"] = network.ToString().ToLower();
101+
this.initParams["network"] = web3AuthOptions.network.ToString().ToLower();
102102

103103
}
104104

105105
private void onDeepLinkActivated(string url)
106106
{
107-
this.setResultUrl(new Uri(url));
107+
try
108+
{
109+
setResultUrl(new Uri(url));
110+
}
111+
catch (Exception e)
112+
{
113+
Debug.LogWarning(e.Message);
114+
}
108115
}
109116

110117
#if UNITY_STANDALONE || UNITY_EDITOR
File renamed without changes.

Runtime/codebase/PhantomWallet/PhantomDeepLink.cs renamed to Runtime/codebase/DeepLinkWallets/PhantomDeepLink.cs

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class PhantomDeepLink: WalletBase
2626
private const string PhantomEncryptionPubKeyPrefEntry = "phantom-pk-encryption";
2727
private const string PhantomPublicKeyPrefEntry = "phantom-pk-session";
2828

29-
private readonly PhantomWalletOptions _phantomWalletOptions;
29+
private readonly PhantomWalletOptions _deepLinksWalletOptions;
3030

3131
private static Account _tmpPhantomConnectionAccount = new();
3232
private static byte[] PhantomConnectionAccountPrivateKey
@@ -42,11 +42,11 @@ private static byte[] PhantomConnectionAccountPrivateKey
4242
private TaskCompletionSource<byte[]> _signedMessageTaskCompletionSource;
4343

4444
public PhantomDeepLink(
45-
PhantomWalletOptions phantomWalletOptions,
45+
PhantomWalletOptions deepLinksWalletOptions,
4646
RpcCluster rpcCluster = RpcCluster.DevNet, string customRpcUri = null, string customStreamingRpcUri = null, bool autoConnectOnStartup = false)
4747
: base(rpcCluster, customRpcUri, customStreamingRpcUri, autoConnectOnStartup)
4848
{
49-
_phantomWalletOptions = phantomWalletOptions;
49+
_deepLinksWalletOptions = deepLinksWalletOptions;
5050
Application.deepLinkActivated += OnDeepLinkActivated;
5151
if (!string.IsNullOrEmpty(Application.absoluteURL))
5252
OnDeepLinkActivated(Application.absoluteURL);
@@ -55,7 +55,7 @@ public PhantomDeepLink(
5555
protected override Task<Account> _Login(string password = null)
5656
{
5757
var pk = PlayerPrefs.GetString(PhantomPublicKeyPrefEntry, null);
58-
if (pk != null)
58+
if (!string.IsNullOrEmpty(pk))
5959
{
6060
try
6161
{
@@ -75,9 +75,10 @@ protected override Task<Account> _Login(string password = null)
7575

7676
public override void Logout()
7777
{
78+
StartDisconnect();
7879
DestroySessionInfo();
79-
base.Logout();
8080
Application.deepLinkActivated -= OnDeepLinkActivated;
81+
base.Logout();
8182
}
8283

8384
protected override Task<Transaction> _SignTransaction(Transaction transaction)
@@ -120,14 +121,31 @@ private RpcCluster GetCluster()
120121
private void StartLogin()
121122
{
122123
var url = Utils.CreateLoginDeepLink(
123-
redirectScheme: _phantomWalletOptions.deeplinkUrlScheme,
124-
metadataUrl: _phantomWalletOptions.appMetaDataUrl,
125-
apiVersion: _phantomWalletOptions.phantomApiVersion,
124+
baseUrl: _deepLinksWalletOptions.BaseUrl,
125+
redirectScheme: _deepLinksWalletOptions.DeeplinkUrlScheme,
126+
metadataUrl: _deepLinksWalletOptions.AppMetaDataUrl,
127+
apiVersion: _deepLinksWalletOptions.ApiVersion,
126128
connectionPublicKey: Encoders.Base58.EncodeData(PhantomConnectionAccountPublicKey),
127129
cluster: GetCluster()
128130
);
129131
Application.OpenURL(url);
130132
}
133+
134+
private void StartDisconnect()
135+
{
136+
var url = Utils.CreateDisconnectDeepLink(
137+
phantomEncryptionPubKey: _phantomEncryptionPubKey,
138+
connectionPublicKey: Encoders.Base58.EncodeData(PhantomConnectionAccountPublicKey),
139+
phantomConnectionAccountPrivateKey: PhantomConnectionAccountPrivateKey,
140+
baseUrl: _deepLinksWalletOptions.BaseUrl,
141+
redirectScheme: _deepLinksWalletOptions.DeeplinkUrlScheme,
142+
apiVersion: _deepLinksWalletOptions.ApiVersion,
143+
sessionId: _sessionId,
144+
cluster: GetCluster()
145+
146+
);
147+
Application.OpenURL(url);
148+
}
131149

132150
private void StartSignTransaction(Transaction transaction)
133151
{
@@ -136,8 +154,9 @@ private void StartSignTransaction(Transaction transaction)
136154
phantomEncryptionPubKey: _phantomEncryptionPubKey,
137155
connectionPublicKey: Encoders.Base58.EncodeData(PhantomConnectionAccountPublicKey),
138156
phantomConnectionAccountPrivateKey: PhantomConnectionAccountPrivateKey,
139-
redirectScheme: _phantomWalletOptions.deeplinkUrlScheme,
140-
apiVersion: _phantomWalletOptions.phantomApiVersion,
157+
baseUrl: _deepLinksWalletOptions.BaseUrl,
158+
redirectScheme: _deepLinksWalletOptions.DeeplinkUrlScheme,
159+
apiVersion: _deepLinksWalletOptions.ApiVersion,
141160
sessionId: _sessionId,
142161
cluster: GetCluster()
143162

@@ -152,8 +171,9 @@ private void StartSignMessage(byte[] message)
152171
phantomEncryptionPubKey: _phantomEncryptionPubKey,
153172
connectionPublicKey: Encoders.Base58.EncodeData(PhantomConnectionAccountPublicKey),
154173
phantomConnectionAccountPrivateKey: PhantomConnectionAccountPrivateKey,
155-
redirectScheme: _phantomWalletOptions.deeplinkUrlScheme,
156-
apiVersion: _phantomWalletOptions.phantomApiVersion,
174+
baseUrl: _deepLinksWalletOptions.BaseUrl,
175+
redirectScheme: _deepLinksWalletOptions.DeeplinkUrlScheme,
176+
apiVersion: _deepLinksWalletOptions.ApiVersion,
157177
sessionId: _sessionId,
158178
cluster: GetCluster()
159179

@@ -164,42 +184,46 @@ private void StartSignMessage(byte[] message)
164184
#endregion
165185

166186
#region Callbacks
167-
187+
168188
private void OnDeepLinkActivated(string url)
169189
{
170-
if (url.Contains("transactionSigned"))
190+
if (url.ToLower().Contains("transactionsigned"))
171191
{
172192
ParseSuccessfullySignedTransaction(url);
173193
}
174-
else if(url.Contains("onPhantomConnected"))
194+
else if(url.ToLower().Contains("onphantomconnected"))
175195
{
176196
ParseConnectionSuccessful(url);
177197
}
178-
else if(url.Contains("messageSigned"))
198+
else if(url.ToLower().Contains("messagesigned"))
179199
{
180200
ParseSuccessfullySignedMessage(url);
181201
}
202+
else if(url.ToLower().Contains("disconnect"))
203+
{
204+
Debug.LogError("on disconnect");
205+
DestroySessionInfo();
206+
}
182207
}
183208

184209
private void ParseConnectionSuccessful(string url)
185210
{
186211
var result = ParseQueryString(url);
187-
_phantomEncryptionPubKey = Encoders.Base58.DecodeData(result["phantom_encryption_public_key"]);
212+
_phantomEncryptionPubKey = Encoders.Base58.DecodeData(result[$"{_deepLinksWalletOptions.WalletName}_encryption_public_key"]);
188213
result.TryGetValue("nonce", out var phantomNonce);
189214
result.TryGetValue("data", out var data);
190215
result.TryGetValue("errorMessage", out var errorMessage);
191216
if (!string.IsNullOrEmpty(errorMessage))
192217
{
193-
Debug.LogError($"Deeplink error: {errorMessage}");
194-
_loginTaskCompletionSource.SetResult(null);
218+
_loginTaskCompletionSource?.TrySetResult(null);
195219
return;
196220
}
197221
if (string.IsNullOrEmpty(data))
198222
{
199-
Debug.LogError("Phantom connect canceled.");
200-
_loginTaskCompletionSource.SetResult(null);
223+
_loginTaskCompletionSource?.TrySetResult(null);
201224
return;
202225
}
226+
data = data.Replace("#", "");
203227
var k = MontgomeryCurve25519.KeyExchange(_phantomEncryptionPubKey, PhantomConnectionAccountPrivateKey);
204228
var unencryptedMessage = XSalsa20Poly1305.TryDecrypt(
205229
Encoders.Base58.DecodeData(data), k, Encoders.Base58.DecodeData(phantomNonce));
@@ -210,13 +234,13 @@ private void ParseConnectionSuccessful(string url)
210234
{
211235
_sessionId = connectSuccess.session;
212236
var account = new Account(string.Empty, connectSuccess.public_key);
213-
_loginTaskCompletionSource.SetResult(account);
237+
_loginTaskCompletionSource?.TrySetResult(account);
214238
SaveSessionInfo(account.PublicKey);
215239
}
216240
else
217241
{
218242
if (string.IsNullOrEmpty(error.errorCode)) return;
219-
_loginTaskCompletionSource.SetResult(null);
243+
_loginTaskCompletionSource?.TrySetResult(null);
220244
Debug.LogError($"Deeplink error: {error.errorCode} {error.errorMessage}");
221245
}
222246
}
@@ -227,11 +251,12 @@ private void ParseSuccessfullySignedTransaction(string url)
227251
result.TryGetValue("nonce", out var nonce);
228252
result.TryGetValue("data", out var data);
229253
result.TryGetValue("errorMessage", out var errorMessage);
230-
if (!string.IsNullOrEmpty(errorMessage))
254+
if (!string.IsNullOrEmpty(errorMessage) || string.IsNullOrEmpty(data))
231255
{
232256
Debug.LogError($"Deeplink error: Error: {errorMessage} + Data: {data}");
233257
return;
234258
}
259+
data = data.Replace("#", "");
235260
var k = MontgomeryCurve25519.KeyExchange(_phantomEncryptionPubKey, PhantomConnectionAccountPrivateKey);
236261
var unencryptedMessage = XSalsa20Poly1305.TryDecrypt(Encoders.Base58.DecodeData(data), k, Encoders.Base58.DecodeData(nonce));
237262
var bytesToUtf8String = Encoding.UTF8.GetString(unencryptedMessage);
@@ -247,11 +272,12 @@ private void ParseSuccessfullySignedMessage(string url)
247272
result.TryGetValue("nonce", out var nonce);
248273
result.TryGetValue("data", out var data);
249274
result.TryGetValue("errorMessage", out var errorMessage);
250-
if (!string.IsNullOrEmpty(errorMessage))
275+
if (!string.IsNullOrEmpty(errorMessage) || string.IsNullOrEmpty(data))
251276
{
252277
Debug.LogError($"Deeplink error: Error: {errorMessage} + Data: {data}");
253278
return;
254279
}
280+
data = data.Replace("#", "");
255281
var k = MontgomeryCurve25519.KeyExchange(_phantomEncryptionPubKey, PhantomConnectionAccountPrivateKey);
256282
var unencryptedMessage = XSalsa20Poly1305.TryDecrypt(Encoders.Base58.DecodeData(data), k, Encoders.Base58.DecodeData(nonce));
257283
var bytesToUtf8String = Encoding.UTF8.GetString(unencryptedMessage);
@@ -306,10 +332,14 @@ private void LoadSessionInfo(PublicKey account)
306332

307333
private void DestroySessionInfo()
308334
{
335+
_tmpPhantomConnectionAccount = new();
336+
_sessionId = null;
337+
_phantomEncryptionPubKey = null;
309338
PlayerPrefs.DeleteKey(TempKpPrefEntry);
310339
PlayerPrefs.DeleteKey(SessionIdPrefEntry);
311340
PlayerPrefs.DeleteKey(PhantomEncryptionPubKeyPrefEntry);
312341
PlayerPrefs.DeleteKey(PhantomPublicKeyPrefEntry);
342+
PlayerPrefs.Save();
313343
}
314344

315345
/// <summary>
@@ -318,7 +348,7 @@ private void DestroySessionInfo()
318348
/// <returns></returns>
319349
private string DeriveEncryptionPassword([NotNull] PublicKey account){
320350
if (account == null) throw new ArgumentNullException(nameof(account));
321-
var rawData = account.Key + _phantomWalletOptions.sessionEncryptionPassword + Application.platform;
351+
var rawData = account.Key + _deepLinksWalletOptions.SessionEncryptionPassword + Application.platform;
322352
using SHA256 sha256Hash = SHA256.Create();
323353
var bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
324354
return Encoding.UTF8.GetString(bytes);

Runtime/codebase/PhantomWallet/PhantomTransactionPayload.cs renamed to Runtime/codebase/DeepLinkWallets/PhantomTransactionPayload.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,15 @@ public PhantomTransactionPayload(string transaction, string session)
1616
this.session = session;
1717
}
1818
}
19+
20+
[Serializable]
21+
public class DisconnectPayload
22+
{
23+
public string session;
24+
25+
public DisconnectPayload(string session)
26+
{
27+
this.session = session;
28+
}
29+
}
1930
}

Runtime/codebase/PhantomWallet/PhantomWebGL.cs renamed to Runtime/codebase/DeepLinkWallets/PhantomWebGL.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace Solana.Unity.SDK
1515
public class PhantomWebGL: WalletBase
1616
{
1717

18-
private readonly PhantomWalletOptions _phantomWalletOptions;
18+
private readonly PhantomWalletOptions _deepLinksWalletOptions;
1919

2020
private static TaskCompletionSource<Account> _loginTaskCompletionSource;
2121
private static TaskCompletionSource<Transaction> _signedTransactionTaskCompletionSource;
@@ -24,11 +24,11 @@ public class PhantomWebGL: WalletBase
2424
private static Account _account;
2525

2626
public PhantomWebGL(
27-
PhantomWalletOptions phantomWalletOptions,
27+
PhantomWalletOptions deepLinksWalletOptions,
2828
RpcCluster rpcCluster = RpcCluster.DevNet, string customRpcUri = null, string customStreamingRpcUri = null, bool autoConnectOnStartup = false)
2929
: base(rpcCluster, customRpcUri, customStreamingRpcUri, autoConnectOnStartup)
3030
{
31-
_phantomWalletOptions = phantomWalletOptions;
31+
_deepLinksWalletOptions = deepLinksWalletOptions;
3232
}
3333

3434
protected override Task<Account> _Login(string password = null)

0 commit comments

Comments
 (0)