Commit ce39a68a authored by XFT-dev's avatar XFT-dev
Browse files

initializing repo

parent 8605a110
<router-outlet></router-outlet>
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});
import {Component, OnInit} from '@angular/core';
import {action} from 'mobx-angular';
import {AppService} from './app.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(private appService: AppService) {}
@action ngOnInit() {
this.appService.init();
}
}
import {BrowserModule, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { environment } from '../environments/environment';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {MobxAngularModule} from 'mobx-angular';
import { ServiceWorkerModule } from '@angular/service-worker';
// modules
import { AppRoutingModule } from './app-routing.module';
import {IntegrationsModule} from './integrations/integrations.module';
// components
import {HeaderComponent} from './components/header/header.component';
import { AppComponent } from './app.component';
import {LoginComponent} from './pages/login/login.component';
import {SharedModule} from './shared/shared.module';
import {FormComponent} from './pages/form/form.component';
// directives
import {NumberOnlyDirective} from './shared/directives/number-only/number-only.directive';
import {AngularWeb3RecentTransactionsService} from 'angular-web3-components';
import {GestureConfig} from '@angular/material/core';
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
@NgModule({
declarations: [
AppComponent,
FormComponent,
HeaderComponent,
NumberOnlyDirective,
LoginComponent
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
HttpClientModule,
IntegrationsModule,
SharedModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
}),
ServiceWorkerModule.register('ngsw-worker.js', {enabled: environment.production}),
],
exports: [
SharedModule
],
providers: [{ provide: HAMMER_GESTURE_CONFIG, useClass: GestureConfig }, AngularWeb3RecentTransactionsService],
bootstrap: [AppComponent]
})
export class AppModule { }
import {Injectable} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {AuthService} from './core/services/auth/auth.service';
import {TransactionsService} from './core/services/services/transactions.service';
@Injectable({
providedIn: 'root'
})
export class AppService {
constructor(
private translate: TranslateService,
private transactionsService: TransactionsService,
private authService: AuthService,
) { }
init() {
this.authService.init();
this.translate.setDefaultLang('en');
this.translate.use('en');
this.transactionsService.init();
}
}
<ng-container *mobxAutorun>
<div class="header-box">
<div class="header-box__logo">
<a routerLink="/">
<img [src]="'assets/img/logo-icon.svg'" alt="logo"/>
</a>
</div>
<div class="display-flex">
<div *ngIf="isLogged" class="header-box__logo__status">
<ng-web3-recent-transactions
[web3]="web3"
[storageService]="storageService"
[accountAddress]="accountAddress"
[applicationName]="applicationName">
</ng-web3-recent-transactions>
</div>
<div class="header-box__logout-icon" [matTooltip]="'Back to origin site'"
aria-label="Back to origin site">
<a href="https://www.offshift.io/">
<img [src]="'assets/img/logout.svg'" alt="logo"/>
</a>
</div>
</div>
</div>
</ng-container>
@import "./src/themes/variables";
.display-flex{
display: flex;
justify-content: center;
align-items: center;
}
.header-box{
height: 90px;
background-color: $white-color;
display: flex;
justify-content: space-between;
align-items: center;
&__logo{
img{
width: 160px;
padding-left: 25px;
}
&__status{
margin-right: 20px;
}
}
&__logout-icon{
img{
width: 30px;
padding-right: 25px;
}
}
//&__menu-list {
// display: flex;
// height: 90px;
// align-items: flex-end;
// margin-right: 30px;
// &__item{
// color: $black-color;
// font-style: normal;
// font-size: 16px;
// line-height: 20px;
// text-align: center;
// font-weight: 600;
// white-space: nowrap;
// text-transform: uppercase;
// margin: 0 20px;
// padding-bottom: 20px;
// &__active{
// padding-bottom: 16px;
// border-bottom: solid 4px $form-color;
// }
// }
//}
}
import {Component, OnInit} from '@angular/core';
import {WEB3} from '../../integrations/dictionaries/meta-mask.dictionary';
import {LocalStorageService} from '../../core/services/services/storage.service';
import {AuthService} from '../../core/services/auth/auth.service';
import {computed} from 'mobx-angular';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
})
export class HeaderComponent implements OnInit {
public web3 = window[WEB3];
public accountAddress: string;
public applicationName: string;
constructor(public storageService: LocalStorageService,
private authService: AuthService) {}
ngOnInit() {
this.accountAddress = this.authService.user?.address;
this.applicationName = 'offshift';
}
@computed get isLogged() {
return this.authService.isLogged;
}
}
import {Injectable} from '@angular/core';
import {CanActivate, Router, RouterStateSnapshot, ActivatedRouteSnapshot} from '@angular/router';
import {action} from 'mobx-angular';
import {AuthService} from '../../services/auth/auth.service';
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
constructor(
private router: Router,
private authenticationService: AuthService
) { }
@action canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (!this.authenticationService.isLogged) {
this.router.navigate(['/login']);
return false;
}
return true;
}
}
import {Injectable} from '@angular/core';
import {observable, action, computed} from 'mobx-angular';
import {Router} from '@angular/router';
import {Web3Service} from '../../../integrations/services/web3/web3.service';
import { LOCAL_STORAGE_ADDRESS_KEY} from '../../../integrations/dictionaries/meta-mask.dictionary';
import {UtilsService} from '../services/utils.service';
export interface User {
address: string;
}
@Injectable({
providedIn: 'root'
})
export class AuthService {
@observable user: User;
constructor(private web3: Web3Service,
private utilsService: UtilsService,
private router: Router) {}
@action async init() {
this.user = this.getUserLoggedIn;
if ( this.user) {
this.setUserLoggedIn(this.user);
await this.web3.setMetamaskProvider();
} else {
this.web3.setInfuraProvider().then();
}
}
@action connectToMetaMask() {
this.web3.connectToMetaMask().subscribe( res => {
this.setUserLoggedIn({address: res});
this.router.navigate(['/']).then();
});
}
@action setUserLoggedIn(user: User) {
this.user = user;
localStorage.setItem(LOCAL_STORAGE_ADDRESS_KEY, JSON.stringify(user));
console.log('saved on localStorage');
}
@computed get getUserLoggedIn(): User {
if (localStorage.getItem(LOCAL_STORAGE_ADDRESS_KEY)) {
return JSON.parse(localStorage.getItem(LOCAL_STORAGE_ADDRESS_KEY));
} else {
return null;
}
}
@action logout() {
this.removeUser();
this.web3.setInfuraProvider().then();
}
@action removeUser() {
window.localStorage.removeItem(LOCAL_STORAGE_ADDRESS_KEY);
this.router.navigate(['/']).then();
this.user = null;
}
@computed get isLogged(): boolean {
return this.user != null;
}
}
import {Injectable} from '@angular/core';
import {Contract} from 'web3-eth-contract';
import {Subject} from 'rxjs';
import {Web3Service} from '../../../integrations/services/web3/web3.service';
import {UtilsService} from './utils.service';
import {BLOCKS_PER_DAY, DIVIDER_FOR_BALANCE, PID, STAKING_CONTRACT_ADDRESS_MAIN_NET, TOKEN_DECIMALS, WEB3, XFT_APY_CONST} from '../../../integrations/dictionaries/meta-mask.dictionary';
import {ONSEN_CONTRACT_ADDRESS_MAIN_NET} from '../../../integrations/dictionaries/meta-mask.dictionary';
import sushiData from '@sushiswap/sushi-data';
import {AngularWeb3RecentTransactionsService} from 'angular-web3-components';
@Injectable({
providedIn: 'root'
})
export class StakeSlpService {
private slpBalance: string;
public slpBalanceChange = new Subject<string>();
private staked: string;
public stakedChange = new Subject<string>();
private slpAllowance: string;
public slpAllowanceChange = new Subject<string>();
private rewardsXFT: number;
public rewardsXFTChange = new Subject<number>();
private rewardsSushi: number;
public rewardsSushiChange = new Subject<number>();
private apySushi: any;
public apySushiChange = new Subject<number>();
private apyXFT: any;
public apyXFTChange = new Subject<number>();
constructor(
private web3Service: Web3Service,
private utilsService: UtilsService,
private recentTransactionsService: AngularWeb3RecentTransactionsService,
) {}
public getSLPBalance(accountAddress: string): void {
if (this.slpBalance) {
this.slpBalanceChange.next(this.slpBalance);
} else {
this.fetchSLPBalance(accountAddress);
}
}
public fetchSLPBalance(accountAddress: string): void {
this.web3Service.getSlpContract().then((contract: Contract) => {
contract.methods.balanceOf(accountAddress).call({from: accountAddress}).then((res: string) => {
this.slpBalance = res;
this.slpBalanceChange.next(this.slpBalance);
});
});
}
public getStaked(accountAddress: string): void {
if (this.staked) {
this.stakedChange.next(this.staked);
} else {
this.fetchStaked(accountAddress);
}
}
public fetchStaked(accountAddress: string): void {
this.web3Service.getStakingContract().then((contract: Contract) => {
contract.methods.balanceOf(accountAddress).call({from: accountAddress}).then((res: string) => {
this.staked = res;
this.stakedChange.next(this.staked);
});
});
}
public getSLPAllowance(accountAddress: string): void {
if (this.slpAllowance) {
this.slpAllowanceChange.next(this.slpAllowance);
} else {
this.fetchSLPAllowance(accountAddress);
}
}
public fetchSLPAllowance(accountAddress: string): void {
this.web3Service.getSlpContract().then((contract: Contract) => {
contract.methods.allowance(accountAddress, STAKING_CONTRACT_ADDRESS_MAIN_NET).call({from: accountAddress}).then((res: string) => {
this.slpAllowance = res;
this.slpAllowanceChange.next(this.slpAllowance);
});
});
}
public approveNewAllowance(amount: string, accountAddress: string): Promise<any> {
return this.web3Service.getSlpContract().then((contract: Contract) => {
return contract.methods.approve(
STAKING_CONTRACT_ADDRESS_MAIN_NET,
amount
).send({from: accountAddress}, (err, hash) => {
if (!err) {
this.recentTransactionsService.saveTransaction('Approve new allowance for stake SLP', hash);
}
});
});
}
public stake(amount: string, accountAddress: string): Promise<any> {
return new Promise<any>((resolve, reject) => {
this.web3Service.getStakingContract().then((contract: Contract) => {
contract.methods.stake(amount).send({from: accountAddress}, (err, hash) => {
if (!err) {
this.recentTransactionsService.saveTransaction('Stake SLP', hash);
resolve(hash);
} else {
reject(err);
}
});
});
});
}
public unStake(amount: string, accountAddress: string): Promise<any> {
return new Promise<any>((resolve, reject) => {
this.web3Service.getStakingContract().then((contract: Contract) => {
contract.methods.withdraw(amount).send({from: accountAddress}, (err, hash) => {
if (!err) {
this.recentTransactionsService.saveTransaction('Withdraw SLP', hash);
resolve(hash);
} else {
reject(err);
}
});
});
});
}
public claimReward(accountAddress: string): Promise<any> {
return new Promise<any>((resolve, reject) => {
return this.web3Service.getStakingContract().then((contract: Contract) => {
contract.methods.getReward().send({from: accountAddress}, (err, hash) => {
if (!err) {
this.recentTransactionsService.saveTransaction('Get reward', hash);
resolve(hash);
} else {
reject(err);
}
});
});
});
}
public getRewardsXFT(accountAddress: string): void {
if (this.rewardsXFT) {
this.rewardsXFTChange.next(this.rewardsXFT);
} else {
this.fetchRewardsXFT(accountAddress);
}
}
public fetchRewardsXFT(accountAddress: string): void {
this.web3Service.getStakingContract().then((contract: Contract) => {
contract.methods.earnedXFT(accountAddress).call({from: accountAddress}).then((res: string) => {
this.rewardsXFT = this.utilsService.parseAmount(res, DIVIDER_FOR_BALANCE);
this.rewardsXFT = this.rewardsXFT / 100;
this.rewardsXFTChange.next(this.rewardsXFT);
});
});
}
public getRewardsSushi(accountAddress: string): void {
if (this.rewardsSushi) {
this.rewardsSushiChange.next(this.rewardsSushi);
} else {
this.fetchRewardsSushi(accountAddress);
}
}
public fetchRewardsSushi(accountAddress: string): void {
this.web3Service.getStakingContract().then((contract: Contract) => {
contract.methods.earnedSushi(accountAddress).call({from: accountAddress}).then((res: string) => {
this.rewardsSushi = this.utilsService.parseAmount(res, DIVIDER_FOR_BALANCE);
this.rewardsSushi = this.rewardsSushi / 100;
this.rewardsSushiChange.next(this.rewardsSushi);
});
});
}
public getAPYSushi(accountAddress: string): void {
if (this.apySushi) {
this.apySushiChange.next(this.apySushi);
} else {
this.fetchAPYSushi(accountAddress).then();
}
}
public async fetchAPYSushi(accountAddress: string) {
const info = await sushiData.sushi.info();
const masterchefInfo = await sushiData.masterchef.info();
const derivedETH = info.derivedETH * Math.pow(10, 18);
this.web3Service.getSlpContract().then((slpContract: Contract) => {
slpContract.methods.totalSupply().call({from: accountAddress}).then((totalSupplyResult: any) => {
const totalSupply = totalSupplyResult;
this.web3Service.getOnsenContract().then((onsenContract: Contract) => {
onsenContract.methods.poolInfo(PID).call({from: accountAddress}).then((rewardPerBlockResult: any) => {
const allocPoint = rewardPerBlockResult['allocPoint'];
slpContract.methods.balanceOf(ONSEN_CONTRACT_ADDRESS_MAIN_NET).call({from: accountAddress}).then((slpBalanceResult: string) => {
const slpBalance = slpBalanceResult;
slpContract.methods.getReserves().call({from: accountAddress}).then((reservesResult: any) => {
const totalValueETH = reservesResult['_reserve1'];
onsenContract.methods.sushiPerBlock().call({from: accountAddress}).then((sushiPerBlockResult: any) => {
const sushiPerBlock = sushiPerBlockResult;
this.apySushi = this.calcSushiAPY(
derivedETH,
sushiPerBlock,
allocPoint,
masterchefInfo.totalAllocPoint,
totalValueETH,
slpBalance,
totalSupply
);
this.apySushi = this.apySushi * 100;
this.apySushi = this.utilsService.parseAmount(this.apySushi.toString(), 16) / 100 ;
this.apySushiChange.next(this.apySushi);
});
});
});
});
});