示例#1
0
        public void CreateFundingTransactionNotEnoughFundsTest()
        {
            var keyService = new Mock <IWalletService>();
            var blockchainClientService = new Mock <IBlockchainClientService>();
            var fundingKeyPrivateKey    = new ECKeyPair("DD06232AE9A50384A72D85CED6351DCB35C798231D4985615C77D6847F83FC65", true);
            var pubKeyAddress           = fundingKeyPrivateKey.ToPubKey().GetAddress(NBitcoin.Network.TestNet);
            var inputTx = Transaction.Parse("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0100f2052a010000001976a9143ca33c2e4446f4a305f23c80df8ad1afdcf652f988ac00000000", NBitcoin.Network.TestNet);

            keyService.Setup(k => k.Key).Returns(fundingKeyPrivateKey);
            keyService.Setup(k => k.PubKeyAddress).Returns(pubKeyAddress);
            blockchainClientService.Setup(b => b.ListUtxo(1, Int32.MaxValue, pubKeyAddress))
            .Returns(new List <Utxo>()
            {
                new Utxo()
                {
                    AmountSatoshi = 100000,
                    OutPoint      = new OutPoint(inputTx, 0),
                    ScriptPubKey  = inputTx.Outputs[0].ScriptPubKey
                }
            });

            FundingService fundingService = new FundingService(new LoggerFactory(), keyService.Object, blockchainClientService.Object, null);

            fundingService.Initialize(NetworkParameters.BitcoinTestnet);

            ECKeyPair pubKey1 = new ECKeyPair("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb", false);
            ECKeyPair pubKey2 = new ECKeyPair("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1", false);

            Assert.Throws <FundingException>(() => fundingService.CreateFundingTransaction(10000000, 1000, pubKey1, pubKey2));
        }
示例#2
0
        public async Task AddAmountAsync_AllParamsAreCorrect_Ok()
        {
            //arrange
            Guid    fundingId  = Guid.NewGuid();
            Guid    investorId = Guid.NewGuid();
            decimal amount     = 5000;

            Funding funding = new Funding
            {
                Id          = Guid.NewGuid(),
                Name        = "Fund 1",
                Description = "The description of the Fund 1",
                GoalAmount  = 75000
            };

            _repository.GetFundingAsync(Arg.Any <Guid>()).Returns(funding);

            //act
            IFundingService service = new FundingService(_repository);
            await service.AddAmountAsync(fundingId, investorId, amount);

            //assert
            Assert.Equal(amount, funding.CollectedAmount);
            Assert.Contains(investorId, funding.InvestorIds);
            await _repository.Received(1).AddAmountAsync(funding, investorId, amount);
        }
示例#3
0
        public async void ShouldNotBeAbleToChangeOwnerWhenNotOwner()
        {
            await Task.Delay(1);

            var         fs  = new FundingService(_contracts.Web3SecondaryUser, _contracts.Deployment.FundingService.ContractHandler.ContractAddress);
            Func <Task> act = async() => await fs.TransferOwnershipRequestAndWaitForReceiptAsync(_contracts.Web3SecondaryUser.TransactionManager.Account.Address);

            act.Should().Throw <SmartContractRevertException>().WithMessage(AUTH_EXCEPTION_ONLY_OWNER);
        }
示例#4
0
        public async Task AddAmountAsync_FundingNotFound_Exception()
        {
            //arrange
            Guid    fundingId  = Guid.NewGuid();
            Guid    investorId = Guid.NewGuid();
            decimal amount     = 1000;

            IFundingService service = new FundingService(_repository);
            await Assert.ThrowsAsync <ArgumentException>(() =>
                                                         service.AddAmountAsync(fundingId, investorId, amount));
        }
示例#5
0
        public JsonResult GetList(int page_index = 1)
        {
            var ent = new QueryBase <MemberFundingModel>
            {
                UserId    = base.UserId,
                PageIndex = page_index
            };

            FundingService.GetList(ent);
            return(base.GetJosn(ent.DataList.Select(m => new
            {
                op_type = m.OpType,
                change_type = m.ChangeType,
                score = m.OpValue,
                remark = m.Remark,
                create_time = m.CreateTime
            })));
        }
