• Talinn, Estonia
  • support@lnsolutions.ee

Sprache auswählen

Aufbau einer sicheren Spring Boot Anwendung mit Kotlin, Spring Security und Coroutines

Aufbau einer sicheren Spring Boot Anwendung mit Kotlin, Spring Security und Coroutines

Mehr auf Medium lesen

 

In diesem Tutorial erfahren Sie, wie Sie mit Kotlin eine sichere Spring Boot-Anwendung erstellen, Spring Security für die Authentifizierung integrieren, Coroutines für die asynchrone Programmierung nutzen und mit AWS-Services wie Athena und Cognito integrieren. Wir werden auch die Datenbankmigration mit Flyway und das kontinuierliche Deployment mit Jenkins behandeln.

Voraussetzungen:

  • Grundkenntnisse der Programmiersprache Kotlin.
  • Vertrautheit mit dem Spring Boot-Framework.
  • Ein AWS-Konto mit Zugriff auf die Dienste Athena und Cognito.
  • Grundlegendes Verständnis von Gradle für die Projektverwaltung.

1. Einrichten des Projekts

Lass uns zunächst das Spring Boot Projekt mit Kotlin unter Verwendung von Gradle einrichten:

Schritt 1: Erzeugen des Spring Boot Projekts

Sie können Spring Initializr verwenden, um das Projekt mit den erforderlichen Konfigurationen zu generieren. Gehen Sie zu https://start.spring.io/ und geben Sie die folgenden Details ein:

  • Projekt: Kotlin
  • Dependencies: Spring Security, AWS Athena, AWS Cognito, Spring Data JPA, H2 Database, Flyway, Gradle, und Spring Boot DevTools.

Klicken Sie auf “Generate”, um die Projekt-Zip-Datei herunterzuladen.

Schritt 2: Gradle einrichten

Entpacken Sie das heruntergeladene Projekt, und im Root-Ordner finden Sie eine build.gradle-Datei. Ändern Sie diese so, dass sie die notwendigen Konfigurationen für die Elastic Beanstalk-Bundle-Generierung und die Jenkins-Integration enthält.

plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'org.jetbrains.kotlin.jvm' version '1.5.21'
id 'org.jetbrains.kotlin.plugin.spring' version '1.5.21'
id 'org.jetbrains.kotlin.plugin.jpa' version '1.5.21'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java.sourceCompatibility = JavaVersion.VERSION_11
kotlin {
experimental {
coroutines 'enable'
}
}
repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.amazonaws:aws-java-sdk-athena'
implementation 'com.amazonaws:aws-java-sdk-cognitoidp'
implementation 'com.amazonaws:aws-java-sdk-core'
implementation 'com.amazonaws:aws-java-sdk-elasticbeanstalk'
implementation 'com.h2database:h2'
implementation 'org.flywaydb:flyway-core'

developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

springBoot {
buildInfo {
properties {
additional = ['build.version': version]
}
}
}

tasks.named('test') {
useJUnitPlatform()
}

Schritt 3: Einrichten von Spring Security und AWS Cognito

Erstellen Sie eine Konfigurationsklasse für Spring Security mit AWS Cognito-Integration:

@Configuration
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.oauth2Login()
}
}

Schritt 4: Authentifizierungsanbieter anpassen

Konfigurieren Sie einen benutzerdefinierten Authentifizierungsanbieter für die Integration mit AWS Cognito:

@Component
class CustomAuthenticationProvider : AuthenticationProvider {

override fun authenticate(authentication: Authentication): Authentication {
// Implement authentication logic with AWS Cognito
}

override fun supports(authentication: Class<*>): Boolean {
return UsernamePasswordAuthenticationToken::class.java.isAssignableFrom(authentication)
}
}

Schritt 5: UserDetailsService erstellen

Implementieren Sie einen benutzerdefinierten UserDetailsService, um Benutzerdetails aus AWS Cognito zu laden:

@Service
class CustomUserDetailsService : UserDetailsService {
override fun loadUserByUsername(username: String): UserDetails {
// Load user details from AWS Cognito
}
}

Schritt 6: Datenbankkonfiguration einrichten

Erstellen Sie eine Konfigurationsklasse für die verschiedenen Profile (local, dev, prod):

@Configuration
class DatabaseConfig {
@Bean
@Profile("local")
fun dataSource(): DataSource {
return EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build()
}

@Bean
@Profile("dev", "prod")
fun dataSourceDevProd(): DataSource {
val dataSource = DriverManagerDataSource()
dataSource.setDriverClassName("YOUR_DATABASE_DRIVER")
dataSource.url = "YOUR_DATABASE_URL"
dataSource.username = "YOUR_DATABASE_USERNAME"
dataSource.password = "YOUR_DATABASE_PASSWORD"
return dataSource
}
}

Schritt 7: Flyway-Migration einrichten

Erstellen Sie ein Migrationsskript unter src/main/resources/db/migration für Flyway, um Änderungen am Datenbankschema zu verwalten.

Schritt 8: Erstellen einer Spring Boot Hauptklasse

Erstellen Sie eine Kotlin-Klasse, die als Einstiegspunkt für Ihre Spring Boot-Anwendung dient:

@SpringBootApplication
class DemoApplication

fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}

Schritt 9: Einrichten der AWS Athena-Integration

Sie können die Integration mit AWS Athena mithilfe des AWS SDK für Java und den entsprechenden Anmeldeinformationen vornehmen. Sie können den entsprechenden Code für AWS Athena-Abfragen in Ihrer Service-Schicht oder Ihrem Controller hinzufügen.

