예제 #1
0
        /// <summary>
        /// Issues a short-lived channel access token.
        /// </summary>
        /// <param name="issueTokenRequest"></param>
        /// <returns></returns>
        public async Task <LineClientResult <AccessTokenResponse> > IssueToken(IssueTokenRequest issueTokenRequest)
        {
            if (issueTokenRequest == null)
            {
                throw new ArgumentNullException(nameof(IssueTokenRequest));
            }

            var request = new LinePostFormUrlEncodedRequest <AccessTokenResponse>(this, $"oauth/accessToken");

            request.Params.Add(new KeyValuePair <string, string>("grant_type", issueTokenRequest.grant_type));
            request.Params.Add(new KeyValuePair <string, string>("client_id", issueTokenRequest.client_id));
            request.Params.Add(new KeyValuePair <string, string>("client_secret", issueTokenRequest.client_secret));

            return(await request.Execute(issueTokenRequest));
        }
예제 #2
0
        public async Task <IActionResult> PostAsync([FromBody] IssueTokenRequest req, CancellationToken cancellationToken)
        {
            using (var propertyManagementRpc = await this.factory.CreatePropertyManagementRpcAsync(cancellationToken))
                using (var rawTransactionRpc = await this.factory.CreateRawTransactionRpcAsync(cancellationToken))
                {
                    var property = new Property(this.zcoinConfig.Property.Id, this.zcoinConfig.Property.Type);

                    Transaction tx;
                    try
                    {
                        tx = await propertyManagementRpc.GrantAsync(
                            property,
                            this.zcoinConfig.Property.Issuer.Address,
                            this.zcoinConfig.Property.Distributor.Address,
                            req.Amount,
                            req.Note,
                            cancellationToken);
                    }
                    catch (RPCException ex) when(ex.IsInsufficientFee())
                    {
                        return(this.InsufficientFee());
                    }

                    var id = await rawTransactionRpc.SendAsync(tx, cancellationToken);

                    var callback = await this.helper.RegisterCallbackAsync(this, CancellationToken.None);

                    if (callback != null)
                    {
                        var callbackResult = new { Tx = id };

                        await this.watcher.AddTransactionAsync(
                            id,
                            this.apiConfig.Default.RequiredConfirmation,
                            this.apiConfig.Default.TransactionTimeout,
                            callback,
                            new CallbackResult(CallbackResult.StatusSuccess, callbackResult),
                            new CallbackResult("tokens-issuing-timeout", callbackResult),
                            CancellationToken.None);
                    }

                    return(Accepted(new { Tx = id }));
                }
        }
예제 #3
0
        public async Task PostAsync_AndFeeIsInsufficient_ShouldReturnValidStatus()
        {
            // Arrange.
            var amount   = PropertyAmount.One;
            var property = new Property(new PropertyId(3), PropertyType.Divisible);

            var ex = RPCExceptionTesting.BuildException((RPCErrorCode)(-212), "", new
            {
                Result = (object)null,
                Error  = new
                {
                    Code    = -212,
                    Message = "Error choosing inputs for the send transaction",
                }
            });

            this.propertyManagementRpc.Setup(
                r => r.GrantAsync(
                    property,
                    It.IsAny <BitcoinAddress>(),
                    It.IsAny <BitcoinAddress>(),
                    amount,
                    It.IsAny <String>(),
                    It.IsAny <CancellationToken>()
                    )).ThrowsAsync(ex).Verifiable();

            var req = new IssueTokenRequest
            {
                Amount = amount,
            };

            ControllerTesting.SetHttpContext(this.subject);

            // Act.
            var response = await this.subject.PostAsync(req, CancellationToken.None);

            // Assert.
            this.propertyManagementRpc.Verify();

            response.Should().NotBeNull();
            response.As <ObjectResult>().StatusCode.Should().Be((int)HttpStatusCode.InternalServerError);
        }
예제 #4
0
        public async Task <IActionResult> PostAsync([FromBody] IssueTokenRequest req, CancellationToken cancellationToken)
        {
            using (var propertyManagementRpc = await this.factory.CreatePropertyManagementRpcAsync(cancellationToken))
                using (var rawTransactionRpc = await this.factory.CreateRawTransactionRpcAsync(cancellationToken))
                {
                    var property = new Property(this.zcoinConfig.Property.Id, this.zcoinConfig.Property.Type);

                    var tx = await propertyManagementRpc.GrantAsync
                             (
                        property,
                        this.zcoinConfig.Property.Issuer.Address,
                        this.zcoinConfig.Property.Distributor.Address,
                        req.Amount,
                        req.Note,
                        cancellationToken
                             );

                    var id = await rawTransactionRpc.SendAsync(tx, cancellationToken);

                    var callback = await this.AddCallbackAsync(CancellationToken.None);

                    if (callback != null)
                    {
                        var callbackResult = new { Tx = id };

                        await this.WatchTransactionAsync
                        (
                            id,
                            new CallbackResult(CallbackResult.StatusSuccess, callbackResult),
                            new CallbackResult("tokens-issuing-timeout", callbackResult),
                            callback,
                            CancellationToken.None
                        );
                    }

                    return(Ok(new { Tx = id }));
                };
        }
예제 #5
0
 /// <summary>
 /// Issue token
 /// </summary>
 /// <param name="issueTokenRequest"></param>
 /// <returns></returns>
 public async Task <LineClientResult <AccessTokenResponse> > IssueToken(IssueTokenRequest issueTokenRequest)
 {
     return(await authenticateClient.IssueToken(issueTokenRequest));
 }