示例#6
0
        public async void ShouldNotBeAbleToTransferFundsWhenNotRegisteredCaller()
        {
            // Try to transfer funds for a PO using preexisting Funding contract, but with tx executed by the non-authorised ("secondary") user
            // PO may or may not exist, exception thrown will be before PO existence check
            await Task.Delay(1);

            var         fs   = new FundingService(_contracts.Web3SecondaryUser, _contracts.Deployment.FundingService.ContractHandler.ContractAddress);
            Func <Task> act1 = async() => await fs.TransferInFundsForPoFromBuyerWalletRequestAndWaitForReceiptAsync(1);

            act1.Should().Throw <SmartContractRevertException>().WithMessage(AUTH_EXCEPTION_ONLY_REGISTERED);

            Func <Task> act2 = async() => await fs.TransferOutFundsForPoItemToBuyerRequestAndWaitForReceiptAsync(1, 1);

            act2.Should().Throw <SmartContractRevertException>().WithMessage(AUTH_EXCEPTION_ONLY_REGISTERED);

            Func <Task> act3 = async() => await fs.TransferOutFundsForPoItemToSellerRequestAndWaitForReceiptAsync(1, 1);

            act3.Should().Throw <SmartContractRevertException>().WithMessage(AUTH_EXCEPTION_ONLY_REGISTERED);
        }
示例#7
0
        private async Task GetAllBalances()
        {
            var rpcClient = new RpcClient(new Uri(RpcUrl), new HttpClient());
            var web3      = new Web3(rpcClient);

            var wbs    = new WalletBuyerService(web3, WalletBuyerAddress);
            var wbsBal = await wbs.GetTokenBalanceOwnedByThisQueryAsync(TokenAddress);

            WalletBuyerBalance = $"{wbsBal.ToString()} {TokenSymbol}";

            var fs    = new FundingService(web3, FundingAddress);
            var fsBal = await fs.GetBalanceOfThisQueryAsync(TokenAddress);

            FundingBalance = $"{fsBal.ToString()} {TokenSymbol}";

            var wss    = new WalletSellerService(web3, WalletSellerAddress);
            var wssBal = await wss.GetTokenBalanceOwnedByThisQueryAsync(TokenAddress);

            WalletSellerBalance = $"{wssBal.ToString()} {TokenSymbol}";
        }
示例#8
0
        public void CreateFundingTransactionTest()
        {
            var keyService = new Mock <IWalletService>();
            var blockchainClientService = new Mock <IBlockchainClientService>();
            var secret = new BitcoinSecret("cRCH7YNcarfvaiY1GWUKQrRGmoezvfAiqHtdRvxe16shzbd7LDMz");

            var fundingKeyPrivateKey = new ECKeyPair(secret.PrivateKey.GetBytes(), true);
            var pubKeyAddress        = fundingKeyPrivateKey.ToPubKey().GetAddress(NBitcoin.Network.TestNet);
            var inputTx = Transaction.Parse("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0100f2052a010000001976a9143ca33c2e4446f4a305f23c80df8ad1afdcf652f988ac00000000", NBitcoin.Network.TestNet);

            keyService.Setup(k => k.Key).Returns(fundingKeyPrivateKey);
            keyService.Setup(k => k.PubKeyAddress).Returns(pubKeyAddress);
            blockchainClientService.Setup(b => b.ListUtxo(1, Int32.MaxValue, pubKeyAddress))
            .Returns(new List <Utxo>()
            {
                new Utxo()
                {
                    AmountSatoshi = 100000000,
                    OutPoint      = new OutPoint(inputTx, 0),
                    ScriptPubKey  = inputTx.Outputs[0].ScriptPubKey
                }
            });

            FundingService fundingService = new FundingService(new LoggerFactory(), keyService.Object, blockchainClientService.Object, null);

            fundingService.Initialize(NetworkParameters.BitcoinTestnet);

            ECKeyPair pubKey1 = new ECKeyPair("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb", false);
            ECKeyPair pubKey2 = new ECKeyPair("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1", false);

            FundingTransaction fundingTransaction = fundingService.CreateFundingTransaction(10000000, 1000, pubKey1, pubKey2);

            Assert.Equal(1, fundingTransaction.FundingOutputIndex);
            Assert.Single(fundingTransaction.Transaction.Inputs);
            Assert.Equal(2, fundingTransaction.Transaction.Outputs.Count);
            Assert.Equal(89999765, fundingTransaction.Transaction.Outputs[0].Value.Satoshi);
            Assert.Equal(10000000, fundingTransaction.Transaction.Outputs[1].Value.Satoshi);
            Assert.Equal("35effff7a94b0fbd819b2feec4737d88a9c2f1a7cca481bd6fb206d23029c974", fundingTransaction.Transaction.GetHash().ToString());
        }