Schritt 10: Erzeugen eines Elastic Beanstalk-Bündels in Gradle

Um ein Elastic Beanstalk-Bundle zu erstellen, müssen Sie das CLI-Tool von AWS Elastic Beanstalk verwenden, das Sie über Gradle aufrufen können. Hier ist ein Beispiel dafür, wie Sie es tun können:

task createElasticBeanstalkBundle(type: Exec) {
workingDir projectDir
commandLine 'eb', 'create'
// Add necessary AWS Elastic Beanstalk configurations here
}
tasks.named('build').dependsOn createElasticBeanstalkBundle

Dadurch wird der Befehl eb create ausgeführt, wenn Sie die Gradle-Bauaufgabe ausführen.

Schritt 11: Jenkins-Integration einrichten

Für die Jenkins-Integration müssen Sie Ihre Jenkins-Pipeline so konfigurieren, dass das Projekt unter Verwendung des generierten Gradle-Wrappers gebaut und bereitgestellt wird.

Mit diesen Schritten sollten Sie ein Spring Boot-Projekt mit Kotlin, Spring Security, AWS Cognito, AWS Athena-Integration und Flyway-Datenbankmigration haben. Darüber hinaus verfügen Sie über Konfigurationen für lokale, Dev- und Prod-Umgebungen und eine Gradle-Aufgabe für die Generierung von Elastic Beanstalk-Bundles, die zur Bereitstellung in Jenkins integriert werden können.

 

Mehr auf Medium lesen

Anpassung von ccGains für die Erstellung eines jährlichen Krypto-Steuerbericht in Ländern, in denen eine Steuerbefreiung für Krypto-Bestände gilt, die ein Jahr oder länger gehalten werden

Anpassung von ccGains für die Erstellung eines jährlichen Krypto-Steuerbericht in Ländern, in denen eine Steuerbefreiung für Krypto-Bestände gilt, die ein Jahr oder länger gehalten werden

For English here

In Medium lesen

 

Bild von fabrikasimf bei Freepik

 

Einleitung

In der dynamischen Welt der Kryptowährungen, in der sich Volatilität und Innovation überschneiden, entwickelt sich die regulatorische Landschaft ständig weiter. Ein bemerkenswerter Aspekt dieser Entwicklung ist die Besteuerung von Kryptowährungsgewinnen. Während viele Länder verschiedene Steuerregelungen für Kryptowährungen eingeführt haben, bieten einige Länder eine günstige Politik, die langfristige Inhaber von bestimmten Steuerpflichten befreit. Eine solche Politik, die in mehreren Ländern an Zugkraft gewinnt, ist die Steuerbefreiung für Kryptobestände, die ein Jahr oder länger gehalten werden.

Was ist die Ein-Jahres-Haltefrist?

Die Politik des einjährigen Haltens, auch bekannt als Behandlung langfristiger Kapitalgewinne, ist ein steuerlicher Rahmen, der Steuerbefreiungen oder ermäßigte Steuersätze für Gewinne aus dem Verkauf oder Tausch von Kryptowährungen gewährt, die für eine Mindestdauer von einem Jahr gehalten werden. Diese Politik zielt darauf ab, Anreize für langfristige Investitionen in Kryptowährungen zu schaffen und gleichzeitig die Stabilität auf dem Markt zu fördern.

Länder mit steuerfreier Krypto-Gewinnpolitik

Mehrere Länder haben das Konzept der steuerfreien Kryptogewinne für langfristige Inhaber übernommen. Einige dieser Länder sind:

  1. Deutschland: Deutschland hat sich als einer der Vorreiter bei der Schaffung von Klarheit bei der Besteuerung von Kryptowährungen erwiesen. Wenn Sie in Deutschland Ihre Kryptowährungen länger als ein Jahr halten, sind alle daraus resultierenden Gewinne vollständig steuerfrei.
  2. Die Schweiz: Die Schweiz, die für ihr günstiges regulatorisches Umfeld für Finanzen und Technologie bekannt ist, behandelt Kryptowährungen für Steuerzwecke als Vermögenswerte und nicht als Währungen. Folglich sind Kapitalgewinne aus dem langfristigen Besitz von Kryptowährungen für Privatpersonen in der Regel steuerfrei.
  3. Portugal: Portugal hat durch seine steuerfreundliche Politik gegenüber Kryptowährungen Aufmerksamkeit erregt. Das Land besteuert keine Kapitalgewinne aus dem Verkauf von Kryptowährungen, wenn diese länger als ein Jahr gehalten werden.
  4. Singapur: Singapur ist bekannt für sein wirtschaftsfreundliches Umfeld und hat einen ähnlichen Ansatz für Kryptowährungen gewählt. Kapitalgewinne aus dem langfristigen Besitz von Kryptowährungen werden in Singapur nicht besteuert, sofern bestimmte Bedingungen erfüllt sind.
  5. Weißrussland: Weißrussland hat eine Gesetzgebung eingeführt, die Einzelpersonen und Unternehmen bis 2023 von Steuern auf Kryptowährungstransaktionen, einschließlich Kapitalgewinnen, befreit. Diese Politik zielt darauf ab, Investitionen und Innovationen in den aufstrebenden Tech-Sektor des Landes anzuziehen.

Was ist ccGains?

