/// <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); }
protected async Task FundAccountAsync(ulong amount, string address) { var request = await IndyPayments.BuildMintRequestAsync(Context.Wallet, Trustee.Did, new[] { new { recipient = address, amount = amount } }.ToJson(), null); await TrusteeMultiSignAndSubmitRequestAsync(request.Result); }
protected async Task FundDefaultAccountAsync(ulong amount) { var record = await provisioningService.GetProvisioningAsync(Context.Wallet); var addressRecord = await recordService.GetAsync <PaymentAddressRecord>(Context.Wallet, record.DefaultPaymentAddressId); // Mint tokens to the address to fund initially var request = await IndyPayments.BuildMintRequestAsync(Context.Wallet, Trustee.Did, new[] { new { recipient = addressRecord.Address, amount = amount } }.ToJson(), null); await TrusteeMultiSignAndSubmitRequestAsync(request.Result); await paymentService.RefreshBalanceAsync(Context, addressRecord); }
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); }
/// <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); }
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); }
private async Task <string> SignAndSubmitAsync(IAgentContext context, string submitterDid, string request, TransactionCost paymentInfo) { if (paymentInfo != null) { var requestWithFees = await IndyPayments.AddRequestFeesAsync( wallet : context.Wallet, submitterDid : null, reqJson : request, inputsJson : paymentInfo.PaymentAddress.Sources.Select(x => x.Source).ToJson(), outputsJson : new[] { new IndyPaymentOutputSource { Recipient = paymentInfo.PaymentAddress.Address, Amount = paymentInfo.PaymentAddress.Balance - paymentInfo.Amount } }.ToJson(), extra : null); request = requestWithFees.Result; } var signedRequest = await _signingService.SignRequestAsync(context, submitterDid, request); var response = await IndyLedger.SubmitRequestAsync(await context.Pool, signedRequest); EnsureSuccessResponse(response); if (paymentInfo != null) { var responsePayment = await IndyPayments.ParseResponseWithFeesAsync(paymentInfo.PaymentMethod, response); var paymentOutputs = responsePayment.ToObject <IList <IndyPaymentOutputSource> >(); paymentInfo.PaymentAddress.Sources = paymentOutputs .Where(x => x.Recipient == paymentInfo.PaymentAddress.Address) .Select(x => new IndyPaymentInputSource { Amount = x.Amount, PaymentAddress = x.Recipient, Source = x.Receipt }) .ToList(); } return(response); }
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); }
//[Fact(DisplayName = "Transfer funds between Sovrin addresses with ledger fees")] public async Task TransferFundsAsync() { // Generate from address var addressFrom = await paymentService.CreatePaymentAddressAsync(Context); await SetFeesForPublicXferTransactionsAsync(2); // Mint tokens to the address to fund initially var request = await IndyPayments.BuildMintRequestAsync(Context.Wallet, Trustee.Did, new[] { new { recipient = addressFrom.Address, amount = 15 } }.ToJson(), null); await TrusteeMultiSignAndSubmitRequestAsync(request.Result); // Generate destination address var addressTo = await paymentService.CreatePaymentAddressAsync(Context); // Create payment record and make payment var paymentRecord = new PaymentRecord { Address = addressTo.Address, Amount = 10 }; await recordService.AddAsync(Context.Wallet, paymentRecord); await paymentService.MakePaymentAsync(Context, paymentRecord, addressFrom); var fee = await paymentService.GetTransactionFeeAsync(Context, TransactionTypes.XFER_PUBLIC); Assert.Equal(2UL, fee); await paymentService.RefreshBalanceAsync(Context, addressFrom); await paymentService.RefreshBalanceAsync(Context, addressTo); Assert.Equal(10UL, addressTo.Balance); Assert.Equal(3UL, addressFrom.Balance); await UnsetFeesForPublicXferTransactionsAsync(); }
/// <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); }
//[Fact(DisplayName = "Set transaction fees")] public async Task SetTransactionFees() { var request = await IndyPayments.BuildSetTxnFeesRequestAsync(Context.Wallet, Trustee.Did, TokenConfiguration.MethodName, new Dictionary <string, ulong> { { "101", 1 }, { "10001", 2 } }.ToJson()); var response = await TrusteeMultiSignAndSubmitRequestAsync(request); var jResponse = JObject.Parse(response); Assert.Equal("REPLY", jResponse["op"].ToString()); // Cleanup and revert back fees to 0 request = await IndyPayments.BuildSetTxnFeesRequestAsync(Context.Wallet, Trustee.Did, TokenConfiguration.MethodName, new Dictionary <string, ulong> { { "101", 0 }, { "10001", 0 } }.ToJson()); await TrusteeMultiSignAndSubmitRequestAsync(request); }
/// <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); }