Skip to content

Commit

Permalink
Merge branch 'feat/atom-detailed-amount' into 'develop'
Browse files Browse the repository at this point in the history
Feat/atom detailed amount

See merge request papers/airgap/airgap-wallet!212
  • Loading branch information
godenzim committed Apr 22, 2020
2 parents b7e0535 + b5cc600 commit d739bb2
Show file tree
Hide file tree
Showing 24 changed files with 215 additions and 37 deletions.
25 changes: 22 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"@ngx-translate/http-loader": "^4.0.0",
"@sentry/browser": "5.1.3",
"@zxing/ngx-scanner": "1.3.0",
"airgap-coin-lib": "^0.8.0-beta.19",
"airgap-coin-lib": "^0.8.0-beta.21",
"angular2-template-loader": "^0.6.2",
"angularx-qrcode": "^1.5.3",
"bignumber.js": "8.0.1",
Expand Down
3 changes: 3 additions & 0 deletions src/app/components/components.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { WidgetInputText } from './widget-input-text/widget-input-text'
import { WidgetAccount } from './widget-account/widget-account'
import { WidgetRewardList } from './widget-reward-list/widget-reward-list'
import { WidgetAccountSummary } from './widget-account-summary/widget-account-summary'
import { WidgetAccountExtendedDetails } from './widget-account-extended-details/widget-account-extended-details'

