/// <inheritdoc />
        public async Task RefreshBalanceAsync(IAgentContext agentContext, PaymentAddressRecord paymentAddress = null)
        {
            if (paymentAddress == null)
            {
                var provisioning = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

                if (provisioning.DefaultPaymentAddressId == null)
                {
                    throw new AriesFrameworkException(ErrorCode.RecordNotFound, "Default PaymentAddressRecord not found");
                }

                paymentAddress = await recordService.GetAsync <PaymentAddressRecord>(agentContext.Wallet, provisioning.DefaultPaymentAddressId);
            }

            // Cache sources data in record for one hour
            var request = await IndyPayments.BuildGetPaymentSourcesAsync(agentContext.Wallet, null, paymentAddress.Address);

            var response = await IndyLedger.SubmitRequestAsync(await agentContext.Pool, request.Result);

            var sourcesJson = await IndyPayments.ParseGetPaymentSourcesAsync(paymentAddress.Method, response);

            var sources = sourcesJson.ToObject <IList <IndyPaymentInputSource> >();

            paymentAddress.Sources         = sources;
            paymentAddress.SourcesSyncedAt = DateTime.Now;

            await recordService.UpdateAsync(agentContext.Wallet, paymentAddress);
        }
Exemplo n.º 2
0
        /// <inheritdoc />
        public async Task <IndyTaa> GetTaaAsync(string poolName)
        {
            IndyTaa ParseTaa(string response)
            {
                var jresponse = JObject.Parse(response);

                if (jresponse["result"]["data"].HasValues)
                {
                    return(new IndyTaa
                    {
                        Text = jresponse["result"]["data"]["text"].ToString(),
                        Version = jresponse["result"]["data"]["version"].ToString()
                    });
                }
                return(null);
            };

            if (Taas.TryGetValue(poolName, out var taa))
            {
                return(taa);
            }

            var pool = await GetPoolAsync(poolName, 2);

            var req = await IndyLedger.BuildGetTxnAuthorAgreementRequestAsync(null, null);

            var res = await IndyLedger.SubmitRequestAsync(pool, req);

            EnsureSuccessResponse(res);

            taa = ParseTaa(res);
            Taas.TryAdd(poolName, taa);
            return(taa);
        }
Exemplo n.º 3
0
        /// <inheritdoc />
        public async Task <IndyAml> GetAmlAsync(string poolName, DateTimeOffset timestamp = default, string version = null)
        {
            IndyAml ParseAml(string response)
            {
                var jresponse = JObject.Parse(response);

                if (jresponse["result"]["data"].HasValues)
                {
                    return(jresponse["result"]["data"].ToObject <IndyAml>());
                }
                return(null);
            };

            if (Amls.TryGetValue(poolName, out var aml))
            {
                return(aml);
            }

            var pool = await GetPoolAsync(poolName, 2);

            var req = await IndyLedger.BuildGetAcceptanceMechanismsRequestAsync(
                submitter_did : null,
                timestamp : timestamp == DateTimeOffset.MinValue? -1 : timestamp.ToUnixTimeSeconds(),
                version : version);

            var res = await IndyLedger.SubmitRequestAsync(pool, req);

            EnsureSuccessResponse(res);

            aml = ParseAml(res);
            Amls.TryAdd(poolName, aml);
            return(aml);
        }
        /// <inheritdoc />
        public async Task <IList <AuthorizationRule> > LookupAuthorizationRulesAsync(Pool pool)
        {
            var req = await IndyLedger.BuildGetAuthRuleRequestAsync(null, null, null, null, null, null);

            var res = await IndyLedger.SubmitRequestAsync(pool, req);

            EnsureSuccessResponse(res);

            var jobj = JObject.Parse(res);

            return(jobj["result"]["data"].ToObject <IList <AuthorizationRule> >());
        }
        private async Task <IDictionary <string, ulong> > GetTransactionFeesAsync(IAgentContext agentContext)
        {
            if (_transactionFees == null)
            {
                var feesRequest = await IndyPayments.BuildGetTxnFeesRequestAsync(agentContext.Wallet, null, TokenConfiguration.MethodName);

                var feesResponse = await IndyLedger.SubmitRequestAsync(await agentContext.Pool, feesRequest);

                var feesParsed = await IndyPayments.ParseGetTxnFeesResponseAsync(TokenConfiguration.MethodName, feesResponse);

                _transactionFees = feesParsed.ToObject <IDictionary <string, ulong> >();
            }
            return(_transactionFees);
        }