示例#9
0
        public async Task AddAmountAsync_GoalAmountExceeded_Exception()
        {
            //arrange
            Guid    fundingId  = Guid.NewGuid();
            Guid    investorId = Guid.NewGuid();
            decimal amount     = 5000;

            Funding funding = new Funding
            {
                Id              = Guid.NewGuid(),
                Name            = "Fund 1",
                Description     = "The description of the Fund 1",
                CollectedAmount = 74000,
                GoalAmount      = 75000
            };

            _repository.GetFundingAsync(Arg.Any <Guid>()).Returns(funding);

            IFundingService service = new FundingService(_repository);
            await Assert.ThrowsAsync <ArgumentException>(() =>
                                                         service.AddAmountAsync(fundingId, investorId, amount));
        }
示例#10
0
 public Result <int> Withdrawal(decimal amount, int userid)
 {
     return(FundingService.WithdrawalApply(base.UserId, amount));
 }
        private async Task DeployAndConfigureEShopAsync()
        {
            try
            {
                Log($"Deploying eShop: {ContractNewDeploymentConfig.Eshop.EShopId} {ContractNewDeploymentConfig.Eshop.EShopDescription}...");

                //-----------------------------------------------------------------------------------
                // Contract deployments
                //-----------------------------------------------------------------------------------
                #region contract deployments
                // Deploy Address Registry
                Log();
                var contractName = CONTRACT_NAME_ADDRESS_REGISTRY;
                Log($"Deploying {contractName}...");
                var addressRegDeployment = new AddressRegistryDeployment();
                AddressRegistryService = await AddressRegistryService.DeployContractAndGetServiceAsync(
                    _web3, addressRegDeployment).ConfigureAwait(false);

                var addressRegOwner = await AddressRegistryService.OwnerQueryAsync().ConfigureAwait(false);

                Log($"{contractName} address is: {AddressRegistryService.ContractHandler.ContractAddress}");
                Log($"{contractName} owner is  : {addressRegOwner}");

                // Deploy Eternal Storage
                Log();
                contractName = CONTRACT_NAME_ETERNAL_STORAGE;
                Log($"Deploying {contractName}...");
                var eternalStorageDeployment = new EternalStorageDeployment();
                EternalStorageService = await EternalStorageService.DeployContractAndGetServiceAsync(
                    _web3, eternalStorageDeployment).ConfigureAwait(false);

                var eternalStorageOwner = await EternalStorageService.OwnerQueryAsync().ConfigureAwait(false);

                Log($"{contractName} address is: {EternalStorageService.ContractHandler.ContractAddress}");
                Log($"{contractName} owner is  : {eternalStorageOwner}");

                // Deploy Business Partner Storage
                Log();
                contractName = CONTRACT_NAME_BUSINESS_PARTNER_STORAGE;
                Log($"Deploying {contractName}...");
                var bpStorageDeployment = new BusinessPartnerStorageDeployment()
                {
                    ContractAddressOfRegistry = AddressRegistryService.ContractHandler.ContractAddress
                };
                BusinessPartnerStorageService = await BusinessPartnerStorageService.DeployContractAndGetServiceAsync(
                    _web3, bpStorageDeployment).ConfigureAwait(false);

                var bpStorageOwner = await BusinessPartnerStorageService.OwnerQueryAsync().ConfigureAwait(false);

                Log($"{contractName} address is: {BusinessPartnerStorageService.ContractHandler.ContractAddress}");
                Log($"{contractName} owner is  : {bpStorageOwner}");

                // Deploy PO Storage
                Log();
                contractName = CONTRACT_NAME_PO_STORAGE;
                Log($"Deploying {contractName}...");
                var poStorageDeployment = new PoStorageDeployment()
                {
                    ContractAddressOfRegistry = AddressRegistryService.ContractHandler.ContractAddress
                };
                PoStorageService = await PoStorageService.DeployContractAndGetServiceAsync(
                    _web3, poStorageDeployment).ConfigureAwait(false);

                var poStorageOwner = await PoStorageService.OwnerQueryAsync().ConfigureAwait(false);

                Log($"{contractName} address is: {PoStorageService.ContractHandler.ContractAddress}");
                Log($"{contractName} owner is  : {poStorageOwner}");

                // Deploy Wallet Buyer
                Log();
                contractName = CONTRACT_NAME_BUYER_WALLET;
                Log($"Deploying {contractName}...");
                var buyerWalletDeployment = new BuyerWalletDeployment()
                {
                    ContractAddressOfRegistry = AddressRegistryService.ContractHandler.ContractAddress
                };
                BuyerWalletService = await BuyerWalletService.DeployContractAndGetServiceAsync(
                    _web3, buyerWalletDeployment).ConfigureAwait(false);

                var buyerWalletOwner = await BuyerWalletService.OwnerQueryAsync().ConfigureAwait(false);

                Log($"{contractName} address is: {BuyerWalletService.ContractHandler.ContractAddress}");
                Log($"{contractName} owner is  : {buyerWalletOwner}");

                // Deploy Wallet Seller
                Log();
                contractName = CONTRACT_NAME_SELLER_ADMIN;
                Log($"Deploying {contractName}...");
                var sellerAdminDeployment = new SellerAdminDeployment()
                {
                    ContractAddressOfRegistry = AddressRegistryService.ContractHandler.ContractAddress,
                    SellerIdString            = ContractNewDeploymentConfig.Seller.SellerId,
                };
                SellerAdminService = await SellerAdminService.DeployContractAndGetServiceAsync(
                    _web3, sellerAdminDeployment).ConfigureAwait(false);

                var sellerAdminOwner = await SellerAdminService.OwnerQueryAsync().ConfigureAwait(false);

                Log($"{contractName} address is: {SellerAdminService.ContractHandler.ContractAddress}");
                Log($"{contractName} owner is  : {sellerAdminOwner}");

                // Deploy Purchasing
                Log();
                contractName = CONTRACT_NAME_PURCHASING;
                Log($"Deploying {contractName}...");
                var purchasingDeployment = new PurchasingDeployment()
                {
                    ContractAddressOfRegistry = AddressRegistryService.ContractHandler.ContractAddress,
                    EShopIdString             = ContractNewDeploymentConfig.Eshop.EShopId
                };
                PurchasingService = await PurchasingService.DeployContractAndGetServiceAsync(
                    _web3, purchasingDeployment).ConfigureAwait(false);

                var purchasingOwner = await PurchasingService.OwnerQueryAsync().ConfigureAwait(false);

                Log($"{contractName} address is: {PurchasingService.ContractHandler.ContractAddress}");
                Log($"{contractName} owner is  : {purchasingOwner}");

                // Deploy Funding
                Log();
                contractName = CONTRACT_NAME_FUNDING;
                Log($"Deploying {contractName}...");
                var fundingDeployment = new FundingDeployment()
                {
                    ContractAddressOfRegistry = AddressRegistryService.ContractHandler.ContractAddress
                };
                FundingService = await FundingService.DeployContractAndGetServiceAsync(
                    _web3, fundingDeployment).ConfigureAwait(false);

                var fundingOwner = await FundingService.OwnerQueryAsync().ConfigureAwait(false);

                Log($"{contractName} address is: {FundingService.ContractHandler.ContractAddress}");
                Log($"{contractName} owner is  : {fundingOwner}");

                #endregion

                //-----------------------------------------------------------------------------------
                // Configure Address Registry
                //-----------------------------------------------------------------------------------
                #region configure address registry
                Log();
                Log($"Configuring Address Registry...");

                // Add address entry for eternal storage
                contractName = CONTRACT_NAME_ETERNAL_STORAGE;
                Log($"Configuring Address Registry, adding {contractName}...");
                var txReceipt = await AddressRegistryService.RegisterAddressStringRequestAndWaitForReceiptAsync(
                    contractName, EternalStorageService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                // Add address entry for BP storage
                contractName = CONTRACT_NAME_BUSINESS_PARTNER_STORAGE;
                Log($"Configuring Address Registry, adding {contractName}...");
                txReceipt = await AddressRegistryService.RegisterAddressStringRequestAndWaitForReceiptAsync(
                    contractName, BusinessPartnerStorageService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                // Add address entry for PO storage
                contractName = CONTRACT_NAME_PO_STORAGE;
                Log($"Configuring Address Registry, adding {contractName}...");
                txReceipt = await AddressRegistryService.RegisterAddressStringRequestAndWaitForReceiptAsync(
                    contractName, PoStorageService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                // Add address entry for Purchasing
                contractName = CONTRACT_NAME_PURCHASING;
                Log($"Configuring Address Registry, adding {contractName}...");
                txReceipt = await AddressRegistryService.RegisterAddressStringRequestAndWaitForReceiptAsync(
                    contractName, PurchasingService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                // Add address entry for Funding
                contractName = CONTRACT_NAME_FUNDING;
                Log($"Configuring Address Registry, adding {contractName}...");
                txReceipt = await AddressRegistryService.RegisterAddressStringRequestAndWaitForReceiptAsync(
                    contractName, FundingService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                // Authorisations. Nothing needed.
                #endregion

                //-----------------------------------------------------------------------------------
                // Configure Eternal Storage
                //-----------------------------------------------------------------------------------
                #region configure eternal storage
                // Authorisations. Bind all contracts that will use eternal storage
                Log();
                Log($"Authorisations for Eternal Storage...");
                contractName = CONTRACT_NAME_BUSINESS_PARTNER_STORAGE;
                Log($"Configuring Eternal Storage, binding {contractName}...");
                txReceipt = await EternalStorageService.BindAddressRequestAndWaitForReceiptAsync(
                    BusinessPartnerStorageService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                contractName = CONTRACT_NAME_PO_STORAGE;
                Log($"Configuring Eternal Storage, binding {contractName}...");
                txReceipt = await EternalStorageService.BindAddressRequestAndWaitForReceiptAsync(
                    PoStorageService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");
                #endregion

                //-----------------------------------------------------------------------------------
                // Configure Business Partner Storage
                //-----------------------------------------------------------------------------------
                #region configure business partner storage and store master data
                Log();
                Log($"Configuring BP Storage...");
                txReceipt = await BusinessPartnerStorageService.ConfigureRequestAndWaitForReceiptAsync(
                    CONTRACT_NAME_ETERNAL_STORAGE).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                //-----------------------------------------------------------------------------------
                // Add some Business Partner master data
                //-----------------------------------------------------------------------------------
                // Need at least one eShop and one Seller to be a useful deployment
                Log($"Adding eShop master data...");
                txReceipt = await BusinessPartnerStorageService.SetEshopRequestAndWaitForReceiptAsync(
                    new Eshop()
                {
                    EShopId                   = ContractNewDeploymentConfig.Eshop.EShopId,
                    EShopDescription          = ContractNewDeploymentConfig.Eshop.EShopDescription,
                    PurchasingContractAddress = PurchasingService.ContractHandler.ContractAddress,
                    IsActive                  = true,
                    CreatedByAddress          = string.Empty, // filled by contract
                    QuoteSignerCount          = Convert.ToUInt32(ContractNewDeploymentConfig.Eshop.QuoteSigners.Count),
                    QuoteSigners              = ContractNewDeploymentConfig.Eshop.QuoteSigners
                }).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                Log($"Adding Seller master data...");
                txReceipt = await BusinessPartnerStorageService.SetSellerRequestAndWaitForReceiptAsync(
                    new Seller()
                {
                    SellerId             = ContractNewDeploymentConfig.Seller.SellerId,
                    SellerDescription    = ContractNewDeploymentConfig.Seller.SellerDescription,
                    AdminContractAddress = SellerAdminService.ContractHandler.ContractAddress,
                    IsActive             = true,
                    CreatedByAddress     = string.Empty  // filled by contract
                }).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");
                #endregion

                // Authorisations.
                // Bind all contracts that will use BP storage here - currently none other than owner

                //-----------------------------------------------------------------------------------
                // Configure PO Storage
                //-----------------------------------------------------------------------------------
                Log();
                Log($"Configuring PO Storage...");
                txReceipt = await PoStorageService.ConfigureRequestAndWaitForReceiptAsync(
                    CONTRACT_NAME_ETERNAL_STORAGE).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                // Authorisations. Bind all contracts that will use PO storage
                // Bind Purchasing to PO Storage
                Log($"Authorisations for PO Storage...");
                contractName = CONTRACT_NAME_PURCHASING;
                Log($"Configuring PO Storage, binding {contractName}...");
                txReceipt = await PoStorageService.BindAddressRequestAndWaitForReceiptAsync(
                    PurchasingService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                //-----------------------------------------------------------------------------------
                // Configure Seller Admin
                //-----------------------------------------------------------------------------------
                Log();
                Log($"Configuring Seller Admin...");
                txReceipt = await SellerAdminService.ConfigureRequestAndWaitForReceiptAsync(
                    CONTRACT_NAME_BUSINESS_PARTNER_STORAGE).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                //-----------------------------------------------------------------------------------
                // Configure Buyer Wallet
                //-----------------------------------------------------------------------------------
                Log();
                Log($"Configuring Buyer Wallet...");
                txReceipt = await BuyerWalletService.ConfigureRequestAndWaitForReceiptAsync(
                    CONTRACT_NAME_BUSINESS_PARTNER_STORAGE).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                //-----------------------------------------------------------------------------------
                // Configure Purchasing
                //-----------------------------------------------------------------------------------
                Log();
                Log($"Configuring Purchasing...");
                txReceipt = await PurchasingService.ConfigureRequestAndWaitForReceiptAsync(
                    CONTRACT_NAME_PO_STORAGE, CONTRACT_NAME_BUSINESS_PARTNER_STORAGE, CONTRACT_NAME_FUNDING)
                            .ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                // Authorisations. Bind all contracts that will use Purchasing
                Log($"Authorisations for Purchasing...");
                // Bind BuyerWallet to Purchasing
                contractName = CONTRACT_NAME_BUYER_WALLET;
                Log($"Configuring Purchasing, binding {contractName}...");
                txReceipt = await PurchasingService.BindAddressRequestAndWaitForReceiptAsync(
                    BuyerWalletService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");
                // Bind SellerAdmin to Purchasing
                contractName = CONTRACT_NAME_SELLER_ADMIN;
                Log($"Configuring Purchasing, binding {contractName}...");
                txReceipt = await PurchasingService.BindAddressRequestAndWaitForReceiptAsync(
                    SellerAdminService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");
                // Bind Funding to Purchasing
                contractName = CONTRACT_NAME_FUNDING;
                Log($"Configuring Purchasing, binding {contractName}...");
                txReceipt = await PurchasingService.BindAddressRequestAndWaitForReceiptAsync(
                    FundingService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                //-----------------------------------------------------------------------------------
                // Configure Funding
                //-----------------------------------------------------------------------------------
                Log();
                Log($"Configuring Funding...");
                txReceipt = await FundingService.ConfigureRequestAndWaitForReceiptAsync(
                    CONTRACT_NAME_PO_STORAGE, CONTRACT_NAME_BUSINESS_PARTNER_STORAGE)
                            .ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");

                // Authorisations. Bind all contracts that will use Funding
                Log($"Authorisations for Funding...");
                // Bind BuyerWallet to Funding
                contractName = CONTRACT_NAME_BUYER_WALLET;
                Log($"Configuring Funding, binding {contractName}...");
                txReceipt = await FundingService.BindAddressRequestAndWaitForReceiptAsync(
                    BuyerWalletService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");
                // Bind Purchasing to Funding
                contractName = CONTRACT_NAME_PURCHASING;
                Log($"Configuring Funding, binding {contractName}...");
                txReceipt = await FundingService.BindAddressRequestAndWaitForReceiptAsync(
                    PurchasingService.ContractHandler.ContractAddress).ConfigureAwait(false);

                Log($"Tx status: {txReceipt.Status.Value}");
            }
            catch (Exception ex)
            {
                Log($"Exception thrown: {ex.Message}");
            }
            finally
            {
                Log($"Deploy and configure complete.");
            }
        }