Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d97e06a
tmp commit
Jun 16, 2022
89006ab
Merge branch 'master' into fb-takyoon-message-onchain
takYoon Jun 17, 2022
2dfb9fc
tmp commit
takYoon Jun 17, 2022
d0d9d6c
add message reply component
takYoon Jun 21, 2022
d08da80
Merge branch 'master' into fb-takyoon-message-onchain
eric-son12 Mar 9, 2023
eb09c40
implement ui onchain message
eric-son12 Mar 20, 2023
4608c97
implement onchain message
eric-son12 Mar 20, 2023
169d5a6
apply logic encrypt and decrypt message
takYoon Mar 23, 2023
fc6a445
Merge branch 'fb-takyoon-tmp-onchain' into fb-takyoon-message-onchain
takYoon Mar 23, 2023
4129a88
only wallet xpi and single address can use feature onchain message
takYoon Mar 23, 2023
d82079a
Merge branch 'master' into fb-takyoon-message-onchain
takYoon Mar 23, 2023
b07c162
Merge branch 'master' into fb-takyoon-message-onchain
takYoon Mar 23, 2023
92c5ed2
pump version for bitcore-wallet-client
takYoon Mar 23, 2023
d5058f4
fix issue onchain
takYoon Mar 27, 2023
74806be
Merge branch 'master' into fb-takyoon-message-onchain
takYoon Mar 27, 2023
b089426
fix loading screen
takYoon Mar 28, 2023
47f813b
Merge branch 'master' into fb-takyoon-message-onchain
eric-son12 Mar 28, 2023
af196e5
commit code
takYoon Mar 29, 2023
fde1f59
added new whitelist for chronik api
takYoon Mar 29, 2023
cf20359
polish ui 30032023
eric-son12 Mar 29, 2023
b8ae7ba
Merge branch 'master' into fb-takyoon-message-onchain
eric-son12 Apr 5, 2023
73df200
refactor code
eric-son12 Apr 6, 2023
46f5e67
Merge branch 'master' into fb-takyoon-message-onchain
takYoon Jul 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"buffer-compare": "^1.1.1",
"capacitor-resources": "^2.0.5",
"chart.js": "^3.5.1",
"chronik-client": "^0.8.2",
"cordova": "^10.0.0",
"cordova-android": "^10.1.0",
"cordova-clipboard": "^1.3.0",
Expand Down
25 changes: 25 additions & 0 deletions src/app/components/message-reply/message-reply.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<action-sheet>
<div class="reply-to-container">
<div class="reply-to-title">
<ion-icon [src]="currentTheme == 'dark' ? 'assets/img/ico-reply-dark.svg' : 'assets/img/ico-reply-light.svg'"></ion-icon>
{{'Replying to ' | translate }} {{ messageReplyInfo.addressTo }}
</div>
<div class="reply-to-message">
{{messageReplyInfo.messageOnChain}}
</div>
</div>

<form [formGroup]="messageReplySend">
<mat-form-field appearance="outline">
<mat-label translate>{{'Private message' | translate}}</mat-label>
<textarea matInput formControlName="messageOnChain" [(ngModel)]="message" (keyup)="changeMessage()" [placeholder]="'Type your private message' | translate" maxlength="206"></textarea>
</mat-form-field>
<mat-hint class="hint-reply-message">
{{Buffer.from(this.message).length}} / 206 bytes
</mat-hint>
</form>

<ion-button fill="clear" type="submit" class="button-standard safe-area button-send-onchain" [disabled]="!validMessage" (click)="send()">
{{ 'Send' | translate }}
</ion-button>
</action-sheet>
93 changes: 93 additions & 0 deletions src/app/components/message-reply/message-reply.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
message-reply-component {
.scanner-icon {
z-index: 99;
font-size: 28px;
color: var(--ion-color-primary);
}
.check {
font-size: 22px;
padding-top: 1rem;
&.success {
color: var(--ion-color-success);
}
&.fail {
color: var(--ion-color-danger);
}
}

label-tip {
margin-top: 1.8rem;
}

.slide-title {
h3 {
margin: 0;
font-weight: 400;
font-size: 24px;
line-height: 32px;
color: #001e2e;
margin-bottom: 2rem;
}
}
form {
margin: 0 8px 24px 8px;
ion-item {
margin: 2rem 0;
border: 2px solid rgba(0, 30, 46, 0.38);
--inner-padding-start: 1rem;
--inner-padding-end: 1rem;
--inner-padding-end: 0;
--padding-start: 0;
--padding-end: 0;
--color: #001e2e;
--background: #fafafb;
border-radius: 4px;
ion-input {
font-weight: 400;
font-size: 16px !important;
line-height: 24px;
letter-spacing: 0.5px;
}
ion-icon {
padding: 0;
}
}
.form-field {
margin-bottom: 3rem !important;
padding: 0 !important;
}
.mat-form-field-subscript-wrapper {
margin-top: 2rem !important;
padding: 0 !important;
}

.mobile-view {
.mat-form-field-infix {
max-width: 85%;
}
}
}
.reply-to-container {
background: linear-gradient(0deg, rgba(0, 101, 141, 0.14), rgba(0, 101, 141, 0.14)), #FAFAFB;
border: 1px solid rgba(126, 208, 255, 0.08);
border-radius: 8px;
padding: 8px;
margin: 24px;
.reply-to-title {
color: #1C3745;
font-size: 16px;
font-weight: 600;
letter-spacing: 0.1px;
}
.reply-to-message {
color: #1C3745;
letter-spacing: 0.25px;
font-size: 14px;
}
}

.button-send-onchain {
width: fit-content !important;
margin: 5px 24px 25px auto !important;
}
}
24 changes: 24 additions & 0 deletions src/app/components/message-reply/message-reply.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';

