diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..1a70b8c Binary files /dev/null and b/.DS_Store differ diff --git a/Beacon.Sdk.Sample.Dapp/.DS_Store b/Beacon.Sdk.Sample.Dapp/.DS_Store new file mode 100644 index 0000000..ee640fe Binary files /dev/null and b/Beacon.Sdk.Sample.Dapp/.DS_Store differ diff --git a/Beacon.Sdk.Sample.Dapp/Beacon.Sdk.Sample.Dapp.csproj b/Beacon.Sdk.Sample.Dapp/Beacon.Sdk.Sample.Dapp.csproj index d9268cc..e08872f 100644 --- a/Beacon.Sdk.Sample.Dapp/Beacon.Sdk.Sample.Dapp.csproj +++ b/Beacon.Sdk.Sample.Dapp/Beacon.Sdk.Sample.Dapp.csproj @@ -12,9 +12,11 @@ - - - + + + + + diff --git a/Beacon.Sdk.Sample.Dapp/Program.cs b/Beacon.Sdk.Sample.Dapp/Program.cs index becd0b3..9c66535 100644 --- a/Beacon.Sdk.Sample.Dapp/Program.cs +++ b/Beacon.Sdk.Sample.Dapp/Program.cs @@ -7,7 +7,6 @@ internal class Program private static async Task Main(string[] args) { await Sample.Run(); - Console.ReadLine(); return 0; } } diff --git a/Beacon.Sdk.Sample.Dapp/Sample.cs b/Beacon.Sdk.Sample.Dapp/Sample.cs index c7c0e44..6decac0 100644 --- a/Beacon.Sdk.Sample.Dapp/Sample.cs +++ b/Beacon.Sdk.Sample.Dapp/Sample.cs @@ -2,18 +2,29 @@ namespace Beacon.Sdk.Sample.Dapp; using System.Runtime.InteropServices; using Beacon; +using Beacon.Operation; using Beacon.Permission; +using Beacon.Sign; using BeaconClients; using BeaconClients.Abstract; using Core.Domain.Services; using Microsoft.Extensions.Logging; +using Netezos.Keys; +using Newtonsoft.Json.Linq; using Serilog; using Serilog.Extensions.Logging; +using Hex = Netezos.Encoding.Hex; using ILogger = Serilog.ILogger; public class Sample { const string DbPath = "dapp-sample.db"; + private const string TzButtonColorsContract = "KT1RPW5kTX6WFxg8JK34rGEU24gqEEudyfvz"; + private const string TokenId = "925"; + + private const string PayloadToSign = + "05010000008654657a6f73205369676e6564204d6573736167653a20436f6e6669726d696e67206d79206964656e7469747920617320747a31524445344a64556f37336278323363776a72393767446b6350363362344e664744206f6e206f626a6b742e636f6d2c207369673a6f5252764f6374513638726463457555394965782d72496b45516d46426652"; + private DappBeaconClient BeaconDappClient { get; set; } private ILogger Logger { get; set; } @@ -45,22 +56,79 @@ public async Task Run() string pairingRequestQrData = await BeaconDappClient.GetPairingRequestInfo(); Logger.Information("Pairing data is Is\n{Data}", pairingRequestQrData); - var activePeer = BeaconDappClient.GetActivePeer().Result; + var activePeer = await BeaconDappClient.GetActivePeer(); + if (activePeer == null) return; + + var permissions = await BeaconDappClient + .PermissionInfoRepository + .TryReadBySenderIdAsync(activePeer.SenderId); + if (permissions == null) return; + + var permissionsString = permissions?.Scopes.Aggregate(string.Empty, + (res, scope) => res + $"{scope}, ") ?? string.Empty; + + var pubKey = PubKey.FromBase58(permissions!.PublicKey); + + Logger.Information("We have active peer {Peer} with permissions {Permissions} and address {Address}", + activePeer.Name, permissionsString, pubKey.Address); + + var requestCommand = true; - if (activePeer != null) + while (requestCommand) { - var permissions = BeaconDappClient - .PermissionInfoRepository - .TryReadBySenderIdAsync(activePeer.SenderId) - .Result; - - var permissionsString = permissions?.Scopes.Aggregate(string.Empty, - (res, scope) => res + $"{scope}, ") ?? string.Empty; - - Logger.Information("We have active peer {Peer} with permissions {Permissions}", - activePeer.Name, permissionsString); + var command = Console.ReadLine(); + + switch (command) + { + case "exit": + { + requestCommand = false; + break; + } + case "sign": + { + var signPayloadRequest = new SignPayloadRequest( + id: KeyPairService.CreateGuid(), + version: Constants.BeaconVersion, + senderId: BeaconDappClient.SenderId, + signingType: SignPayloadType.raw, + payload: PayloadToSign, + sourceAddress: pubKey.Address); + + await BeaconDappClient.SendResponseAsync(activePeer.SenderId, signPayloadRequest); + break; + } + case "operation": + { + var operationDetails = new List + { + new( + Amount: "0", + Destination: TzButtonColorsContract, + Parameters: new JObject + { + ["entrypoint"] = "set_color", + ["value"] = new JObject + { + ["int"] = TokenId + } + }) + }; + + var operationRequest = new OperationRequest( + type: BeaconMessageType.operation_request, + version: Constants.BeaconVersion, + id: KeyPairService.CreateGuid(), + senderId: BeaconDappClient.SenderId, + network: permissions.Network, + operationDetails: operationDetails, + sourceAddress: pubKey.Address); + + await BeaconDappClient.SendResponseAsync(activePeer.SenderId, operationRequest); + break; + } + } } - } private async void OnBeaconDappClientMessageReceived(object? sender, BeaconMessageEventArgs e) @@ -96,7 +164,7 @@ private async void OnBeaconDappClientMessageReceived(object? sender, BeaconMessa await BeaconDappClient.SendResponseAsync(peer.SenderId, permissionRequest); return; } - + var message = e.Request; switch (message.Type) { @@ -107,15 +175,45 @@ private async void OnBeaconDappClientMessageReceived(object? sender, BeaconMessa var permissionsString = permissionResponse.Scopes.Aggregate(string.Empty, (res, scope) => res + $"{scope}, "); - - Logger.Information("{DappName} received permissions {Permissions} from {From} with address {Address} and public key {Pk}", + + Logger.Information( + "{DappName} received permissions {Permissions} from {From} with address {Address} and public key {Pk}", BeaconDappClient.AppName, permissionsString, permissionResponse.AppMetadata.Name, permissionResponse.Address, permissionResponse.PublicKey); break; - }; + } + + case BeaconMessageType.operation_response: + { + if (message is not OperationResponse operationResponse) + return; + + Logger.Debug("Operation completed with transaction hash {Tx}", operationResponse.TransactionHash); + break; + } + + case BeaconMessageType.sign_payload_response: + { + if (message is not SignPayloadResponse signPayloadResponse) + return; + + var senderPermissions = await BeaconDappClient + .PermissionInfoRepository + .TryReadBySenderIdAsync(signPayloadResponse.SenderId); + if (senderPermissions == null) return; + + var pubKey = PubKey.FromBase58(senderPermissions.PublicKey); + var payloadBytes = Hex.Parse(PayloadToSign); + var verified = pubKey.Verify(payloadBytes, signPayloadResponse.Signature); + var stringVerifyResult = verified ? "Successfully" : "Unsuccessfully"; + + Logger.Information("{Result} signed payload by {Sender}, signature is {Signature}", + stringVerifyResult, senderPermissions.AppMetadata.Name, signPayloadResponse.Signature); + break; + } } } } \ No newline at end of file diff --git a/Beacon.Sdk/.DS_Store b/Beacon.Sdk/.DS_Store new file mode 100644 index 0000000..ee640fe Binary files /dev/null and b/Beacon.Sdk/.DS_Store differ diff --git a/Beacon.Sdk/Beacon.Sdk.csproj b/Beacon.Sdk/Beacon.Sdk.csproj index b9d3cb1..bb4927a 100644 --- a/Beacon.Sdk/Beacon.Sdk.csproj +++ b/Beacon.Sdk/Beacon.Sdk.csproj @@ -14,7 +14,7 @@ Mikhail Tatarenko Beacon.Sdk Beacon .NET SDK for Tezos wallet developers to seamlessly connect to multiple dApps. - 1.0.7 + 1.0.8 Copyright © Baking Bad 2019-2022 enable netstandard2.0 @@ -27,6 +27,7 @@ + diff --git a/Beacon.Sdk/Beacon/Permission/NetworkType.cs b/Beacon.Sdk/Beacon/Permission/NetworkType.cs index 811d384..63a7146 100644 --- a/Beacon.Sdk/Beacon/Permission/NetworkType.cs +++ b/Beacon.Sdk/Beacon/Permission/NetworkType.cs @@ -9,12 +9,17 @@ namespace Beacon.Sdk.Beacon.Permission public enum NetworkType { mainnet, + ghostnet, // Long running testnet + mondaynet, // Testnet, resets every monday + dailynet, // Testnet, resets every day delphinet, edonet, florencenet, granadanet, hangzhounet, ithacanet, + jakartanet, + kathmandunet, custom } } \ No newline at end of file diff --git a/Beacon.Sdk/BeaconClients/DappBeaconClient.cs b/Beacon.Sdk/BeaconClients/DappBeaconClient.cs index c1b668b..5de707b 100644 --- a/Beacon.Sdk/BeaconClients/DappBeaconClient.cs +++ b/Beacon.Sdk/BeaconClients/DappBeaconClient.cs @@ -126,15 +126,17 @@ private async Task OnP2PMessagesReceived(object? sender, P2PMessageEventArgs e) } foreach (string message in e.Messages) - await HandleMessage(message); + await HandleReceivedMessage(message); } - private async Task HandleMessage(string message) + private async Task HandleReceivedMessage(string message) { (_, BaseBeaconMessage requestMessage) = _requestMessageHandler.Handle(message, SenderId); - await _responseMessageHandler.Handle(requestMessage, requestMessage.SenderId); + if (requestMessage.Type == BeaconMessageType.permission_response) + await _responseMessageHandler.Handle(requestMessage, requestMessage.SenderId); + OnBeaconMessageReceived?.Invoke(this, new BeaconMessageEventArgs(requestMessage.SenderId, requestMessage)); } diff --git a/Beacon.Sdk/Core/Domain/RequestMessageHandler.cs b/Beacon.Sdk/Core/Domain/RequestMessageHandler.cs index 452f492..a3dd5b4 100644 --- a/Beacon.Sdk/Core/Domain/RequestMessageHandler.cs +++ b/Beacon.Sdk/Core/Domain/RequestMessageHandler.cs @@ -32,8 +32,11 @@ public RequestMessageHandler(IAppMetadataRepository appMetadataRepository, BeaconMessageType.permission_request => (ack, HandlePermissionRequest(message)), BeaconMessageType.operation_request => (ack, HandleOperationRequest(message)), BeaconMessageType.sign_payload_request => (ack, HandleSignPayloadRequest(message)), - + + // todo: remove this to response handler BeaconMessageType.permission_response => (ack, HandlePermissionResponse(message)), + BeaconMessageType.operation_response => (ack, HandleOperationResponse(message)), + BeaconMessageType.sign_payload_response => (ack, HandleSignPayloadResponse(message)), _ => throw new Exception("Unknown beaconMessage.Type.") }; } @@ -54,18 +57,17 @@ private BaseBeaconMessage HandleOperationRequest(string message) return operationRequest; } - - private BaseBeaconMessage HandleSignPayloadRequest(string message) - { - var signPayloadRequest = _jsonSerializerService.Deserialize(message); - return signPayloadRequest; - } + private BaseBeaconMessage HandleSignPayloadRequest(string message) => + _jsonSerializerService.Deserialize(message); - // todo: remove this to response handler - private BaseBeaconMessage HandlePermissionResponse(string message) - { - var permissionResponse = _jsonSerializerService.Deserialize(message); - return permissionResponse; - } + + private BaseBeaconMessage HandlePermissionResponse(string message) => + _jsonSerializerService.Deserialize(message); + + private BaseBeaconMessage HandleOperationResponse(string message) => + _jsonSerializerService.Deserialize(message); + + private BaseBeaconMessage HandleSignPayloadResponse(string message) => + _jsonSerializerService.Deserialize(message); } } \ No newline at end of file diff --git a/Beacon.Sdk/Core/Domain/ResponseMessageHandler.cs b/Beacon.Sdk/Core/Domain/ResponseMessageHandler.cs index 0625923..af04ac0 100644 --- a/Beacon.Sdk/Core/Domain/ResponseMessageHandler.cs +++ b/Beacon.Sdk/Core/Domain/ResponseMessageHandler.cs @@ -48,8 +48,14 @@ await HandlePermissionResponse(receiverId, response as PermissionResponse), HandleDisconnectResponse(response as DisconnectMessage), BeaconMessageType.error => HandleError(response as BaseBeaconError), + + // todo: replace BeaconMessageType.permission_request => HandlePermissionRequest(response as PermissionRequest), + BeaconMessageType.operation_request => + HandleOperationRequest(response as OperationRequest), + BeaconMessageType.sign_payload_request => + HandleSignPayloadRequest(response as SignPayloadRequest), _ => throw new ArgumentException("Invalid beacon message type") }; @@ -141,5 +147,11 @@ private string HandleError(BaseBeaconError response) private string HandlePermissionRequest(PermissionRequest request) => _jsonSerializerService.Serialize(request); + + private string HandleOperationRequest(OperationRequest request) => + _jsonSerializerService.Serialize(request); + + private string HandleSignPayloadRequest(SignPayloadRequest request) => + _jsonSerializerService.Serialize(request); } } \ No newline at end of file