/// <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 AgentFrameworkException(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 Ledger.SubmitRequestAsync(await agentContext.Pool, request.Result); var sourcesJson = await Indy.Payments.ParseGetPaymentSourcesAsync(paymentAddress.Method, response); var sources = sourcesJson.ToObject <IList <IndyPaymentInputSource> >(); paymentAddress.Sources = sources; paymentAddress.SourcesSyncedAt = DateTime.Now; await recordService.UpdateAsync(agentContext.Wallet, paymentAddress); }
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 Ledger.SubmitRequestAsync(await agentContext.Pool, feesRequest); var feesParsed = await IndyPayments.ParseGetTxnFeesResponseAsync(TokenConfiguration.MethodName, feesResponse); _transactionFees = feesParsed.ToObject <IDictionary <string, ulong> >(); } return(_transactionFees); }
/// <inheritdoc /> public async Task <PaymentAddressRecord> CreatePaymentAddressAsync(IAgentContext agentContext, AddressOptions configuration = null) { var address = await IndyPayments.CreatePaymentAddressAsync(agentContext.Wallet, TokenConfiguration.MethodName, new { seed = configuration?.Seed }.ToJson()); var addressRecord = new PaymentAddressRecord { Id = Guid.NewGuid().ToString("N"), Method = TokenConfiguration.MethodName, Address = address, SourcesSyncedAt = DateTime.MinValue }; await recordService.AddAsync(agentContext.Wallet, addressRecord); return(addressRecord); }
public async Task <bool> VerifyPaymentAsync(IAgentContext context, PaymentRecord paymentRecord) { if (paymentRecord.State != PaymentState.Paid && paymentRecord.State != PaymentState.ReceiptReceived) { throw new AgentFrameworkException(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 Ledger.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 async Task MakePaymentAsync(IAgentContext agentContext, PaymentRecord paymentRecord, PaymentAddressRecord addressFromRecord = null) { if (paymentRecord.Amount == 0) { throw new AgentFrameworkException(ErrorCode.InvalidRecordData, "Cannot make a payment with 0 amount"); } await paymentRecord.TriggerAsync(PaymentTrigger.ProcessPayment); if (paymentRecord.Address == null) { throw new AgentFrameworkException(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 AgentFrameworkException(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 Ledger.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); }