@NgModule({
declarations: [
Expand All @@ -58,6 +59,7 @@ import { WidgetAccountSummary } from './widget-account-summary/widget-account-su
WidgetSelector,
WidgetAccount,
WidgetAccountSummary,
WidgetAccountExtendedDetails,
WidgetIconText,
WidgetInputText,
WidgetRewardList
Expand Down Expand Up @@ -98,6 +100,7 @@ import { WidgetAccountSummary } from './widget-account-summary/widget-account-su
WidgetSelector,
WidgetAccount,
WidgetAccountSummary,
WidgetAccountExtendedDetails,
WidgetIconText,
WidgetInputText,
WidgetRewardList
Expand Down
9 changes: 9 additions & 0 deletions src/app/components/from-to/from-to.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
<ion-row class="ion-justify-content-center"><div class="line"></div></ion-row>
</ion-col>
<ion-col size="9" class="ion-padding-bottom">
<ng-container *ngIf="transaction.extra">
<ion-label position="stacked" class="ion-text-uppercase">{{ 'from-to.type_label' | translate }}</ion-label>
<div class="ion-padding-bottom">
<span class="typography--mono">
{{ transaction.extra }}
</span>
</div>
</ng-container>

<ion-label position="stacked" class="ion-text-uppercase">{{ 'from-to.amount_label' | translate }}</ion-label>
<div class="ion-padding-bottom">
<span class="typography--mono ion-padding-bottom">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<ng-container *ngFor="let item of widget.items">
<ion-row class="ion-padding-horizontal ion-padding-top">
<ion-col>
<ion-text color="blackLight">
<h3 class="typography--mono ion-no-margin">
{{ item.label | translate }}
</h3>
</ion-text>
</ion-col>
<ion-col>
<p class="ion-text-end ion-no-margin">
<strong>
{{ item.text }}
</strong>
</p>
</ion-col>
</ion-row>
</ng-container>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Component, Input } from '@angular/core'
import { UIAccountExtendedDetails } from 'src/app/models/widgets/display/UIAccountExtendedDetails'

@Component({
selector: 'widget-account-extended-details',
templateUrl: 'widget-account-extended-details.html',
styleUrls: ['widget-account-extended-details.scss']
})
export class WidgetAccountExtendedDetails {
@Input()
public readonly widget: UIAccountExtendedDetails
}
33 changes: 32 additions & 1 deletion src/app/extensions/delegation/CosmosDelegationExtensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { FormBuilder, Validators } from '@angular/forms'
import { UIAccountSummary } from 'src/app/models/widgets/display/UIAccountSummary'
import { ShortenStringPipe } from 'src/app/pipes/shorten-string/shorten-string.pipe'
import { DecimalValidator } from 'src/app/validators/DecimalValidator'
import { UIAccountExtendedDetails, UIAccountExtendedDetailsItem } from 'src/app/models/widgets/display/UIAccountExtendedDetails'

enum ArgumentName {
VALIDATOR = 'validator',
Expand Down Expand Up @@ -99,6 +100,36 @@ export class CosmosDelegationExtensions extends ProtocolDelegationExtensions<Cos
)
}

public async createAccountExtendedDetails(protocol: CosmosProtocol, address: string): Promise<UIAccountExtendedDetails> {
const results = await Promise.all([
protocol.getAvailableBalanceOfAddresses([address]),
protocol.fetchTotalDelegatedAmount(address),
protocol.fetchTotalUnbondingAmount(address),
protocol.fetchTotalReward(address)
])
const items: UIAccountExtendedDetailsItem[] = [
{
label: 'account-transaction-detail.available_label',
text: `${this.amountConverterPipe.transformValueOnly(results[0], { protocol: protocol, maxDigits: 0 })} ${protocol.symbol}`
},
{
label: 'account-transaction-detail.delegated_label',
text: `${this.amountConverterPipe.transformValueOnly(results[1], { protocol: protocol, maxDigits: 0 })} ${protocol.symbol}`
},
{
label: 'account-transaction-detail.unbonding_label',
text: `${this.amountConverterPipe.transformValueOnly(results[2], { protocol: protocol, maxDigits: 0 })} ${protocol.symbol}`
},
{
label: 'account-transaction-detail.reward_label',
text: `${this.amountConverterPipe.transformValueOnly(results[3], { protocol: protocol, maxDigits: 0 })} ${protocol.symbol}`
}
]
return new UIAccountExtendedDetails({
items: items
})
}

private async getExtraValidatorDetails(protocol: CosmosProtocol, validatorDetails: DelegateeDetails): Promise<AirGapDelegateeDetails> {
const results = await Promise.all([
protocol.nodeClient.fetchValidator(validatorDetails.address),
Expand Down Expand Up @@ -161,7 +192,7 @@ export class CosmosDelegationExtensions extends ProtocolDelegationExtensions<Cos
): Promise<AirGapDelegatorDetails> {
const [delegations, availableBalance, rewards] = await Promise.all([
protocol.fetchDelegations(delegatorDetails.address),
protocol.fetchAvailableBalance(delegatorDetails.address).then(availableBalance => new BigNumber(availableBalance)),
protocol.getAvailableBalanceOfAddresses([delegatorDetails.address]).then(availableBalance => new BigNumber(availableBalance)),
protocol
.fetchRewardForDelegation(delegatorDetails.address, validator)
.then(rewards => new BigNumber(rewards))
Expand Down
12 changes: 11 additions & 1 deletion src/app/extensions/delegation/ProtocolDelegationExtensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { AirGapDelegationDetails } from 'src/app/interfaces/IAirGapCoinDelegateP
import { UIInputTextConfig, UIInputText } from 'src/app/models/widgets/input/UIInputText'
import BigNumber from 'bignumber.js'
import { UIAccountSummary } from 'src/app/models/widgets/display/UIAccountSummary'
import { UIAccountExtendedDetails } from 'src/app/models/widgets/display/UIAccountExtendedDetails'

export abstract class ProtocolDelegationExtensions<T extends ICoinDelegateProtocol> {
private static readonly AIR_GAP_DELEGATEE_KEY = 'airGapDelegatee'
private static readonly DELEGATEE_LABEL_KEY = 'delegateeLabel'
private static readonly GET_EXTRA_DELEGATION_DETAILS_FROM_ADDRESS_KEY = 'getExtraDelegationDetailsFromAddress'
private static readonly CREATE_DELEGATEES_SUMMARY_KEY = 'createDelegateesSummary'
private static readonly CREATE_ACCOUNT_EXTENDED_DETAILS_SUMMARY_KEY = 'createAccountExtendedDetails'

public static load<T extends ICoinDelegateProtocol>(protocol: new () => T, extensions: ProtocolDelegationExtensions<T>) {
const alreadyLoaded =
Expand All @@ -22,7 +24,8 @@ export abstract class ProtocolDelegationExtensions<T extends ICoinDelegateProtoc
[ProtocolDelegationExtensions.AIR_GAP_DELEGATEE_KEY, 'property'],
[ProtocolDelegationExtensions.DELEGATEE_LABEL_KEY, 'property'],
[ProtocolDelegationExtensions.GET_EXTRA_DELEGATION_DETAILS_FROM_ADDRESS_KEY, 'function'],
[ProtocolDelegationExtensions.CREATE_DELEGATEES_SUMMARY_KEY, 'function']
[ProtocolDelegationExtensions.CREATE_DELEGATEES_SUMMARY_KEY, 'function'],
[ProtocolDelegationExtensions.CREATE_ACCOUNT_EXTENDED_DETAILS_SUMMARY_KEY, 'function']
)
}
}
Expand Down Expand Up @@ -84,6 +87,13 @@ export abstract class ProtocolDelegationExtensions<T extends ICoinDelegateProtoc
)
}

public async createAccountExtendedDetails(_protocol: T, _address: string): Promise<UIAccountExtendedDetails> {
// default implementation provides no details
return new UIAccountExtendedDetails({
items: []
})
}

protected createAmountWidget(id: string, maxValue: string, config: Partial<UIInputTextConfig> = {}): UIInputText {
return new UIInputText({
id,
Expand Down
3 changes: 2 additions & 1 deletion src/app/helpers/delegation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function supportsAirGapDelegation(protocol: ICoinProtocol): protocol is I
return (
delegateProtocol.delegateeLabel !== undefined &&
!!delegateProtocol.getExtraDelegationDetailsFromAddress &&
!!delegateProtocol.createDelegateesSummary
!!delegateProtocol.createDelegateesSummary &&
!!delegateProtocol.createAccountExtendedDetails
)
}
12 changes: 5 additions & 7 deletions src/app/helpers/promise-timeout.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
export async function promiseTimeout<T>(ms: number, promise: Promise<T>): Promise<T> {
// Create a promise that rejects in <ms> milliseconds
const timeout: Promise<T> = new Promise<T>(
(_resolve, reject): void => {
setTimeout(() => {
reject(`Timed out in ${ms} ms.`)
}, ms)
}
)
const timeout: Promise<T> = new Promise<T>((_resolve, reject): void => {
setTimeout(() => {
reject(`Timed out in ${ms} ms.`)
}, ms)
})

// Returns a race between our timeout and the passed in promise
return Promise.race([promise, timeout])
Expand Down
2 changes: 2 additions & 0 deletions src/app/interfaces/IAirGapCoinDelegateProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DelegateeDetails, DelegatorDetails } from 'airgap-coin-lib/dist/protoco
import { FormGroup } from '@angular/forms'
import { UIRewardList } from '../models/widgets/display/UIRewardList'
import { UIAccountSummary } from '../models/widgets/display/UIAccountSummary'
import { UIAccountExtendedDetails } from '../models/widgets/display/UIAccountExtendedDetails'

export interface AirGapDelegateeUsageDetails {
usage: BigNumber
Expand Down Expand Up @@ -54,4 +55,5 @@ export interface IAirGapCoinDelegateProtocol extends ICoinDelegateProtocol {

getExtraDelegationDetailsFromAddress(delegator: string, delegatees: string[]): Promise<AirGapDelegationDetails[]>
createDelegateesSummary(delegatees: string[]): Promise<UIAccountSummary[]>
createAccountExtendedDetails(address: string): Promise<UIAccountExtendedDetails>
}
1 change: 1 addition & 0 deletions src/app/models/widgets/UIWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BehaviorSubject } from 'rxjs'
export enum UIWidgetType {
ACCOUNT = 'account',
ACCOUNT_SUMMARY = 'account_summary',
ACCOUNT_EXTENDED_DETAILS = 'account_extended_details',
CHECKBOX = 'checkbox',
ICON_TEXT = 'icon_text',
INPUT_TEXT = 'input_text',
Expand Down
21 changes: 21 additions & 0 deletions src/app/models/widgets/display/UIAccountExtendedDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { UIWidget, UIWidgetType, UIWidgetConfig } from '../UIWidget'

export interface UIAccountExtendedDetailsConfig extends UIWidgetConfig {
items: UIAccountExtendedDetailsItem[]
}

export interface UIAccountExtendedDetailsItem {
label: string
text: string
}

export class UIAccountExtendedDetails extends UIWidget {
public type = UIWidgetType.ACCOUNT_EXTENDED_DETAILS

public items: UIAccountExtendedDetailsItem[]

constructor(config: UIAccountExtendedDetailsConfig) {
super(config)
this.items = config.items
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<h5>{{protocol.name}}</h5>
</ion-col>
<ion-col size="2" class="ion-justify-content-center">
<ion-icon name="md-link" color="dark" size="large"></ion-icon>
<ion-icon name="link-outline" color="dark" size="large"></ion-icon>
</ion-col>
<ion-col size="5">
<img src="assets/symbols/{{subProtocol.symbol.toLowerCase()}}.svg" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
(click)="openPreparePage()"
></card-actionable>

<widget-account-extended-details
*ngIf="accountExtendedDetails !== undefined"
[widget]="accountExtendedDetails"
></widget-account-extended-details>

<transaction-list
[transactionType]="'pendingTransaction'"
[hasPendingTransactions]="hasPendingTransactions"
Expand Down Expand Up @@ -97,10 +102,6 @@
<ion-infinite-scroll [disabled]="infiniteEnabled" (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>

<ion-infinite-scroll [disabled]="infiniteEnabled" (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-grid>
<ion-fab vertical="bottom" slot="fixed">
<ion-row>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { ErrorCategory, handleErrorSentry } from '../../services/sentry-error-ha
import { SettingsKey, StorageProvider } from '../../services/storage/storage'
import { supportsDelegation } from 'src/app/helpers/delegation'
import { timer, Subscription } from 'rxjs'
import { ExtensionsService } from 'src/app/services/extensions/extensions.service'
import { UIAccountExtendedDetails } from 'src/app/models/widgets/display/UIAccountExtendedDetails'

declare let cordova
export const refreshRate = 3000
Expand Down Expand Up @@ -53,6 +55,8 @@ export class AccountTransactionListPage {
public pendingTransactions: IAirGapTransaction[] = []
public formattedExchangeTransactions: IAirGapTransaction[] = []

public accountExtendedDetails: UIAccountExtendedDetails

// XTZ
public isKtDelegated: boolean = false

Expand All @@ -65,6 +69,8 @@ export class AccountTransactionListPage {
private readonly TRANSACTION_LIMIT: number = 10
private readonly actionGroup: ActionGroup

private readonly walletChanged: Subscription

constructor(
public readonly alertCtrl: AlertController,
public readonly navController: NavController,
Expand All @@ -80,13 +86,19 @@ export class AccountTransactionListPage {
private readonly storageProvider: StorageProvider,
private readonly toastController: ToastController,
private readonly pushBackendProvider: PushBackendProvider,
private readonly exchangeProvider: ExchangeProvider
private readonly exchangeProvider: ExchangeProvider,
private readonly extensionsService: ExtensionsService
) {
const info = this.route.snapshot.data.special
if (this.route.snapshot.data.special) {
this.wallet = info.wallet
}

this.updateExtendedDetails()
this.walletChanged = accountProvider.walletChangedObservable.subscribe(() => {
this.updateExtendedDetails()
})

this.subscription = this.timer$.subscribe(async () => {
if (this.formattedExchangeTransactions.length > 0) {
this.formattedExchangeTransactions = await this.exchangeProvider.getExchangeTransactionsByProtocol(
Expand Down Expand Up @@ -368,7 +380,16 @@ export class AccountTransactionListPage {
toast.present().catch(handleErrorSentry(ErrorCategory.NAVIGATION))
}

private updateExtendedDetails() {
if (supportsDelegation(this.wallet.coinProtocol) && this.wallet.receivingPublicAddress !== undefined) {
this.extensionsService.loadDelegationExtensions().then(async () => {
this.accountExtendedDetails = await this.operationsProvider.getAccountExtendedDetails(this.wallet)
})
}
}

public ngOnDestroy(): void {
this.subscription.unsubscribe()
this.walletChanged.unsubscribe()
}
}
Loading

0 comments on commit d739bb2

Please sign in to comment.