Das Paket ccGains (cryptocurrency gains) bietet eine Python-Bibliothek zur Berechnung von Kapitalgewinnen aus dem Handel mit Kryptowährungen oder Fremdwährungen. Es wurde von Jürgen Probst erstellt und wird in Github gehostet (Link hier). Einige ihrer Funktionen sind:

  • Berechnet die Kapitalgewinne nach dem First-in/First-out-Prinzip (FIFO), — erstellt Kapitalgewinnberichte als CSV, HTML oder PDF (sofort zum Ausdrucken für das Finanzamt),
  • Kann einen detaillierteren Kapitalgewinnbericht erstellen, in dem die Berechnung und die verwendeten Taschen beschrieben werden,
    Unterscheidet zwischen kurz- und langfristigen Gewinnen (Beträge, die weniger oder mehr als ein Jahr gehalten werden),
  • Behandelt Beträge, die an verschiedenen Börsen gehalten und gehandelt werden, getrennt,
  • Behandelt Börsengebühren und Transaktionsgebühren, die direkt aus dem Handel resultieren, als Verluste,
  • Bietet Methoden zum Importieren Ihrer Handelshistorie von verschiedenen Börsen,
  • Lädt historische Kryptowährungspreise aus CSV-Dateien und/oder
  • Lädt historische Preise von APIs, die von Börsen bereitgestellt werden,
  • Zwischenspeicherung historischer Kursdaten auf der Festplatte für schnelleren und Offline-Abruf und weniger Datenverkehr mit Börsen,
  • Verwendet für höchste Genauigkeit den dezimalen Datentyp für alle Beträge
  • Unterstützt das Speichern und Laden des Status Ihres Portfolios als JSON-Datei zur Verwendung in ccGains-Berechnungen in den folgenden Jahren

Installation

Sie benötigen Python (ccGains wurde unter Python 2.7 und Python 3.x getestet). Sie erhalten es hier: https://www.python.org/

ccGains kann dann einfach über den Python-Paketmanager pip installiert werden:

  • Laden Sie den Quellcode herunter, z.B. git clone https://github.com/probstj/ccgains.git
  • Innerhalb des ccGains-Hauptverzeichnisses führen Sie aus: pip install . (beachten Sie das . am Ende)
  • Alternativ können Sie auch lokal ohne Administratorrechte installieren: pip install --user .
  • Und wenn Sie Änderungen am Quellcode vornehmen und es schnell ausprobieren wollen, ohne neu zu installieren, kann pip installieren, indem Sie auf den Quellcode-Ordner verlinken: pip install -e .

Verwendung

Bitte schauen Sie sich die Datei examples/example.pyan und folgen Sie den Kommentaren, um sie für Ihre Zwecke anzupassen.

Kopieren Sie es in eine neue Datei, zum Beispiel taxReport2023.py.

1. Stellen Sie eine Liste der historischen BTC-Kurse in Ihrer Heimatwährung bereit.

Stündliche Daten für viele Börsenplätze stehen zum Download bereit unter:
https://api.bitcoincharts.com/v1/csv/
Um zu verstehen, welche Datei heruntergeladen werden soll, konsultieren Sie diese Liste:
https://bitcoincharts.com/markets/list/

Für EUR-Kurse auf Kraken laden Sie bitte die folgende Datei herunter: https://api.bitcoincharts.com/v1/csv/krakenEUR.csv.gz und legen Sie sie in den Ordner ../data.

Für CHF-Preise, laden Sie herunter: https://api.bitcoincharts.com/v1/csv/anxhkCHF.csv.gz

Für SGD-Preise, laden Sie herunter: https://api.bitcoincharts.com/v1/csv/anxhkSGD.csv.gz

Die Datei besteht aus drei durch Komma getrennten Spalten: dem Unix-Zeitstempel, dem Preis und dem Volumen (gehandelter Betrag).

Erstellen Sie das HistoricData-Objekt, indem Sie die genannte Datei laden und die Preiseinheit, d.h. fiat/btc, angibt:

h1 = ccgains.HistoricDataCSV(
'../data/bitcoin_de_EUR_abridged_as_example.csv.gz', 'EUR/BTC')

2. Quelle für historische BTC-Preise für alle gehandelten Altcoins bereitstellen

Für alle Coins, die Sie irgendwann einmal besessen haben, muss ihr historischer Preis in Ihrer heimischen Fiat-Währung bekannt sein, der auch aus ihrem BTC-Preis und dem oben angegebenen BTC/Fiat-Preis abgeleitet werden kann (oder sogar aus ihrem Preis in einem anderen Altcoin, dessen Preis wiederum abgeleitet werden kann).

Diese Daten können von jeder Website zur Verfügung gestellt werden, die diese Daten über eine API bereitstellt, oder aus einer csv-Datei, wie oben. Beachten Sie, dass derzeit nur die API von Poloniex.com implementiert ist.

Erstellen Sie HistoricData-Objekte, um Kurse von Poloniex.com abzurufen: (es ist wichtig, hier zumindest alle gehandelten Coins zu erwähnen)

    h2 = ccgains.HistoricDataAPI('data', 'btc/xmr')