예제 #6
0
        public async Task PostAsync_WithValidArgumentAndCallbackUrlIsSet_ShouldSuccess()
        {
            // Arrange.
            var amount         = PropertyAmount.One;
            var note           = "Test Issuing";
            var tx             = NBitcoin.Transaction.Parse(TestTransaction.Raw1, ZcoinNetworks.Instance.Mainnet);
            var rawCallbackUrl = "https://zcoin.io/callback";
            var callbackUrl    = new Uri(rawCallbackUrl);

            // Setup Rpc client
            this.propertyManagementRpc.Setup
            (
                c => c.GrantAsync
                (
                    It.Is <Property>(p => p.Id == this.zcoinConfiguration.Property.Id && p.Type == this.zcoinConfiguration.Property.Type),
                    this.zcoinConfiguration.Property.Issuer.Address,
                    this.zcoinConfiguration.Property.Distributor.Address,
                    amount,
                    note,
                    It.IsAny <CancellationToken>()
                )
            ).ReturnsAsync(tx).Verifiable();

            this.rawTransactionRpc.Setup
            (
                c => c.SendAsync
                (
                    tx,
                    It.IsAny <CancellationToken>()
                )
            ).ReturnsAsync(tx.GetHash()).Verifiable();

            // Construct payload
            var req = new IssueTokenRequest
            {
                Amount = amount,
                Note   = note,
            };

            // Mock and set url to request's header
            var httpContext = new DefaultHttpContext();

            this.subject.ControllerContext = new ControllerContext
            {
                HttpContext = httpContext
            };
            httpContext.Connection.RemoteIpAddress = IPAddress.Loopback;
            httpContext.Request.Headers.TryAdd("X-Callback-URL", rawCallbackUrl);

            // Add callback and register tx to watcher
            var callback = new Callback(Guid.NewGuid(), IPAddress.Loopback, DateTime.UtcNow, false, callbackUrl);

            this.callbackRepository.Setup
            (
                r => r.AddAsync(IPAddress.Loopback, callbackUrl, It.IsAny <CancellationToken>())
            ).ReturnsAsync(callback).Verifiable();

            this.watcher.Setup(
                r => r.AddTransactionAsync
                (
                    tx.GetHash(),
                    It.Is <int>(c => c >= 1),
                    It.Is <TimeSpan>(wt => wt < TimeSpan.Zero),
                    callback,
                    It.Is <CallbackResult>(rs => rs.Status == "success"),
                    It.Is <CallbackResult>(rs => rs.Status == "tokens-issuing-timeout"),
                    It.IsAny <CancellationToken>()
                )
                ).ReturnsAsync(
                (uint256 _tx, int _confirmations, TimeSpan _waiting, Callback _callback, CallbackResult _success, CallbackResult _timeout, CancellationToken _) =>
                new Rule
                (
                    Guid.NewGuid(),
                    _tx,
                    _confirmations,
                    _waiting,
                    _success,
                    _timeout,
                    _callback,
                    DateTime.UtcNow
                )
                );

            // Act.
            var result = await this.subject.PostAsync(req, CancellationToken.None);

            // Assert.
            this.propertyManagementRpc.Verify();
            this.rawTransactionRpc.Verify();

            result.Should().BeOfType <OkObjectResult>()
            .Which.Value.Should().BeEquivalentTo(new { Tx = tx.GetHash() });

            this.callbackRepository.Verify();
            this.watcher.Verify();

            httpContext.Response.Headers.Should().Contain("X-Callback-ID", callback.Id.ToString());
        }
예제 #7
0
        public async Task PostAsync_WithValidArgumentAndUrlWasNotSet_ShouldSuccessButNotAddCallback()
        {
            // Arrange.
            var amount = PropertyAmount.One;
            var note   = "Test Issuing";
            var tx     = NBitcoin.Transaction.Parse(TestTransaction.Raw1, ZcoinNetworks.Instance.Mainnet);

            this.propertyManagementRpc.Setup
            (
                c => c.GrantAsync
                (
                    It.Is <Property>(p => p.Id == this.zcoinConfiguration.Property.Id && p.Type == this.zcoinConfiguration.Property.Type),
                    this.zcoinConfiguration.Property.Issuer.Address,
                    this.zcoinConfiguration.Property.Distributor.Address,
                    amount,
                    note,
                    It.IsAny <CancellationToken>()
                )
            ).ReturnsAsync(tx).Verifiable();

            this.rawTransactionRpc.Setup
            (
                c => c.SendAsync
                (
                    tx,
                    It.IsAny <CancellationToken>()
                )
            ).ReturnsAsync(tx.GetHash()).Verifiable();

            var req = new IssueTokenRequest
            {
                Amount = amount,
                Note   = note,
            };

            var httpContext = new DefaultHttpContext();

            this.subject.ControllerContext = new ControllerContext
            {
                HttpContext = httpContext
            };

            // Act.
            var result = await this.subject.PostAsync(req, CancellationToken.None);

            // Assert.
            this.propertyManagementRpc.Verify();
            this.rawTransactionRpc.Verify();

            result.Should().BeOfType <OkObjectResult>()
            .Which.Value.Should().BeEquivalentTo(new { Tx = tx.GetHash() });

            this.watcher.Verify(
                w => w.AddTransactionAsync
                (
                    It.IsAny <uint256>(),
                    It.IsAny <int>(),
                    It.IsAny <TimeSpan>(),
                    It.IsAny <Callback>(),
                    It.IsAny <CallbackResult>(),
                    It.IsAny <CallbackResult>(),
                    It.IsAny <CancellationToken>()
                ),
                Times.Never()
                );

            this.callbackRepository.Verify(
                r => r.AddAsync
                (
                    It.IsAny <IPAddress>(),
                    It.IsAny <Uri>(),
                    It.IsAny <CancellationToken>()
                ),
                Times.Never()
                );
        }