-
Notifications
You must be signed in to change notification settings - Fork 49
Add coin base unit [draft] #210
base: master
Are you sure you want to change the base?
Changes from all commits
a5098c9
1bfcdd3
a35f6c0
145b9c4
e7251b4
bab1a41
040aef4
6c8d73d
ee9cec8
88889e8
7a7495a
f5250b4
879379d
8c43c5d
bfa1436
b4de434
c00bf08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export class BaseUnit { | ||
constructor(public name: string, public multiple: number, public defaultFormat: string) { } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { CoinsComponent } from './coins.component'; | ||
|
||
describe('CoinsComponent', () => { | ||
let component: CoinsComponent; | ||
let fixture: ComponentFixture<CoinsComponent>; | ||
|
||
beforeEach(async(() => { | ||
TestBed.configureTestingModule({ | ||
declarations: [ CoinsComponent ] | ||
}) | ||
.compileComponents(); | ||
})); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(CoinsComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { Component, OnInit, Input } from '@angular/core'; | ||
import { GlobalService } from '../services/global.service'; | ||
import { BaseUnit } from "../BaseUnit"; | ||
import { Subject } from 'rxjs'; | ||
|
||
@Component({ | ||
selector: 'coins', | ||
template: ` | ||
<span>{{ (amount ? amount : 0) | coinNotation:baseUnit.multiple | number:format }}</span><span *ngIf="showUnit"> {{ this.coinUnit | prefixCoinUnit:baseUnit.name }}</span> | ||
` | ||
}) | ||
export class CoinsComponent implements OnInit { | ||
|
||
@Input() | ||
amount: number = 0; | ||
|
||
@Input() | ||
showUnit: boolean = true; | ||
|
||
@Input() | ||
format: string = undefined; | ||
|
||
baseUnit: BaseUnit; | ||
coinUnit: string; | ||
baseUnitSubscription: any; | ||
|
||
constructor(private globalService: GlobalService) { | ||
this.baseUnitSubscription = this.globalService.baseUnit.subscribe(b => { | ||
this.baseUnit = b; | ||
this.format = this.format != undefined ? this.format : b.defaultFormat; | ||
}); | ||
|
||
this.coinUnit = this.globalService.getCoinUnit(); | ||
} | ||
|
||
ngOnInit() { | ||
} | ||
|
||
ngOnDestroy() { | ||
this.baseUnitSubscription.unsubscribe(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,10 +8,10 @@ export class CoinNotationPipe implements PipeTransform { | |
|
||
private decimalLimit = 8; | ||
|
||
transform(value: number): number { | ||
let temp; | ||
transform(value: number, multiple: number = 100000000): number { | ||
let temp; | ||
if (typeof value === 'number') { | ||
temp = value / 100000000; | ||
temp = value / multiple; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might need to check that |
||
return temp.toFixed(this.decimalLimit); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { PrefixCoinUnitPipe } from './prefix-coin-unit.pipe'; | ||
|
||
describe('PrefixCoinUnitPipe', () => { | ||
it('create an instance', () => { | ||
const pipe = new PrefixCoinUnitPipe(); | ||
expect(pipe).toBeTruthy(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Pipe, PipeTransform } from '@angular/core'; | ||
|
||
@Pipe({ | ||
name: 'prefixCoinUnit' | ||
}) | ||
export class PrefixCoinUnitPipe implements PipeTransform { | ||
|
||
transform(value: string, baseUnit: string): any { | ||
if (baseUnit === 'sats') { | ||
return baseUnit; | ||
} | ||
|
||
return baseUnit + value; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
import {Injectable} from "@angular/core"; | ||
import { ElectronService } from 'ngx-electron'; | ||
import { BehaviorSubject, Observable } from "rxjs"; | ||
import { take, map } from "rxjs/operators"; | ||
import { BaseUnit } from "../BaseUnit"; | ||
|
||
@Injectable({ | ||
providedIn: 'root' | ||
|
@@ -10,6 +13,15 @@ export class GlobalService { | |
this.setSidechainEnabled(); | ||
this.setTestnetEnabled(); | ||
this.setApiPort(); | ||
|
||
// Store by name so we can match the object and populate the settings list correctly. | ||
let storedBaseUnitName = localStorage.getItem('baseUnit'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
if (storedBaseUnitName) { | ||
let baseUnit = this.baseUnits.find(b => b.name === storedBaseUnitName); | ||
if (baseUnit) | ||
this.baseUnit.next(baseUnit); | ||
} | ||
} | ||
|
||
private applicationVersion: string = "1.0.0"; | ||
|
@@ -25,6 +37,23 @@ export class GlobalService { | |
private coinUnit: string; | ||
private network: string; | ||
|
||
// Base units relative to sats | ||
private baseUnits = [ | ||
new BaseUnit('', 100000000, '1.8-8'), // BTC = 100,000,000 sats | ||
new BaseUnit('m', 100000, '1.5-8'), // mBTC = 100,000 sats | ||
new BaseUnit('μ', 100, '1.2-8'), // μBTC = 100 sats | ||
new BaseUnit('sats', 1, '1.0-0') // Defaults are in sats, no decimal places | ||
]; | ||
|
||
public baseUnit: BehaviorSubject<BaseUnit> = new BehaviorSubject<BaseUnit>(this.baseUnits[0]); | ||
|
||
public formattedBaseUnit: Observable<string> = this.baseUnit.pipe(map(baseUnit => { | ||
if (baseUnit.name === 'sats') { | ||
return baseUnit.name; | ||
} | ||
|
||
return baseUnit.name + this.coinUnit; | ||
})); | ||
|
||
getApplicationVersion() { | ||
return this.applicationVersion; | ||
|
@@ -105,4 +134,13 @@ export class GlobalService { | |
setCoinUnit(coinUnit: string) { | ||
this.coinUnit = coinUnit; | ||
} | ||
|
||
setBaseUnit(baseUnit: BaseUnit) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should probably use property
|
||
localStorage.setItem('baseUnit', baseUnit.name); | ||
this.baseUnit.next(baseUnit); | ||
} | ||
|
||
getBaseUnits() { | ||
return this.baseUnits; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<div class="card p-4"> | ||
<div class="card-header">Change Base Unit</div> | ||
<div class="card-body" style="min-height:200px;"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we move all inline styles into a |
||
<div class="row"> | ||
<div class='col-4 blockLabel'> | ||
Base Unit: | ||
</div> | ||
<div class='col blockText'> | ||
<select class="custom-select col-12" [(ngModel)]="selectedBaseUnit" [ngModelOptions]="{standalone: true}" (change)="onBaseUnitChanged()"> | ||
<option *ngFor="let baseUnit of baseUnits" [ngValue]="baseUnit">{{ coinUnit | prefixCoinUnit:baseUnit.name }}</option> | ||
</select> | ||
<span style="padding-left: 15px;">1 Strat = <coins [amount]="100000000"></coins></span> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we move all inline styles into a |
||
</div> | ||
</div> | ||
</div> | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { BaseUnitComponent } from './base-unit.component'; | ||
|
||
describe('BaseUnitComponent', () => { | ||
let component: BaseUnitComponent; | ||
let fixture: ComponentFixture<BaseUnitComponent>; | ||
|
||
beforeEach(async(() => { | ||
TestBed.configureTestingModule({ | ||
declarations: [ BaseUnitComponent ] | ||
}) | ||
.compileComponents(); | ||
})); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(BaseUnitComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Component, OnInit } from '@angular/core'; | ||
import { GlobalService } from '../../../../shared/services/global.service'; | ||
import { BaseUnit } from '../../../../shared/BaseUnit'; | ||
import { take } from 'rxjs/operators'; | ||
|
||
@Component({ | ||
selector: 'app-base-unit', | ||
templateUrl: './base-unit.component.html', | ||
styleUrls: ['./base-unit.component.css'] | ||
}) | ||
export class BaseUnitComponent implements OnInit { | ||
coinUnit: string; | ||
baseUnits: BaseUnit[]; | ||
|
||
constructor(private globalService: GlobalService) { | ||
// Set the initial value | ||
this.globalService.baseUnit.pipe(take(1)).subscribe(b => { | ||
this.selectedBaseUnit = b; | ||
}); | ||
|
||
this.coinUnit = this.globalService.getCoinUnit(); | ||
this.baseUnits = this.globalService.getBaseUnits(); | ||
} | ||
|
||
selectedBaseUnit: BaseUnit; | ||
|
||
ngOnInit() { | ||
} | ||
|
||
onBaseUnitChanged() { | ||
this.globalService.setBaseUnit(this.selectedBaseUnit); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,12 +8,12 @@ | |
<div class="col-9 text-left"> | ||
<h5>Spendable balance</h5> | ||
<p class="lead"> | ||
<strong>{{ (confirmedBalance | coinNotation) || (0 | coinNotation) }}</strong> | ||
<small class="text-uppercase"> {{ coinUnit }}</small> | ||
<strong><coins [amount]="confirmedBalance" [showUnit]="false"></coins></strong> | ||
<small> {{ coinUnit }}</small> | ||
</p> | ||
<ul class="list-unstyled"> | ||
<!-- <li><strong>{{ (awaitingMaturity | coinNotation) || (0 | coinNotation) }}</strong><em> (staking)</em></li> --> | ||
<li><strong>{{ (unconfirmedBalance | coinNotation) || (0 | coinNotation) }}</strong><em> (unconfirmed)</em></li> | ||
<li><strong><coins [amount]="unconfirmedBalance"></coins></strong><em> (unconfirmed)</em></li> | ||
<!-- <li><strong>805.65900153</strong> <em>(staking)</em></li> --> | ||
</ul> | ||
</div> | ||
|
@@ -66,9 +66,9 @@ <h5>Spendable balance</h5> | |
<th class="text-center" *ngIf="!transaction.transactionConfirmedInBlock"><span class="bubble bg-warning"></span></th> | ||
<th class="text-center" *ngIf="transaction.transactionConfirmedInBlock"><span class="bubble bg-success"></span></th> | ||
<td class="text-uppercase text-left">{{ transaction.transactionType }}</td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'sent'"><strong>- {{ transaction.transactionAmount + transaction.transactionFee | coinNotation }} {{ coinUnit }}</strong></td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'received'"><strong>+ {{ transaction.transactionAmount + transaction.transactionFee | coinNotation }} {{ coinUnit }}</strong></td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'staked'"><strong>+ {{ transaction.transactionAmount + transaction.transactionFee | coinNotation }} {{ coinUnit }}</strong></td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'sent'"><strong>- <coins [amount]="transaction.transactionAmount + transaction.transactionFee"></coins></strong></td> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably move |
||
<td class="text-left" *ngIf="transaction.transactionType == 'received'"><strong>+ <coins [amount]="transaction.transactionAmount + transaction.transactionFee"></coins></strong></td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'staked'"><strong>+ <coins [amount]="transaction.transactionAmount + transaction.transactionFee"></coins></strong></td> | ||
<td class="text-left">{{ transaction.transactionTimestamp * 1000 | date:'medium' }}</td> | ||
<td class="text-center"><a class="link" (click)="openTransactionDetailDialog(transaction)">details</a></td> | ||
</tr> | ||
|
@@ -145,9 +145,9 @@ <h5>Spendable balance</h5> | |
<ul class="list-unstyled mb-3"> | ||
<li *ngIf="isStarting">Waiting for staking to start...</li> | ||
<div *ngIf="!isStarting"> | ||
<li>Staking weight: <strong>{{ stakingWeight | coinNotation | number: '1.0-0' }} {{ coinUnit }}</strong></li> | ||
<li>Coins awaiting maturity: <strong>{{ awaitingMaturity | coinNotation | number: '1.0-0' }} {{ coinUnit }}</strong></li> | ||
<li>Network weight: <strong>{{ netStakingWeight | coinNotation | number: '1.0-0' }} {{ coinUnit }}</strong></li> | ||
<li>Staking weight: <strong><coins [amount]="stakingWeight" [format]="'1.0-0'"></coins></strong></li> | ||
<li>Coins awaiting maturity: <strong><coins [amount]="awaitingMaturity" [format]="'1.0-0'"></coins></strong></li> | ||
<li>Network weight: <strong><coins [amount]="netStakingWeight" [format]="'1.0-0'"></coins></strong></li> | ||
<li class="mt-2">Expected reward time is:</li> | ||
<li><strong>{{ dateTime }}</strong></li> | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,9 +16,9 @@ | |
<th class="text-center" *ngIf="!transaction.transactionConfirmedInBlock"><span class="bubble bg-warning"></span></th> | ||
<th class="text-center" *ngIf="transaction.transactionConfirmedInBlock"><span class="bubble bg-success"></span></th> | ||
<td class="text-uppercase text-left">{{ transaction.transactionType }}</td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'sent'"><strong>- {{ transaction.transactionAmount + transaction.transactionFee | coinNotation }} {{ coinUnit }}</strong></td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'received'"><strong>+ {{ transaction.transactionAmount + transaction.transactionFee | coinNotation }} {{ coinUnit }}</strong></td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'staked'"><strong>+ {{ transaction.transactionAmount + transaction.transactionFee | coinNotation }} {{ coinUnit }}</strong></td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'sent'"><strong>- <coins [amount]="transaction.transactionAmount + transaction.transactionFee"></coins></strong></td> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably move |
||
<td class="text-left" *ngIf="transaction.transactionType == 'received'"><strong>+ <coins [amount]="transaction.transactionAmount + transaction.transactionFee"></coins></strong></td> | ||
<td class="text-left" *ngIf="transaction.transactionType == 'staked'"><strong>+ <coins [amount]="transaction.transactionAmount + transaction.transactionFee"></coins></strong></td> | ||
<td class="text-left">{{ transaction.transactionTimestamp * 1000 | date:'medium' }}</td> | ||
<td class="text-center"><a class="link" (click)="openTransactionDetailDialog(transaction)">details</a></td> | ||
</tr> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be safe, I would go with
!!this.format ? this.format : b.defaultFormat
instead ofthis.format != undefined ? this.format : b.defaultFormat