h3 = ccgains.HistoricDataAPI('data', 'btc/eth')
h4 = ccgains.HistoricDataAPI('data', 'btc/usdt')
h5 = ccgains.HistoricDataAPI('data', 'btc/link')
h6 = ccgains.HistoricDataAPI('data', 'btc/bat')
h7 = ccgains.HistoricDataAPI('data', 'btc/zrx')
h8 = ccgains.HistoricDataAPI('data', 'btc/cvc')
h9 = ccgains.HistoricDataAPI('data', 'btc/dash')
h10 = ccgains.HistoricDataAPI('data', 'btc/knc')
h11 = ccgains.HistoricDataAPI('data', 'btc/mkr')
h12 = ccgains.HistoricDataAPI('data', 'btc/matic')
h13 = ccgains.HistoricDataAPI('data', 'btc/doge')
h14 = ccgains.HistoricDataAPI('data', 'btc/bch')
h15 = ccgains.HistoricDataAPI('data', 'btc/dot')
h16 = ccgains.HistoricDataAPI('data', 'btc/qtum')
h17 = ccgains.HistoricDataAPI('data', 'btc/ren')
h18 = ccgains.HistoricDataAPI('data', 'btc/str')
h19 = ccgains.HistoricDataAPI('data', 'btc/xtz')
h20 = ccgains.HistoricDataAPI('data', 'btc/trx')
h21 = ccgains.HistoricDataAPI('data', 'btc/zec')
h22 = ccgains.HistoricDataAPI('data', 'btc/ltc')
h23 = ccgains.HistoricDataAPI('data', 'btc/xrp')
h24 = ccgains.HistoricDataAPI('data', 'btc/omg')
h25 = ccgains.HistoricDataAPI('data', 'btc/etc')
h26 = ccgains.HistoricDataAPI('data', 'btc/dot')
h27 = ccgains.HistoricDataAPI('data', 'btc/dai')
h28 = ccgains.HistoricDataAPI('data', 'btc/usdc')
h29 = ccgains.HistoricDataAPICoinbase('data', 'cro/eur')
h30 = ccgains.HistoricDataAPIBinance('data', 'btc/uni')
h31 = ccgains.HistoricDataAPIBinance('data', 'avax/eur')
h32 = ccgains.HistoricDataAPIBinance('data', 'btc/dydx')
h33 = ccgains.HistoricDataAPIBinance('data', 'btc/iota')
h34 = ccgains.HistoricDataAPIBinance('data', 'btc/axs')

In h2 bis h28 habe ich die Klasse HistoricDataAPI verwendet, die die öffentliche Poloniex-API verwendet: https://poloniex.com/public?command=returnTradeHistory, da dies die Börse ist, an der diese Paare im Jahr 2023 in diesem Beispiel gehandelt werden.

In h29 habe ich die Klasse HistoricDataAPICoinbase verwendet, die die öffentliche Coinbase-API verwendet: “https://api.pro.coinbase.com/products/:SYMBOL:/candles".

In h30 bis h34 habe ich die Klasse HistoricDataAPIBinance verwendet, die transparent Daten auf Anfrage (get_price) von der öffentlichen Binance-API abruft: https://api.binance.com/api/v1/klines

Um die Ladezeiten bei künftigen Aufrufen zu verkürzen, wird aus den angeforderten Daten eine HDF5-Datei erstellt, die bei der nächsten Anfrage für denselben Tag und dasselbe Paar transparent verwendet wird. Diese HDF5-Dateien werden im Ordner cache_folder gespeichert. Die Einheit muss ein String in der Form “kryptowährung_eins/kryptowährung_zwei” sein, z. B. “NEO/BTC”. Die Daten werden neu abgetastet, indem der gewichtete Preis für die durch interval angegebenen Intervallschritte berechnet wird. Siehe: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases für mögliche Werte.

prepare_request(dtime) Gibt einen Pandas DataFrame zurück, der die Daten für den angeforderten Zeitpunkt dtime enthält.

3. Alle Objekte von oben in ein einziges ‘CurrencyRelation’-Objekt zusammenfügen

Erstellen Sie ein CurrencyRelation-Objekt, das alle angegebenen HistoricData-Währungen in Beziehung setzt, um Wechselkurse für ein beliebiges Paar dieser Währungen zu liefern:

rel = ccgains.CurrencyRelation(h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11, h12, h13, h14, h15, h16, h17, h18, h19, h20, h21, h22, h23, h24, h25, h26,h27, h28, h29, h30, h31, h32, h33, h34)

4. Erstellen Sie die “BagQueue”, die die Kapitalgewinne berechnet

Erstellen Sie das BagQueue-Objekt, das den steuerpflichtigen Gewinn aus Geschäften nach der First-in/First-out-Methode berechnet:

(dieses Objekt muss Ihre native Fiat-Währung und die oben erstellte CurrencyRelation kennen)

bf = ccgains.BagQueue('EUR', rel)

5. Erstellen Sie das Objekt, das alle Ihre Trades laden wird

Das TradeHistory-Objekt bietet Methoden zum Laden Ihrer Trades aus CSV-Dateien, die von verschiedenen Börsen oder Anwendungen exportiert wurden.

th = ccgains.TradeHistory()

6. Laden Sie alle Ihre Trades aus csv-Dateien

Exportieren Sie Ihre Trades von Börsen oder Apps als kommagetrennte Dateien und fügen Sie sie an die Liste der Trades an, die vom TradeHistory-Objekt verwaltet werden. Alle Trades werden automatisch sortiert.

Um von einer unterstützten Börse zu laden, verwenden Sie die Methoden namens `append_<exchange_name>_csv` in TradeHistory (siehe trades.py).

