Skip to content

Commit

Permalink
Merge branch 'main' into ripple-native-builds
Browse files Browse the repository at this point in the history
  • Loading branch information
IscoRuta98 committed Aug 21, 2023
2 parents 002d9b6 + 4d48917 commit 5f4e71e
Show file tree
Hide file tree
Showing 24 changed files with 253 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ <h6>{{ bookmark?.address }}</h6>
</ion-label>
<ion-buttons>
<ion-button (click)="sendFund(bookmark.address)">
<ion-icon slot="icon-only" name="card"></ion-icon>
</ion-button>
<ion-button (click)="pullPay(bookmark.address)">
<ion-icon slot="icon-only" name="cash"></ion-icon>
</ion-button>
<ion-button (click)="deleteBookmark(bookmark.id)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export class BookmarkListComponent implements OnInit {
});
}

pullPay(address: string) {
this.navCtrl.navigateForward('pull', {
state: { address },
});
}

deleteBookmark(id: string) {
this.notification.swal.fire({
icon: 'warning',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,21 @@ <h1 class="font-semibold font-nasalization">Set Schedule</h1>
<ion-list lines="none" mode="ios">
<ion-item>
<ion-label position="stacked" for="frequency"
>Set Frequency</ion-label
>Select Frequency</ion-label
>
<ion-select formControlName="frequency">
<ion-select-option value="1">Every Day</ion-select-option>
<ion-select-option value="7">Every Week</ion-select-option>
<ion-select-option value="30">Every Month</ion-select-option>
<ion-select-option value="91">Quarterly</ion-select-option>
</ion-select>
<ion-input labelPlacement="end" class="ion-text-right">
<ion-select
justify="space-between"
label-placement="floating"
label="Select Frequency"
formControlName="frequency"
>
<ion-select-option value="1">Every Day</ion-select-option>
<ion-select-option value="7">Every Week</ion-select-option>
<ion-select-option value="30">Every Month</ion-select-option>
<ion-select-option value="91">Quarterly</ion-select-option>
</ion-select>
</ion-input>
</ion-item>
<ion-text
slot="error"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ion-select::part(icon) {
color: white;
opacity: 1;
}
11 changes: 10 additions & 1 deletion web-client/src/app/services/auto-logout.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const STORE_KEY = 'lastAction';
providedIn: 'root',
})
export class AutoLogoutService {
private autoLogoutEnabled = true;
constructor(
private navCtrl: NavController,
private sessionStore: SessionStore,
Expand Down Expand Up @@ -55,8 +56,16 @@ export class AutoLogoutService {
});
}

public disableAutoLogout() {
this.autoLogoutEnabled = false;
}

public enableAutoLogout() {
this.autoLogoutEnabled = true;
}

check() {
if (this.sessionQuery.isActiveSession()) {
if (this.autoLogoutEnabled && this.sessionQuery.isActiveSession()) {
const now = Date.now();
const timeLeft =
this.getLastAction() + MINUTES_UNTIL_AUTO_LOGOUT * 60 * 1000;
Expand Down
2 changes: 2 additions & 0 deletions web-client/src/app/state/session.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ export class SessionService {
} else if ('Failed' in result) {
console.error(result);
throw new Error(result.Failed);
} else if ('AccountLocked' in result) {
return 'You have failed to enter the correct pin 3 times. Please reset your pin in order to access your account.';
} else {
throw never(result);
}
Expand Down
5 changes: 5 additions & 0 deletions web-client/src/app/utils/errors/global-error-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export class GlobalErrorHandler implements ErrorHandler {
return;
}

if (error.message.includes('setPhotoOptions failed')) {
console.warn('GlobalErrorHandler ignoring:', error);
return;
}

// ToDo (refactor): Do not skip specific errors in the global error handler.
if (error.message.includes('Local error:')) {
return;
Expand Down
57 changes: 57 additions & 0 deletions web-client/src/app/utils/notification/swal-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,63 @@ export class SwalHelper {
});
}

showDeletedWalletError() {
this.swal.fire({
icon: 'error',
title: 'Transaction Failed',
text: 'You cannot send funds to a wallet that has been deleted.',
});
}

showDeletedWalletErrorPull() {
this.swal.fire({
icon: 'error',
title: 'Transaction Failed',
text: 'You cannot pull funds from a wallet that has been deleted.',
});
}

showDeleteAccountError() {
this.swal.fire({
icon: 'error',
title: 'Transaction Failed',
text: 'Wallet cannot be deleted currently. Please try again later.',
});
}

showCurrencyNotOptIn() {
this.swal.fire({
icon: 'error',
title: 'Transaction Failed',
text: 'The receiver needs to opt into this currency first, before trying again.',
});
}

showCurrencyNotOptInPull() {
this.swal.fire({
icon: 'error',
title: 'Transaction Failed',
text: 'The receiver may have insufficient funds or has not opted into this currency.',
});
}

showInsufficientFunds() {
const reserveAmount = 10;
this.swal.fire({
icon: 'error',
title: 'Insufficient Funds',
text: `Your transaction exceeds the minimum reserve of ${reserveAmount} XRP. Please adjust the amount and try again.`,
});
}

showInsufficientFundsPullPayment() {
this.swal.fire({
icon: 'error',
title: 'Insufficient Funds',
text: 'There are insufficient funds from the wallet you are pulling from.',
});
}

showIncorrectOTPWarning() {
this.swal.fire({
icon: 'warning',
Expand Down
42 changes: 25 additions & 17 deletions web-client/src/app/views/deposit-funds/deposit-funds.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,31 @@ export class DepositFundsPage implements OnInit {
}

async deleteWallet(): Promise<void> {
await withConsoleGroupCollapsed(
'Defaulting asset / token opt-ins',
async () => {
await this.defaultXrplTokenOptIns();
}
);

if (this.receiverAddress) {
const result = await withLoadingOverlayOpts<
{ xrplResult: TxResponse } | undefined
>(this.loadingCtrl, { message: 'Confirming Transaction' }, () => {
if (this.receiverAddress) {
return this.deleteByLedgerType(this.receiverAddress);
try {
await withConsoleGroupCollapsed(
'Defaulting asset / token opt-ins',
async () => {
await this.defaultXrplTokenOptIns();
}
);

if (this.receiverAddress) {
const result = await withLoadingOverlayOpts<
{ xrplResult: TxResponse } | undefined
>(this.loadingCtrl, { message: 'Confirming Transaction' }, async () => {
if (this.receiverAddress) {
return this.deleteByLedgerType(this.receiverAddress);
}
return Promise.resolve(undefined);
});

if (result) {
await this.notifyResult(result, this.receiverAddress);
}
return Promise.resolve(undefined);
});
if (result) {
await this.notifyResult(result, this.receiverAddress);
}
} catch (error) {
console.log('Error in deleteWallet:', error);
this.notification.showDeleteAccountError();
}
}

Expand Down Expand Up @@ -121,6 +127,8 @@ export class DepositFundsPage implements OnInit {
txId: txResponse.id.toString(),
timestamp: new Date(),
});
} else if (resultCode === 'tecTOO_SOON') {
this.notification.showDeleteAccountError();
} else {
await this.notifyXrplFailure({ resultCode });
}
Expand Down
15 changes: 15 additions & 0 deletions web-client/src/app/views/pay/pay.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { LoadingController, NavController } from '@ionic/angular';
import { Observable, pluck } from 'rxjs';
import { Payment } from 'src/app/components/pay/pay.component';
import { TransactionConfirmation } from 'src/app/services/algosdk.utils';
import { AutoLogoutService } from 'src/app/services/auto-logout.service';
import { OtpPromptService } from 'src/app/services/otp-prompt.service';
import { checkTxResponseSucceeded } from 'src/app/services/xrpl.utils';
import { ConnectorQuery } from 'src/app/state/connector';
Expand Down Expand Up @@ -73,6 +74,7 @@ export class PayPage implements OnInit {
this.sessionQuery.onfidoCheckIsClear;

constructor(
private autoLogoutService: AutoLogoutService,
private router: Router,
private navCtrl: NavController,
private sessionAlgorandService: SessionAlgorandService,
Expand Down Expand Up @@ -123,6 +125,7 @@ export class PayPage implements OnInit {
return;
}

this.autoLogoutService.disableAutoLogout();
const result = await withLoadingOverlayOpts(
this.loadingCtrl,
{ message: 'Checking OTP...' },
Expand All @@ -145,19 +148,22 @@ export class PayPage implements OnInit {
}
}
);
this.autoLogoutService.enableAutoLogout();
}

async confirmTransaction(
amount: AssetAmount,
receiverAddress: string
): Promise<void> {
this.autoLogoutService.disableAutoLogout();
const result = await withLoadingOverlayOpts(
this.loadingCtrl,
{ message: 'Confirming Transaction' },
() => this.sendByLedgerType(amount, receiverAddress)
);

await this.notifyResult(result, amount, receiverAddress);
this.autoLogoutService.enableAutoLogout();

if (this.connectorQuery.getValue().walletId) {
resetStores({ exclude: ['connector'] });
Expand Down Expand Up @@ -279,6 +285,15 @@ export class PayPage implements OnInit {
txId: txResponse.id.toString(),
timestamp: new Date(),
});
} else if (resultCode === 'tecUNFUNDED_PAYMENT') {
this.notification.showInsufficientFunds();
this.navCtrl.back();
} else if (resultCode === 'tecPATH_DRY') {
this.notification.showCurrencyNotOptIn();
this.navCtrl.back();
} else if (resultCode === 'tecNO_DST_INSUF_XRP') {
this.notification.showDeletedWalletError();
this.navCtrl.back();
} else {
await this.notifyXrplFailure({ resultCode });
}
Expand Down
44 changes: 35 additions & 9 deletions web-client/src/app/views/pull/pull.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { LoadingController, NavController } from '@ionic/angular';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { firstValueFrom, map } from 'rxjs';
import { TransactionConfirmation } from 'src/app/services/algosdk.utils';
import { AutoLogoutService } from 'src/app/services/auto-logout.service';
import { checkTxResponseSucceeded } from 'src/app/services/xrpl.utils';
import { BookmarkQuery } from 'src/app/state/bookmark';
import { ConnectorQuery } from 'src/app/state/connector';
Expand Down Expand Up @@ -71,6 +72,7 @@ export class PullPage implements OnInit {
maxAmount = 1000000000;

constructor(
private autoLogoutService: AutoLogoutService,
public sessionQuery: SessionQuery,
private router: Router,
private navCtrl: NavController,
Expand Down Expand Up @@ -137,15 +139,30 @@ export class PullPage implements OnInit {
const amount = defined(this.amount);
const sender = defined(this.senderAddress);
if (isAssetAmountXrp(amount) || isAssetAmountXrplToken(amount)) {
const result = await withLoadingOverlayOpts(
this.loadingCtrl,
{ message: 'Confirming Transaction' },
() => this.receiveXrpl(amount, sender, pin)
);
await this.notifyResult(result, amount, sender);
if (this.connectorQuery.getValue().walletId) {
resetStores({ exclude: ['connector'] });
await this.navCtrl.back();
try {
this.autoLogoutService.disableAutoLogout();
const result = await withLoadingOverlayOpts(
this.loadingCtrl,
{ message: 'Confirming Transaction' },
() => this.receiveXrpl(amount, sender, pin)
);
this.autoLogoutService.enableAutoLogout();
await this.notifyResult(result, amount, sender);
if (this.connectorQuery.getValue().walletId) {
resetStores({ exclude: ['connector'] });
await this.navCtrl.navigateRoot('/');
}
} catch (error: any) {
this.autoLogoutService.enableAutoLogout();
if (error.message.includes('Account not found.')) {
this.notification.showDeletedWalletErrorPull();
this.navCtrl.back();
}

console.log(error);

this.notification.showUnexpectedFailureWarning();
this.navCtrl.back();
}
}
}
Expand Down Expand Up @@ -230,6 +247,15 @@ export class PullPage implements OnInit {
txId: txResponse.id.toString(),
timestamp: new Date(),
});
} else if (resultCode === 'tecUNFUNDED_PAYMENT') {
this.notification.showInsufficientFundsPullPayment();
this.navCtrl.back();
} else if (resultCode === 'tecNO_DST_INSUF_XRP') {
this.notification.showDeletedWalletErrorPull();
this.navCtrl.back();
} else if (resultCode === 'tecPATH_DRY') {
this.notification.showCurrencyNotOptInPull();
this.navCtrl.back();
} else {
await this.notifyXrplFailure({ resultCode });
}
Expand Down
2 changes: 1 addition & 1 deletion web-client/src/app/views/schedule-pay/schedule-pay.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export class SchedulePayPage implements OnInit {
),
});
await this.notification.showRecurringPaySuccessNotification();
this.navCtrl.navigateRoot(['/recurring-pay']);
this.navCtrl.back();
}
);
} else if (otpResult.data.status === 'pending') {
Expand Down
11 changes: 8 additions & 3 deletions web-client/src/app/views/transfer-funds/transfer-funds.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ActionItem } from 'src/app/components/action-item/action-item.component
import { SessionQuery } from 'src/app/state/session.query';
import { deviceHasCamera } from 'src/app/utils/camara.helpers';
import { SwalHelper } from 'src/app/utils/notification/swal-helper';
import { addressType } from 'src/app/utils/validators';
import { ManualAddressPage } from '../manual-address/manual-address.page';
import { handleScan } from '../scanner.helpers';

Expand Down Expand Up @@ -84,9 +85,13 @@ export class TransferFundsPage implements OnInit {
const { data } = await modal.onDidDismiss();
if (data?.success && data?.address) {
const { address } = data;
this.navCtrl.navigateForward(this.transferType, {
state: { address },
});
if (addressType(address)) {
this.navCtrl.navigateForward(this.transferType, {
state: { address },
});
} else {
this.notification.showInvalidAddress();
}
}
}

Expand Down
Loading

0 comments on commit 5f4e71e

Please sign in to comment.