diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml new file mode 100644 index 000000000..3383c717e --- /dev/null +++ b/.github/workflows/dart.yml @@ -0,0 +1,42 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Dart + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + # Note: This workflow uses the latest stable version of the Dart SDK. + # You can specify other versions if desired, see documentation here: + # https://github.com/dart-lang/setup-dart/blob/main/README.md + # - uses: dart-lang/setup-dart@v1 + - uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603 + + - name: Install dependencies + run: dart pub get + + # Uncomment this step to verify the use of 'dart format' on each commit. + # - name: Verify formatting + # run: dart format --output=none --set-exit-if-changed . + + # Consider passing '--fatal-infos' for slightly stricter analysis. + - name: Analyze project source + run: dart analyze + + # Your project will need to have tests in test/ and a dependency on + # package:test for this step to succeed. Note that Flutter projects will + # want to change this to 'flutter test'. + - name: Run tests + run: dart test diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 000000000..217f7cbec --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,28 @@ +# This workflow will build a .NET project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net + +name: .NET + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 000000000..0b443f376 --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,28 @@ +# This workflow will build a golang project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go + +name: Go + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.20' + + - name: Build + run: go build -v ./... + + - name: Test + run: go test -v ./... diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 000000000..27400c2ba --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,67 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + # Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Build with Gradle Wrapper + run: ./gradlew build + + # NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html). + # If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version. + # + # - name: Setup Gradle + # uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + # with: + # gradle-version: '8.5' + # + # - name: Build with Gradle 8.5 + # run: gradle build + + dependency-submission: + + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. + # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md + - name: Generate and submit dependency graph + uses: gradle/actions/dependency-submission@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml new file mode 100644 index 000000000..fd8c644e6 --- /dev/null +++ b/.github/workflows/laravel.yml @@ -0,0 +1,35 @@ +name: Laravel + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + laravel-tests: + + runs-on: ubuntu-latest + + steps: + - uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e + with: + php-version: '8.0' + - uses: actions/checkout@v4 + - name: Copy .env + run: php -r "file_exists('.env') || copy('.env.example', '.env');" + - name: Install Dependencies + run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist + - name: Generate key + run: php artisan key:generate + - name: Directory Permissions + run: chmod -R 777 storage bootstrap/cache + - name: Create Database + run: | + mkdir -p database + touch database/database.sqlite + - name: Execute tests (Unit and Feature tests) via PHPUnit/Pest + env: + DB_CONNECTION: sqlite + DB_DATABASE: database/database.sqlite + run: php artisan test diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 000000000..6d573d77d --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,31 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Node.js CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [14.x, 16.x, 18.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - run: npm ci + - run: npm run build --if-present + - run: npm test diff --git a/.github/workflows/r.yml b/.github/workflows/r.yml new file mode 100644 index 000000000..ed8aacfa6 --- /dev/null +++ b/.github/workflows/r.yml @@ -0,0 +1,40 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# +# See https://github.com/r-lib/actions/tree/master/examples#readme for +# additional example workflows available for the R community. + +name: R + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build: + runs-on: macos-latest + strategy: + matrix: + r-version: ['3.6.3', '4.1.1'] + + steps: + - uses: actions/checkout@v4 + - name: Set up R ${{ matrix.r-version }} + uses: r-lib/actions/setup-r@f57f1301a053485946083d7a45022b278929a78a + with: + r-version: ${{ matrix.r-version }} + - name: Install dependencies + run: | + install.packages(c("remotes", "rcmdcheck")) + remotes::install_deps(dependencies = TRUE) + shell: Rscript {0} + - name: Check + run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "error") + shell: Rscript {0} diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml new file mode 100644 index 000000000..5d80832d3 --- /dev/null +++ b/.github/workflows/ruby.yml @@ -0,0 +1,38 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake +# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby + +name: Ruby + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + test: + + runs-on: ubuntu-latest + strategy: + matrix: + ruby-version: ['2.6', '2.7', '3.0'] + + steps: + - uses: actions/checkout@v4 + - name: Set up Ruby + # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, + # change this to (see https://github.com/ruby/setup-ruby#versioning): + # uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - name: Run tests + run: bundle exec rake diff --git a/.github/workflows/symfony.yml b/.github/workflows/symfony.yml new file mode 100644 index 000000000..e9b7c26f6 --- /dev/null +++ b/.github/workflows/symfony.yml @@ -0,0 +1,47 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Symfony + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + symfony-tests: + runs-on: ubuntu-latest + steps: + # To automatically get bug fixes and new Php versions for shivammathur/setup-php, + # change this to (see https://github.com/shivammathur/setup-php#bookmark-versioning): + # uses: shivammathur/setup-php@v2 + - uses: shivammathur/setup-php@2cb9b829437ee246e9b3cac53555a39208ca6d28 + with: + php-version: '8.0' + - uses: actions/checkout@v4 + - name: Copy .env.test.local + run: php -r "file_exists('.env.test.local') || copy('.env.test', '.env.test.local');" + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + - name: Install Dependencies + run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist + - name: Create Database + run: | + mkdir -p data + touch data/database.sqlite + - name: Execute tests (Unit and Feature tests) via PHPUnit + env: + DATABASE_URL: sqlite:///%kernel.project_dir%/data/database.sqlite + run: vendor/bin/phpunit diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml new file mode 100644 index 000000000..540e8040b --- /dev/null +++ b/.github/workflows/terraform.yml @@ -0,0 +1,93 @@ +# This workflow installs the latest version of Terraform CLI and configures the Terraform CLI configuration file +# with an API token for Terraform Cloud (app.terraform.io). On pull request events, this workflow will run +# `terraform init`, `terraform fmt`, and `terraform plan` (speculative plan via Terraform Cloud). On push events +# to the "main" branch, `terraform apply` will be executed. +# +# Documentation for `hashicorp/setup-terraform` is located here: https://github.com/hashicorp/setup-terraform +# +# To use this workflow, you will need to complete the following setup steps. +# +# 1. Create a `main.tf` file in the root of this repository with the `remote` backend and one or more resources defined. +# Example `main.tf`: +# # The configuration for the `remote` backend. +# terraform { +# backend "remote" { +# # The name of your Terraform Cloud organization. +# organization = "example-organization" +# +# # The name of the Terraform Cloud workspace to store Terraform state files in. +# workspaces { +# name = "example-workspace" +# } +# } +# } +# +# # An example resource that does nothing. +# resource "null_resource" "example" { +# triggers = { +# value = "A example resource that does nothing!" +# } +# } +# +# +# 2. Generate a Terraform Cloud user API token and store it as a GitHub secret (e.g. TF_API_TOKEN) on this repository. +# Documentation: +# - https://www.terraform.io/docs/cloud/users-teams-organizations/api-tokens.html +# - https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets +# +# 3. Reference the GitHub secret in step using the `hashicorp/setup-terraform` GitHub Action. +# Example: +# - name: Setup Terraform +# uses: hashicorp/setup-terraform@v1 +# with: +# cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }} + +name: 'Terraform' + +on: + push: + branches: [ "main" ] + pull_request: + +permissions: + contents: read + +jobs: + terraform: + name: 'Terraform' + runs-on: ubuntu-latest + environment: production + + # Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest + defaults: + run: + shell: bash + + steps: + # Checkout the repository to the GitHub Actions runner + - name: Checkout + uses: actions/checkout@v4 + + # Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token + - name: Setup Terraform + uses: hashicorp/setup-terraform@v1 + with: + cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }} + + # Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc. + - name: Terraform Init + run: terraform init + + # Checks that all Terraform configuration files adhere to a canonical format + - name: Terraform Format + run: terraform fmt -check + + # Generates an execution plan for Terraform + - name: Terraform Plan + run: terraform plan -input=false + + # On push to "main", build or change infrastructure according to Terraform configuration files + # Note: It is recommended to set up a required "strict" status check in your repository for "Terraform Cloud". See the documentation on "strict" required status checks for more information: https://help.github.com/en/github/administering-a-repository/types-of-required-status-checks + - name: Terraform Apply + if: github.ref == 'refs/heads/"main"' && github.event_name == 'push' + run: terraform apply -auto-approve -input=false diff --git a/.github/workflows/webpack.yml b/.github/workflows/webpack.yml new file mode 100644 index 000000000..25e64c08e --- /dev/null +++ b/.github/workflows/webpack.yml @@ -0,0 +1,28 @@ +name: NodeJS with Webpack + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [14.x, 16.x, 18.x] + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - name: Build + run: | + npm install + npx webpack diff --git a/ai/ai.py b/ai/ai.py new file mode 100644 index 000000000..338a2be76 --- /dev/null +++ b/ai/ai.py @@ -0,0 +1,43 @@ +import numpy as np +import tensorflow as tf +from tensorflow import keras + +class AI: + def __init__(self, input_shape, output_shape, hidden_layers=None, activation_function=tf.nn.relu): + """ + Initializes the AI class with the specified input and output shapes, and optional hidden layer sizes and activation function. + """ + self.input_shape = input_shape + self.output_shape = output_shape + self.hidden_layers = hidden_layers + self.activation_function = activation_function + + self.model = None + + def build_model(self): + """ + Builds the AI model using the specified input and output shapes, hidden layer sizes, and activation function. + """ + inputs = keras.Input(shape=self.input_shape) + x = inputs + + if self.hidden_layers is not None: + for hidden_layer in self.hidden_layers: + x = keras.layers.Dense(hidden_layer, activation=self.activation_function)(x) + + outputs = keras.layers.Dense(self.output_shape)(x) + + self.model = keras.Model(inputs=inputs, outputs=outputs) + + def train(self, x_train, y_train, epochs=10, batch_size=32): + """ + Trains the AI model using the specified training data, number of epochs, and batch size. + """ + self.model.compile(optimizer="adam", loss="mse") + self.model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size) + + def predict(self, x): + """ + Makes predictions using the AI model for the specified input data. + """ + return self.model.predict(x) diff --git a/ai/data_processing.py b/ai/data_processing.py new file mode 100644 index 000000000..87cff1092 --- /dev/null +++ b/ai/data_processing.py @@ -0,0 +1,33 @@ +import pandas as pd +import numpy as np + +def preprocess_data(data): + """ + Preprocesses the specified data by cleaning, transforming, and scaling it. + """ + # Clean missing values + data = data.dropna() + + # Transform categorical variables to numerical variables + data = pd.get_dummies(data) + + # Scale numerical variables to have zero mean and unit variance + scaler = StandardScaler() + data = pd.DataFrame(scaler.fit_transform(data), columns=data.columns) + + return data + +def split_data(data, test_size=0.2): + """ + Splits the specified data into training and testing sets. + """ + np.random.seed(42) + shuffled_index = np.random.permutation(len(data)) + test_set_size = int(len(data) * test_size) + test_indices = shuffled_index[:test_set_size] + train_indices = shuffled_index[test_set_size:] + + train_data = data.iloc[train_indices] + test_data = data.iloc[test_indices] + + return train_data, test_data diff --git a/api/__init__.py b/api/__init__.py index f02c44442..e61ac4911 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -1,10 +1,12 @@ from flask import Flask -from .endpoints import endpoints + from .authentication import jwt_manager +from .endpoints import endpoints + def create_app(): app = Flask(__name__) - app.config.from_object('config') - app.register_blueprint(endpoints, url_prefix='/api') + app.config.from_object("config") + app.register_blueprint(endpoints, url_prefix="/api") jwt_manager.init_app(app) return app diff --git a/api/endpoints.py b/api/endpoints.py index 8deff8235..6bc4572c6 100644 --- a/api/endpoints.py +++ b/api/endpoints.py @@ -1,24 +1,28 @@ -from flask import Blueprint, request, jsonify +from flask import Blueprint, jsonify, request + from .authentication import jwt_required -from .serializers import UserSchema, TransactionSchema +from .serializers import TransactionSchema, UserSchema + +endpoints = Blueprint("endpoints", __name__) -endpoints = Blueprint('endpoints', __name__) -@endpoints.route('/users', methods=['POST']) +@endpoints.route("/users", methods=["POST"]) def create_user(): user_schema = UserSchema() user = user_schema.load(request.get_json()) # Create user in the database return user_schema.jsonify(user), 201 -@endpoints.route('/users/', methods=['GET']) + +@endpoints.route("/users/", methods=["GET"]) @jwt_required() def get_user(user_id): user = get_user_from_database(user_id) user_schema = UserSchema() return user_schema.jsonify(user) -@endpoints.route('/users/', methods=['PUT']) + +@endpoints.route("/users/", methods=["PUT"]) @jwt_required() def update_user(user_id): user = get_user_from_database(user_id) @@ -27,14 +31,16 @@ def update_user(user_id): # Update user in the database return user_schema.jsonify(user) -@endpoints.route('/users/', methods=['DELETE']) + +@endpoints.route("/users/", methods=["DELETE"]) @jwt_required() def delete_user(user_id): user = get_user_from_database(user_id) # Delete user from the database - return '', 204 + return "", 204 -@endpoints.route('/transactions', methods=['POST']) + +@endpoints.route("/transactions", methods=["POST"]) @jwt_required() def create_transaction(): transaction_schema = TransactionSchema() @@ -42,21 +48,24 @@ def create_transaction(): # Create transaction in the database return transaction_schema.jsonify(transaction), 201 -@endpoints.route('/transactions', methods=['GET']) + +@endpoints.route("/transactions", methods=["GET"]) @jwt_required() def get_transactions(): transactions = get_transactions_from_database() transaction_schema = TransactionSchema(many=True) return transaction_schema.jsonify(transactions) -@endpoints.route('/transactions/', methods=['GET']) + +@endpoints.route("/transactions/", methods=["GET"]) @jwt_required() def get_transaction(transaction_id): transaction = get_transaction_from_database(transaction_id) transaction_schema = TransactionSchema() return transaction_schema.jsonify(transaction) -@endpoints.route('/transactions/', methods=['PUT']) + +@endpoints.route("/transactions/", methods=["PUT"]) @jwt_required() def update_transaction(transaction_id): transaction = get_transaction_from_database(transaction_id) @@ -65,9 +74,10 @@ def update_transaction(transaction_id): # Update transaction in the database return transaction_schema.jsonify(transaction) -@endpoints.route('/transactions/', methods=['DELETE']) + +@endpoints.route("/transactions/", methods=["DELETE"]) @jwt_required() def delete_transaction(transaction_id): transaction = get_transaction_from_database(transaction_id) # Delete transaction from the database - return '', 204 + return "", 204 diff --git a/api/serializers.py b/api/serializers.py index 881af2596..ad0d700fe 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -1,11 +1,13 @@ from marshmallow import Schema, fields + class UserSchema(Schema): id = fields.Int(dump_only=True) name = fields.Str(required=True) email = fields.Email(required=True) password = fields.Str(required=True, load_only=True) + class TransactionSchema(Schema): id = fields.Int(dump_only=True) user_id = fields.Int(required=True) diff --git a/api/test_endpoints.py b/api/test_endpoints.py index 805c982cc..864c6d238 100644 --- a/api/test_endpoints.py +++ b/api/test_endpoints.py @@ -1,7 +1,10 @@ import unittest + from app import create_app + from api.endpoints import endpoints -from api.serializers import UserSchema, TransactionSchema +from api.serializers import TransactionSchema, UserSchema + class TestEndpoints(unittest.TestCase): def setUp(self): @@ -16,11 +19,11 @@ def tearDown(self): def test_create_user(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password': 'testpassword' + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - response = self.client.post('/api/users', json=user_data) + response = self.client.post("/api/users", json=user_data) self.assertEqual(response.status_code, 201) user_schema = UserSchema() user = user_schema.load(response.get_json()) @@ -28,54 +31,51 @@ def test_create_user(self): def test_get_user(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password': 'testpassword' + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - self.client.post('/api/users', json=user_data) - response = self.client.get('/api/users/1') + self.client.post("/api/users", json=user_data) + response = self.client.get("/api/users/1") self.assertEqual(response.status_code, 200) user_schema = UserSchema() user = user_schema.load(response.get_json()) - self.assertEqual(user.name, 'Test User') - self.assertEqual(user.email, 'test@example.com') + self.assertEqual(user.name, "Test User") + self.assertEqual(user.email, "test@example.com") def test_update_user(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password': 'testpassword' + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - self.client.post('/api/users', json=user_data) - user_data['name'] = 'Updated Test User' - response = self.client.put('/api/users/1', json=user_data) + self.client.post("/api/users", json=user_data) + user_data["name"] = "Updated Test User" + response = self.client.put("/api/users/1", json=user_data) self.assertEqual(response.status_code, 200) user_schema = UserSchema() user = user_schema.load(response.get_json()) - self.assertEqual(user.name, 'Updated Test User') + self.assertEqual(user.name, "Updated Test User") def test_delete_user(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password': 'testpassword' + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - self.client.post('/api/users', json=user_data) - response = self.client.delete('/api/users/1') + self.client.post("/api/users", json=user_data) + response = self.client.delete("/api/users/1") self.assertEqual(response.status_code, 204) def test_create_transaction(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password': 'testpassword' - } - self.client.post('/api/users', json=user_data) - transaction_data = { - 'user_id': 1, - 'amount': 100.0 + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - response = self.client.post('/api/transactions', json=transaction_data) + self.client.post("/api/users", json=user_data) + transaction_data = {"user_id": 1, "amount": 100.0} + response = self.client.post("/api/transactions", json=transaction_data) self.assertEqual(response.status_code, 201) transaction_schema = TransactionSchema() transaction = transaction_schema.load(response.get_json()) @@ -83,17 +83,14 @@ def test_create_transaction(self): def test_get_transactions(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password':'testpassword' + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - self.client.post('/api/users', json=user_data) - transaction_data = { - 'user_id': 1, - 'amount': 100.0 - } - self.client.post('/api/transactions', json=transaction_data) - response = self.client.get('/api/transactions') + self.client.post("/api/users", json=user_data) + transaction_data = {"user_id": 1, "amount": 100.0} + self.client.post("/api/transactions", json=transaction_data) + response = self.client.get("/api/transactions") self.assertEqual(response.status_code, 200) transaction_schema = TransactionSchema(many=True) transactions = transaction_schema.load(response.get_json()) @@ -101,17 +98,14 @@ def test_get_transactions(self): def test_get_transaction(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password': 'testpassword' - } - self.client.post('/api/users', json=user_data) - transaction_data = { - 'user_id': 1, - 'amount': 100.0 + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - self.client.post('/api/transactions', json=transaction_data) - response = self.client.get('/api/transactions/1') + self.client.post("/api/users", json=user_data) + transaction_data = {"user_id": 1, "amount": 100.0} + self.client.post("/api/transactions", json=transaction_data) + response = self.client.get("/api/transactions/1") self.assertEqual(response.status_code, 200) transaction_schema = TransactionSchema() transaction = transaction_schema.load(response.get_json()) @@ -119,18 +113,15 @@ def test_get_transaction(self): def test_update_transaction(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password': 'testpassword' + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - self.client.post('/api/users', json=user_data) - transaction_data = { - 'user_id': 1, - 'amount': 100.0 - } - self.client.post('/api/transactions', json=transaction_data) - transaction_data['amount'] = 200.0 - response = self.client.put('/api/transactions/1', json=transaction_data) + self.client.post("/api/users", json=user_data) + transaction_data = {"user_id": 1, "amount": 100.0} + self.client.post("/api/transactions", json=transaction_data) + transaction_data["amount"] = 200.0 + response = self.client.put("/api/transactions/1", json=transaction_data) self.assertEqual(response.status_code, 200) transaction_schema = TransactionSchema() transaction = transaction_schema.load(response.get_json()) @@ -138,15 +129,12 @@ def test_update_transaction(self): def test_delete_transaction(self): user_data = { - 'name': 'Test User', - 'email': 'test@example.com', - 'password': 'testpassword' - } - self.client.post('/api/users', json=user_data) - transaction_data = { - 'user_id': 1, - 'amount': 100.0 + "name": "Test User", + "email": "test@example.com", + "password": "testpassword", } - self.client.post('/api/transactions', json=transaction_data) - response = self.client.delete('/api/transactions/1') + self.client.post("/api/users", json=user_data) + transaction_data = {"user_id": 1, "amount": 100.0} + self.client.post("/api/transactions", json=transaction_data) + response = self.client.delete("/api/transactions/1") self.assertEqual(response.status_code, 204) diff --git a/banking/accounts.py b/banking/accounts.py new file mode 100644 index 000000000..71a3a9781 --- /dev/null +++ b/banking/accounts.py @@ -0,0 +1,34 @@ +class BankAccount: + """ + Represents a bank account with a balance and transaction history. + """ + def __init__(self, account_number, balance=0): + """ + Initializes a new bank account with the specified account number and balance. + """ + self.account_number = account_number + self.balance = balance + self.transaction_history = [] + + def deposit(self, amount): + """ + Deposits the specified amount into the bank account. + """ + self.balance += amount + self.transaction_history.append(f"Deposit: ${amount:.2f}") + + def withdraw(self, amount): + """ + Withdraws the specified amount from the bank account, if sufficient funds are available. + """ + if self.balance >= amount: + self.balance -= amount + self.transaction_history.append(f"Withdraw: ${amount:.2f}") + else: + raise InsufficientFundsError(f"Insufficient funds to withdraw ${amount:.2f} from account {self.account_number}") + +class InsufficientFundsError(Exception): + """ + Raised when there are insufficient funds to complete a withdrawal. + """ + pass diff --git a/banking/bank.py b/banking/bank.py new file mode 100644 index 000000000..f60deb6f8 --- /dev/null +++ b/banking/bank.py @@ -0,0 +1,70 @@ +from banking.accounts import BankAccount, SavingsAccount, CheckingAccount, InsufficientFundsError +from banking.transactions import transfer, pay_bill + +def create_account(account_type, account_number): + """ + Creates a new bank account with the specified account type and account number. + """ + if account_type == "savings": + account = SavingsAccount(account_number) + elif account_type == "checking": + account = CheckingAccount(account_number) + else: + raise ValueError(f"Invalid account type: {account_type}") + + return account + +def get_account(account_number): + """ + Retrieves the bank account with the specified account number. + """ + # Load account data from database or other storage system + account_data = load_account_data(account_number) + + # Create new account if it doesn't exist + if account_data is None: + account_type = None + else: + account_type = account_data["type"] + + account = create_account(account_type, account_number) + + return account + +def save_account(account): + """ + Saves the specified bank account to the database or other storage system. + """ + # Save account data to database or other storage system + save_account_data(account.account_number, account.type, account.balance) + +def process_transaction(transaction): + """ + Processes the specified transaction by transferring funds between bank accounts or paying a bill. + """ + transaction_type = transaction["type"] + + if transaction_type == "transfer": + from_account_number = transaction["from_account"] + to_account_number = transaction["to_account"] + amount = transaction["amount"] + + from_account = get_account(from_account_number) + to_account = get_account(to_account_number) + + transfer(from_account, to_account, amount) + + save_account(from_account) + save_account(to_account) + + elif transaction_type == "pay_bill": + account_number = transaction["account"] + payee = transaction["payee"] + amount = transaction["amount"] + due_date = transaction["due_date"] + + account = get_account(account_number) + + pay_bill(account, payee, amount, due_date) + + save_account(account) diff --git a/banking/transaction.py b/banking/transaction.py new file mode 100644 index 000000000..9c6217151 --- /dev/null +++ b/banking/transaction.py @@ -0,0 +1,16 @@ +from datetime import datetime +from banking.accounts import BankAccount + +def transfer(from_account: BankAccount, to_account: BankAccount, amount): + """ + Transfers the specified amount from the from_account to the to_account. + """ + from_account.withdraw(amount) + to_account.deposit(amount) + + transaction_date = datetime.now() + from_account_number = from_account.account_number + to_account_number = to_account.account_number + transaction_amount = amount + + print(f"Transfer from account {from_account_number} to account {to_account_number} for ${transaction_amount:.2f} on {transaction_date}") diff --git a/banking/transaction_processing.py b/banking/transaction_processing.py new file mode 100644 index 000000000..bc86a6e49 --- /dev/null +++ b/banking/transaction_processing.py @@ -0,0 +1,86 @@ +# banking/transaction_processing.py + +import logging + +def deposit(account_id: int, amount: float) -> bool: + """ + Deposit an amount into an account. + + Args: + account_id (int): The ID of the account. + amount (float): The amount to deposit. + + Returns: + bool: True if the deposit was successful, False otherwise. + """ + # implementation + logging.info(f"Depositing {amount} into account {account_id}") + # Retrieve the account from the database or in-memory data structure + account = get_account_by_id(account_id) + + # Validate the input parameters + if amount < 0: + raise ValueError("Amount cannot be negative") + + # Update the account balance + account['balance'] += amount + + # Save the updated account back to the database or in-memory data structure + save_account(account) + + # Return True to indicate success + return True + +def withdraw(account_id: int, amount: float) -> bool: + """ + Withdraw an amount from an account. + + Args: + account_id (int): The ID of the account. + amount (float): The amount to withdraw. + + Returns: + bool: True if the withdrawal was successful, False otherwise. + """ + # implementation + logging.info(f"Withdrawing {amount} from account {account_id}") + # Retrieve the account from the database or in-memory data structure + account = get_account_by_id(account_id) + + # Validate the input parameters + if amount < 0: + raise ValueError("Amount cannot be negative") + if account['balance'] < amount: + raise ValueError("Insufficient balance") + + # Update the account balance + account['balance'] -= amount + + # Save the updated account back to the database or in-memory data structure + save_account(account) + + # Return True to indicate success + return True + +def transfer(from_account_id: int, to_account_id: int, amount: float) -> bool: + """ + Transfer an amount between two accounts. + + Args: + from_account_id (int): The ID of the source account. + to_account_id (int): The ID of the destination account. + amount (float): The amount to transfer. + + Returns: + bool: True if the transfer was successful, False otherwise. + """ + # implementation + logging.info(f"Transferring {amount} from account {from_account_id} to account {to_account_id}") + # Withdraw the amount from the source account + withdraw(from_account_id, amount) + + # Deposit the amount into the destination account + deposit(to_account_id, amount) + + # Return True to indicate success + return True diff --git a/blockchain/__init__.py b/blockchain/__init__.py index 2fe5e113f..112888f97 100644 --- a/blockchain/__init__.py +++ b/blockchain/__init__.py @@ -1,6 +1,6 @@ -from .pi_network import PiNetwork -from .ethereum import Ethereum from .bitcoin import Bitcoin from .block import Block from .chain import Blockchain +from .ethereum import Ethereum from .miner import Miner +from .pi_network import PiNetwork diff --git a/blockchain/block.py b/blockchain/block.py index ca6f44246..7945ecbae 100644 --- a/blockchain/block.py +++ b/blockchain/block.py @@ -1,6 +1,7 @@ import hashlib import time + class Block: def __init__(self, index, previous_hash, timestamp, data, hash): self.index = index @@ -12,13 +13,13 @@ def __init__(self, index, previous_hash, timestamp, data, hash): @staticmethod def calculate_hash(index, previous_hash, timestamp, data): value = str(index) + str(previous_hash) + str(timestamp) + str(data) - return hashlib.sha256(value.encode('utf-8')).hexdigest() + return hashlib.sha256(value.encode("utf-8")).hexdigest() def __str__(self): - return 'Block: {index}, Previous Hash: {previous_hash}, Timestamp: {timestamp}, Data: {data}, Hash: {hash}'.format( + return "Block: {index}, Previous Hash: {previous_hash}, Timestamp: {timestamp}, Data: {data}, Hash: {hash}".format( index=self.index, previous_hash=self.previous_hash, timestamp=self.timestamp, data=self.data, - hash=self.hash + hash=self.hash, ) diff --git a/blockchain/blockchain.py b/blockchain/blockchain.py new file mode 100644 index 000000000..f56ac485b --- /dev/null +++ b/blockchain/blockchain.py @@ -0,0 +1,40 @@ +import hashlib +import time + +class Block: + def __init__(self, index, previous_hash, timestamp, data, hash): + self.index = index + self.previous_hash = previous_hash + self.timestamp = timestamp + self.data = data + self.hash = hash + +class Blockchain: + def __init__(self): + self.chain = [self.create_genesis_block()] + self.difficulty = 5 + + def create_genesis_block(self): + return Block(0, "0" * 64, int(time.time()), "Genesis Block", self.calculate_hash(0, "0" * 64, int(time.time()), "Genesis Block")) + + def calculate_hash(self, index, previous_hash, timestamp, data): + value = str(index) + str(previous_hash) + str(timestamp) + str(data) + return hashlib.sha256(value.encode('utf-8')).hexdigest() + + def add_block(self, block): + block.previous_hash = self.chain[-1].hash + block.hash = self.calculate_hash(block.index, block.previous_hash, block.timestamp, block.data) + self.chain.append(block) + + def is_valid(self): + for i in range(1, len(self.chain)): + current_block = self.chain[i] + previous_block = self.chain[i - 1] + + if current_block.hash != self.calculate_hash(current_block.index, current_block.previous_hash, current_block.timestamp, current_block.data): + return False + + if previous_block.hash != current_block.previous_hash: + return False + + return True diff --git a/blockchain/chain.py b/blockchain/chain.py index ad5ad80d5..ee2bc218f 100644 --- a/blockchain/chain.py +++ b/blockchain/chain.py @@ -1,23 +1,35 @@ import hashlib + class Blockchain: def __init__(self): self.chain = [self.create_genesis_block()] self.difficulty = 2 def create_genesis_block(self): - return Block(0, '0' * 64, int(time.time()), 'Genesis Block', self.calculate_hash(0, '0' * 64, int(time.time()), 'Genesis Block')) + return Block( + 0, + "0" * 64, + int(time.time()), + "Genesis Block", + self.calculate_hash(0, "0" * 64, int(time.time()), "Genesis Block"), + ) def calculate_hash(self, index, previous_hash, timestamp, data): value = str(index) + str(previous_hash) + str(timestamp) + str(data) - return hashlib.sha256(value.encode('utf-8')).hexdigest() + return hashlib.sha256(value.encode("utf-8")).hexdigest() def is_chain_valid(self, chain): for i in range(1, len(chain)): current_block = chain[i] previous_block = chain[i - 1] - if current_block.hash != self.calculate_hash(current_block.index, current_block.previous_hash, current_block.timestamp, current_block.data): + if current_block.hash != self.calculate_hash( + current_block.index, + current_block.previous_hash, + current_block.timestamp, + current_block.data, + ): return False if current_block.previous_hash != previous_block.hash: @@ -26,8 +38,15 @@ def is_chain_valid(self, chain): return True def add_block(self, data): - new_block = Block(len(self.chain), self.chain[-1].hash, int(time.time()), data, None) - new_block.hash = self.calculate_hash(new_block.index, new_block.previous_hash, new_block.timestamp, new_block.data) + new_block = Block( + len(self.chain), self.chain[-1].hash, int(time.time()), data, None + ) + new_block.hash = self.calculate_hash( + new_block.index, + new_block.previous_hash, + new_block.timestamp, + new_block.data, + ) self.chain.append(new_block) def replace_chain(self, chain): diff --git a/blockchain/miner.py b/blockchain/miner.py index 2a0a17daf..024156d65 100644 --- a/blockchain/miner.py +++ b/blockchain/miner.py @@ -1,6 +1,8 @@ import time + from blockchain.block import Blockchain + class Miner: def __init__(self, blockchain): self.blockchain = blockchain @@ -9,12 +11,12 @@ def mine_block(self, data): while True: if self.blockchain.is_chain_valid(self.blockchain.chain): self.blockchain.add_block(data) - print('Block successfully mined!') - print('Proof of work: {}'.format(self.blockchain.chain[-1].hash)) + print("Block successfully mined!") + print("Proof of work: {}".format(self.blockchain.chain[-1].hash)) break else: - print('Block not mined. Invalid chain.') + print("Block not mined. Invalid chain.") self.blockchain.chain = [self.blockchain.create_genesis_block()] self.blockchain.difficulty += 1 - print('New difficulty: {}'.format(self.blockchain.difficulty)) + print("New difficulty: {}".format(self.blockchain.difficulty)) time.sleep(1) diff --git a/blockchain/test/test_blockchain.py b/blockchain/test/test_blockchain.py index bd7e51ad8..d3217a024 100644 --- a/blockchain/test/test_blockchain.py +++ b/blockchain/test/test_blockchain.py @@ -1,6 +1,8 @@ import unittest + from blockchain import Blockchain + class TestBlockchain(unittest.TestCase): def setUp(self): self.blockchain = Blockchain() @@ -8,40 +10,66 @@ def setUp(self): def test_create_genesis_block(self): genesis_block = self.blockchain.create_genesis_block() self.assertEqual(genesis_block.index, 0) - self.assertEqual(genesis_block.previous_hash, '0' * 64) + self.assertEqual(genesis_block.previous_hash, "0" * 64) self.assertIsNotNone(genesis_block.timestamp) - self.assertEqual(genesis_block.data, 'Genesis Block') - self.assertEqual(genesis_block.hash, '0' * 64) + self.assertEqual(genesis_block.data, "Genesis Block") + self.assertEqual(genesis_block.hash, "0" * 64) def test_calculate_hash(self): block = self.blockchain.create_genesis_block() - block.data = 'New Data' + block.data = "New Data" block.hash = None - calculated_hash = self.blockchain.calculate_hash(block.index, block.previous_hash, block.timestamp, block.data) - self.assertEqual(calculated_hash, '0' * 64) + calculated_hash = self.blockchain.calculate_hash( + block.index, block.previous_hash, block.timestamp, block.data + ) + self.assertEqual(calculated_hash, "0" * 64) def test_is_chain_valid(self): self.assertTrue(self.blockchain.is_chain_valid(self.blockchain.chain)) invalid_chain = self.blockchain.chain[:-1] - invalid_chain.append(Block(len(invalid_chain), invalid_chain[-1].hash, int(time.time()), 'Invalid Data', None)) + invalid_chain.append( + Block( + len(invalid_chain), + invalid_chain[-1].hash, + int(time.time()), + "Invalid Data", + None, + ) + ) self.assertFalse(self.blockchain.is_chain_valid(invalid_chain)) def test_add_block(self): - self.blockchain.add_block('Test Data') + self.blockchain.add_block("Test Data") self.assertEqual(len(self.blockchain.chain), 2) - self.assertEqual(self.blockchain.chain[-1].data, 'Test Data') + self.assertEqual(self.blockchain.chain[-1].data, "Test Data") def test_replace_chain(self): self.blockchain.replace_chain(self.blockchain.chain[:-1]) self.assertEqual(len(self.blockchain.chain), 1) invalid_chain = self.blockchain.chain[:-1] - invalid_chain.append(Block(len(invalid_chain), invalid_chain[-1].hash, int(time.time()), 'Invalid Data', None)) + invalid_chain.append( + Block( + len(invalid_chain), + invalid_chain[-1].hash, + int(time.time()), + "Invalid Data", + None, + ) + ) self.blockchain.replace_chain(invalid_chain) self.assertFalse(self.blockchain.is_chain_valid(self.blockchain.chain)) valid_chain = self.blockchain.chain[:-1] - valid_chain.append(Block(len(valid_chain), valid_chain[-1].hash, int(time.time()), 'Valid Data', None)) + valid_chain.append( + Block( + len(valid_chain), + valid_chain[-1].hash, + int(time.time()), + "Valid Data", + None, + ) + ) self.blockchain.replace_chain(valid_chain) self.assertTrue(self.blockchain.is_chain_valid(self.blockchain.chain)) diff --git a/blockchain/transaction.py b/blockchain/transaction.py new file mode 100644 index 000000000..0a49fcf79 --- /dev/null +++ b/blockchain/transaction.py @@ -0,0 +1,15 @@ +class Transaction: + def __init__(self, sender, receiver, amount): + self.sender = sender + self.receiver = receiver + self.amount = amount + + def to_string(self): + return ( + "Sender: " + + self.sender + + ", Receiver: " + + self.receiver + + ", Amount: " + + str(self.amount) + ) diff --git a/blockchain/wallet.py b/blockchain/wallet.py new file mode 100644 index 000000000..0435c425d --- /dev/null +++ b/blockchain/wallet.py @@ -0,0 +1,14 @@ +import hashlib +import time + +class Wallet: + def __init__(self): + self.private_key = hashlib.sha256(str(time.time()).encode('utf-8')).hexdigest() + self.public_key = hashlib.sha256(self.private_key.encode('utf-8')).hexdigest() + + def generate_address(self): + return hashlib.sha256(self.public_key.encode('utf-8')).hexdigest() + + def send_transaction(self, recipient, amount): + transaction = Transaction(self.generate_address(), recipient, amount) + return transaction diff --git a/customer_service/chatbot.py b/customer_service/chatbot.py index 8ff98a9a1..786d199bd 100644 --- a/customer_service/chatbot.py +++ b/customer_service/chatbot.py @@ -1,5 +1,6 @@ import time + class Chatbot: def __init__(self, nlp_model, knowledge_base): self.nlp_model = nlp_model @@ -9,6 +10,6 @@ def chat(self, user_input): entities = self.nlp_model.extract_entities(user_input) intent = self.nlp_model.extract_intent(user_input) response = self.knowledge_base.get_response(intent) - print('User:', user_input) - print('Chatbot:', response) + print("User:", user_input) + print("Chatbot:", response) time.sleep(1) diff --git a/customer_service/knowledge_base.py b/customer_service/knowledge_base.py index eab799fb7..267a37c3a 100644 --- a/customer_service/knowledge_base.py +++ b/customer_service/knowledge_base.py @@ -1,18 +1,18 @@ class KnowledgeBase: def __init__(self): self.knowledge_base = { - 'account': { - 'open': 'To open a new account, please visit our website and fill out the account opening form.', - 'close': 'To close an existing account, please contact our customer support team.', - 'balance': 'To check your account balance, please log in to your account on our website or mobile app.' + "account": { + "open": "To open a new account, please visit our website and fill out the account opening form.", + "close": "To close an existing account, please contact our customer support team.", + "balance": "To check your account balance, please log in to your account on our website or mobile app.", }, - 'transaction': { - 'make': 'To make a new transaction, please log in to your account on our website or mobile app.', - 'history': 'To view your transaction history, please log in to your account on our website or mobile app.' + "transaction": { + "make": "To make a new transaction, please log in to your account on our website or mobile app.", + "history": "To view your transaction history, please log in to your account on our website or mobile app.", + }, + "other": { + "help": "For assistance, please contact our customer support team." }, - 'other': { - 'help': 'For assistance, please contact our customer support team.' - } } def get_response(self, intent): @@ -21,4 +21,4 @@ def get_response(self, intent): if value: return self.knowledge_base[key] else: - return self.knowledge_base['other'] + return self.knowledge_base["other"] diff --git a/customer_service/natural_language_processing.py b/customer_service/natural_language_processing.py index 07490f49a..6a1aef356 100644 --- a/customer_service/natural_language_processing.py +++ b/customer_service/natural_language_processing.py @@ -1,6 +1,7 @@ import spacy -nlp = spacy.load('en_core_web_sm') +nlp = spacy.load("en_core_web_sm") + class NLP: def __init__(self): @@ -13,14 +14,14 @@ def extract_entities(self, text): def extract_intent(self, text): doc = self.nlp(text) - intents = {'account': False, 'transaction': False, 'other': False} + intents = {"account": False, "transaction": False, "other": False} for token in doc: - if token.text.lower() in ['account', 'accounts']: - intents['account'] = True - elif token.text.lower() in ['transaction', 'transactions']: - intents['transaction'] = True + if token.text.lower() in ["account", "accounts"]: + intents["account"] = True + elif token.text.lower() in ["transaction", "transactions"]: + intents["transaction"] = True if any(intents.values()): return intents else: - intents['other'] = True + intents["other"] = True return intents diff --git a/data_analytics/data_analysis.py b/data_analytics/data_analysis.py index 20bc30414..88523a5c6 100644 --- a/data_analytics/data_analysis.py +++ b/data_analytics/data_analysis.py @@ -2,6 +2,7 @@ import pandas as pd from sklearn.cluster import KMeans + class DataAnalysis: def __init__(self, data): self.data = data @@ -9,16 +10,18 @@ def __init__(self, data): def analyze_data(self): # Perform data cleaning and preprocessing self.data = self.data.dropna() - self.data = pd.get_dummies(self.data, columns=['transaction_type']) + self.data = pd.get_dummies(self.data, columns=["transaction_type"]) # Perform data analysis - kmeans = KMeans(n_clusters=3, random_state=0).fit(self.data[['amount', 'frequency']]) - self.data['cluster'] = kmeans.labels_ + kmeans = KMeans(n_clusters=3, random_state=0).fit( + self.data[["amount", "frequency"]] + ) + self.data["cluster"] = kmeans.labels_ # Perform statistical analysis summary_stats = self.data.describe() - summary_stats.loc['count'] = len(self.data) - summary_stats.loc['mean'] = np.mean(self.data) - summary_stats.loc['std'] = np.std(self.data) + summary_stats.loc["count"] = len(self.data) + summary_stats.loc["mean"] = np.mean(self.data) + summary_stats.loc["std"] = np.std(self.data) return summary_stats diff --git a/data_analytics/data_ingestion.py b/data_analytics/data_ingestion.py index 7cf151c16..5183e94cc 100644 --- a/data_analytics/data_ingestion.py +++ b/data_analytics/data_ingestion.py @@ -1,5 +1,6 @@ import pandas as pd + class DataIngestion: def __init__(self, data_source): self.data_source = data_source diff --git a/data_analytics/data_visualization.py b/data_analytics/data_visualization.py index 96414dd96..3f711a046 100644 --- a/data_analytics/data_visualization.py +++ b/data_analytics/data_visualization.py @@ -1,16 +1,17 @@ import plotly.express as px + class DataVisualization: def __init__(self, data): self.data = data def visualize_data(self): # Create interactive dashboards - fig = px.scatter(self.data, x='amount', y='frequency', color='cluster') + fig = px.scatter(self.data, x="amount", y="frequency", color="cluster") fig.show() - fig = px.histogram(self.data, x='transaction_type', nbins=20) + fig = px.histogram(self.data, x="transaction_type", nbins=20) fig.show() - fig = px.box(self.data, x='cluster', y='amount') + fig = px.box(self.data, x="cluster", y="amount") fig.show() diff --git a/database/database.py b/database/database.py index e8b01f30d..297d7e2e7 100644 --- a/database/database.py +++ b/database/database.py @@ -1,20 +1,27 @@ import sqlite3 + class Database: def __init__(self): - self.connection = sqlite3.connect('banking.db') + self.connection = sqlite3.connect("banking.db") self.cursor = self.connection.cursor() def create_table(self): - self.cursor.execute('''CREATE TABLE IF NOT EXISTS accounts (id INTEGER PRIMARY KEY, name TEXT, balance REAL)''') + self.cursor.execute( + """CREATE TABLE IF NOT EXISTS accounts (id INTEGER PRIMARY KEY, name TEXT, balance REAL)""" + ) self.connection.commit() def insert_account(self, name, balance): - self.cursor.execute("INSERT INTO accounts (name, balance) VALUES (?, ?)", (name, balance)) + self.cursor.execute( + "INSERT INTO accounts (name, balance) VALUES (?, ?)", (name, balance) + ) self.connection.commit() def update_account(self, id, name, balance): - self.cursor.execute("UPDATE accounts SET name=?, balance=? WHERE id=?", (name, balance, id)) + self.cursor.execute( + "UPDATE accounts SET name=?, balance=? WHERE id=?", (name, balance, id) + ) self.connection.commit() def delete_account(self, id): diff --git a/fraud_detection/anomaly_detection.py b/fraud_detection/anomaly_detection.py index 290777c23..1295cd588 100644 --- a/fraud_detection/anomaly_detection.py +++ b/fraud_detection/anomaly_detection.py @@ -2,6 +2,7 @@ import pandas as pd from sklearn.ensemble import IsolationForest + class AnomalyDetection: def __init__(self, transaction_data): self.transaction_data = transaction_data diff --git a/fraud_detection/fraud_detection_model.py b/fraud_detection/fraud_detection_model.py index 7182d5030..edac1a2fa 100644 --- a/fraud_detection/fraud_detection_model.py +++ b/fraud_detection/fraud_detection_model.py @@ -3,14 +3,17 @@ from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split + class FraudDetectionModel: def __init__(self, data): self.data = data - self.X = self.data.drop('fraudulent', axis=1) - self.y = self.data['fraudulent'] + self.X = self.data.drop("fraudulent", axis=1) + self.y = self.data["fraudulent"] def train_model(self): - X_train, X_test, y_train, y_test = train_test_split(self.X, self.y, test_size=0.2, random_state=42) + X_train, X_test, y_train, y_test = train_test_split( + self.X, self.y, test_size=0.2, random_state=42 + ) self.model = RandomForestClassifier(n_estimators=100, random_state=42) self.model.fit(X_train, y_train) diff --git a/fraud_detection/fraud_response.py b/fraud_detection/fraud_response.py index b4ee601cd..199695e3e 100644 --- a/fraud_detection/fraud_response.py +++ b/fraud_detection/fraud_response.py @@ -6,13 +6,13 @@ def __init__(self, fraud_detection_model, anomaly_detection): def respond_to_fraud(self, transactions): for transaction in transactions: fraud_level = self.fraud_detection_model.predict_fraud(transaction) - if fraud_level == 'fraudulent': + if fraud_level == "fraudulent": anomaly_score = self.anomaly_detection.detect_anomalies(transaction) if anomaly_score == -1: # Implement fraud response strategies here # For example, you could flag the transaction for review or decline it altogether - print('Fraudulent transaction detected: Flagged for review') + print("Fraudulent transaction detected: Flagged for review") else: - print('Anomalous transaction detected: Flagged for review') + print("Anomalous transaction detected: Flagged for review") else: - print('Non-fraudulent transaction detected: Transaction approved') + print("Non-fraudulent transaction detected: Transaction approved") diff --git a/hardware_integration/hardware.py b/hardware_integration/hardware.py new file mode 100644 index 000000000..888d1c51a --- /dev/null +++ b/hardware_integration/hardware.py @@ -0,0 +1,29 @@ +import RPi.GPIO as GPIO + +def setup_i2c(sda_pin, scl_pin): + """ + Sets up the I2C communication protocol using the specified SDA and SCL pins. + """ + GPIO.setmode(GPIO.BCM) + GPIO.setup(sda_pin, GPIO.OUT) + GPIO.setup(scl_pin, GPIO.OUT) + GPIO.output(sda_pin, GPIO.HIGH) + GPIO.output(scl_pin, GPIO.HIGH) + GPIO.setmode(GPIO.BCM) + GPIO.setup(sda_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) + GPIO.setup(scl_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) + +def setup_spi(sclk_pin, mosi_pin, miso_pin): + """ + Sets up the SPI communication protocol using the specified SCLK, MOSI, and MISO pins. + """ + GPIO.setmode(GPIO.BCM) + GPIO.setup(sclk_pin, GPIO.OUT) + GPIO.setup(mosi_pin, GPIO.OUT) + GPIO.setup(miso_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) + +def cleanup(): + """ + Cleans up the GPIO pins and resets the GPIO library. + """ + GPIO.cleanup() diff --git a/hardware_integration/sensor.py b/hardware_integration/sensor.py new file mode 100644 index 000000000..b6b37c29e --- /dev/null +++ b/hardware_integration/sensor.py @@ -0,0 +1,49 @@ +import hardware + +def read_temperature_sensor(i2c_address): + """ + Reads the temperature from the specified I2C temperature sensor. + """ + # Set up I2C communication + sda_pin = 2 + scl_pin = 3 + hardware.setup_i2c(sda_pin, scl_pin) + + # Read temperature sensor data + temperature_data = [0x00, 0x00] + for i in range(2): + hardware.write_i2c_data(i2c_address, [0x00], 1) + temperature_data[i] = hardware.read_i2c_data(i2c_address, 1)[0] + + # Convert temperature data to temperature value + temperature = (temperature_data[0] << 8) | temperature_data[1] + temperature = temperature / 16.0 + + # Clean up I2C communication + hardware.cleanup() + + return temperature + +def read_humidity_sensor(i2c_address): + """ + Reads the humidity from the specified I2C humidity sensor. + """ + # Set up I2C communication + sda_pin = 2 + scl_pin = 3 + hardware.setup_i2c(sda_pin, scl_pin) + + # Read humidity sensor data + humidity_data = [0x00, 0x00] + for i in range(2): + hardware.write_i2c_data(i2c_address, [0x00], 1) + humidity_data[i] = hardware.read_i2c_data(i2c_address, 1)[0] + + # Convert humidity data to humidity value + humidity = (humidity_data[0] << 8) | humidity_data[1] + humidity = humidity / 16.0 + + # Clean up I2C communication + hardware.cleanup() + + return humidity diff --git a/logging/logging.py b/logging/logging.py index 0db567ee3..dea11d2be 100644 --- a/logging/logging.py +++ b/logging/logging.py @@ -1,12 +1,13 @@ import logging + class Logging: def __init__(self): - self.logger = logging.getLogger('banking_network') + self.logger = logging.getLogger("banking_network") self.logger.setLevel(logging.DEBUG) def setup_logging(self): - formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") console_handler = logging.StreamHandler() console_handler.setLevel(logging.DEBUG) console_handler.setFormatter(formatter) diff --git a/machine_learning/machine_learning.py b/machine_learning/machine_learning.py index f53b8d14a..67f4caf10 100644 --- a/machine_learning/machine_learning.py +++ b/machine_learning/machine_learning.py @@ -1,19 +1,20 @@ -import pandas as pd import numpy as np +import pandas as pd from sklearn.linear_model import LinearRegression + class MachineLearning: def __init__(self): pass def train_model(self, data): - X = data[['feature1', 'feature2']] - y = data['target'] + X = data[["feature1", "feature2"]] + y = data["target"] model = LinearRegression() model.fit(X, y) return model def predict(self, model, data): - X = data[['feature1', 'feature2']] + X = data[["feature1", "feature2"]] y = model.predict(X) return y diff --git a/network/communication.py b/network/communication.py new file mode 100644 index 000000000..a5d98ef28 --- /dev/null +++ b/network/communication.py @@ -0,0 +1,51 @@ +import json +import requests +import websockets + +def send_http_request(url, method, headers=None, data=None): + """ + Sends an HTTP request to the specified URL using the specified method, headers, and data. + """ + if headers is None: + headers = {} + + if method == "GET": + response = requests.get(url, headers=headers, data=data) + elif method == "POST": + response = requests.post(url, headers=headers, data=json.dumps(data)) + elif method == "PUT": + response = requests.put(url, headers=headers, data=json.dumps(data)) + elif method == "DELETE": +response = requests.delete(url, headers=headers, data=data) + else: + raise ValueError("Invalid HTTP method") + + if response.status_code != 200: + raise Exception("HTTP request failed with status code {}".format(response.status_code)) + + return response.json() + +def send_websocket_message(websocket, message): + """ + Sends a message over a WebSocket connection. + """ + websocket.send(json.dumps(message)) + +def receive_websocket_message(websocket): + """ + Receives a message over a WebSocket connection. + """ + return json.loads(websocket.recv()) + +def create_websocket_connection(url): + """ + Creates a new WebSocket connection to the specified URL. + """ + websocket = websockets.connect(url) + return websocket + +def close_websocket_connection(websocket): + """ + Closes the specified WebSocket connection. + """ + websocket.close() diff --git a/network/networking.py b/network/networking.py index 0425688bf..177b46779 100644 --- a/network/networking.py +++ b/network/networking.py @@ -1,8 +1,9 @@ import socket + class Networking: def __init__(self): - self.host = '0.0.0.0' + self.host = "0.0.0.0" self.port = 8080 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.bind((self.host, self.port)) @@ -11,7 +12,7 @@ def listen_for_connections(self): self.socket.listen(5) while True: connection, address = self.socket.accept() - print(f'Connection from {address} has been established!') + print(f"Connection from {address} has been established!") self.handle_connection(connection) def handle_connection(self, connection): diff --git a/quantum_module/quantum_encryption.py b/quantum_module/quantum_encryption.py new file mode 100644 index 000000000..8a2cd47c6 --- /dev/null +++ b/quantum_module/quantum_encryption.py @@ -0,0 +1,46 @@ +# Import necessary libraries +import numpy as np +from qiskit import QuantumCircuit, execute +from qiskit.providers.aer import AerSimulator + +# Define a function to generate a quantum key +def generate_quantum_key(size): + # Create a quantum circuit with two qubits + qc = QuantumCircuit(2) + + # Apply Hadamard gates to both qubits + qc.h(0) + qc.h(1) + + # Measure the qubits to generate a random key + qc.measure_all() + + # Execute the circuit on a simulator + simulator = AerSimulator() + job = execute(qc, simulator, shots=1) + result = job.result() + key = result.get_counts(qc) + + # Convert the key to a binary string + key_str = ''.join(format(x, 'b') for x in key) + + return key_str[:size] + +# Define a function to encrypt data using quantum encryption +def encrypt_data(plain_text, key): + # Convert the plain text to a binary string + plain_text_bin = ''.join(format(ord(c), '08b') for c in plain_text) + + # Encrypt the plain text using the quantum key + cipher_text_bin = ''.join(str(int(plain_text_bin[i]) ^ int(key[i % len(key)])) for i in range(len(plain_text_bin))) + + # Convert the cipher text back to a string + cipher_text = ''.join(chr(int(cipher_text_bin[i*8:i*8+8], 2)) for i in range(len(cipher_text_bin)//8)) + + return cipher_text + +# Example usage +key = generate_quantum_key(256) +plain_text = "This is a secret message" +cipher_text = encrypt_data(plain_text, key) +print("Encrypted text:", cipher_text) diff --git a/quantum_module/quantum_optimization.py b/quantum_module/quantum_optimization.py new file mode 100644 index 000000000..c5832a997 --- /dev/null +++ b/quantum_module/quantum_optimization.py @@ -0,0 +1,43 @@ +# Import necessary libraries +import numpy as np +from qiskit import QuantumCircuit, execute +from qiskit.providers.aer import AerSimulator +from qiskit.optimization import QuadraticProgram + +# Define a function to optimize a portfolio using quantum computing +def optimize_portfolio(stocks, weights, risk_tolerance): + # Define the quadratic program + qp = QuadraticProgram() + qp.binary_var_list(stocks, name='x') + qp.minimize(linear={stocks[i]: weights[i] for i in range(len(stocks))}) + qp.subject_to(LinearConstraint(sense='LE', rhs=risk_tolerance, coeffs={stocks[i]: weights[i] for i in range(len(stocks))})) + + # Convert the quadratic program to a QUBO problem + qubo = qp.to_qubo() + + # Create a quantum circuit to solve the QUBO problem + qc = QuantumCircuit(len(stocks)) + qc.h(range(len(stocks))) + qc.barrier() + qc.x(range(len(stocks))) + qc.barrier() + qc.measure_all() + + # Execute the circuit on a simulator + simulator = AerSimulator() + job = execute(qc, simulator, shots=1000) + result = job.result() + counts = result.get_counts(qc) + + # Extract the optimal solution from the counts + optimal_solution = max(counts, key=counts.get) + optimal_portfolio = [stocks[i] for i, x in enumerate(optimal_solution) if x == '1'] + + return optimal_portfolio + +# Example usage +stocks = ['AAPL', 'GOOG', 'MSFT'] +weights = [0.3, 0.4, 0.3] +risk_tolerance = 0.5 +optimal_portfolio = optimize_portfolio(stocks, weights, risk_tolerance) +print("Optimal portfolio:", optimal_portfolio) diff --git a/quantum_module/quantum_simulation.py b/quantum_module/quantum_simulation.py new file mode 100644 index 000000000..36a5cc522 --- /dev/null +++ b/quantum_module/quantum_simulation.py @@ -0,0 +1,37 @@ +# Import necessary libraries +import numpy as np +from qiskit import QuantumCircuit, execute +from qiskit.providers.aer import AerSimulator + +# Define a function to simulate a complex financial scenario using quantum computing +def simulate_financial_scenario(initial_investment, interest_rate, time_steps): + # Create a quantum circuit to simulate the financial scenario + qc = QuantumCircuit(1) + qc.h(0) + qc.barrier() + for i in range(time_steps): + qc.rx(np.arcsin(interest_rate), 0) + qc.barrier() + qc.measure_all() + + # Execute the circuit on a simulator + simulator = AerSimulator() + job = execute(qc, simulator, shots=1000) + result = job.result() + counts = result.get_counts(qc) + + # Extract the final investment from the counts + final_investment = initial_investment * (1 + interest_rate) ** time_steps + for i in range(time_steps): + final_investment *= (1 + interest_rate) + final_investment = final_investment / 1000 + final_investment = sum(counts[x] * final_investment for x in counts) + + return final_investment + +# Example usage +initial_investment = 1000 +interest_rate = 0.05 +time_steps = 10 +final_investment = simulate_financial_scenario(initial_investment, interest_rate, time_steps) +print("Final investment:", final_investment) diff --git a/risk_management/risk_assessment.py b/risk_management/risk_assessment.py index 6bdb51647..22e91a390 100644 --- a/risk_management/risk_assessment.py +++ b/risk_management/risk_assessment.py @@ -3,14 +3,17 @@ from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split + class RiskAssessment: def __init__(self, data): self.data = data - self.X = self.data.drop('risk_level', axis=1) - self.y = self.data['risk_level'] + self.X = self.data.drop("risk_level", axis=1) + self.y = self.data["risk_level"] def train_model(self): - X_train, X_test, y_train, y_test = train_test_split(self.X, self.y, test_size=0.2, random_state=42) + X_train, X_test, y_train, y_test = train_test_split( + self.X, self.y, test_size=0.2, random_state=42 + ) self.model = RandomForestClassifier(n_estimators=100, random_state=42) self.model.fit(X_train, y_train) diff --git a/risk_management/risk_mitigation.py b/risk_management/risk_mitigation.py index 77d3327ca..c7166831e 100644 --- a/risk_management/risk_mitigation.py +++ b/risk_management/risk_mitigation.py @@ -4,13 +4,13 @@ def __init__(self, risk_assessment_model): def mitigate_risk(self, transaction): risk_level = self.risk_assessment_model.predict_risk(transaction) - if risk_level == 'high': + if risk_level == "high": # Implement risk mitigation strategies here # For example, you could flag the transaction for review or decline it altogether - return 'Flagged for review' - elif risk_level == 'medium': + return "Flagged for review" + elif risk_level == "medium": # Implement risk mitigation strategies here # For example, you could require additional authentication or verification - return 'Additional authentication required' + return "Additional authentication required" else: - return 'Transaction approved' + return "Transaction approved" diff --git a/risk_management/risk_monitoring.py b/risk_management/risk_monitoring.py index 52eaa2db9..653c69773 100644 --- a/risk_management/risk_monitoring.py +++ b/risk_management/risk_monitoring.py @@ -1,5 +1,6 @@ import time + class RiskMonitoring: def __init__(self, risk_assessment_model, risk_mitigation_model): self.risk_assessment_model = risk_assessment_model @@ -8,12 +9,16 @@ def __init__(self, risk_assessment_model, risk_mitigation_model): def monitor_risks(self, transactions): for transaction in transactions: risk_level = self.risk_assessment_model.predict_risk(transaction) - if risk_level == 'high': - mitigation_result = self.risk_mitigation_model.mitigate_risk(transaction) - print(f'High-risk transaction detected: {mitigation_result}') - elif risk_level == 'medium': - mitigation_result = self.risk_mitigation_model.mitigate_risk(transaction) - print(f'Medium-risk transaction detected: {mitigation_result}') + if risk_level == "high": + mitigation_result = self.risk_mitigation_model.mitigate_risk( + transaction + ) + print(f"High-risk transaction detected: {mitigation_result}") + elif risk_level == "medium": + mitigation_result = self.risk_mitigation_model.mitigate_risk( + transaction + ) + print(f"Medium-risk transaction detected: {mitigation_result}") else: - print(f'Low-risk transaction detected: Transaction approved') + print(f"Low-risk transaction detected: Transaction approved") time.sleep(1) diff --git a/security/authentication.py b/security/authentication.py index f85c9eb66..54d08b6c3 100644 --- a/security/authentication.py +++ b/security/authentication.py @@ -1,14 +1,19 @@ import hashlib import secrets + class Authentication: def __init__(self): self.salt = secrets.token_hex(16) def generate_password_hash(self, password): - password_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), self.salt.encode(), 100000) + password_hash = hashlib.pbkdf2_hmac( + "sha256", password.encode(), self.salt.encode(), 100000 + ) return password_hash.hex() def verify_password(self, password, password_hash): - password_hash_check = hashlib.pbkdf2_hmac('sha256', password.encode(), self.salt.encode(), 100000) + password_hash_check = hashlib.pbkdf2_hmac( + "sha256", password.encode(), self.salt.encode(), 100000 + ) return password_hash_check.hex() == password_hash diff --git a/smart_contracts/contract.py b/smart_contracts/contract.py new file mode 100644 index 000000000..589a4e277 --- /dev/null +++ b/smart_contracts/contract.py @@ -0,0 +1,31 @@ +import hashlib +import time +from transaction import Transaction + +class Contract: + def __init__(self, address, code): + self.address = address + self.code = code + self.state = {} + + def execute(self, transaction): + # Check if the transaction sender has enough funds + if self.state.get(transaction.sender, 0) < transaction.amount: + return False + + # Execute the contract code + code_output = eval(self.code) + + # Update the contract state + self.state[transaction.receiver] = self.state.get(transaction.receiver, 0) + transaction.amount + self.state[transaction.sender] = self.state.get(transaction.sender, 0) - transaction.amount + + # Return the output of the contract code + return code_output + + def to_dict(self): + return { + 'address': self.address, + 'code': self.code, + 'state': self.state + } diff --git a/src/app.js b/src/app.js index a2ed7cd55..286ba6401 100644 --- a/src/app.js +++ b/src/app.js @@ -1,35 +1,35 @@ -const express = require("express"); -const bodyParser = require("body-parser"); -const cors = require("cors"); -const mongoose = require("mongoose"); +const express = require('express') +const bodyParser = require('body-parser') +const cors = require('cors') +const mongoose = require('mongoose') -const { JWT_SECRET, MONGODB_URI } = process.env; +const { JWT_SECRET, MONGODB_URI } = process.env -const app = express(); +const app = express() -app.use(bodyParser.json()); -app.use(cors()); +app.use(bodyParser.json()) +app.use(cors()) -const router = require("./routes"); -app.use("/api", router); +const router = require('./routes') +app.use('/api', router) const connectToMongoDB = async () => { try { await mongoose.connect(MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true, - useCreateIndex: true, - }); - console.log("Connected to MongoDB"); + useCreateIndex: true + }) + console.log('Connected to MongoDB') } catch (error) { - console.error("Failed to connect to MongoDB", error); - process.exit(1); + console.error('Failed to connect to MongoDB', error) + process.exit(1) } -}; +} -connectToMongoDB(); +connectToMongoDB() -const PORT = process.env.PORT || 5000; +const PORT = process.env.PORT || 5000 app.listen(PORT, () => { - console.log(`Server running on port ${PORT}`); -}); + console.log(`Server running on port ${PORT}`) +}) diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 7a59dbdaf..8b93c643f 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -1,16 +1,16 @@ -const Account = require("../models/account"); +const Account = require('../models/account') exports.list = async (req, res) => { - const accounts = await Account.find({ owner: req.user._id }); - res.json(accounts); -}; + const accounts = await Account.find({ owner: req.user._id }) + res.json(accounts) +} exports.create = async (req, res) => { const account = new Account({ account_name: req.body.account_name, initial_balance: req.body.initial_balance, - owner: req.user._id, - }); - await account.save(); - res.json({ message: "Account created!", account }); -}; + owner: req.user._id + }) + await account.save() + res.json({ message: 'Account created!', account }) +} diff --git a/src/controllers/index.js b/src/controllers/index.js index 639a0fa07..6a19656de 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -1,10 +1,10 @@ -const express = require("express"); -const router = express.Router(); +const express = require('express') +const router = express.Router() -const AccountsController = require("./accounts"); -const TransfersController = require("./transfers"); +const AccountsController = require('./accounts') +const TransfersController = require('./transfers') -router.use("/accounts", AccountsController); -router.use("/transfers", TransfersController); +router.use('/accounts', AccountsController) +router.use('/transfers', TransfersController) -module.exports = router; +module.exports = router diff --git a/src/controllers/transfers.js b/src/controllers/transfers.js index ecc8b9e1f..b20c4b778 100644 --- a/src/controllers/transfers.js +++ b/src/controllers/transfers.js @@ -1,31 +1,31 @@ -const Transfer = require("../models/transfer"); -const Account = require("../models/account"); +const Transfer = require('../models/transfer') +const Account = require('../models/account') exports.create = async (req, res) => { - const senderAccount = await Account.findById(req.body.sender_account_id); - const receiverAccount = await Account.findById(req.body.receiver_account_id); + const senderAccount = await Account.findById(req.body.sender_account_id) + const receiverAccount = await Account.findById(req.body.receiver_account_id) if (!senderAccount || !receiverAccount) { - return res.status(400).json({ message: "Account not found" }); + return res.status(400).json({ message: 'Account not found' }) } if (senderAccount.balance < req.body.amount) { - return res.status(400).json({ message: "Insufficient balance" }); + return res.status(400).json({ message: 'Insufficient balance' }) } const transfer = new Transfer({ sender_account_id: req.body.sender_account_id, receiver_account_id: req.body.receiver_account_id, - amount: req.body.amount, - }); + amount: req.body.amount + }) - await transfer.save(); + await transfer.save() - senderAccount.balance -= req.body.amount; - receiverAccount.balance += req.body.amount; + senderAccount.balance -= req.body.amount + receiverAccount.balance += req.body.amount - await senderAccount.save(); - await receiverAccount.save(); + await senderAccount.save() + await receiverAccount.save() - res.json({ message: "Transfer successful", transfer }); -}; + res.json({ message: 'Transfer successful', transfer }) +} diff --git a/src/middleware/auth.js b/src/middleware/auth.js index 46ae82670..3c436ec5a 100644 --- a/src/middleware/auth.js +++ b/src/middleware/auth.js @@ -1,20 +1,20 @@ -const jwt = require("jsonwebtoken"); -const User = require("../models/user"); +const jwt = require('jsonwebtoken') +const User = require('../models/user') const authenticate = async (req, res, next) => { - const token = req.header("Authorization")?.split(" ")[1]; + const token = req.header('Authorization')?.split(' ')[1] if (!token) { - return res.status(401).json({ message: "Access Denied" }); + return res.status(401).json({ message: 'Access Denied' }) } try { - const decoded = jwt.verify(token, process.env.JWT_SECRET); - req.user = await User.findById(decoded.user_id); - next(); + const decoded = jwt.verify(token, process.env.JWT_SECRET) + req.user = await User.findById(decoded.user_id) + next() } catch (error) { - res.status(400).json({ message: "Invalid Token" }); + res.status(400).json({ message: 'Invalid Token' }) } -}; +} -module.exports = authenticate; +module.exports = authenticate diff --git a/src/middleware/network.js b/src/middleware/network.js index 8e58f6c1b..636f053e5 100644 --- a/src/middleware/network.js +++ b/src/middleware/network.js @@ -1,30 +1,40 @@ -const { PRIVATE_KEY, PRIVATE_KEY_PASSWORD, PRIVATE_KEY_PASSWORD_SALT, ENDPOINT, CHAIN_ID } = process.env; +const { + PRIVATE_KEY, + PRIVATE_KEY_PASSWORD, + PRIVATE_KEY_PASSWORD_SALT, + ENDPOINT, + CHAIN_ID +} = process.env -const Web3 = require("web3"); -const EthereumTx = require("ethereumjs-tx"); +const Web3 = require('web3') +const EthereumTx = require('ethereumjs-tx') -const web3 = new Web3(new Web3.providers.HttpProvider(ENDPOINT)); +const web3 = new Web3(new Web3.providers.HttpProvider(ENDPOINT)) const createTransaction = async (from, to, value) => { - const nonce = await web3.eth.getTransactionCount(from); - const gasPrice = await web3.eth.getGasPrice(); - const gasLimit = 21000; + const nonce = await web3.eth.getTransactionCount(from) + const gasPrice = await web3.eth.getGasPrice() + const gasLimit = 21000 const tx = new EthereumTx({ nonce, gasPrice, gasLimit, to, - value, - }); + value + }) - const privateKey = web3.utils.sha3(PRIVATE_KEY_PASSWORD + PRIVATE_KEY_PASSWORD_SALT); - tx.sign(privateKey); + const privateKey = web3.utils.sha3( + PRIVATE_KEY_PASSWORD + PRIVATE_KEY_PASSWORD_SALT + ) + tx.sign(privateKey) - const serializedTx = tx.serialize(); - const transactionHash = await web3.eth.sendSignedTransaction("0x" + serializedTx.toString("hex")); + const serializedTx = tx.serialize() + const transactionHash = await web3.eth.sendSignedTransaction( + '0x' + serializedTx.toString('hex') + ) - return transactionHash; -}; + return transactionHash +} -module.exports = createTransaction; +module.exports = createTransaction diff --git a/src/models/transfer.js b/src/models/transfer.js index d1cf4802b..ca77421f7 100644 --- a/src/models/transfer.js +++ b/src/models/transfer.js @@ -1,12 +1,16 @@ -const mongoose = require("mongoose"); +const mongoose = require('mongoose') const transferSchema = new mongoose.Schema({ - sender_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }, + sender_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, receiver_account_id: { type: String, required: true }, amount: { type: Number, required: true }, - transaction_hash: { type: String }, -}); + transaction_hash: { type: String } +}) -const Transfer = mongoose.model("Transfer", transferSchema); +const Transfer = mongoose.model('Transfer', transferSchema) -module.exports = Transfer; +module.exports = Transfer diff --git a/src/models/user.js b/src/models/user.js index e827eec76..2e171d0da 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -1,20 +1,20 @@ -const mongoose = require("mongoose"); -const bcrypt = require("bcrypt"); +const mongoose = require('mongoose') +const bcrypt = require('bcrypt') const UserSchema = new mongoose.Schema({ username: { type: String, required: true, unique: true }, - password: { type: String, required: true }, -}); + password: { type: String, required: true } +}) -UserSchema.pre("save", async function (next) { - if (this.isModified("password")) { - this.password = await bcrypt.hash(this.password, 10); +UserSchema.pre('save', async function (next) { + if (this.isModified('password')) { + this.password = await bcrypt.hash(this.password, 10) } - next(); -}); + next() +}) UserSchema.methods.comparePassword = function (password) { - return bcrypt.compare(password, this.password); -}; + return bcrypt.compare(password, this.password) +} -module.exports = mongoose.model("User", UserSchema); +module.exports = mongoose.model('User', UserSchema) diff --git a/src/routes/index.js b/src/routes/index.js index d1800ab91..cdb9ac6b2 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,8 +1,8 @@ -const express = require("express"); -const router = express.Router(); +const express = require('express') +const router = express.Router() -router.get("/", (req, res) => { - res.json({ message: "Welcome to the PI Nexus Autonomous Banking Network!" }); -}); +router.get('/', (req, res) => { + res.json({ message: 'Welcome to the PI Nexus Autonomous Banking Network!' }) +}) -module.exports = router; +module.exports = router diff --git a/src/routes/transfers.js b/src/routes/transfers.js index 01b221fe7..a61bd45bc 100644 --- a/src/routes/transfers.js +++ b/src/routes/transfers.js @@ -1,20 +1,24 @@ -const express = require("express"); -const router = express.Router(); +const express = require('express') +const router = express.Router() -const TransferController = require("../controllers/transfers"); -const authenticate = require("../middleware/auth"); -const createTransaction = require("../middleware/network"); +const TransferController = require('../controllers/transfers') +const authenticate = require('../middleware/auth') +const createTransaction = require('../middleware/network') -router.post("/", authenticate, async (req, res) => { +router.post('/', authenticate, async (req, res) => { try { - const transfer = await TransferController.create(req, res); - const transactionHash = await createTransaction(req.user.wallet_address, req.body.receiver_account_id, req.body.amount); - transfer.transaction_hash = transactionHash; - await transfer.save(); - res.json({ message: "Transfer successful", transfer }); + const transfer = await TransferController.create(req, res) + const transactionHash = await createTransaction( + req.user.wallet_address, + req.body.receiver_account_id, + req.body.amount + ) + transfer.transaction_hash = transactionHash + await transfer.save() + res.json({ message: 'Transfer successful', transfer }) } catch (error) { - res.status(400).json({ message: error.message }); + res.status(400).json({ message: error.message }) } -}); +}) -module.exports = router; +module.exports = router diff --git a/src/tests/integration_tests/test_ui.py b/src/tests/integration_tests/test_ui.py index 9d7546cde..60627e4e2 100644 --- a/src/tests/integration_tests/test_ui.py +++ b/src/tests/integration_tests/test_ui.py @@ -2,13 +2,15 @@ import pytest from selenium import webdriver from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait + @pytest.fixture def browser(): return webdriver.Chrome() + def test_login(browser): # Test login functionality browser.get("https://pi-nexus-autonomous-banking-network.com/login") @@ -19,12 +21,14 @@ def test_login(browser): browser.find_element_by_name("login").click() WebDriverWait(browser, 10).until(EC.title_contains("Dashboard")) + def test_account_list(browser): # Test account list page browser.get("https://pi-nexus-autonomous-banking-network.com/accounts") account_list = browser.find_elements_by_css_selector(".account-list li") assert len(account_list) > 0 + def test_create_account(browser): # Test create account functionality browser.get("https://pi-nexus-autonomous-banking-network.com/accounts/new") diff --git a/system_monitoring/issue_detection.py b/system_monitoring/issue_detection.py index 8e65205c6..ee70d6e36 100644 --- a/system_monitoring/issue_detection.py +++ b/system_monitoring/issue_detection.py @@ -4,8 +4,8 @@ def __init__(self, system_monitoring): def detect_issues(self): if self.system_monitoring.cpu_percent > 80: - print('High CPU usage detected!') + print("High CPU usage detected!") if self.system_monitoring.memory_percent > 80: - print('High memory usage detected!') + print("High memory usage detected!") if self.system_monitoring.disk_percent > 80: - print('High disk usage detected!') + print("High disk usage detected!") diff --git a/system_monitoring/self_healing.py b/system_monitoring/self_healing.py index c0cc472de..f88eed8f4 100644 --- a/system_monitoring/self_healing.py +++ b/system_monitoring/self_healing.py @@ -1,10 +1,11 @@ import subprocess + class SelfHealing: def __init__(self): pass def heal_system(self): # Implement automatic healing techniques - subprocess.run(['systemctl', 'restart', 'nginx']) - subprocess.run(['systemctl', 'restart', 'postgresql']) + subprocess.run(["systemctl", "restart", "nginx"]) + subprocess.run(["systemctl", "restart", "postgresql"]) diff --git a/system_monitoring/system_monitoring.py b/system_monitoring/system_monitoring.py index 9db46a92e..2c874966e 100644 --- a/system_monitoring/system_monitoring.py +++ b/system_monitoring/system_monitoring.py @@ -1,18 +1,20 @@ -import psutil import time +import psutil + + class SystemMonitoring: def __init__(self): self.cpu_percent = psutil.cpu_percent() self.memory_percent = psutil.virtual_memory().percent - self.disk_percent = psutil.disk_usage('/').percent + self.disk_percent = psutil.disk_usage("/").percent def monitor_system(self): while True: time.sleep(60) self.cpu_percent = psutil.cpu_percent() self.memory_percent = psutil.virtual_memory().percent - self.disk_percent = psutil.disk_usage('/').percent - print(f'CPU: {self.cpu_percent}%') - print(f'Memory: {self.memory_percent}%') - print(f'Disk: {self.disk_percent}%') + self.disk_percent = psutil.disk_usage("/").percent + print(f"CPU: {self.cpu_percent}%") + print(f"Memory: {self.memory_percent}%") + print(f"Disk: {self.disk_percent}%") diff --git a/testing.py b/testing.py index c6db305da..c507e3c5d 100644 --- a/testing.py +++ b/testing.py @@ -1,8 +1,10 @@ import unittest + class Testing(unittest.TestCase): def test_something(self): self.assertTrue(True) -if __name__ == '__main__': + +if __name__ == "__main__": unittest.main() diff --git a/transaction_processing/transaction_processing.py b/transaction_processing/transaction_processing.py index df41a2cb5..133311667 100644 --- a/transaction_processing/transaction_processing.py +++ b/transaction_processing/transaction_processing.py @@ -1,5 +1,6 @@ import time + class TransactionProcessor: def __init__(self, transaction_validator, transaction_router): self.transaction_validator = transaction_validator @@ -8,11 +9,11 @@ def __init__(self, transaction_validator, transaction_router): def process_transaction(self, transaction): errors = self.transaction_validator.validate_transaction(transaction) if errors: - print('Transaction errors:', errors) + print("Transaction errors:", errors) return False else: channel = self.transaction_router.route_transaction(transaction) - print('Transaction routed to:', channel) + print("Transaction routed to:", channel) time.sleep(1) - print('Transaction processed successfully.') + print("Transaction processed successfully.") return True diff --git a/transaction_processing/transaction_routing.py b/transaction_processing/transaction_routing.py index e11ee5ea2..499748e38 100644 --- a/transaction_processing/transaction_routing.py +++ b/transaction_processing/transaction_routing.py @@ -1,18 +1,20 @@ class TransactionRouter: def __init__(self): self.routing_rules = { - 'domestic': { - 'regex': r'^\d{10}$', - 'message': 'Invalid account number format. Please enter a 10-digit account number.' + "domestic": { + "regex": r"^\d{10}$", + "message": "Invalid account number format. Please enter a 10-digit account number.", + }, + "international": { + "regex": r"^\d{12}$", + "message": "Invalid account number format. Please enter a 12-digit account number.", }, - 'international': { - 'regex': r'^\d{12}$', - 'message': 'Invalid account number format. Please enter a 12-digit account number.' - } } def route_transaction(self, transaction): for rule in self.routing_rules: - if re.match(self.routing_rules[rule]['regex'], transaction['account_number']): + if re.match( + self.routing_rules[rule]["regex"], transaction["account_number"] + ): return rule - raise ValueError('Invalid account number format.') + raise ValueError("Invalid account number format.") diff --git a/transaction_processing/transaction_validation.py b/transaction_processing/transaction_validation.py index f119832ff..23da6ba7e 100644 --- a/transaction_processing/transaction_validation.py +++ b/transaction_processing/transaction_validation.py @@ -1,17 +1,18 @@ import re + class TransactionValidation: def __init__(self): self.validation_rules = { - 'account_number': { - 'regex': r'^\d{10}$', - 'message': 'Invalid account number format. Please enter a 10-digit account number.' + "account_number": { + "regex": r"^\d{10}$", + "message": "Invalid account number format. Please enter a 10-digit account number.", + }, + "amount": { + "min": 0, + "max": 1000000, + "message": "Transaction amount must be between 0 and 1,000,000.", }, - 'amount': { - 'min': 0, - 'max': 1000000, - 'message': 'Transaction amount must be between 0 and 1,000,000.' - } } def validate_transaction(self, transaction): @@ -19,13 +20,17 @@ def validate_transaction(self, transaction): for field, rules in self.validation_rules.items(): if field in transaction: for rule in rules: - if rule == 'regex': + if rule == "regex": if not re.match(rules[rule], transaction[field]): - errors.append(rules['message']) - elif rule == 'min': + errors.append(rules["message"]) + elif rule == "min": if float(transaction[field]) < rules[rule]: - errors.append(f'Transaction amount must be at least {rules[rule]}') - elif rule == 'max': + errors.append( + f"Transaction amount must be at least {rules[rule]}" + ) + elif rule == "max": if float(transaction[field]) > rules[rule]: - errors.append(f'Transaction amount must not exceed {rules[rule]}') + errors.append( + f"Transaction amount must not exceed {rules[rule]}" + ) return errors