th.append_poloniex_csv(
'./data/2020/poloniex_depositHistory_2023.csv',
'deposits')
th.append_poloniex_csv(
'./data/2020/poloniex_tradeHistory_2023.csv',
'trades',
condense_trades=True)
th.append_poloniex_csv(
'./data/2020/poloniex_withdrawalHistory_2023.csv',
'withdr')

th.append_binance_csv(
'./data/2020/binance_depositHistory_2023.csv',
'deposits')
th.append_binance_csv(
'./data/2020/binance_tradeHistory_2023.csv',
'deposits')
th.append_binance_csv(
'./data/2020/binance_withdrawalHistory_2023.csv',
'deposits')
th.append_wirex_csv(
'./data/2020/wirex_btc_tradeHistory_2023.csv',
'trades')
th.append_cro_csv(
'./data/2021/cro_tradeHistory_2023.csv',
'trades')

Wenn Ihre Börse noch nicht unterstützt wird, fügen Sie eine neue Methode in trades.py hinzu. In diesem Beispiel werden die Methoden append_wirex_csv und append_cro_csv im ursprünglichen GitHub-Projekt nicht unterstützt.

Als nächstes werde ich zeigen, wie ich es mit append_cro_csv (Crypto.com) gemacht habe. Importieren Sie zunächst TPLOC_CRO_TRADES, die Bibliothek, die weiß, wie man die CSV-Datei von der Crypto.com-Börse liest.

from .cro_util import (
TPLOC_CRO_TRADES)
def append_cro_csv(
self, file_name, which_data='trades', delimiter=',',
skiprows=1, default_timezone=tz.tzutc()
):

wdata = which_data[:5].lower()
if wdata not in ['trade']:
raise ValueError(
'`which_data` must be one of "trades"')

plocs = TPLOC_CRO_TRADES
self.append_csv(
file_name=file_name,
param_locs=plocs,
delimiter=delimiter,
skiprows=skiprows,
default_timezone=default_timezone
)

Erzeugen Sie nun die Datei cro_util.py

from decimal import Decimal

def kind_for(csv_line):
if 'Withdraw' in (csv_line[1].strip('" \n\t')) or ('Transfer' in (csv_line[1].strip('" \n\t')) and 'App' in csv_line[1].strip('" \n\t').split("->")[0]):
return 'Withdrawal'
elif 'Deposit' in (csv_line[1].strip('" \n\t')) or 'Reward' in (csv_line[1].strip('" \n\t')) or ('Transfer' in (csv_line[1].strip('" \n\t')) and 'Exchange' in csv_line[1].strip('" \n\t').split("->")[0]):
return 'Deposit'
elif 'Buy' in (csv_line[1].strip('" \n\t')):
return 'Buy'
elif '->' in csv_line[1].strip('" \n\t'):
return 'Sell'
else:
return None

def get_buy_currency(csv_line):
if not '->' in csv_line[1].strip('" \n\t') and (kind_for(csv_line) == 'Buy' or kind_for(csv_line) == 'Deposit' or 'App' in csv_line[1].strip('" \n\t').split("->")[0]):
return csv_line[2].strip('" \n\t')
elif '->' in csv_line[1].strip('" \n\t') and (kind_for(csv_line) == 'Buy' or kind_for(csv_line) == 'Deposit' or 'App' in csv_line[1].strip('" \n\t').split("->")[0]):
return csv_line[2].strip('" \n\t')
else:
return csv_line[1].strip('" \n\t').split("->")[1]

def get_sell_currency(csv_line):
if not '->' in csv_line[1].strip('" \n\t') and (kind_for(csv_line) == 'Sell' or kind_for(csv_line) == 'Withdrawal' or 'Exchange' in csv_line[1].strip('" \n\t').split("->")[0]):
return csv_line[2].strip('" \n\t')
elif '->' in csv_line[1].strip('" \n\t') and (kind_for(csv_line) == 'Sell' or kind_for(csv_line) == 'Withdrawal' or 'Exchange' in csv_line[1].strip('" \n\t').split("->")[0]):
return csv_line[2].strip('" \n\t')
else:
return csv_line[1].strip('" \n\t').split("->")[0]

#Trade parameters in csv from Crypto.com
TPLOC_CRO_TRADES = {
'kind': lambda cols: kind_for(cols),
'dtime': 0,
'buy_currency': lambda cols: get_buy_currency(cols) if kind_for(cols) == 'Buy' or kind_for(cols) == 'Deposit' else cols[4] if cols[4].strip('" \n\t') != '' else '',
'buy_amount': lambda cols: abs(Decimal(cols[3])) if kind_for(cols) == 'Buy' or kind_for(cols) == 'Deposit' else abs(Decimal(cols[5])) if cols[5].strip('" \n\t') != '' else '',
'sell_currency': lambda cols: get_sell_currency(cols) if kind_for(cols) == 'Sell' or kind_for(cols) == 'Withdrawal' else 'EUR',
'sell_amount': lambda cols: abs(Decimal(cols[3])) if kind_for(cols) == 'Sell' or kind_for(cols) == 'Withdrawal' else cols[7],
'fee_currency': -1,
'fee_amount': -1,
'exchange': 'Crypto.com', 'mark': -1,
'comment': lambda cols: cols[1]
}

7. Optional: Festsetzung von Abhebungsgebühren

Einige Börsen, wie Poloniex, enthalten keine Abhebungsgebühren in ihren exportierten csv-Dateien. Es wird versucht, diese fehlenden Gebühren zu ergänzen, indem die abgehobenen Beträge mit den Beträgen verglichen werden, die kurz nach der Abhebung an anderen Börsen eingezahlt wurden. Rufen Sie dies erst auf, nachdem alle Transaktionen von allen beteiligten Börsen und Wallets importiert wurden.

