Add payment methods screen
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Socket } from 'ngx-socket-io';
|
import { Socket } from 'ngx-socket-io';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following interfaces are copied from the backend.
|
* The following interfaces are copied from the backend.
|
||||||
@@ -26,17 +27,16 @@ export interface ICart {
|
|||||||
|
|
||||||
export interface IPaymentMethod {
|
export interface IPaymentMethod {
|
||||||
method: any;
|
method: any;
|
||||||
amount: number
|
amount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PaymentStatus {
|
export enum PaymentStatus {
|
||||||
|
CANCELLED = -2,
|
||||||
|
REQUESTED = -1,
|
||||||
PENDING = 0,
|
PENDING = 0,
|
||||||
PARTIALLY = 1,
|
UNCONFIRMED = 1,
|
||||||
UNCONFIRMED = 2,
|
DONE = 2,
|
||||||
DONE = 3,
|
|
||||||
CANCELLED = 4
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IInvoice {
|
export interface IInvoice {
|
||||||
selector: string;
|
selector: string;
|
||||||
paymentMethods: IPaymentMethod[];
|
paymentMethods: IPaymentMethod[];
|
||||||
@@ -62,33 +62,132 @@ export class BackendService {
|
|||||||
|
|
||||||
SERVER_URL = 'http://localhost:2009';
|
SERVER_URL = 'http://localhost:2009';
|
||||||
|
|
||||||
|
invoice: IInvoice | null = null;
|
||||||
|
invoiceUpdate: BehaviorSubject<IInvoice | null>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private socket: Socket,
|
private socket: Socket,
|
||||||
private http: HttpClient
|
private http: HttpClient
|
||||||
) {
|
) {
|
||||||
|
this.invoiceUpdate = new BehaviorSubject<IInvoice | null>(null);
|
||||||
this.socket.on('status', (data: any) => {
|
this.socket.on('status', (data: any) => {
|
||||||
console.log('Status has been updated to: ', data);
|
console.log('Status has been updated to: ', data);
|
||||||
});
|
});
|
||||||
this.socket.on('subscribe', (success: boolean) => {
|
this.socket.on('subscribe', (success: boolean) => {
|
||||||
if (success) { console.log('We\'re getting the progress of this invoice!'); }
|
if (success) { console.log('We\'re getting the progress of this invoice!'); }
|
||||||
else { console.log('Subscription failed'); }
|
else { console.log('Subscribtion failed'); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribeTo(selector: string) {
|
getSocket(): Socket {
|
||||||
|
return this.socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeTo(selector: string): void {
|
||||||
|
this.socket.on('subscribe', (status: boolean) => {
|
||||||
|
if (status) {
|
||||||
|
this.updateInvoice();
|
||||||
|
console.log('Successfully subscribed to this invoice');
|
||||||
|
}
|
||||||
|
else { console.log('Failed to subscribe'); }
|
||||||
|
});
|
||||||
|
|
||||||
this.socket.emit('subscribe', { selector });
|
this.socket.emit('subscribe', { selector });
|
||||||
}
|
}
|
||||||
|
|
||||||
getInvoice(selector: string): Promise<IInvoice> {
|
updateInvoice(): void {
|
||||||
|
if (this.invoice !== undefined || this.invoice !== null) {
|
||||||
|
this.setInvoice(this.invoice?.selector!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setInvoice(selector: string): Promise<IInvoice> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
this.http.get(this.SERVER_URL + '/invoice/' + selector, {
|
this.http.get(this.SERVER_URL + '/invoice/' + selector, {
|
||||||
observe: 'body',
|
observe: 'body',
|
||||||
responseType: 'json'
|
responseType: 'json'
|
||||||
}).toPromise().then((invoice) => {
|
}).toPromise().then((invoice) => {
|
||||||
resolve(invoice as IInvoice);
|
this.invoice = invoice as IInvoice;
|
||||||
|
this.invoiceUpdate.next(this.invoice);
|
||||||
|
resolve(this.invoice);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setPaymentMethod(method: CryptoUnits): Promise<void> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
this.http.post(`${this.SERVER_URL}/invoice/${this.invoice?.selector}/setmethod`, { method }, {
|
||||||
|
responseType: 'json'
|
||||||
|
}).toPromise().then(() => {
|
||||||
|
this.setInvoice(this.invoice!!.selector);
|
||||||
|
}).catch(err => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns Path to icon
|
||||||
|
*/
|
||||||
|
getIcon(unit: CryptoUnits): string {
|
||||||
|
switch (unit) {
|
||||||
|
case CryptoUnits.BITCOIN:
|
||||||
|
return 'assets/Bitcoin.svg';
|
||||||
|
case CryptoUnits.BITCOINCASH:
|
||||||
|
return 'assets/BitcoinCash.svg';
|
||||||
|
case CryptoUnits.DOGECOIN:
|
||||||
|
return 'assets/Dogecoin.png';
|
||||||
|
case CryptoUnits.ETHEREUM:
|
||||||
|
return 'assets/Ethereum.svg';
|
||||||
|
case CryptoUnits.LITECOIN:
|
||||||
|
return 'assets/Litecoin.svg';
|
||||||
|
case CryptoUnits.MONERO:
|
||||||
|
return 'assets/Monero.svg';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findCryptoBySymbol(symbol: string): string | null {
|
||||||
|
for (const coin in CryptoUnits) {
|
||||||
|
// @ts-ignore: This actually works but I thing it's too hacky for TS. Allow me this one, please?
|
||||||
|
if (CryptoUnits[coin] === symbol.toUpperCase()) {
|
||||||
|
return coin.charAt(0).toUpperCase() + coin.toLowerCase().slice(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAmount(): string | undefined {
|
||||||
|
return this.invoice?.paymentMethods.find(item => {
|
||||||
|
return item.method === CryptoUnits.BITCOIN;
|
||||||
|
})?.amount.toFixed(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
getStatus(): string {
|
||||||
|
switch (this.invoice?.status) {
|
||||||
|
case PaymentStatus.PENDING:
|
||||||
|
return 'Pending';
|
||||||
|
case PaymentStatus.UNCONFIRMED:
|
||||||
|
return 'Unconfirmed';
|
||||||
|
case PaymentStatus.DONE:
|
||||||
|
return 'Paid';
|
||||||
|
case PaymentStatus.CANCELLED:
|
||||||
|
return 'Cancelled';
|
||||||
|
default:
|
||||||
|
return 'Unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isInvoiceDone(): boolean {
|
||||||
|
return this.invoice?.status === PaymentStatus.DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
isInvoicePending(): boolean {
|
||||||
|
return this.invoice?.status === PaymentStatus.PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
isInvoiceRequested(): boolean {
|
||||||
|
return this.invoice?.status === PaymentStatus.REQUESTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="header">
|
<div class="header">
|
||||||
<h2>LibrePay</h2>
|
<h2>LibrePay</h2>
|
||||||
<a>Cancel payment</a>
|
<a *ngIf="this.backend.isInvoicePending()">Cancel payment</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { BackendService } from '../backend.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
@@ -7,7 +8,7 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class HeaderComponent implements OnInit {
|
export class HeaderComponent implements OnInit {
|
||||||
|
|
||||||
constructor() { }
|
constructor(public backend: BackendService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,17 @@
|
|||||||
/* box-shadow: 1px 1px 112px 23px rgba(0,0,0,0.75); */
|
/* box-shadow: 1px 1px 112px 23px rgba(0,0,0,0.75); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.smaller {
|
||||||
|
min-width: 200px;
|
||||||
|
width: 40vw !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
.content {
|
||||||
|
width: 100vw !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.content * {
|
.content * {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<div class="cube"></div>
|
<div class="cube"></div>
|
||||||
<div class="cube"></div>
|
<div class="cube"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content" [ngClass]="{smaller: this.backend.isInvoiceRequested()}">
|
||||||
<app-header></app-header>
|
<app-header></app-header>
|
||||||
<app-payment></app-payment>
|
<app-payment></app-payment>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { BackendService } from '../backend.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pay',
|
selector: 'app-pay',
|
||||||
@@ -7,7 +8,7 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class PayComponent implements OnInit {
|
export class PayComponent implements OnInit {
|
||||||
|
|
||||||
constructor() { }
|
constructor(public backend: BackendService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
.payment {
|
.payment {
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 400px;
|
height: 500px;
|
||||||
background-color: hsl(0, 0%, 11%);
|
background-color: hsl(0, 0%, 11%);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
transform: translateY(-8px);
|
transform: translateY(-8px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.request {
|
||||||
|
transform: translateY(-40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
display: grid;
|
||||||
|
height: 400px;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
.qr {
|
.qr {
|
||||||
position: relative;
|
position: relative;
|
||||||
transform: translateY(25%);
|
transform: translateY(25%);
|
||||||
@@ -42,12 +50,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Data */
|
/* Data */
|
||||||
.data {
|
.main .data {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 50px;
|
grid-template-columns: 1fr 50px;
|
||||||
grid-template-rows: 1fr 4rem 4rem 4rem 1fr;
|
grid-template-rows: 1fr 4rem 4rem 4rem 1fr;
|
||||||
}
|
}
|
||||||
#target {
|
.main #target {
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
}
|
}
|
||||||
#amount {
|
#amount {
|
||||||
@@ -57,6 +65,65 @@
|
|||||||
grid-row: 4;
|
grid-row: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
.main h3 {
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title {
|
||||||
|
padding-top: 2rem;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 20pt;
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#price {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list {
|
||||||
|
overflow-y: scroll;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#list::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list li {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-left: 5%;
|
||||||
|
padding-right: 5%;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: grid;
|
||||||
|
cursor: pointer;
|
||||||
|
grid-template-columns: 75px 1fr;
|
||||||
|
grid-row: 1fr;
|
||||||
|
list-style: none;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
transition: .3s ease;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
#list li:hover {
|
||||||
|
box-shadow: 0px 0px 61px 3px rgba(0,0,0,0.3) inset;
|
||||||
|
}
|
||||||
|
#list li img {
|
||||||
|
height: 42px;
|
||||||
|
width: 42px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding-top: 12px;
|
||||||
|
grid-row-start: 1;
|
||||||
|
grid-row-end: 2;
|
||||||
|
}
|
||||||
|
#list li p {
|
||||||
|
grid-row: 1;
|
||||||
|
grid-column: 2;
|
||||||
|
}
|
||||||
|
#list li h4 {
|
||||||
|
grid-row: 2;
|
||||||
|
grid-column: 2;
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,23 @@
|
|||||||
<div class="payment">
|
<div class="payment request" *ngIf="this.backend.isInvoiceRequested()">
|
||||||
|
<h3 id="title">Choose your<br>payment method</h3>
|
||||||
|
<p id="price">{{ this.backend.invoice!!.totalPrice!!.toFixed(2) }} €</p>
|
||||||
|
|
||||||
|
<ul id="list">
|
||||||
|
<li *ngFor="let coin of this.backend.invoice!!.paymentMethods" (click)="chooseMethod(coin.method)">
|
||||||
|
<img [src]="this.backend.getIcon(coin.method)">
|
||||||
|
<div>
|
||||||
|
<h4>{{ this.backend.findCryptoBySymbol(coin.method) }}</h4>
|
||||||
|
<p>{{ coin.amount }} {{ coin.method }}</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="payment main" *ngIf="!this.backend.isInvoiceRequested() && ready">
|
||||||
<div class="qrWrapper">
|
<div class="qrWrapper">
|
||||||
<div class="qr">
|
<div class="qr">
|
||||||
<img src="assets/Bitcoin.svg">
|
<img src="assets/Bitcoin.svg">
|
||||||
<qrcode
|
<qrcode
|
||||||
[qrdata]="'bitcoin:' + invoice!!.receiveAddress"
|
[qrdata]="'bitcoin:' + this.backend.invoice!!.receiveAddress"
|
||||||
[width]="256"
|
[width]="256"
|
||||||
[errorCorrectionLevel]="'M'"
|
[errorCorrectionLevel]="'M'"
|
||||||
[elementType]="'svg'"
|
[elementType]="'svg'"
|
||||||
@@ -12,16 +26,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="data" *ngIf="ready">
|
<div class="data">
|
||||||
<!-- Payment data -->
|
<!-- Payment data -->
|
||||||
<span id="target">Send to
|
<span id="target">Send to
|
||||||
<h3>{{ invoice!!.receiveAddress }}</h3>
|
<h3>{{ this.backend.invoice!.receiveAddress }}</h3>
|
||||||
</span>
|
</span>
|
||||||
<span id="amount">Amount
|
<span id="amount">Amount
|
||||||
<h3>{{ getAmount() }} BTC</h3>
|
<h3>{{ this.backend.getAmount() }} BTC</h3>
|
||||||
</span>
|
</span>
|
||||||
<span id="status">Status
|
<span id="status">Status
|
||||||
<h3>{{ getStatus() }}</h3>
|
<h3>{{ this.backend.getStatus() }}</h3>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { BackendService, IInvoice, CryptoUnits, PaymentStatus } from '../backend.service';
|
import { BackendService, IInvoice, CryptoUnits, PaymentStatus, IPaymentMethod } from '../backend.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-payment',
|
selector: 'app-payment',
|
||||||
@@ -12,10 +12,9 @@ export class PaymentComponent implements OnInit {
|
|||||||
paymentSelector = '';
|
paymentSelector = '';
|
||||||
choosenPaymentMethod = CryptoUnits.BITCOIN;
|
choosenPaymentMethod = CryptoUnits.BITCOIN;
|
||||||
ready = false;
|
ready = false;
|
||||||
invoice: IInvoice | null = null;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private backend: BackendService,
|
public backend: BackendService,
|
||||||
private route: ActivatedRoute
|
private route: ActivatedRoute
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@@ -27,32 +26,13 @@ export class PaymentComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async get() {
|
chooseMethod(coin: CryptoUnits) {
|
||||||
this.invoice = await this.backend.getInvoice(this.paymentSelector);
|
this.backend.setPaymentMethod(coin);
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(): Promise<void> {
|
||||||
|
await this.backend.setInvoice(this.paymentSelector);
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAmount() {
|
|
||||||
return this.invoice?.paymentMethods.find(item => {
|
|
||||||
return item.method === CryptoUnits.BITCOIN;
|
|
||||||
})?.amount.toFixed(8);
|
|
||||||
}
|
|
||||||
|
|
||||||
getStatus() {
|
|
||||||
switch (this.invoice?.status) {
|
|
||||||
case PaymentStatus.PENDING:
|
|
||||||
return 'Pending';
|
|
||||||
case PaymentStatus.PARTIALLY:
|
|
||||||
return 'Partly';
|
|
||||||
case PaymentStatus.UNCONFIRMED:
|
|
||||||
return 'Unconfirmed';
|
|
||||||
case PaymentStatus.DONE:
|
|
||||||
return 'Paid';
|
|
||||||
case PaymentStatus.CANCELLED:
|
|
||||||
return 'Cancelled';
|
|
||||||
default:
|
|
||||||
return 'Unknown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/assets/BitcoinCash.svg
Normal file
63
src/assets/BitcoinCash.svg
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
height="64"
|
||||||
|
width="64"
|
||||||
|
version="1.1"
|
||||||
|
id="svg905"
|
||||||
|
sodipodi:docname="BitcoinCash.svg"
|
||||||
|
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||||
|
<metadata
|
||||||
|
id="metadata911">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs909" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1024"
|
||||||
|
id="namedview907"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="8.859375"
|
||||||
|
inkscape:cx="32"
|
||||||
|
inkscape:cy="32"
|
||||||
|
inkscape:window-x="1920"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="g903" />
|
||||||
|
<g
|
||||||
|
transform="translate(0.00630876,-0.00301984)"
|
||||||
|
id="g903">
|
||||||
|
<path
|
||||||
|
fill="#f7931a"
|
||||||
|
d="m63.033,39.744c-4.274,17.143-21.637,27.576-38.782,23.301-17.138-4.274-27.571-21.638-23.295-38.78,4.272-17.145,21.635-27.579,38.775-23.305,17.144,4.274,27.576,21.64,23.302,38.784z"
|
||||||
|
id="path899"
|
||||||
|
style="fill:#679a1b;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
fill="#FFF"
|
||||||
|
d="m46.103,27.444c0.637-4.258-2.605-6.547-7.038-8.074l1.438-5.768-3.511-0.875-1.4,5.616c-0.923-0.23-1.871-0.447-2.813-0.662l1.41-5.653-3.509-0.875-1.439,5.766c-0.764-0.174-1.514-0.346-2.242-0.527l0.004-0.018-4.842-1.209-0.934,3.75s2.605,0.597,2.55,0.634c1.422,0.355,1.679,1.296,1.636,2.042l-1.638,6.571c0.098,0.025,0.225,0.061,0.365,0.117-0.117-0.029-0.242-0.061-0.371-0.092l-2.296,9.205c-0.174,0.432-0.615,1.08-1.609,0.834,0.035,0.051-2.552-0.637-2.552-0.637l-1.743,4.019,4.569,1.139c0.85,0.213,1.683,0.436,2.503,0.646l-1.453,5.834,3.507,0.875,1.439-5.772c0.958,0.26,1.888,0.5,2.798,0.726l-1.434,5.745,3.511,0.875,1.453-5.823c5.987,1.133,10.489,0.676,12.384-4.739,1.527-4.36-0.076-6.875-3.226-8.515,2.294-0.529,4.022-2.038,4.483-5.155zm-8.022,11.249c-1.085,4.36-8.426,2.003-10.806,1.412l1.928-7.729c2.38,0.594,10.012,1.77,8.878,6.317zm1.086-11.312c-0.99,3.966-7.1,1.951-9.082,1.457l1.748-7.01c1.982,0.494,8.365,1.416,7.334,5.553z"
|
||||||
|
id="path901" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/assets/Dogecoin.png
Normal file
BIN
src/assets/Dogecoin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
11
src/assets/Ethereum.svg
Normal file
11
src/assets/Ethereum.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="256px" height="417px" viewBox="0 0 256 417" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||||
|
<g>
|
||||||
|
<polygon fill="#343434" points="127.9611 0 125.1661 9.5 125.1661 285.168 127.9611 287.958 255.9231 212.32"/>
|
||||||
|
<polygon fill="#8C8C8C" points="127.962 0 0 212.32 127.962 287.959 127.962 154.158"/>
|
||||||
|
<polygon fill="#3C3C3B" points="127.9611 312.1866 126.3861 314.1066 126.3861 412.3056 127.9611 416.9066 255.9991 236.5866"/>
|
||||||
|
<polygon fill="#8C8C8C" points="127.962 416.9052 127.962 312.1852 0 236.5852"/>
|
||||||
|
<polygon fill="#141414" points="127.9611 287.9577 255.9211 212.3207 127.9611 154.1587"/>
|
||||||
|
<polygon fill="#393939" points="0.0009 212.3208 127.9609 287.9578 127.9609 154.1588"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 840 B |
1
src/assets/Litecoin.svg
Normal file
1
src/assets/Litecoin.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2500" viewBox="0.847 0.876 329.254 329.256"><title>Litecoin</title><path d="M330.102 165.503c0 90.922-73.705 164.629-164.626 164.629C74.554 330.132.848 256.425.848 165.503.848 74.582 74.554.876 165.476.876c90.92 0 164.626 73.706 164.626 164.627" fill="#bebebe"/><path d="M295.15 165.505c0 71.613-58.057 129.675-129.674 129.675-71.616 0-129.677-58.062-129.677-129.675 0-71.619 58.061-129.677 129.677-129.677 71.618 0 129.674 58.057 129.674 129.677" fill="#bebebe"/><path d="M155.854 209.482l10.693-40.264 25.316-9.249 6.297-23.663-.215-.587-24.92 9.104 17.955-67.608h-50.921l-23.481 88.23-19.605 7.162-6.478 24.395 19.59-7.156-13.839 51.998h135.521l8.688-32.362h-84.601" fill="#fff"/></svg>
|
||||||
|
After Width: | Height: | Size: 750 B |
18
src/assets/Monero.svg
Normal file
18
src/assets/Monero.svg
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="monero" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:none;}
|
||||||
|
.st1{fill:#F16822;}
|
||||||
|
.st2{fill:#4D4D4D;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M197.5,100c0,53.8-43.7,97.5-97.5,97.5c-53.8,0-97.5-43.7-97.5-97.5C2.5,46.1,46.1,2.5,100,2.5
|
||||||
|
C153.8,2.5,197.5,46.1,197.5,100z"/>
|
||||||
|
<path id="_149931032_1_" class="st1" d="M100,2.5C46.2,2.5,2.4,46.2,2.5,100c0,10.8,1.7,21.1,4.9,30.8h29.2v-82l63.4,63.4
|
||||||
|
l63.4-63.4v82h29.2c3.2-9.7,4.9-20,5-30.8C197.6,46.2,153.8,2.5,100,2.5L100,2.5z"/>
|
||||||
|
<path id="_149931160_1_" class="st2" d="M85.4,126.7L57.8,99v51.6H47.2H36.6l-20,0c17.1,28.1,48,46.9,83.3,46.9
|
||||||
|
c35.3,0,66.2-18.8,83.3-46.9l-20,0h-18.9h-2.2V99l-27.7,27.7L100,141.3L85.4,126.7L85.4,126.7z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1020 B |
@@ -1,8 +1,13 @@
|
|||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
*{
|
* {
|
||||||
font-family: 'Inter', sans-serif;
|
font-family: 'Inter', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body, html {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
:host{
|
:host{
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
|||||||
Reference in New Issue
Block a user