Skip to content

Commit

Permalink
Merge pull request #311 from Cryptorubic/develop
Browse files Browse the repository at this point in the history
Iframe redesigned and instant trades table added
  • Loading branch information
siandreev authored May 21, 2021
2 parents 6b27328 + a1e4fdc commit 9298f71
Show file tree
Hide file tree
Showing 135 changed files with 4,027 additions and 31,298 deletions.
30,403 changes: 348 additions & 30,055 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,6 @@
"stylelint-scss": "^3.19.0",
"ts-node": "~7.0.0",
"tslint": "~6.1.0",
"typescript": "~4.0.7"
"typescript": "^4.1.5"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class LoginButtonComponent {
const isIframe = new AsyncPipe(this.cdr).transform(this.queryParamsService.$isIframe);
try {
if (isIframe) {
await this.authService.signInWithoutBackend();
await this.authService.iframeSignIn();
} else {
await this.authService.signIn();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<span
class="user-profile__text"
[ngClass]="{ 'user-profile__text_iconless': !($currentBlockchain | async)?.imagePath }"
>{{ ($currentUser | async)?.address }}</span>
>{{ ($currentUser | async)?.address | shortAddress: 5:3 }}</span>
</div>
<ul *ngIf="$isMobile | async" class="user-profile__list">
<li class="user-profile__item">
Expand Down
2 changes: 0 additions & 2 deletions src/app/core/header/components/header/header.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ export class HeaderComponent {
const isIframe = new AsyncPipe(this.cdr).transform(this.queryParamsService.$isIframe);
if (!isIframe) {
this.authService.loadUser();
} else {
this.authService.loginWithoutBackend();
}
this.$currentUser = this.authService.getCurrentUser();
this.pageScrolled = false;
Expand Down
35 changes: 20 additions & 15 deletions src/app/core/services/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class AuthService {
/**
* Is auth process going in.
*/
private isAuthProcess: boolean = false;
private isAuthProcess: boolean;

/**
* Current user data.
Expand All @@ -36,6 +36,7 @@ export class AuthService {
private readonly web3Service: Web3PrivateService,
private readonly queryParamsService: QueryParamsService
) {
this.isAuthProcess = false;
this.$currentUser = new BehaviorSubject<UserInterface>(undefined);
this.web3Service.onAddressChanges.subscribe(address => {
if (this.isAuthProcess) {
Expand All @@ -50,7 +51,7 @@ export class AuthService {
if (isIframe) {
this.$currentUser.next({ address });
} else {
window.location.reload();
// window.location.reload();
}
});
// TODO: надо продумать модальные окна на кейсы, когда юзер сменил адрес в метамаске но не подписал nonce с бэка
Expand Down Expand Up @@ -115,15 +116,6 @@ export class AuthService {
);
}

/**
* @description Login user without backend.
*/
public async loginWithoutBackend(): Promise<void> {
await this.web3Service.activate();
const { address } = this.web3Service;
this.$currentUser.next(address ? { address } : null);
}

/**
* @description Initiate authentication via metamask.
*/
Expand All @@ -139,11 +131,19 @@ export class AuthService {
this.isAuthProcess = false;
}

public async signInWithoutBackend(): Promise<void> {
public async iframeSignIn(): Promise<void> {
this.isAuthProcess = true;
await this.web3Service.activate();
const { address } = this.web3Service;
this.$currentUser.next({ address } || null);
const permissions = await this.web3Service.requestPermissions();
const accountsPermission = permissions.find(
permission => permission.parentCapability === 'eth_accounts'
);
if (accountsPermission) {
await this.web3Service.activate();
const { address } = this.web3Service;
this.$currentUser.next({ address } || null);
} else {
this.$currentUser.next(null);
}
this.isAuthProcess = false;
}

Expand All @@ -158,4 +158,9 @@ export class AuthService {
})
);
}

public iframeSignOut(): void {
this.web3Service.deActivate();
this.$currentUser.next(null);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { InstantTradesTradeData } from 'src/app/features/swaps-page/models/trade-data';
import { FROM_BACKEND_BLOCKCHAINS } from 'src/app/shared/constants/blockchain/BACKEND_BLOCKCHAINS';
import { HttpService } from '../../http/http.service';
import { BLOCKCHAIN_NAME } from '../../../../shared/models/blockchain/BLOCKCHAIN_NAME';
import InstantTrade from '../../../../features/swaps-page/instant-trades/models/InstantTrade';
import { BOT_URL } from '../constants/BOT_URL';
import { InstantTradesRequestApi, InstantTradesResponseApi } from './types/trade-api';
import { Web3PublicService } from '../../blockchain/web3-public-service/web3-public.service';
import { UseTestingModeService } from '../../use-testing-mode/use-testing-mode.service';
import { Web3PrivateService } from '../../blockchain/web3-private-service/web3-private.service';

const instantTradesApiRoutes = {
createData: 'instant_trades/',
editData: 'instant_trades/',
getData: 'instant_trades/'
};

@Injectable({
providedIn: 'root'
})
export class InstantTradesApiService {
constructor(private httpService: HttpService) {}
private isTestingMode: boolean;

constructor(
private httpService: HttpService,
private useTestingModeService: UseTestingModeService,
private web3PrivateService: Web3PrivateService
) {
this.useTestingModeService.isTestingMode.subscribe(res => (this.isTestingMode = res));
}

public notifyInstantTradesBot(body: {
provider: string;
Expand All @@ -29,4 +51,77 @@ export class InstantTradesApiService {

return this.httpService.post(BOT_URL.INSTANT_TRADES, req).toPromise();
}

/**
* @description send request to server for add trade
* @param tradeInfo data body for request
* @return instant trade object
*/
public createTrade(tradeInfo: InstantTradesRequestApi): Observable<InstantTradesResponseApi> {
if (this.isTestingMode) tradeInfo.network = 'ethereum-test';
return this.httpService.post(instantTradesApiRoutes.createData, tradeInfo);
}

/**
* @description update status of trade
* @param hash hash of transaction what we want to update
* @param status status of trade what we want to set
*/
public patchTrade(hash: string, status: string): Observable<InstantTradesResponseApi> {
const url = instantTradesApiRoutes.editData + hash;
return this.httpService.patch(url, { status });
}

/**
* @description get list of trades from server
* @return list of trades
*/
// TODO: use AuthService to get user wallet address instead of Web3Private after Coinbase realease
public fetchSwaps(): Observable<InstantTradesTradeData[]> {
return this.httpService
.get(instantTradesApiRoutes.getData, { user: this.web3PrivateService.address })
.pipe(
map((swaps: InstantTradesResponseApi[]) =>
swaps.map(swap => this.tradeApiToTradeData(swap))
)
);
}

/**
* @description transform data structure to our format
* @param tradeApi data from server
*/
public tradeApiToTradeData(tradeApi: InstantTradesResponseApi): InstantTradesTradeData {
const tradeData = ({
hash: tradeApi.hash,
provider: tradeApi.contract.name,
token: {
from: {
...tradeApi.from_token,
blockchain: FROM_BACKEND_BLOCKCHAINS[tradeApi.from_token.blockchain_network],
price: tradeApi.from_token.usd_price
},
to: {
...tradeApi.to_token,
blockchain: FROM_BACKEND_BLOCKCHAINS[tradeApi.to_token.blockchain_network],
price: tradeApi.to_token.usd_price
}
},
blockchain:
FROM_BACKEND_BLOCKCHAINS[tradeApi.contract.blockchain_network.title] || 'ETH_TESTNET',
status: tradeApi.status,
date: new Date(tradeApi.status_updated_at)
} as unknown) as InstantTradesTradeData;

tradeData.fromAmount = Web3PublicService.tokenWeiToAmount(
tradeData.token.from,
tradeApi.from_amount
);
tradeData.toAmount = Web3PublicService.tokenWeiToAmount(
tradeData.token.from,
tradeApi.to_amount
);

return tradeData;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import InputToken from 'src/app/shared/models/tokens/InputToken';
import { PROVIDERS } from '../../../../../features/swaps-page/instant-trades/models/providers.enum';

interface InstantTradesBlockchainNetwork {
title: string;
}

interface InstantTradesContract {
name: string;
address: string;
blockchain_network: InstantTradesBlockchainNetwork;
}

interface InstantTradesTokenApi extends InputToken {
blockchain_network: string;
coingecko_id: string;
usd_price: number;
}

export interface InstantTradesRequestApi {
hash: string;
provider: string;
network: string;
}

export interface InstantTradesResponseApi {
hash: string;
contract: InstantTradesContract;
user: { username: string };
from_token: InstantTradesTokenApi;
to_token: InstantTradesTokenApi;
from_amount: string;
to_amount: string;
gas_price: string;
gas_limit: string;
status: string;
status_updated_at: string;
}

interface InstantTradesOthersApi {
hash: string;
provider: PROVIDERS;
network: string;
}

interface InstantTradesOneInchApi {
hash: string;
provider: PROVIDERS;
network: string;
from_token: string;
to_token: string;
from_amount: number;
to_amount: number;
}

export type InstantTradesPostApi = InstantTradesOthersApi | InstantTradesOneInchApi;
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ export class OrderBookApiService {
uniqueLink,

token: {
base: undefined,
quote: undefined
from: undefined,
to: undefined
},
blockchain: FROM_BACKEND_BLOCKCHAINS[tradeApi.network],
expirationDate: moment.utc(tradeApi.stop_date),
Expand All @@ -99,8 +99,8 @@ export class OrderBookApiService {
brokerAddress: tradeApi.broker_fee_address,
status: ORDER_BOOK_TRADE_STATUS[tradeApi.state]
} as OrderBookTradeData;
await this.setTokensData('base', tradeApi, tradeData);
await this.setTokensData('quote', tradeApi, tradeData);
await this.setTokensData('from', tradeApi, tradeData);
await this.setTokensData('to', tradeApi, tradeData);

return tradeData;
}
Expand All @@ -110,9 +110,11 @@ export class OrderBookApiService {
tradeApi: OrderBookTradeApi,
tradeData: OrderBookTradeData
): Promise<void> {
const tokenPartApi = tokenPart === 'from' ? 'base' : 'quote';

tradeData.token[tokenPart] = {
blockchain: tradeData.blockchain,
address: tradeApi[`${tokenPart}_address`]
address: tradeApi[`${tokenPartApi}_address`]
} as OrderBookDataToken;

const foundToken = this._tokens.find(
Expand All @@ -134,13 +136,13 @@ export class OrderBookApiService {
...tradeData.token[tokenPart],
amountTotal: Web3PublicService.tokenWeiToAmount(
tradeData.token[tokenPart],
tradeApi[`${tokenPart}_limit`]
tradeApi[`${tokenPartApi}_limit`]
),
minContribution: Web3PublicService.tokenWeiToAmount(
tradeData.token[tokenPart],
tradeApi[`min_${tokenPart}_wei`]
tradeApi[`min_${tokenPartApi}_wei`]
),
brokerPercent: tradeApi[`broker_fee_${tokenPart}`]
brokerPercent: tradeApi[`broker_fee_${tokenPartApi}`]
};
}

Expand All @@ -157,10 +159,10 @@ export class OrderBookApiService {
link: `${
window.location.origin === this.PROD_ORIGIN ? this.PROD_ORIGIN : this.TEST_ORIGIN
}/trades/public-v3/${uniqueLink}`,
amountFrom: tradeForm.token.base.amount,
amountTo: tradeForm.token.quote.amount,
symbolFrom: tradeForm.token.base.symbol,
symbolTo: tradeForm.token.quote.symbol
amountFrom: tradeForm.token.from.amount,
amountTo: tradeForm.token.to.amount,
symbolFrom: tradeForm.token.from.symbol,
symbolTo: tradeForm.token.to.symbol
};

this.httpService.post(`${BOT_URL.ORDER_BOOKS}/create`, tradeBot).subscribe();
Expand Down
18 changes: 9 additions & 9 deletions src/app/core/services/backend/order-book-api/types/trade-api.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
export interface OrderBookTradeApi {
memo: string; // unique id, returned from smart-contract after creation
contract_address: string; // address of smart-contract
base_address: string; // address of base token
quote_address: string; // address of quote token
base_limit: string; // total amount of base tokens
quote_limit: string; // total amount of base tokens
base_address: string; // address of from token
quote_address: string; // address of to token
base_limit: string; // total amount of from tokens
quote_limit: string; // total amount of to tokens
base_amount_contributed: string;
quote_amount_contributed: string;
stop_date: string; // the date of expiration
public: boolean; // is trade public or not
min_base_wei: string; // min amount of base tokens to contribute
min_quote_wei: string; // min amount of quote tokens to contribute
min_base_wei: string; // min amount of from tokens to contribute
min_quote_wei: string; // min amount of to tokens to contribute
broker_fee: boolean; // is with broker's fee or not
broker_fee_address: string; // broker's adress
broker_fee_base: number; // broker's percent on base token
broker_fee_quote: number; // broker's percent on quote token
broker_fee_base: number; // broker's percent on from token
broker_fee_quote: number; // broker's percent on to token
unique_link?: string; // Unique link to display trade.

// to delete or change
name: string; // base.token_short_title + ' <> ' + quote.token_short_title
name: string; // token.from.name + ' <> ' + token.to.name
network: string;
state: string;
contract_state: 'ACTIVE';
Expand Down
Loading

0 comments on commit 9298f71

Please sign in to comment.