Da dieser Algorithmus sehr einfach ist, kann nicht garantiert werden, dass er in jedem Fall funktioniert, vor allem, wenn Sie Abhebungen in kurzer Folge an verschiedenen Börsen vorgenommen haben; überprüfen Sie daher bitte die Ausgabe.

th.add_missing_transaction_fees(raise_on_error=False)

8. Optional können Sie Währungen umbenennen

Einige Währungen haben seit ihrem ersten Auflistungsdatum ihr Tickersymbol geändert (z. B. AntShares (ANS) -> Neo (NEO)). Dies kann zu Situationen führen, in denen alle historischen Preisdaten das neue Tickersymbol auflisten, die Transaktionshistorie jedoch noch das alte Tickersymbol enthält.

Diese Methode ermöglicht die Umbenennung von Symbolen in der TradeHistory, wenn ein Vorkommen des alten Namens/Tickers gefunden wird.

th.update_ticker_names({'ANS': 'NEO'})

9. Optional können Sie alle Trades zur späteren Verwendung exportieren.

Sie können alle importierten Trades zur späteren Verwendung in eine einzige Datei exportieren, optional gefiltert nach Jahr.

…entweder als kommagetrennte Textdatei (kann in ccgains importiert werden):

th.export_to_csv('transactions2023.csv', year=2023)

…oder als html- oder pdf-Datei, mit der Möglichkeit, Spaltenüberschriften oder Inhalte zu filtern oder umzubenennen:
(Dies ist ein Beispiel für eine Übersetzung ins Deutsche)

my_column_names=[
'Art', 'Datum', 'Kaufmenge', 'Verkaufsmenge', u'Gebühren', u'Börse']
transdct = {'Buy': 'Anschaffung',
'BUY': 'Anschaffung',
'Sell': 'Tausch',
'SELL': 'Tausch',
'Purchase': 'Anschaffung',
'Exchange': 'Tausch', 'Disbursement': 'Abhebung',
'Deposit': 'Einzahlung',
'Withdrawal': 'Abhebung',
'Received funds': 'Einzahlung',
'Withdrawn from wallet': 'Abhebung',
'Create offer fee: a5ed7482': u'Börsengebühr',
'Buy BTC' : 'Anschaffung',
'MultiSig deposit: a5ed7482': 'Abhebung',
'MultiSig payout: a5ed7482' : 'Einzahlung'}
th.export_to_pdf('Transactions2021.pdf',
year=2021, drop_columns=['mark', 'comment'],
font_size=12,
caption=u"Handel mit digitalen Währungen %(year)s",
intro=u"<h4>Auflistung aller Transaktionen zwischen "
"%(fromdate)s und %(todate)s:</h4>",
locale="de_DE",
custom_column_names=my_column_names,
custom_formatters={
'Art': lambda x: transdct[x] if x in transdct else x})

10. Jetzt kann die Berechnung endlich beginnen

Wenn die Berechnung bereits für frühere Jahre gelaufen ist, können wir hier den Stand der Taschen laden, ohne alles erneut berechnen zu müssen:

bf.load('./status2022.json')

