Crypto currency isn't static anymore

- Notification when transaction got confirmed
This commit is contained in:
2021-01-17 18:48:00 +01:00
parent 32340eb4cc
commit 59ebcb54c6
10 changed files with 73 additions and 17 deletions

8
package-lock.json generated
View File

@@ -7527,6 +7527,14 @@
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true "dev": true
}, },
"ng-push-ivy": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/ng-push-ivy/-/ng-push-ivy-1.0.7.tgz",
"integrity": "sha512-uUzIKBc6LA9Bw0sl7aj6x3eUr2UcCbXEw1PKpLFZ2OxzbnAhqh3IVX4ah0PRiDpfscFhmGUR2amLo19njAbMVg==",
"requires": {
"tslib": "^2.0.0"
}
},
"ngx-socket-io": { "ngx-socket-io": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/ngx-socket-io/-/ngx-socket-io-3.2.0.tgz", "resolved": "https://registry.npmjs.org/ngx-socket-io/-/ngx-socket-io-3.2.0.tgz",

View File

@@ -20,6 +20,7 @@
"@angular/platform-browser-dynamic": "~11.0.5", "@angular/platform-browser-dynamic": "~11.0.5",
"@angular/router": "~11.0.5", "@angular/router": "~11.0.5",
"angularx-qrcode": "^10.0.11", "angularx-qrcode": "^10.0.11",
"ng-push-ivy": "^1.0.7",
"ngx-socket-io": "^3.2.0", "ngx-socket-io": "^3.2.0",
"rxjs": "~6.6.0", "rxjs": "~6.6.0",
"tslib": "^2.0.0", "tslib": "^2.0.0",

View File

@@ -13,6 +13,7 @@ import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from 'src/routes'; import { AppRoutingModule } from 'src/routes';
import { NotFoundComponent } from './not-found/not-found.component'; import { NotFoundComponent } from './not-found/not-found.component';
import { CartComponent } from './cart/cart.component'; import { CartComponent } from './cart/cart.component';
import { PushNotificationsModule } from 'ng-push-ivy';
const config: SocketIoConfig = { url: 'http://localhost:2009', options: {} }; const config: SocketIoConfig = { url: 'http://localhost:2009', options: {} };
@@ -31,7 +32,8 @@ const config: SocketIoConfig = { url: 'http://localhost:2009', options: {} };
QRCodeModule, QRCodeModule,
HttpClientModule, HttpClientModule,
AppRoutingModule, AppRoutingModule,
SocketIoModule.forRoot(config) SocketIoModule.forRoot(config),
PushNotificationsModule
], ],
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]

View File

