/// <summary>
        /// Pair appication to registered applications in scatter
        /// </summary>
        /// <param name="passthrough">pass through rekey process</param>
        /// <param name="timeout">set response timeout that overrides the default one</param>
        /// <returns></returns>
        public async Task Pair(bool passthrough = false, int?timeout = null)
        {
            var pairOpenTask = new TaskCompletionSource <object>();
            var openTask     = new OpenTask()
            {
                PromiseTask     = pairOpenTask,
                TaskRequestTime = DateTime.Now,
                TaskTimeoutMS   = timeout.HasValue ? timeout.Value : TimeoutMS
            };

            if (OpenTasks.ContainsKey(PairOpenId))
            {
                OpenTasks[PairOpenId] = openTask;
            }
            else
            {
                OpenTasks.Add(PairOpenId, openTask);
            }

            await SockIO.EmitAsync("pair", new RequestWrapper()
            {
                data = new PairRequest()
                {
                    appkey      = StorageProvider.GetAppkey(),
                    passthrough = passthrough,
                    origin      = AppName
                },
                plugin = AppName
            });

            await pairOpenTask.Task;
        }
 private void HandleRekeyResponse(IEnumerable <object> args)
 {
     GenerateNewAppKey();
     SockIO.EmitAsync("rekeyed", new
     {
         plugin = AppName,
         data   = new
         {
             origin = AppName,
             appkey = StorageProvider.GetAppkey()
         }
     });
 }
        public async Task Pair(bool passthrough = false)
        {
            PairOpenTask = new TaskCompletionSource <bool>();

            await SockIO.EmitAsync("pair", new RequestWrapper()
            {
                data = new PairRequest()
                {
                    appkey      = StorageProvider.GetAppkey(),
                    passthrough = passthrough,
                    origin      = AppName
                },
                plugin = AppName
            });

            await PairOpenTask.Task;
        }
        /// <summary>
        /// Send api request to scatter
        /// </summary>
        /// <typeparam name="TRequest">Request type param</typeparam>
        /// <typeparam name="TReturn">Return type param</typeparam>
        /// <param name="request">Request object</param>
        /// <param name="timeout">set response timeout that overrides the default one</param>
        /// <returns></returns>
        public async Task <TReturn> SendApiRequest <TRequest, TReturn>(Request <TRequest> request, int?timeout = null)
        {
            if (request.type == "identityFromPermissions" && !Paired)
            {
                return(default(TReturn));
            }

            await Pair();

            if (!Paired)
            {
                throw new Exception("The user did not allow this app to connect to their Scatter");
            }

            var tcs = new TaskCompletionSource <object>();

            do
            {
                request.id = UtilsHelper.RandomNumber(24);
            }while (OpenTasks.ContainsKey(request.id));

            request.appkey = StorageProvider.GetAppkey();
            request.nonce  = StorageProvider.GetNonce() ?? "";

            var nextNonce = UtilsHelper.RandomNumberBytes();

            request.nextNonce = UtilsHelper.ByteArrayToHexString(Sha256Manager.GetHash(nextNonce));
            StorageProvider.SetNonce(UtilsHelper.ByteArrayToHexString(nextNonce));

            OpenTasks.Add(request.id, new OpenTask()
            {
                PromiseTask     = tcs,
                TaskRequestTime = DateTime.Now,
                TaskTimeoutMS   = timeout.HasValue ? timeout.Value : TimeoutMS
            });

            await SockIO.EmitAsync("api", new RequestWrapper()
            {
                data   = request,
                plugin = AppName
            });

            return(BuildApiResponse <TReturn>(await tcs.Task));
        }