Oder, wenn die aktuelle Berechnung abgestürzt ist (z.B. weil Sie vergessen haben, eine gehandelte Währung in #2 oben hinzuzufügen), wird die Datei ‘precrash.json’ automatisch erstellt. Laden Sie sie hier, um fortzufahren:

bf.load('./precrash.json')

Im Folgenden wird lediglich nachgeschaut, wo mit der Berechnung der Trades begonnen werden soll, falls Sie bereits einige berechnet und durch das Laden von ‘precrash.json’ neu gestartet haben:

last_trade = 0
while (last_trade < len(th.tlist)
and th[last_trade].dtime <= bf._last_date):
last_trade += 1
if last_trade > 0:
logger.info("continuing with trade #%i" % (last_trade + 1))

# Now, the calculation. This goes through your imported list of trades:
for i, trade in enumerate(th.tlist[last_trade:]):
# Most of this is just the log output to the console and to the
# file 'ccgains_<date-time>.log'
# (check out this file for all gory calculation details!):
logger.info('TRADE #%i', i + last_trade + 1)
logger.info(trade)
# This is the important part:
bf.process_trade(trade)
# more logging:
log_bags(bf)
logger.info("Totals: %s", str(bf.totals))
logger.info("Gains (in %s): %s\n" % (bf.currency, str(bf.profit)))

11. Speichern Sie den Stand Ihrer Bestände für die im nächsten Jahr fällige Berechnung

bf.save('status2023.json')

12. Erstellen Sie Ihren Kapitalertragsbericht für den Handel mit Kryptowährungen

Die im Bericht verwendeten Standard-Spaltennamen sehen nicht sehr schön aus: [‘Art’, ‘bag_spent’, ‘Währung’, ‘bag_date’, ‘sell_date’, ‘exchange’, ‘short_term’, ‘spent_cost’, ‘proceeds’, ‘profit’], also benennen wir sie um:

my_column_names=[
'Type', 'Amount spent', u'Currency', 'Purchase date',
'Sell date', u'Exchange', u'Short term', 'Purchase cost',
'Proceeds', 'Profit']

Hier erstellen wir den pdf-Bericht für Kapitalgewinne im Jahr 2023.

Die Angabe date_precision=’D’ bedeutet, dass wir nur den Tag des Abschlusses erwähnen, nicht die genaue Uhrzeit. Außerdem stellen wir combine=True ein, so dass mehrere Trades, die am selben Tag und an derselben Börse getätigt wurden, im Bericht zu einem einzigen Trade zusammengefasst werden:

my_column_names=[
'Art', 'Verkaufsmenge', u'Währung', 'Erwerbsdatum',
'Verkaufsdatum', u'Börse', u'in\xa0Besitz',
'Anschaffungskosten', u'Verkaufserlös', 'Gewinn']
transdct = {'sale': u'Veräußerung',
'withdrawal fee': u'Börsengebühr',
'deposit fee': u'Börsengebühr',
'exchange fee': u'Börsengebühr'}
convert_short_term=[u'>\xa01\xa0Jahr', u'<\xa01\xa0Jahr']

bf.report.export_report_to_pdf(
'Report2021_de.pdf', year=2023,
date_precision='D', combine=True,
custom_column_names=my_column_names,
custom_formatters={
u'in\xa0Besitz': lambda b: convert_short_term[b],
'Art': lambda x: transdct[x]},
locale="de_DE",
template_file='shortreport_de.html'
)
# If you rather want your report in a spreadsheet, you can export
# to csv:
bf.report.export_short_report_to_csv(
'report_2023.csv', year=2023,
date_precision='D', combine=False,
convert_timezone=True, strip_timezone=True)

13. Optional: Erstellen Sie einen detaillierten Bericht, der die Berechnung beschreibt

Der oben erstellte einfache Kapitalertragsbericht ist nur eine einfache Auflistung aller Trades und der erzielten Gewinne, die für den Steuerbericht ausreicht.

Eine detailliertere Auflistung, in der die Berechnung dargestellt wird, ist ebenfalls verfügbar:

bf.report.export_extended_report_to_pdf(
'Details_2023.pdf', year=2023,
date_precision='S', combine=False,
font_size=10, locale="en_US")

Und noch einmal, übersetzen wir diesen Bericht ins Deutsche: (Wiederum mit transdct von oben, um die Zahlungsart zu übersetzen)

bf.report.export_extended_report_to_pdf(
'Details_2023_de.pdf', year=2023,
date_precision='S', combine=False,
font_size=10, locale="de_DE",
template_file='fullreport_de.html',
payment_kind_translation=transdct)

Jetzt ausführen

python taxReport2023.py

Dies sollte die pdf-Dateien Details_2023.pdf und Details_2023_de.pdf erzeugen, die vom Finanzamt benötigt werden.

Für weitere Informationen zur Erstellung von Krypto-Steuerberichten oder zur Anpassung an Ihre Bedürfnisse kontaktieren Sie uns unter lnsolutions.ee

Referenzen

 
 
 

 

Unterdrücken der MySQL-Passwort-Warnung in Terminal- und Bash-Skripten

Unterdrücken der MySQL-Passwort-Warnung in Terminal- und Bash-Skripten

 

Für Englisch hier

Einführung

Wenn Sie MySQL-Befehle in einem Terminal oder in Bash-Skripten verwenden, können Sie auf diese Warnmeldung stoßen:

Warnung: Die Verwendung eines Passworts auf der Befehlszeilenschnittstelle kann unsicher sein.

Diese Warnung weist auf potenzielle Sicherheitslücken hin, da auf diese Weise eingegebene Passwörter für andere Benutzer sichtbar sein können. MySQL bietet jedoch mit dem Tool mysql_config_editor eine sichere Lösung, mit der Benutzer ihre Authentifizierungsdaten sicher speichern können. In dieser Anleitung zeigen wir Ihnen, wie Sie die Warnmeldung unterdrücken und MySQL-Passwörter mit mysql_config_editor sicher verwalten können.

Schritt 1: Installieren Sie MySQL und mysql_config_editor: Stellen Sie sicher, dass MySQL auf Ihrem System zusammen mit dem mysql_config_editor Tool installiert ist. Wenn Sie MySQL noch nicht installiert haben, können Sie dies mit Hilfe der offiziellen Installationsanleitung von MySQL für Ihr Betriebssystem nachholen.

Schritt 2: Authentifizierungsdaten einrichten: Sobald MySQL installiert ist, können Sie die Authentifizierungsdaten mit dem mysql_config_editor Tool sicher einrichten. Öffnen Sie Ihr Terminal und führen Sie den folgenden Befehl aus:

mysql_config_editor set --login-path=client --host=localhost --user=username --port=your_db_port --password

Ersetzen Sie username durch Ihren MySQL-Benutzernamen. Nachdem Sie diesen Befehl ausgeführt haben, werden Sie aufgefordert, Ihr MySQL-Passwort einzugeben. Sobald Sie es eingegeben haben, wird das Passwort sicher gespeichert.

Schritt 3: Warnmeldung unterdrücken: Um die Warnmeldung über die Verwendung eines unsicheren Passworts zu unterdrücken, verwenden Sie einfach die Option — login-path zusammen mit Ihrem MySQL-Befehl. Zum Beispiel:

mysql --login-path=client -e "SELECT * FROM your_table;"

Ersetzen Sie your_table durch den Namen der Tabelle, die se abfragen möchten.Durch die Verwendung von --login-path=client holt MySQL die Authentifizierungsdaten sicher aus der von mysql_config_editor gespeicherten Konfiguration, und die Warnmeldung wird unterdrückt.

Schritt 4: Einbinden in Bash-Skripte: Sie können die sichere Authentifizierungsmethode in Ihre Bash-Skripte integrieren, indem Sie die Option --login-pathin MySQL-Befehlen verwenden. Hier ist ein Beispielskript:

#!/bin/bash# MySQL command with secure authentication
mysql --login-path=client -e "SELECT * FROM your_table;"

Ersetzen Sie your_table durch den entsprechenden Tabellennamen oder die Abfrage für Ihr Skript.

Um zu sehen, was mysql_config_editor in die Datei .mylogin.cnf schreibt, benutzen Sie den Befehl print:

$> mysql_config_editor print --all
[client]
user = localuser
password = *****
host = localhost
[remote]
user = remoteuser
password = *****
host = remote.example.com

Schlussfolgerung

Durch die Verwendung von mysql_config_editor und der Option --login-path können Sie die MySQL-Authentifizierungsdaten sicher verwalten und Warnmeldungen über unsichere Passwortverwendung sowohl in Terminalbefehlen als auch in Bash-Skripten unterdrücken. Dies gewährleistet den Schutz sensibler Informationen bei gleichzeitiger Beibehaltung von Komfort und Effizienz im MySQL-Betrieb.

 

Mehr auf Medium lesen

Featured

Lebenslauf Jorge Elizondo

Aufbau einer Microservice-Architektur mit TypeScript und Angular

Aufbau einer Microservice-Architektur mit TypeScript und Angular

 

Weiter lesen auf Medium

Die Microservice-Architektur wird immer beliebter, um skalierbare und wartbare Anwendungen zu erstellen. In diesem Artikel erfahren Sie, wie Sie eine Microservice-Architektur mit TypeScript für das Backend und Angular für das Frontend aufbauen können.

Einführung in Microservices

Microservices ist ein Architekturstil, der eine Anwendung als eine Sammlung lose gekoppelter Dienste strukturiert. Jeder Dienst ist für eine bestimmte Funktion zuständig und kann unabhängig entwickelt, bereitgestellt und skaliert werden. Dieser Ansatz bietet mehrere Vorteile, darunter:

  1. Skalierbarkeit: Die Dienste können je nach Bedarf unabhängig voneinander skaliert werden.
  2. Flexibilität: Verschiedene Dienste können mit unterschiedlichen Technologien entwickelt werden.
  3. Wartbarkeit: Die Dienste sind kleiner und fokussierter, wodurch sie leichter zu verstehen und zu warten sind.
  4. Ausfallsicherheit: Der Ausfall eines Dienstes hat nicht unbedingt Auswirkungen auf das gesamte System.

Einrichten des Backends mit NestJS

NestJS ist ein Framework für die Entwicklung effizienter, zuverlässiger und skalierbarer serverseitiger Anwendungen. Es ist mit TypeScript aufgebaut und kombiniert Elemente von OOP, FP und FRP.

Zu den wichtigsten Merkmalen von NestJS gehören:

  1. Modularität: NestJS fördert eine modulare Architektur, indem es die Codebasis in Module gliedert, die jeweils für einen bestimmten Bereich oder eine bestimmte Funktion zuständig sind. Module können leicht zusammengesetzt und wiederverwendet werden, was die Codeorganisation und die Trennung von Belangen fördert.
  2. Injektion von Abhängigkeiten: NestJS nutzt Dependency Injection, um die Erstellung und Auflösung von Anwendungsabhängigkeiten zu verwalten. Dies hilft beim Schreiben von testbarem und wartbarem Code, indem es Komponenten entkoppelt und die Wiederverwendbarkeit fördert.
  3. Dekoratoren und Metadaten: NestJS verwendet ausgiebig Dekoratoren und Metadatenreflexion, um verschiedene Aspekte einer Anwendung zu definieren und zu konfigurieren, wie z. B. Routing, Middleware, Validierung und mehr. Dekoratoren bieten eine deklarative Möglichkeit, das Verhalten und die Eigenschaften verschiedener Komponenten zu definieren.
  4. Leistungsstarke CLI: NestJS bietet eine leistungsstarke Befehlszeilenschnittstelle (CLI), die gängige Entwicklungsaufgaben wie die Generierung von Modulen, Controllern, Diensten und mehr automatisiert. Die CLI hilft Entwicklern, neue Projekte zu starten und die Codebasis schnell zu erweitern.
  5. Unterstützung für TypeScript: NestJS lässt sich gut mit anderen beliebten Bibliotheken und Frameworks im Node.js-Ökosystem integrieren, wie TypeORM, Sequelize, Passport, WebSocket und anderen. Dies ermöglicht es Entwicklern, vorhandene Tools und Lösungen zu nutzen, um Anwendungen mit vollem Funktionsumfang zu erstellen.

Insgesamt zielt NestJS darauf ab, eine produktive und skalierbare Entwicklungserfahrung für die Erstellung serverseitiger Anwendungen mit Node.js zu bieten. Es kombiniert die Vertrautheit beliebter Frameworks wie Express.js mit den leistungsstarken Funktionen von TypeScript, Dependency Injection und modularer Architektur, um die Erstellung gut strukturierter und wartbarer Codebases zu erleichtern.

 

Weiter lesen auf Medium

recent posts
  • Talinn, Estonia
  • support@lnsolutions.ee
About
We support your software projects and solutions. We specialize in Java Backend, Web development, BPM Workflow design and Bitcoin payment solutions.
Subscribe