Exemplo n.º 6
0
        private async Task SetFeesForSchemaTransactionsAsync(ulong amount)
        {
            var request = await IndyPayments.BuildSetTxnFeesRequestAsync(Context.Wallet, Trustee.Did, TokenConfiguration.MethodName,
                                                                         new Dictionary <string, ulong>
            {
                { "fees_for_schema", amount }
            }.ToJson());

            await TrusteeMultiSignAndSubmitRequestAsync(request);

            request = await IndyLedger.BuildAuthRuleRequestAsync(Trustee.Did, "101", "ADD", "*", "*", "*", new
            {
                constraint_id    = "OR",
                auth_constraints = new[] {
                    new {
                        metadata = new {
                            fees = "fees_for_schema"
                        },
                        constraint_id    = "ROLE",
                        need_to_be_owner = false,
                        role             = "0",
                        sig_count        = 1
                    },
                    new {
                        metadata = new {
                            fees = "fees_for_schema"
                        },
                        constraint_id    = "ROLE",
                        need_to_be_owner = false,
                        role             = "2",
                        sig_count        = 1
                    },
                    new {
                        metadata = new {
                            fees = "fees_for_schema"
                        },
                        constraint_id    = "ROLE",
                        need_to_be_owner = false,
                        role             = "101",
                        sig_count        = 1
                    }
                }
            }.ToJson());
            await TrusteeMultiSignAndSubmitRequestAsync(request);
        }
        /// <inheritdoc />
        public async Task <string> SignRequestAsync(IAgentContext context, string submitterDid, string requestJson)
        {
            try
            {
                var provisioning = await provisioningService.GetProvisioningAsync(context.Wallet);

                if (provisioning?.TaaAcceptance != null)
                {
                    requestJson = await IndyLedger.AppendTxnAuthorAgreementAcceptanceToRequestAsync(requestJson, provisioning.TaaAcceptance.Text,
                                                                                                    provisioning.TaaAcceptance.Version, provisioning.TaaAcceptance.Digest, provisioning.TaaAcceptance.AcceptanceMechanism, (ulong)DateTimeOffset.Now.ToUnixTimeSeconds());
                }
            }
            catch (AriesFrameworkException ex) when(ex.ErrorCode == ErrorCode.RecordNotFound)
            {
                // OK, used in unit tests and scenarios when we want to simply send ledger commands
            }
            return(await SignRequestAsync(context.Wallet, submitterDid, requestJson));
        }