@@ -66,7 +66,7 @@ export interface IInvoice {
}) })
export class BackendService { export class BackendService {
SERVER_URL = 'http://localhost:2009'; SERVER_URL = 'http://192.168.178.26:2009';
// Fill with empty data // Fill with empty data
invoice: IInvoice = { invoice: IInvoice = {
@@ -138,7 +138,7 @@ export class BackendService {
setInvoice(selector: string): Promise<IInvoice> { setInvoice(selector: string): Promise<IInvoice> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
if (selector === undefined || selector === 'undefined' || selector === '') { if (selector === undefined || selector === 'undefined' || selector === '') {
reject(); reject('There is no selector. Please set one before calling setInvoice(...)');
return; return;
} }
@@ -147,7 +147,6 @@ export class BackendService {
responseType: 'json' responseType: 'json'
}).toPromise().then((invoice) => { }).toPromise().then((invoice) => {
this.invoice = invoice as IInvoice; this.invoice = invoice as IInvoice;
this.invoiceUpdate.next(this.invoice);
resolve(this.invoice); resolve(this.invoice);
}).catch(err => { }).catch(err => {
reject(err); reject(err);
@@ -224,7 +223,14 @@ export class BackendService {
/** /**
* @returns Path to icon in assets folder * @returns Path to icon in assets folder
*/ */
getIcon(unit: CryptoUnits): string { getIcon(unit?: CryptoUnits): string {
if (unit === undefined) {
if (this.invoice.paymentMethod === undefined) {
return 'assets/Bitcoin.svg';
}
unit = this.invoice.paymentMethod;
}
switch (unit) { switch (unit) {
case CryptoUnits.BITCOIN: case CryptoUnits.BITCOIN:
return 'assets/Bitcoin.svg'; return 'assets/Bitcoin.svg';
@@ -241,7 +247,15 @@ export class BackendService {
} }
} }
findCryptoBySymbol(symbol: string): string | null { findCryptoBySymbol(symbol?: string): string | null {
if (symbol === undefined) {
if (this.invoice.paymentMethod === undefined) {
return null;
}
symbol = this.invoice.paymentMethod;
}
for (const coin in CryptoUnits) { for (const coin in CryptoUnits) {
// @ts-ignore: This actually works but I think it's too hacky for TS. Allow me this one, please. // @ts-ignore: This actually works but I think it's too hacky for TS. Allow me this one, please.
if (CryptoUnits[coin] === symbol.toUpperCase()) { if (CryptoUnits[coin] === symbol.toUpperCase()) {

View File

@@ -47,4 +47,9 @@
.price { .price {
text-align: right; text-align: right;
margin: auto; margin: auto;
}
.quantity {
font-weight: lighter;
font-size: 10pt;
} }

View File

@@ -2,8 +2,8 @@
<ul> <ul>
<li *ngFor="let item of this.backend.invoice.cart;let indexOfelement=index;" [ngClass]="{'xyz-in': this.state.showCart.value, 'xyz-out': !this.state.showCart.value}"> <li *ngFor="let item of this.backend.invoice.cart;let indexOfelement=index;" [ngClass]="{'xyz-in': this.state.showCart.value, 'xyz-out': !this.state.showCart.value}">
<img [src]="item.image" class="image"> <img [src]="item.image" class="image">
<h5 class="name">{{ item.name }}</h5> <h5 class="name">{{ item.name }}<span class="quantity" *ngIf="item.quantity !== 1"> x{{ item.quantity }}</span></h5>
<span class="price"><b>{{ item.price.toFixed(2) }} {{ this.backend.currencyPrefix() }}</b><br> <span class="price"><b>{{ (item.price * item.quantity).toFixed(2) }} {{ this.backend.currencyPrefix() }}</b><br>
{{ this.backend.calculateCryptoPrice(indexOfelement).toFixed(8) }} {{ this.backend.invoice.paymentMethod }}</span> {{ this.backend.calculateCryptoPrice(indexOfelement).toFixed(8) }} {{ this.backend.invoice.paymentMethod }}</span>
</li> </li>
</ul> </ul>

View File

@@ -25,9 +25,9 @@
<div class="qrWrapper" [ngClass]="{'xyz-in': !this.state.showCart.value, 'xyz-out': this.state.showCart.value}"> <div class="qrWrapper" [ngClass]="{'xyz-in': !this.state.showCart.value, 'xyz-out': this.state.showCart.value}">
<div class="qr"> <div class="qr">
<img src="assets/Bitcoin.svg"> <img [src]="this.backend.getIcon()">
<qrcode <qrcode
[qrdata]="'bitcoin:' + this.backend.invoice!!.receiveAddress + '?amount=' + this.backend.getAmount()" [qrdata]="this.backend.findCryptoBySymbol()!.toLowerCase() + ':' + this.backend.invoice.receiveAddress + '?amount=' + this.backend.getAmount()"
[width]="256" [width]="256"
[errorCorrectionLevel]="'M'" [errorCorrectionLevel]="'M'"
[elementType]="'svg'" [elementType]="'svg'"
@@ -42,7 +42,7 @@
<h3>{{ this.backend.invoice?.receiveAddress }}</h3> <h3>{{ this.backend.invoice?.receiveAddress }}</h3>
</span> </span>
<span id="amount" [ngClass]="{'xyz-in': !this.state.showCart.value, 'xyz-out': this.state.showCart.value}">Amount <span id="amount" [ngClass]="{'xyz-in': !this.state.showCart.value, 'xyz-out': this.state.showCart.value}">Amount
<h3>{{ this.backend.getAmount() }} BTC <span class="price"> | {{ this.backend.invoice.totalPrice!.toFixed(2) }} {{ this.backend.currencyPrefix() }}</span></h3> <h3>{{ this.backend.getAmount() }} {{ this.backend.invoice.paymentMethod }} <span class="price"> | {{ this.backend.invoice.totalPrice!.toFixed(2) }} {{ this.backend.currencyPrefix() }}</span></h3>
</span> </span>
<span id="status" [ngClass]="{'xyz-in': !this.state.showCart.value, 'xyz-out': this.state.showCart.value}">Status <span id="status" [ngClass]="{'xyz-in': !this.state.showCart.value, 'xyz-out': this.state.showCart.value}">Status
<h3> <h3>

View File

@@ -1,7 +1,8 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { PushNotificationsService } from 'ng-push-ivy';
import { BackendService, CryptoUnits } from '../backend.service'; import { BackendService, CryptoUnits, PaymentStatus } from '../backend.service';
import { StateService } from '../state.service'; import { StateService } from '../state.service';
@Component({ @Component({
@@ -15,6 +16,7 @@ export class PaymentComponent implements OnInit {
confirmations = 0; confirmations = 0;
status: string; status: string;
ready = false; ready = false;
emittedNotification = false;
// XYZ class (will be xyz-out if cart is shown for example) // XYZ class (will be xyz-out if cart is shown for example)
xyzClass: string; xyzClass: string;
@@ -23,7 +25,8 @@ export class PaymentComponent implements OnInit {
constructor( constructor(
public backend: BackendService, public backend: BackendService,
public state: StateService, public state: StateService,
private route: ActivatedRoute private route: ActivatedRoute,
private push: PushNotificationsService
) { ) {
this.status = this.backend.getStatus(); this.status = this.backend.getStatus();
this.hideMain = false; this.hideMain = false;
@@ -49,9 +52,31 @@ export class PaymentComponent implements OnInit {
this.xyzClass = 'xyz-in'; this.xyzClass = 'xyz-in';
}, 600); }, 600);
} }
}) });
this.backend.invoiceUpdate.subscribe(newInvoice => { this.backend.invoiceUpdate.subscribe(newInvoice => {
if (newInvoice?.status === PaymentStatus.UNCONFIRMED) {
this.push.requestPermission();
}
if (newInvoice?.status === PaymentStatus.DONE) {
if (this.emittedNotification) { return; }
this.push.create('Transaction confirmed!', {
body: 'Your transaction just got confirmed.',
lang: 'en',
icon: this.backend.getIcon(),
sticky: true,
vibrate: [250, 400, 250],
sound: 'assets/pay_success.mp3'
}).subscribe(
(res: any) => {
console.log('Success');
},
(err: any) => {
console.error('Error:', err);
}
);
this.emittedNotification = true;
}
this.status = this.backend.getStatus(); this.status = this.backend.getStatus();
}); });
} }
@@ -61,7 +86,8 @@ export class PaymentComponent implements OnInit {
} }
async get(): Promise<void> { async get(): Promise<void> {
await this.backend.setInvoice(this.paymentSelector); const res = await this.backend.setInvoice(this.paymentSelector);
this.status = this.backend.getStatus();
this.backend.getConfirmation().catch(); this.backend.getConfirmation().catch();
this.ready = true; this.ready = true;
} }

View File

@@ -14,13 +14,13 @@ export class StateService {
constructor(private backend: BackendService) { constructor(private backend: BackendService) {
this.showCart = new BehaviorSubject<boolean>(false); this.showCart = new BehaviorSubject<boolean>(false);
this.backend.invoiceUpdate.subscribe(invoice => { this.backend.invoiceUpdate.subscribe(invoice => {
this.showCart.next(false); // Hide cart if status changes this.showCart.next(false); // Hide cart if status changes
}); });
} }
toggleCart() { toggleCart(): void {
this.showCart.next(!this.showCart.value); this.showCart.next(!this.showCart.value);
} }
} }

BIN
src/assets/pay_success.mp3 Normal file

Binary file not shown.