import { MessageReplyComponent } from './message-reply.component';

describe('MessageReplyComponent', () => {
let component: MessageReplyComponent;
let fixture: ComponentFixture<MessageReplyComponent>;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ MessageReplyComponent ],
imports: [IonicModule.forRoot()]
}).compileComponents();

fixture = TestBed.createComponent(MessageReplyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));

it('should create', () => {
expect(component).toBeTruthy();
});
});
53 changes: 53 additions & 0 deletions src/app/components/message-reply/message-reply.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Location } from '@angular/common';
import { Router } from '@angular/router';
import { Logger } from 'src/app/providers/logger/logger';
import { ActionSheetParent } from '../action-sheet/action-sheet-parent';
import { FormBuilder, FormGroup } from '@angular/forms';
import { AppProvider } from 'src/app/providers/app/app';

@Component({
selector: 'message-reply-component',
templateUrl: './message-reply.component.html',
styleUrls: ['./message-reply.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class MessageReplyComponent extends ActionSheetParent{
message = '';
Buffer = Buffer;
messageReplyInfo: any;
public currentTheme: string;
public messageReplySend: FormGroup;
messageOnChainValue;
validMessage: boolean = false;
constructor(
private formBuilder: FormBuilder,
private appProvider: AppProvider,
) {
super();
this.currentTheme = this.appProvider.themeProvider.currentAppTheme;
this.messageReplySend = this.formBuilder.group({
messageOnChain: [
'',
[]
]
});
}

ngOnInit() {
this.messageReplyInfo = this.params;
}

public changeMessage() {
if (this.message.trim().length > 0) {
this.validMessage = true;
} else {
this.validMessage = false;
}
}

send(){
const message = this.messageReplySend.value.messageOnChain;
this.dismiss(message);
}
}
11 changes: 10 additions & 1 deletion src/app/components/recipient/recipient.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,16 @@
<span *ngIf="!token" (click)="changeUnit()" [ngClass]="{'disabled': isSelectedTotalAmout, 'bold-text': !isSelectedTotalAmout}">{{unit}} </span>
<span *ngIf="token" (click)="changeUnit()" class="bold-text">{{unit}}</span>
</ion-item>
<p class="unit-alt-text">{{recipient.altAmountStr}} {{alternativeUnit}}</p>
<ng-conatiner *ngIf="isShowMessage">
<div class="amount-header">
<p class="title">{{'Private message' | translate}}</p>
</div>
<ion-item lines="none" class="amount-wrapper">
<ion-textarea maxlength="206" [placeholder]="'Type your private message' | translate" [(ngModel)]="message" (ionChange)="changeMessage()"></ion-textarea>
</ion-item>
<p class="unit-alt-text">{{Buffer.from(this.message).length}} / 206 bytes</p>
</ng-conatiner>

<div class="selected-amount" lines="none" *ngIf="isShowSelectInput">
<ion-label class="item-title">{{'Send total selected amount' | translate}}</ion-label>
<ion-toggle [(ngModel)]="isSelectedTotalAmout" (ionChange)="changeSelectedAmount($event)" ></ion-toggle>
Expand Down
6 changes: 6 additions & 0 deletions src/app/components/recipient/recipient.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ recipient-component {
font-size: 16px;
}

ion-textarea{
--placeholder-color: rgba(0, 30, 46, 0.38);
--color: #001E2E;
font-size: 16px;
}

.scan-icon {
width: 20px;
height: 20px;
Expand Down
27 changes: 24 additions & 3 deletions src/app/components/recipient/recipient.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import { Keyboard } from '@capacitor/keyboard';
export class RecipientComponent implements OnInit {
public search: string = '';
public amount: string = '';
public amountResult: number = 0;
navParamsData: any;
public isCordova: boolean;
public expression;
Expand All @@ -78,6 +79,7 @@ export class RecipientComponent implements OnInit {
public searchValue: string;
validAddress = false;
validAmount = false;
validMessage = false;
isSelectedTotalAmout: boolean = false;
remaining: number;
isShowReceiveLotus: boolean;
Expand All @@ -86,6 +88,8 @@ export class RecipientComponent implements OnInit {
formatRemaining: string;
messagesReceiveLotus: boolean = false;

message='';
Buffer = Buffer;
@Input()
recipient: RecipientModel;

Expand Down Expand Up @@ -113,8 +117,12 @@ export class RecipientComponent implements OnInit {
@Input()
isDonation?: boolean;

@Output() deleteEvent? = new EventEmitter<number>();
@Output() sendMaxEvent? = new EventEmitter<boolean>();
@Input()
isShowMessage?: boolean;

@Output() deleteEvent?= new EventEmitter<number>();
@Output() sendMaxEvent?= new EventEmitter<boolean>();

@Output() sendOfficialInfo? = new EventEmitter<PageModel>();
private validDataTypeMap: string[] = [
'BitcoinAddress',
Expand Down Expand Up @@ -234,6 +242,17 @@ export class RecipientComponent implements OnInit {
this.updateUnitUI(!!isToken);
}

public changeMessage() {
if (this.message.trim().length > 0) {
this.validMessage = true;
this.recipient.message = this.message;
this.checkRecipientValid();
} else {
this.validMessage = false;
this.checkRecipientValid();
}
}

private updateAddressHandler: any = data => {
if (data.recipientId === this.recipient.id) {
this.searchValue = data.value;
Expand Down Expand Up @@ -506,6 +525,7 @@ export class RecipientComponent implements OnInit {
this.recipient.amount = parseInt(amount, 10);
}
this.validAmount = result > 0;
this.amountResult = result;
this.checkRecipientValid();
if (isSendMax) {
this.sendMaxEvent.emit(true);
Expand Down Expand Up @@ -749,8 +769,9 @@ export class RecipientComponent implements OnInit {

checkRecipientValid() {
if (!this.isDonation) {
this.recipient.isValid = this.validAddress && this.validAmount;
this.recipient.isValid = this.validAddress && (this.validAmount || this.validMessage);
} else {

if (this.isShowReceiveLotus) {
this.recipient.isValid = this.validAddress && this.validAmount;
} else {
Expand Down
1 change: 1 addition & 0 deletions src/app/components/recipient/recipient.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export class RecipientModel {
public amount: number;
public amountToShow: string;
public altAmountStr: string;
public message?: string;
public isOfficialInfo: boolean;
public isValid?: boolean;
public id?: number = Date.now();
Expand Down
33 changes: 33 additions & 0 deletions src/app/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
export const CARD_IAB_CONFIG =
'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,hidden=yes,clearcache=yes,hidespinner=yes,disallowoverscroll=yes,zoom=no,transitionstyle=crossdissolve';
export const DUST_AMOUNT = 546;
export const currency = {
name: 'Lotus',
ticker: 'XPI',
legacyPrefix: 'bitcoincash',
prefixes: ['lotus'],
coingeckoId: 'bitcoin-cash-abc-2',
defaultFee: 1.01,
dustSats: 550,
etokenSats: 546,
cashDecimals: 6,
blockExplorerUrl: 'https://explorer.givelotus.org',
tokenExplorerUrl: 'https://explorer.be.cash',
blockExplorerUrlTestnet: 'https://texplorer.bitcoinabc.org',
tokenName: 'eToken',
tokenTicker: 'eToken',
tokenPrefixes: ['etoken'],
tokenIconsUrl: '', // https://tokens.bitcoin.com/32 for BCH SLP
txHistoryCount: 10,
hydrateUtxoBatchSize: 20,
defaultSettings: { fiatCurrency: 'usd' },
opReturn: {
opReturnPrefixHex: '6a',
opReturnAppPrefixLengthHex: '04',
opPushDataOne: '4c',
appPrefixesHex: {
eToken: '534c5000',
lotusChat: '02020202',
lotusChatEncrypted: '03030303'
},
encryptedMsgByteLimit: 206,
unencryptedMsgByteLimit: 215
}
};
Loading