Exemplo n.º 8
0
        private async Task UnsetFeesForPublicXferTransactionsAsync()
        {
            var request = await IndyPayments.BuildSetTxnFeesRequestAsync(Context.Wallet, Trustee.Did, TokenConfiguration.MethodName,
                                                                         new Dictionary <string, ulong>
            {
                { "fees_for_xfer", 0 }
            }.ToJson());

            await TrusteeMultiSignAndSubmitRequestAsync(request);

            request = await IndyLedger.BuildAuthRuleRequestAsync(Trustee.Did, "10001", "ADD", "*", "*", "*", new
            {
                constraint_id    = "ROLE",
                metadata         = new { },
                need_to_be_owner = false,
                role             = "*",
                sig_count        = 0
            }.ToJson());
            await TrusteeMultiSignAndSubmitRequestAsync(request);
        }
        /// <inheritdoc />
        public async Task <bool> VerifyPaymentAsync(IAgentContext context, PaymentRecord paymentRecord)
        {
            if (paymentRecord.State != PaymentState.Paid && paymentRecord.State != PaymentState.ReceiptReceived)
            {
                throw new AriesFrameworkException(ErrorCode.RecordInInvalidState,
                                                  "Payment record must be in state Paid or ReceiptReceived to verify it");
            }

            var req = await IndyPayments.BuildVerifyPaymentRequestAsync(context.Wallet, null, paymentRecord.ReceiptId);

            var res = await IndyLedger.SubmitRequestAsync(await context.Pool, req.Result);

            var resParsed = JObject.Parse(await IndyPayments.ParseVerifyPaymentResponseAsync("sov", res));
            var receipts  = resParsed["receipts"].ToObject <IList <IndyPaymentOutputSource> >()
                            .Where(x => x.Recipient == paymentRecord.Address)
                            .ToList();

            if (receipts.Any() && receipts.Select(x => x.Amount).Aggregate((x, y) => x + y) == paymentRecord.Amount)
            {
                return(true);
            }
            return(false);
        }
 /// <inheritdoc />
 public Task <string> SignRequestAsync(Wallet wallet, string submitterDid, string requestJson)
 {
     return(IndyLedger.SignRequestAsync(wallet, submitterDid, requestJson));
 }
        /// <inheritdoc />
        public async Task MakePaymentAsync(IAgentContext agentContext, PaymentRecord paymentRecord,
                                           PaymentAddressRecord addressFromRecord = null)
        {
            if (paymentRecord.Amount == 0)
            {
                throw new AriesFrameworkException(ErrorCode.InvalidRecordData, "Cannot make a payment with 0 amount");
            }

            await paymentRecord.TriggerAsync(PaymentTrigger.ProcessPayment);

            if (paymentRecord.Address == null)
            {
                throw new AriesFrameworkException(ErrorCode.InvalidRecordData, "Payment record is missing an address");
            }

            var provisioning = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

            if (addressFromRecord == null)
            {
                addressFromRecord = await GetDefaultPaymentAddressAsync(agentContext);
            }

            await RefreshBalanceAsync(agentContext, addressFromRecord);

            if (addressFromRecord.Balance < paymentRecord.Amount)
            {
                throw new AriesFrameworkException(ErrorCode.PaymentInsufficientFunds,
                                                  "Address doesn't have enough funds to make this payment");
            }
            var txnFee = await GetTransactionFeeAsync(agentContext, TransactionTypes.XFER_PUBLIC);

            var paymentResult = await IndyPayments.BuildPaymentRequestAsync(
                wallet : agentContext.Wallet,
                submitterDid : null,
                inputsJson : addressFromRecord.Sources.Select(x => x.Source).ToJson(),
                outputsJson : new[]
            {
                new IndyPaymentOutputSource
                {
                    Amount    = paymentRecord.Amount,
                    Recipient = paymentRecord.Address
                },
                new IndyPaymentOutputSource
                {
                    Recipient = addressFromRecord.Address,
                    Amount    = addressFromRecord.Balance - paymentRecord.Amount - txnFee
                }
            }.ToJson(),
                extra : null);

            var response = await IndyLedger.SignAndSubmitRequestAsync(await agentContext.Pool, agentContext.Wallet,
                                                                      provisioning.Endpoint.Did, paymentResult.Result);

            var paymentResponse = await IndyPayments.ParsePaymentResponseAsync(TokenConfiguration.MethodName, response);

            var paymentOutputs = paymentResponse.ToObject <IList <IndyPaymentOutputSource> >();
            var paymentOutput  = paymentOutputs.SingleOrDefault(x => x.Recipient == paymentRecord.Address);

            paymentRecord.ReceiptId   = paymentOutput.Receipt;
            addressFromRecord.Sources = paymentOutputs
                                        .Where(x => x.Recipient == addressFromRecord.Address)
                                        .Select(x => new IndyPaymentInputSource
            {
                Amount         = x.Amount,
                PaymentAddress = x.Recipient,
                Source         = x.Receipt
            })
                                        .ToList();

            await recordService.UpdateAsync(agentContext.Wallet, paymentRecord);

            await recordService.UpdateAsync(agentContext.Wallet, addressFromRecord);
        }