diff --git a/.eslintrc.json b/.eslintrc.json index 3b74c86c0..1ea2e5508 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -33,4 +33,3 @@ } ] } - diff --git a/.gitpod.yml b/.gitpod.yml index e9899a1d8..577bd0d5a 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -12,7 +12,7 @@ vscode: - angular.ng-template - ecmel.vscode-html-css - eamodio.gitlens - + # Ports to expose on workspace startup ports: - port: 4200 @@ -21,4 +21,4 @@ ports: # Github integration github: prebuilds: - master: true \ No newline at end of file + master: true diff --git a/.prettierrc b/.prettierrc index b0802dd62..efdc59ee7 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,7 +1,6 @@ { - "printWidth": 120, - "tabWidth": 2, - "useTabs": false, - "quoteProps": "as-needed", - "htmlWhitespaceSensitivity": "ignore", + "tabWidth": 2, + "useTabs": false, + "printWidth": 80, + "singleQuote": true } diff --git a/README.md b/README.md index 06ff2386b..d6e881965 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ![DeSo Logo](src/assets/deso/camelcase_logo.svg) # About DeSo + DeSo is a blockchain built from the ground up to support a fully-featured social network. Its architecture is similar to Bitcoin, only it supports complex social network data like profiles, posts, follows, creator coin transactions, and @@ -9,13 +10,16 @@ more. [Read about the vision](https://docs.deso.org/#the-ultimate-vision) # About This Repo + Documentation for this repo lives on docs.deso.org. Specifically, the following docs should give you everything you need to get started: -* [DeSo Code Walkthrough](https://docs.deso.org/code/walkthrough) -* [Setting Up Your Dev Environment](https://docs.deso.org/code/dev-setup) -* [Making Your First Changes](https://docs.deso.org/code/making-your-first-changes) + +- [DeSo Code Walkthrough](https://docs.deso.org/code/walkthrough) +- [Setting Up Your Dev Environment](https://docs.deso.org/code/dev-setup) +- [Making Your First Changes](https://docs.deso.org/code/making-your-first-changes) # Start Coding + The quickest way to contribute changes to the BitClout Frontend is the following these steps: 1. Open frontend repo in Gitpod @@ -26,9 +30,8 @@ You can use any repo / branch URL and just prepend `https://gitpod.io/#` to it. 2. If needed, login to your github account -3. Set the correct `lastLocalNodeV2` to `"https://api.tijn.club"` in your browser Local Storage for the gitpod preview URL +3. Set the correct `lastLocalNodeV2` to `"https://api.tijn.club"` in your browser Local Storage for the gitpod preview URL 4. Create a new branch to start working To commit / submit a pull reqest from gitpod, you will need to give gitpod additional permissions to your github account: `public_repo, read:org, read:user, repo, user:email, workflow` which you can do on the [GitPod Integrations page](https://gitpod.io/integrations). - diff --git a/angular.json b/angular.json index a9c382511..00739c945 100644 --- a/angular.json +++ b/angular.json @@ -26,10 +26,7 @@ "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "src/tsconfig.app.json", - "assets": [ - "src/assets", - "src/vendor" - ], + "assets": ["src/assets", "src/vendor"], "styles": [ "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "./node_modules/ngx-toastr/toastr.css", @@ -100,18 +97,13 @@ "src/styles.sass" ], "scripts": [], - "assets": [ - "src/assets" - ] + "assets": ["src/assets"] } }, "lint": { "builder": "@angular-eslint/builder:lint", "options": { - "lintFilePatterns": [ - "src/**/*.ts", - "src/**/*.html" - ] + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] } } } @@ -136,10 +128,7 @@ "lint": { "builder": "@angular-eslint/builder:lint", "options": { - "lintFilePatterns": [ - "e2e//**/*.ts", - "e2e//**/*.html" - ] + "lintFilePatterns": ["e2e//**/*.ts", "e2e//**/*.html"] } } } diff --git a/e2e/.eslintrc.json b/e2e/.eslintrc.json index 507101ea2..49d7e73d7 100644 --- a/e2e/.eslintrc.json +++ b/e2e/.eslintrc.json @@ -1,13 +1,9 @@ { "extends": "../.eslintrc.json", - "ignorePatterns": [ - "!**/*" - ], + "ignorePatterns": ["!**/*"], "overrides": [ { - "files": [ - "*.ts" - ], + "files": ["*.ts"], "parserOptions": { "project": [ "e2e//tsconfig.app.json", @@ -36,9 +32,7 @@ } }, { - "files": [ - "*.html" - ], + "files": ["*.html"], "rules": {} } ] diff --git a/e2e/protractor.conf.js b/e2e/protractor.conf.js index 86776a391..98bba7090 100644 --- a/e2e/protractor.conf.js +++ b/e2e/protractor.conf.js @@ -5,11 +5,9 @@ const { SpecReporter } = require('jasmine-spec-reporter'); exports.config = { allScriptsTimeout: 11000, - specs: [ - './src/**/*.e2e-spec.ts' - ], + specs: ['./src/**/*.e2e-spec.ts'], capabilities: { - 'browserName': 'chrome' + browserName: 'chrome', }, directConnect: true, baseUrl: 'http://localhost:4200/', @@ -17,12 +15,14 @@ exports.config = { jasmineNodeOpts: { showColors: true, defaultTimeoutInterval: 30000, - print: function() {} + print: function () {}, }, onPrepare() { require('ts-node').register({ - project: require('path').join(__dirname, './tsconfig.e2e.json') + project: require('path').join(__dirname, './tsconfig.e2e.json'), }); - jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); - } -}; \ No newline at end of file + jasmine + .getEnv() + .addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + }, +}; diff --git a/e2e/src/app.e2e-spec.ts b/e2e/src/app.e2e-spec.ts index 79dec810f..14e819bdc 100644 --- a/e2e/src/app.e2e-spec.ts +++ b/e2e/src/app.e2e-spec.ts @@ -1,16 +1,16 @@ -import { AppPage } from "./app.po"; -import { browser, logging } from "protractor"; +import { AppPage } from './app.po'; +import { browser, logging } from 'protractor'; -describe("workspace-project App", () => { +describe('workspace-project App', () => { let page: AppPage; beforeEach(() => { page = new AppPage(); }); - it("should display welcome message", () => { + it('should display welcome message', () => { page.navigateTo(); - expect(page.getTitleText()).toEqual("Welcome to electron-angular-app!"); + expect(page.getTitleText()).toEqual('Welcome to electron-angular-app!'); }); afterEach(async () => { diff --git a/e2e/src/app.po.ts b/e2e/src/app.po.ts index f3a9c0a21..5776aa9eb 100644 --- a/e2e/src/app.po.ts +++ b/e2e/src/app.po.ts @@ -1,4 +1,4 @@ -import { browser, by, element } from "protractor"; +import { browser, by, element } from 'protractor'; export class AppPage { navigateTo() { @@ -6,6 +6,6 @@ export class AppPage { } getTitleText() { - return element(by.css("app-root h1")).getText() as Promise; + return element(by.css('app-root h1')).getText() as Promise; } } diff --git a/e2e/tsconfig.e2e.json b/e2e/tsconfig.e2e.json index a6dd62202..22e04cb18 100644 --- a/e2e/tsconfig.e2e.json +++ b/e2e/tsconfig.e2e.json @@ -4,10 +4,6 @@ "outDir": "../out-tsc/app", "module": "commonjs", "target": "es5", - "types": [ - "jasmine", - "jasminewd2", - "node" - ] + "types": ["jasmine", "jasminewd2", "node"] } -} \ No newline at end of file +} diff --git a/package.json b/package.json index af3452683..7e2c46ad6 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,13 @@ "lint": "ng lint --fix", "e2e": "ng e2e", "build_prod": "ng build --prod --base-href / --deploy-url /", - "ngcc": "ngcc --properties es2015" + "ngcc": "ngcc --properties es2015", + "format": "npx prettier --write ." + }, + "husky": { + "hooks": { + "pre-commit": "pretty-quick --staged" + } }, "browserslist": [ "> 5%" @@ -103,11 +109,13 @@ "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "ng-packagr": "^11.1.2", - "prettier": "^2.2.1", "protractor": "~7.0.0", "ts-node": "~7.0.0", "typescript": "^4.0.7", - "webpack-cli": "^3.3.10" + "webpack-cli": "^3.3.10", + "husky": "^8.0.1", + "prettier": "^2.7.1", + "pretty-quick": "^3.1.3" }, "main": "main.js" } diff --git a/src/app/add-unlockable-modal/add-unlockable-modal.component.html b/src/app/add-unlockable-modal/add-unlockable-modal.component.html index 90c545c84..d840125bc 100644 --- a/src/app/add-unlockable-modal/add-unlockable-modal.component.html +++ b/src/app/add-unlockable-modal/add-unlockable-modal.component.html @@ -1,31 +1,35 @@
- +
This NFT includes unlockable content. Enter it below.
- +
-
{{ sellNFTCounter }} of {{ sellNFTTotal }} sold
- +
+ {{ sellNFTCounter }} of {{ sellNFTTotal }} sold +
diff --git a/src/app/add-unlockable-modal/add-unlockable-modal.component.ts b/src/app/add-unlockable-modal/add-unlockable-modal.component.ts index a9c5bca97..36418f7ba 100644 --- a/src/app/add-unlockable-modal/add-unlockable-modal.component.ts +++ b/src/app/add-unlockable-modal/add-unlockable-modal.component.ts @@ -1,25 +1,30 @@ -import { Component, OnInit, Input, ViewChild } from "@angular/core"; -import { BsModalRef, BsModalService } from "ngx-bootstrap/modal"; -import { CdkTextareaAutosize } from "@angular/cdk/text-field"; -import { BackendApiService, NFTBidEntryResponse, NFTEntryResponse, PostEntryResponse } from "../backend-api.service"; -import { of } from "rxjs"; -import { concatMap, filter, last, map, take } from "rxjs/operators"; -import { NftSoldModalComponent } from "../nft-sold-modal/nft-sold-modal.component"; -import { GlobalVarsService } from "../global-vars.service"; +import { Component, OnInit, Input, ViewChild } from '@angular/core'; +import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; +import { CdkTextareaAutosize } from '@angular/cdk/text-field'; +import { + BackendApiService, + NFTBidEntryResponse, + NFTEntryResponse, + PostEntryResponse, +} from '../backend-api.service'; +import { of } from 'rxjs'; +import { concatMap, filter, last, map, take } from 'rxjs/operators'; +import { NftSoldModalComponent } from '../nft-sold-modal/nft-sold-modal.component'; +import { GlobalVarsService } from '../global-vars.service'; @Component({ - selector: "add-unlockable-modal", - templateUrl: "./add-unlockable-modal.component.html", + selector: 'add-unlockable-modal', + templateUrl: './add-unlockable-modal.component.html', }) export class AddUnlockableModalComponent implements OnInit { - @ViewChild("autosize") autosize: CdkTextareaAutosize; + @ViewChild('autosize') autosize: CdkTextareaAutosize; @Input() post: PostEntryResponse; @Input() nftEntries: NFTEntryResponse[]; @Input() selectedBidEntries: NFTBidEntryResponse[]; addDisabled = false; sellingNFT = false; - unlockableText: string = ""; + unlockableText: string = ''; constructor( private modalService: BsModalService, @@ -64,9 +69,9 @@ export class AddUnlockableModalComponent implements OnInit { // Hide this modal and open the next one. this.bsModalRef.hide(); this.modalService.show(NftSoldModalComponent, { - class: "modal-dialog-centered modal-sm", + class: 'modal-dialog-centered modal-sm', }); - this.modalService.setDismissReason("nft sold"); + this.modalService.setDismissReason('nft sold'); }, (err) => { console.error(err); diff --git a/src/app/admin-page/admin-page.component.spec.ts b/src/app/admin-page/admin-page.component.spec.ts index f3fa8c721..5e69d7c4f 100644 --- a/src/app/admin-page/admin-page.component.spec.ts +++ b/src/app/admin-page/admin-page.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminPageComponent } from "./admin-page.component"; +import { AdminPageComponent } from './admin-page.component'; -describe("AdminPageComponent", () => { +describe('AdminPageComponent', () => { let component: AdminPageComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("AdminPageComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/admin-page/admin-page.component.ts b/src/app/admin-page/admin-page.component.ts index 3a8367b84..951c3fccd 100644 --- a/src/app/admin-page/admin-page.component.ts +++ b/src/app/admin-page/admin-page.component.ts @@ -1,10 +1,10 @@ -import { Component, OnInit } from "@angular/core"; -import { GlobalVarsService } from "../global-vars.service"; +import { Component, OnInit } from '@angular/core'; +import { GlobalVarsService } from '../global-vars.service'; @Component({ - selector: "app-admin-page", - templateUrl: "./admin-page.component.html", - styleUrls: ["./admin-page.component.scss"], + selector: 'app-admin-page', + templateUrl: './admin-page.component.html', + styleUrls: ['./admin-page.component.scss'], }) export class AdminPageComponent { constructor(public globalVars: GlobalVarsService) {} diff --git a/src/app/admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component.html b/src/app/admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component.html index be4324916..77736efdd 100644 --- a/src/app/admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component.html +++ b/src/app/admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component.html @@ -1,9 +1,11 @@
-
Update Sign-Up Bonus for {{ getCountryName() }}
+
Update Sign-Up Bonus for {{ getCountryName() }}
- +
- + + type="checkbox" + />
- +
- + + type="checkbox" + />
@@ -49,12 +59,13 @@ class="btn btn-primary font-weight-bold ml-15px fs-14px br-12px" style="height: 36px; width: 75px; line-height: 15px" [ngClass]="{ - disabled: updatingCountryLevelBonus, - 'btn-loading': updatingCountryLevelBonus - }" + disabled: updatingCountryLevelBonus, + 'btn-loading': updatingCountryLevelBonus + }" (click)="updateSignUpBonus()" - >Update + > + Update +
- diff --git a/src/app/admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component.ts b/src/app/admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component.ts index 482ee1612..441781979 100644 --- a/src/app/admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component.ts +++ b/src/app/admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component.ts @@ -1,18 +1,18 @@ -import { Component, Input, OnInit } from "@angular/core"; +import { Component, Input, OnInit } from '@angular/core'; import { BackendApiService, CountryCodeDetails, CountryLevelSignUpBonus, CountryLevelSignUpBonusResponse, -} from "../../../backend-api.service"; -import { GlobalVarsService } from "../../../global-vars.service"; -import { BsModalRef } from "ngx-bootstrap/modal"; -import { BsModalService } from "ngx-bootstrap/modal"; -import { Router } from "@angular/router"; +} from '../../../backend-api.service'; +import { GlobalVarsService } from '../../../global-vars.service'; +import { BsModalRef } from 'ngx-bootstrap/modal'; +import { BsModalService } from 'ngx-bootstrap/modal'; +import { Router } from '@angular/router'; @Component({ - selector: "admin-jumio-edit-country-sign-up-bonus", - templateUrl: "./admin-jumio-edit-country-sign-up-bonus.component.html", + selector: 'admin-jumio-edit-country-sign-up-bonus', + templateUrl: './admin-jumio-edit-country-sign-up-bonus.component.html', }) export class AdminJumioEditCountrySignUpBonusComponent implements OnInit { @Input() countryLevelSignUpBonusResponse: CountryLevelSignUpBonusResponse; @@ -34,8 +34,10 @@ export class AdminJumioEditCountrySignUpBonusComponent implements OnInit { ngOnInit(): void { this.newAllowCustomKickbackAmount = this.getAllowCustomKickbackAmount(); this.newAllowCustomReferralAmount = this.getAllowCustomReferralAmount(); - this.newReferralAmountOverrideUSD = this.getReferralAmountOverrideUSDCents() / 100; - this.newKickbackAmountOverrideUSD = this.getKickbackAmountOverrideUSDCents() / 100; + this.newReferralAmountOverrideUSD = + this.getReferralAmountOverrideUSDCents() / 100; + this.newKickbackAmountOverrideUSD = + this.getKickbackAmountOverrideUSDCents() / 100; } getCountryCodeDetails(): CountryCodeDetails { @@ -80,13 +82,17 @@ export class AdminJumioEditCountrySignUpBonusComponent implements OnInit { { AllowCustomKickbackAmount: this.newAllowCustomKickbackAmount, AllowCustomReferralAmount: this.newAllowCustomReferralAmount, - ReferralAmountOverrideUSDCents: Math.trunc(this.newReferralAmountOverrideUSD * 100), - KickbackAmountOverrideUSDCents: Math.trunc(this.newKickbackAmountOverrideUSD * 100), + ReferralAmountOverrideUSDCents: Math.trunc( + this.newReferralAmountOverrideUSD * 100 + ), + KickbackAmountOverrideUSDCents: Math.trunc( + this.newKickbackAmountOverrideUSD * 100 + ), } ) .subscribe( () => { - this.modalService.setDismissReason("sign-up-bonus-updated"); + this.modalService.setDismissReason('sign-up-bonus-updated'); this.bsModalRef.hide(); }, (err) => { diff --git a/src/app/admin/admin-jumio/admin-jumio.component.html b/src/app/admin/admin-jumio/admin-jumio.component.html index 4bdd1ea1b..e1bf1cd62 100644 --- a/src/app/admin/admin-jumio/admin-jumio.component.html +++ b/src/app/admin/admin-jumio/admin-jumio.component.html @@ -2,7 +2,8 @@ + (tabClick)="_handleTabClick($event)" + >
Set Jumio Starter Amount in $USD: @@ -16,10 +17,18 @@ min="0" step="0.01" /> - -
@@ -36,10 +45,18 @@ min="0" step="0.01" /> - -
@@ -53,10 +70,18 @@ class="form-control w-100 fs-15px lh-15px" placeholder="Enter a username or public key." /> - -
@@ -75,23 +100,41 @@ name="country" id="country-callback" [(ngModel)]="jumioCallbackCountrySelected" - class="form-control selector mt-15px"> + class="form-control selector mt-15px" + > + [selected]=" + jumioCallbackCountrySelected === + country.value.CountryCodeDetails.Alpha3 + " + > + {{ country.key }} +
- - -
+
Country
Referral Amount
@@ -99,34 +142,59 @@
Kickback Amount
Allow Kickback Override
-
-
- - {{ signUpBonus.key }} -
-
- {{ globalVars.formatUSD(signUpBonus.value.CountryLevelSignUpBonus.ReferralAmountOverrideUSDCents / 100, 2) }} -
-
- -
-
- {{ globalVars.formatUSD(signUpBonus.value.CountryLevelSignUpBonus.KickbackAmountOverrideUSDCents / 100, 2) }} -
-
- -
+
+
+ + {{ signUpBonus.key }}
+
+ {{ + globalVars.formatUSD( + signUpBonus.value.CountryLevelSignUpBonus + .ReferralAmountOverrideUSDCents / 100, + 2 + ) + }} +
+
+ +
+
+ {{ + globalVars.formatUSD( + signUpBonus.value.CountryLevelSignUpBonus + .KickbackAmountOverrideUSDCents / 100, + 2 + ) + }} +
+
+ +
+
diff --git a/src/app/admin/admin-jumio/admin-jumio.component.spec.ts b/src/app/admin/admin-jumio/admin-jumio.component.spec.ts index ef4ecbb69..f4fecd8c1 100644 --- a/src/app/admin/admin-jumio/admin-jumio.component.spec.ts +++ b/src/app/admin/admin-jumio/admin-jumio.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminJumioComponent } from "./admin-jumio.component"; +import { AdminJumioComponent } from './admin-jumio.component'; -describe("AdminJumioComponent", () => { +describe('AdminJumioComponent', () => { let component: AdminJumioComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("AdminJumioComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/admin/admin-jumio/admin-jumio.component.ts b/src/app/admin/admin-jumio/admin-jumio.component.ts index f30e04b41..cac1df45a 100644 --- a/src/app/admin/admin-jumio/admin-jumio.component.ts +++ b/src/app/admin/admin-jumio/admin-jumio.component.ts @@ -1,35 +1,41 @@ -import { Component } from "@angular/core"; -import { ActivatedRoute, Router } from "@angular/router"; -import { GlobalVarsService } from "../../global-vars.service"; -import { BackendApiService, CountryLevelSignUpBonus, CountryLevelSignUpBonusResponse } from "../../backend-api.service"; -import { SwalHelper } from "../../../lib/helpers/swal-helper"; -import { AdminJumioEditCountrySignUpBonusComponent } from "./admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component"; -import { BsModalService } from "ngx-bootstrap/modal"; -import { Subscription } from "rxjs"; -import { ToastrService } from "ngx-toastr"; +import { Component } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { GlobalVarsService } from '../../global-vars.service'; +import { + BackendApiService, + CountryLevelSignUpBonus, + CountryLevelSignUpBonusResponse, +} from '../../backend-api.service'; +import { SwalHelper } from '../../../lib/helpers/swal-helper'; +import { AdminJumioEditCountrySignUpBonusComponent } from './admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component'; +import { BsModalService } from 'ngx-bootstrap/modal'; +import { Subscription } from 'rxjs'; +import { ToastrService } from 'ngx-toastr'; @Component({ - selector: "admin-jumio", - templateUrl: "./admin-jumio.component.html", - styleUrls: ["./admin-jumio.component.scss"], + selector: 'admin-jumio', + templateUrl: './admin-jumio.component.html', + styleUrls: ['./admin-jumio.component.scss'], }) export class AdminJumioComponent { - usernameToResetJumio = ""; - usernameToExecuteJumioCallback = ""; + usernameToResetJumio = ''; + usernameToExecuteJumioCallback = ''; resettingJumio = false; executingJumioCallback = false; - jumioCallbackCountrySelected: string = ""; + jumioCallbackCountrySelected: string = ''; jumioUSD: number = 0; jumioKickbackUSD: number = 0; updatingJumioUSDCents = false; updatingJumioKickbackUSDCents = false; - countryLevelSignUpBonuses: { [k: string]: CountryLevelSignUpBonusResponse } = {}; + countryLevelSignUpBonuses: { + [k: string]: CountryLevelSignUpBonusResponse; + } = {}; defaultSignUpBonus: CountryLevelSignUpBonus; - static GENERAL = "General"; - static COUNTRY_BONUSES = "Country Bonuses"; + static GENERAL = 'General'; + static COUNTRY_BONUSES = 'Country Bonuses'; tabs = [AdminJumioComponent.GENERAL, AdminJumioComponent.COUNTRY_BONUSES]; activeTab: string = AdminJumioComponent.GENERAL; AdminJumioComponent = AdminJumioComponent; @@ -66,8 +72,8 @@ export class AdminJumioComponent { _resetJumio(): void { this.resettingJumio = true; - let pubKey = ""; - let username = ""; + let pubKey = ''; + let username = ''; if (this.globalVars.isMaybePublicKey(this.usernameToResetJumio)) { pubKey = this.usernameToResetJumio; } else { @@ -82,7 +88,7 @@ export class AdminJumioComponent { ) .subscribe( (res) => { - this.globalVars._alertSuccess("Successfully reset jumio status"); + this.globalVars._alertSuccess('Successfully reset jumio status'); }, (err) => { this.globalVars._alertError(err.error.error); @@ -93,8 +99,8 @@ export class AdminJumioComponent { _executeJumioCallback(): void { this.executingJumioCallback = true; - let pubKey = ""; - let username = ""; + let pubKey = ''; + let username = ''; if (this.globalVars.isMaybePublicKey(this.usernameToExecuteJumioCallback)) { pubKey = this.usernameToExecuteJumioCallback; } else { @@ -110,7 +116,7 @@ export class AdminJumioComponent { ) .subscribe( (res) => { - this.globalVars._alertSuccess("Successfully executed jumio callback"); + this.globalVars._alertSuccess('Successfully executed jumio callback'); }, (err) => { this.globalVars._alertError(err.error.error); @@ -122,7 +128,7 @@ export class AdminJumioComponent { updateJumioUSDCents(): void { SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - title: "Are you ready?", + title: 'Are you ready?', html: `You are about to update the default sign-up amount sent for verifying with Jumio to ${this.globalVars.formatUSD( this.jumioUSD, 2 @@ -131,11 +137,11 @@ export class AdminJumioComponent { showCancelButton: true, reverseButtons: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, - confirmButtonText: "Ok", - cancelButtonText: "Cancel", + confirmButtonText: 'Ok', + cancelButtonText: 'Cancel', }).then((res) => { if (res.isConfirmed) { this.updatingJumioUSDCents = true; @@ -162,7 +168,7 @@ export class AdminJumioComponent { updateJumioKickbackUSDCents(): void { SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - title: "Are you ready?", + title: 'Are you ready?', html: `You are about to update the default kickback amount to ${this.globalVars.formatUSD( this.jumioKickbackUSD, 2 @@ -171,11 +177,11 @@ export class AdminJumioComponent { showCancelButton: true, reverseButtons: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, - confirmButtonText: "Ok", - cancelButtonText: "Cancel", + confirmButtonText: 'Ok', + cancelButtonText: 'Cancel', }).then((res) => { if (res.isConfirmed) { this.updatingJumioKickbackUSDCents = true; @@ -205,15 +211,22 @@ export class AdminJumioComponent { editCountry(country: string, event): void { event.stopPropagation(); - const editBonusModal = this.modalService.show(AdminJumioEditCountrySignUpBonusComponent, { - class: "modal-dialog-centered modal-lg", - initialState: { countryLevelSignUpBonusResponse: this.countryLevelSignUpBonuses[country] }, - }); + const editBonusModal = this.modalService.show( + AdminJumioEditCountrySignUpBonusComponent, + { + class: 'modal-dialog-centered modal-lg', + initialState: { + countryLevelSignUpBonusResponse: this.countryLevelSignUpBonuses[ + country + ], + }, + } + ); editBonusModal.onHide.subscribe((res) => { - if (res === "sign-up-bonus-updated") { + if (res === 'sign-up-bonus-updated') { this.refreshCountryBonuses(); this.toastr.info(`Sign-Up Bonus updated for ${country}`, null, { - positionClass: "toast-top-center", + positionClass: 'toast-top-center', timeOut: 3000, }); } diff --git a/src/app/admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component.html b/src/app/admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component.html index aca8a595c..844326cbd 100644 --- a/src/app/admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component.html +++ b/src/app/admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component.html @@ -1,7 +1,5 @@
-
- Add a new fee recipient for {{ txnType }} transactions -
+
Add a new fee recipient for {{ txnType }} transactions
Fee Amount Received (in $DESO)
- +
-
-
- Existing Fee Recipients for {{ txnType }} Transactions -
-
+
Existing Fee Recipients for {{ txnType }} Transactions
+
- {{ globalVars.nanosToDeSo(transactionFee.AmountNanos) }} $DESO + + {{ globalVars.nanosToDeSo(transactionFee.AmountNanos) }} $DESO +
diff --git a/src/app/admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component.ts b/src/app/admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component.ts index 754a0e62f..687aa738a 100644 --- a/src/app/admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component.ts +++ b/src/app/admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component.ts @@ -1,12 +1,16 @@ -import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core"; -import { BsModalRef } from "ngx-bootstrap/modal"; -import { GlobalVarsService } from "../../../global-vars.service"; -import { BackendApiService, ProfileEntryResponse, TransactionFee } from "../../../backend-api.service"; -import { SwalHelper } from "../../../../lib/helpers/swal-helper"; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { BsModalRef } from 'ngx-bootstrap/modal'; +import { GlobalVarsService } from '../../../global-vars.service'; +import { + BackendApiService, + ProfileEntryResponse, + TransactionFee, +} from '../../../backend-api.service'; +import { SwalHelper } from '../../../../lib/helpers/swal-helper'; @Component({ - selector: "admin-node-add-fees", - templateUrl: "./admin-node-add-fees.component.html", + selector: 'admin-node-add-fees', + templateUrl: './admin-node-add-fees.component.html', }) export class AdminNodeAddFeesComponent implements OnInit { @Input() txnType: string; @@ -26,13 +30,17 @@ export class AdminNodeAddFeesComponent implements OnInit { ) {} ngOnInit() { - if (this.txnType === "ALL") { + if (this.txnType === 'ALL') { this.updatingAllTxns = true; } } setTransactionFees(): void { - if (!this.feeAmount || !this.selectedCreator?.PublicKeyBase58Check || this.updatingTransactionFees) { + if ( + !this.feeAmount || + !this.selectedCreator?.PublicKeyBase58Check || + this.updatingTransactionFees + ) { return; } let newTransactionFees: TransactionFee[] = []; @@ -41,13 +49,19 @@ export class AdminNodeAddFeesComponent implements OnInit { // If we're updating the fee for all transactions, we overwrite. if (!this.updatingAllTxns) { newTransactionFees = this.transactionFeeMap[this.txnType] || []; - swalText = `Click "Confirm" to add a fee on each ${this.txnType} transaction that will send ${ - this.feeAmount - } $DESO to ${this.selectedCreator?.Username || this.selectedCreator?.PublicKeyBase58Check}.`; + swalText = `Click "Confirm" to add a fee on each ${ + this.txnType + } transaction that will send ${this.feeAmount} $DESO to ${ + this.selectedCreator?.Username || + this.selectedCreator?.PublicKeyBase58Check + }.`; } else { swalText = `WARNING: This will overwrite all existing transaction fees you have set.\n Click "Confirm" to add a fee on all transactions that will send ${ this.feeAmount - } $DESO to ${this.selectedCreator?.Username || this.selectedCreator?.PublicKeyBase58Check}.`; + } $DESO to ${ + this.selectedCreator?.Username || + this.selectedCreator?.PublicKeyBase58Check + }.`; } newTransactionFees = newTransactionFees.concat({ @@ -62,11 +76,11 @@ export class AdminNodeAddFeesComponent implements OnInit { showConfirmButton: true, focusConfirm: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, - confirmButtonText: "Confirm", - cancelButtonText: "Cancel", + confirmButtonText: 'Confirm', + cancelButtonText: 'Cancel', reverseButtons: true, }).then((res) => { if (res.isConfirmed) { diff --git a/src/app/admin/admin-node-fees/admin-node-fees.component.html b/src/app/admin/admin-node-fees/admin-node-fees.component.html index 0f3f8399f..05ea740b2 100644 --- a/src/app/admin/admin-node-fees/admin-node-fees.component.html +++ b/src/app/admin/admin-node-fees/admin-node-fees.component.html @@ -1,19 +1,34 @@
- -
- -
+
{{ transactionFee.key }} - +
@@ -22,7 +37,11 @@ (click)="removeFee(transactionFee.key, item.PublicKeyBase58Check)" > @@ -31,20 +50,38 @@
-
+
- -
Users exempt from fees:
-
- +
+ { +describe('AdminNodeFeesComponent', () => { let component: AdminNodeFeesComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("AdminNodeFeesComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/admin/admin-node-fees/admin-node-fees.component.ts b/src/app/admin/admin-node-fees/admin-node-fees.component.ts index 33b656046..c190d4a3a 100644 --- a/src/app/admin/admin-node-fees/admin-node-fees.component.ts +++ b/src/app/admin/admin-node-fees/admin-node-fees.component.ts @@ -1,19 +1,23 @@ -import { Component, OnInit } from "@angular/core"; -import { ActivatedRoute, Router } from "@angular/router"; -import { GlobalVarsService } from "../../global-vars.service"; -import { BackendApiService, ProfileEntryResponse, TransactionFee } from "../../backend-api.service"; -import { SwalHelper } from "../../../lib/helpers/swal-helper"; -import { BsModalService, BsModalRef } from "ngx-bootstrap/modal"; -import { AdminNodeAddFeesComponent } from "./admin-node-add-fee/admin-node-add-fees.component"; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { GlobalVarsService } from '../../global-vars.service'; +import { + BackendApiService, + ProfileEntryResponse, + TransactionFee, +} from '../../backend-api.service'; +import { SwalHelper } from '../../../lib/helpers/swal-helper'; +import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal'; +import { AdminNodeAddFeesComponent } from './admin-node-add-fee/admin-node-add-fees.component'; @Component({ - selector: "admin-node-fees", - templateUrl: "./admin-node-fees.component.html", - styleUrls: ["./admin-node-fees.component.scss"], + selector: 'admin-node-fees', + templateUrl: './admin-node-fees.component.html', + styleUrls: ['./admin-node-fees.component.scss'], }) export class AdminNodeFeesComponent implements OnInit { - static FEES = "Fees"; - static EXEMPT_KEYS = "Exempt Keys"; + static FEES = 'Fees'; + static EXEMPT_KEYS = 'Exempt Keys'; tabs = [AdminNodeFeesComponent.FEES, AdminNodeFeesComponent.EXEMPT_KEYS]; loading = true; removingFee = false; @@ -35,7 +39,10 @@ export class AdminNodeFeesComponent implements OnInit { ngOnInit() { this.backendApi - .AdminGetTransactionFeeMap(this.globalVars.localNode, this.globalVars.loggedInUser?.PublicKeyBase58Check) + .AdminGetTransactionFeeMap( + this.globalVars.localNode, + this.globalVars.loggedInUser?.PublicKeyBase58Check + ) .subscribe( (res) => { this.transactionFeeMap = res.TransactionFeeMap; @@ -47,7 +54,10 @@ export class AdminNodeFeesComponent implements OnInit { .add(() => (this.loading = false)); this.backendApi - .AdminGetExemptPublicKeys(this.globalVars.localNode, this.globalVars.loggedInUser?.PublicKeyBase58Check) + .AdminGetExemptPublicKeys( + this.globalVars.localNode, + this.globalVars.loggedInUser?.PublicKeyBase58Check + ) .subscribe( (res) => { this.exemptPublicKeyMap = res.ExemptPublicKeyMap; @@ -60,15 +70,19 @@ export class AdminNodeFeesComponent implements OnInit { addNewFee(txnType: string) { const addFeeModal = this.modalService.show(AdminNodeAddFeesComponent, { - class: "modal-dialog-centered modal-lg", + class: 'modal-dialog-centered modal-lg', initialState: { txnType, transactionFeeMap: this.transactionFeeMap }, }); - addFeeModal.content.feeAdded.subscribe((transactionFeeMap) => (this.transactionFeeMap = transactionFeeMap)); + addFeeModal.content.feeAdded.subscribe( + (transactionFeeMap) => (this.transactionFeeMap = transactionFeeMap) + ); } removeFee(txnType: string, publicKeyBase58Check: string): void { let transactionFeesForType = this.transactionFeeMap[txnType]; - const txnFeeIndex = transactionFeesForType.findIndex((txn) => txn.PublicKeyBase58Check === publicKeyBase58Check); + const txnFeeIndex = transactionFeesForType.findIndex( + (txn) => txn.PublicKeyBase58Check === publicKeyBase58Check + ); if (txnFeeIndex < 0) { return; } @@ -78,7 +92,9 @@ export class AdminNodeFeesComponent implements OnInit { const txnFee = transactionFeesForType[txnFeeIndex]; SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - html: `Remove fee of ${this.globalVars.nanosToDeSo(txnFee.AmountNanos)} DESO for ${ + html: `Remove fee of ${this.globalVars.nanosToDeSo( + txnFee.AmountNanos + )} DESO for ${ txnFee.ProfileEntryResponse?.Username || txnFee.PublicKeyBase58Check } for all ${txnType} transactions.`, @@ -86,11 +102,11 @@ export class AdminNodeFeesComponent implements OnInit { showConfirmButton: true, focusConfirm: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, - confirmButtonText: "Confirm", - cancelButtonText: "Cancel", + confirmButtonText: 'Confirm', + cancelButtonText: 'Cancel', reverseButtons: true, }).then(async (alertRes: any) => { if (alertRes.isConfirmed) { @@ -132,7 +148,9 @@ export class AdminNodeFeesComponent implements OnInit { ) .subscribe( (res) => { - this.exemptPublicKeyMap[this.selectedCreator?.PublicKeyBase58Check] = this.selectedCreator; + this.exemptPublicKeyMap[ + this.selectedCreator?.PublicKeyBase58Check + ] = this.selectedCreator; this.selectedCreator = null; }, (err) => { diff --git a/src/app/admin/admin-tutorial/admin-tutorial.component.html b/src/app/admin/admin-tutorial/admin-tutorial.component.html index 0d922891b..fdbe9e112 100644 --- a/src/app/admin/admin-tutorial/admin-tutorial.component.html +++ b/src/app/admin/admin-tutorial/admin-tutorial.component.html @@ -1,4 +1,7 @@ -
+
@@ -32,13 +43,18 @@
{{ profileEntryResponse.Username }} - - + + - - + +
-
@@ -65,10 +80,18 @@ class="form-control w-100 fs-15px lh-15px" placeholder="Enter a public key." /> - -
diff --git a/src/app/admin/admin-tutorial/admin-tutorial.component.ts b/src/app/admin/admin-tutorial/admin-tutorial.component.ts index 4699f8ed2..341e0bc34 100644 --- a/src/app/admin/admin-tutorial/admin-tutorial.component.ts +++ b/src/app/admin/admin-tutorial/admin-tutorial.component.ts @@ -1,11 +1,11 @@ -import { Component, OnInit } from "@angular/core"; -import { GlobalVarsService } from "../../global-vars.service"; -import { BackendApiService } from "../../backend-api.service"; -import { filter } from "lodash"; +import { Component, OnInit } from '@angular/core'; +import { GlobalVarsService } from '../../global-vars.service'; +import { BackendApiService } from '../../backend-api.service'; +import { filter } from 'lodash'; @Component({ - selector: "admin-tutorial", - templateUrl: "./admin-tutorial.component.html", + selector: 'admin-tutorial', + templateUrl: './admin-tutorial.component.html', }) export class AdminTutorialComponent implements OnInit { globalVars: GlobalVarsService; @@ -14,16 +14,23 @@ export class AdminTutorialComponent implements OnInit { upAndComingProfiles = []; wellKnownProfiles = []; loading = false; - WELL_KNOWN_TAB = "Well Known"; - UP_AND_COMING_TAB = "Up And Coming"; - RESET_TAB = "Reset"; - adminTutorialTabs = [this.WELL_KNOWN_TAB, this.UP_AND_COMING_TAB, this.RESET_TAB]; + WELL_KNOWN_TAB = 'Well Known'; + UP_AND_COMING_TAB = 'Up And Coming'; + RESET_TAB = 'Reset'; + adminTutorialTabs = [ + this.WELL_KNOWN_TAB, + this.UP_AND_COMING_TAB, + this.RESET_TAB, + ]; activeTutorialTab = this.WELL_KNOWN_TAB; filteredProfileEntryResponses = null; - publicKeyToReset: string = ""; + publicKeyToReset: string = ''; resettingTutorial: boolean = false; - constructor(private _globalVars: GlobalVarsService, private backendApi: BackendApiService) { + constructor( + private _globalVars: GlobalVarsService, + private backendApi: BackendApiService + ) { this.globalVars = _globalVars; } @@ -33,13 +40,19 @@ export class AdminTutorialComponent implements OnInit { return; } this.filteredProfileEntryResponses = - tutorialTabName === this.WELL_KNOWN_TAB ? this.wellKnownProfiles : this.upAndComingProfiles; + tutorialTabName === this.WELL_KNOWN_TAB + ? this.wellKnownProfiles + : this.upAndComingProfiles; } ngOnInit(): void { this.loading = true; this.backendApi - .AdminGetTutorialCreators(this.globalVars.localNode, this.globalVars.loggedInUser.PublicKeyBase58Check, 500) + .AdminGetTutorialCreators( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + 500 + ) .subscribe( (res) => { this.wellKnownProfiles = res.WellKnownProfileEntryResponses; @@ -53,7 +66,10 @@ export class AdminTutorialComponent implements OnInit { ); } - removeCreatorFeaturedTutorialList(profilePublicKeyBase58Check: string, event) { + removeCreatorFeaturedTutorialList( + profilePublicKeyBase58Check: string, + event + ) { event.stopPropagation(); this.backendApi .AdminUpdateTutorialCreators( @@ -65,17 +81,35 @@ export class AdminTutorialComponent implements OnInit { ) .subscribe( (res) => { - this.filteredProfileEntryResponses = filter(this.filteredProfileEntryResponses, (profileEntryResponse) => { - return profileEntryResponse.PublicKeyBase58Check != profilePublicKeyBase58Check; - }); + this.filteredProfileEntryResponses = filter( + this.filteredProfileEntryResponses, + (profileEntryResponse) => { + return ( + profileEntryResponse.PublicKeyBase58Check != + profilePublicKeyBase58Check + ); + } + ); if (this.activeTutorialTab === this.WELL_KNOWN_TAB) { - this.wellKnownProfiles = filter(this.wellKnownProfiles, (profileEntryResponse) => { - return profileEntryResponse.PublicKeyBase58Check != profilePublicKeyBase58Check; - }); + this.wellKnownProfiles = filter( + this.wellKnownProfiles, + (profileEntryResponse) => { + return ( + profileEntryResponse.PublicKeyBase58Check != + profilePublicKeyBase58Check + ); + } + ); } else { - this.upAndComingProfiles = filter(this.upAndComingProfiles, (profileEntryResponse) => { - return profileEntryResponse.PublicKeyBase58Check != profilePublicKeyBase58Check; - }); + this.upAndComingProfiles = filter( + this.upAndComingProfiles, + (profileEntryResponse) => { + return ( + profileEntryResponse.PublicKeyBase58Check != + profilePublicKeyBase58Check + ); + } + ); } }, (err) => { @@ -94,7 +128,7 @@ export class AdminTutorialComponent implements OnInit { ) .subscribe( (res) => { - this.globalVars._alertSuccess("Successfully reset tutorial status"); + this.globalVars._alertSuccess('Successfully reset tutorial status'); }, (err) => { this.globalVars._alertError(err.error.error); @@ -102,5 +136,4 @@ export class AdminTutorialComponent implements OnInit { ) .add(() => (this.resettingTutorial = false)); } - } diff --git a/src/app/admin/admin-wyre/admin-wyre.component.html b/src/app/admin/admin-wyre/admin-wyre.component.html index f32aab85c..14459831d 100644 --- a/src/app/admin/admin-wyre/admin-wyre.component.html +++ b/src/app/admin/admin-wyre/admin-wyre.component.html @@ -8,10 +8,20 @@ class="form-control w-100 fs-15px lh-15px" placeholder="Enter a username or public key." /> - - +
@@ -20,20 +30,29 @@
  • Created at: {{ order.Timestamp }}
  • - Failed Reason: {{ order.LatestWyreWalletOrderWebhookPayload.failedReason }} + Failed Reason: + {{ order.LatestWyreWalletOrderWebhookPayload.failedReason }}
  • -
  • - btc tx: {{ order.LatestWyreTrackWalletOrderResponse.blockchainNetworkTx }} +
  • + btc tx: + {{ order.LatestWyreTrackWalletOrderResponse.blockchainNetworkTx }}
  • - Source amount: {{ order.LatestWyreTrackWalletOrderResponse.sourceAmount }} + Source amount: + {{ order.LatestWyreTrackWalletOrderResponse.sourceAmount }} {{ order.LatestWyreTrackWalletOrderResponse.sourceCurrency }}
  • - Destination amount: {{ order.LatestWyreTrackWalletOrderResponse.destAmount }} + Destination amount: + {{ order.LatestWyreTrackWalletOrderResponse.destAmount }} {{ order.LatestWyreTrackWalletOrderResponse.destCurrency }}
  • -
  • DeSo Nanos Purchased: {{ order.DeSoPurchasedNanos }}
  • +
  • + DeSo Nanos Purchased: {{ order.DeSoPurchasedNanos }} +
  • DeSo Basic Transfer Hash: {{ order.BasicTransferTxnHash }}
  • diff --git a/src/app/admin/admin-wyre/admin-wyre.component.spec.ts b/src/app/admin/admin-wyre/admin-wyre.component.spec.ts index 07bc9f31b..bbe852b19 100644 --- a/src/app/admin/admin-wyre/admin-wyre.component.spec.ts +++ b/src/app/admin/admin-wyre/admin-wyre.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminWyreComponent } from "./admin-wyre.component"; +import { AdminWyreComponent } from './admin-wyre.component'; -describe("AdminWyreComponent", () => { +describe('AdminWyreComponent', () => { let component: AdminWyreComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("AdminWyreComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/admin/admin-wyre/admin-wyre.component.ts b/src/app/admin/admin-wyre/admin-wyre.component.ts index ae975b735..1b5c29761 100644 --- a/src/app/admin/admin-wyre/admin-wyre.component.ts +++ b/src/app/admin/admin-wyre/admin-wyre.component.ts @@ -1,15 +1,15 @@ -import { Component } from "@angular/core"; -import { ActivatedRoute, Router } from "@angular/router"; -import { GlobalVarsService } from "../../global-vars.service"; -import { BackendApiService } from "../../backend-api.service"; +import { Component } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { GlobalVarsService } from '../../global-vars.service'; +import { BackendApiService } from '../../backend-api.service'; @Component({ - selector: "admin-wyre", - templateUrl: "./admin-wyre.component.html", - styleUrls: ["./admin-wyre.component.scss"], + selector: 'admin-wyre', + templateUrl: './admin-wyre.component.html', + styleUrls: ['./admin-wyre.component.scss'], }) export class AdminWyreComponent { - usernameToFetchWyreOrders = ""; + usernameToFetchWyreOrders = ''; loadingWyreOrders = false; wyreOrders = null; @@ -22,8 +22,8 @@ export class AdminWyreComponent { _loadWyreOrders(): void { this.loadingWyreOrders = true; - let pubKey = ""; - let username = ""; + let pubKey = ''; + let username = ''; if (this.globalVars.isMaybePublicKey(this.usernameToFetchWyreOrders)) { pubKey = this.usernameToFetchWyreOrders; } else { diff --git a/src/app/admin/admin.component.html b/src/app/admin/admin.component.html index 76304a073..070872053 100644 --- a/src/app/admin/admin.component.html +++ b/src/app/admin/admin.component.html @@ -5,7 +5,9 @@ class="global__top-bar__height d-flex align-items-center w-100 px-15px fs-18px font-weight-bold fc-default justify-content-between border-bottom border-color-grey" >
    - + Admin
@@ -32,7 +34,11 @@
-
+
@@ -46,16 +52,26 @@
- + Time Window: - - + + {{ timeWindow.key }} @@ -64,18 +80,22 @@ -
- +
-
+
-
-
+
+
Update the hot feed algorithm by updating the values below.
Update Interaction Cap - Global Hot Feed (max $DESO locked) -
+
+ style="width: fit-content" + disabled + > Updating...
@@ -154,7 +185,9 @@
Update Interaction Cap - Tag Specific Feeds (max $DESO locked) -
+
+ style="width: fit-content" + disabled + > Updating...
@@ -182,7 +217,9 @@
Update Time Decay Blocks For Global Feed -
+
+ style="width: fit-content" + disabled + > Updating...
@@ -210,7 +249,9 @@
Update Time Decay Blocks For Tag Feed -
+
+ style="width: fit-content" + disabled + > Updating...
@@ -238,7 +281,10 @@
Update Transaction Type Multipliers -
+
-
+
+ style="width: fit-content" + disabled + > Updating...
- Update User Posts Multiplier (boost all of a user's posts) -
+ Update User Posts Multiplier + (boost all of a user's posts) +
+ style="width: fit-content" + disabled + > Updating...
@@ -319,8 +374,13 @@
- Update User Interaction Multiplier (boost all of a user's interactions) -
+ Update User Interaction Multiplier + (boost all of a user's interactions) +
+ style="width: fit-content" + disabled + > Updating...
@@ -351,9 +413,10 @@
-   - Look Up User Interaction Multipliers -
+   Look Up User Interaction Multipliers +
+ style="width: fit-content" + disabled + > Searching...
-
+
{{ hotFeedUserSearchResults }}
-
+
Select posts below to whitelist.
- +
-
+
@@ -446,9 +521,19 @@ > Blacklist - +
-
+
Successfully added user to blacklist.
@@ -468,20 +553,33 @@ *ngIf="!submittingGraylistUpdate" (click)="updateProfileModerationLevel('graylist')" class="btn btn-secondary fs-15px ml-5px" - style="width: 150px;background-color:#606060 !important;" + style="width: 150px; background-color: #606060 !important" > Graylist  - +
-
+
Successfully added user to graylist.
-
+
Remove from blacklist and graylist:
-
+
Successfully removed user from blacklist and graylist.
@@ -515,8 +617,9 @@
- ⭐ Use the controls below to Whitelist profiles. Profiles that are Whitelisted will automatically have up to five - of their posts added to the global feed per day. + ⭐ Use the controls below to Whitelist profiles. Profiles that are + Whitelisted will automatically have up to five of their posts added to the + global feed per day.
@@ -545,14 +648,20 @@ Working...
-
+
Successfully added user to whitelist.
-
+
Remove user from whitelist:
-
+
Successfully removed user from whitelist.
@@ -591,10 +704,12 @@
-
+
Allow phone number re-registration:
-
By Public Key or Username:
+
By Public Key or Username:
-
By Phone Number:
+
By Phone Number:
-
+
Success.
@@ -652,7 +771,10 @@
-
+
@@ -668,7 +790,11 @@
  • - {{ usernameMap[item.key] }}: + {{ usernameMap[item.key] }}: {{ item.key.slice(0, 15) }}...
    • @@ -677,7 +803,9 @@
    • RemoveFromLeaderboard: - {{ item.value.RemoveFromLeaderboard }} + {{ + item.value.RemoveFromLeaderboard + }}
    • WhitelistPosts: @@ -810,7 +938,11 @@
-
+
@@ -818,12 +950,17 @@
-
+
Txn Type
Txn Count
Total Bytes
-
+
{{ row.key }}
@@ -834,10 +971,15 @@ {{ row.value.TotalBytes }}
-
+
Couldn't find any mempool transactions right now.
-
+
Total
{{ mempoolTxnCount }} @@ -848,8 +990,13 @@
-
-
Next block template
+
+
+ Next block template +
{{ nextBlockStats.TxnCount }} transaction s @@ -858,20 +1005,40 @@
Next failing txn - - (first seen {{ globalVars.abbreviateNumber(nextBlockStats.FailingTxnMinutesSinceAdded, 2) }} minutes ago) + + (first seen + {{ + globalVars.abbreviateNumber( + nextBlockStats.FailingTxnMinutesSinceAdded, + 2 + ) + }} + minutes ago)
-
+
{{ nextBlockStats.FailingTxnHash }}
-
Next failing txn error
-
+
+ Next failing txn error +
+
"{{ nextBlockStats.FailingTxnError }}"
-
Next block stats not available. Try refreshing.
+
+ Next block stats not available. Try refreshing. +
Loading...
@@ -890,7 +1057,7 @@ class="w-100 d-flex flex-column disable-scrollbars" style="overflow-y: scroll" > - +
@@ -899,7 +1066,7 @@ class="w-100 h-100 d-flex flex-column disable-scrollbars" style="overflow-y: scroll; min-height: 400px" > - +
@@ -932,10 +1099,20 @@ />
- - +
@@ -946,20 +1123,36 @@ [(ngModel)]="changeUsernamePublicKey" class="form-control w-100 fs-15px lh-15px" placeholder="Enter a public key" - (change)="searchedForPubKey = false; userMetadataToUpdate = null; userProfileEntryResponseToUpdate = null" + (change)=" + searchedForPubKey = false; + userMetadataToUpdate = null; + userProfileEntryResponseToUpdate = null + " /> - +
User Global Metadata
    -
  • {{ item.key }}: {{ item.value }}
  • +
  • + {{ item.key }}: {{ item.value }} +
-
+
User Profile Entry
    -
  • {{ item.key }}: {{ item.value }}
  • +
  • + {{ item.key }}: {{ item.value }} +
@@ -970,10 +1163,20 @@ />
- - +
@@ -993,7 +1196,13 @@ > Reprocess Block - +
@@ -1019,14 +1228,22 @@ > Execute - +
Update Bitcoin to USD Price -
+
Update -
@@ -1051,7 +1273,9 @@
Create Profile Fee In DeSo -
+
Min. Network Fee Rate (nanos / kb) -
+
Max Copies per NFT -
+
Create NFT Fee in DeSo -
+
Verify - +
@@ -1211,17 +1447,35 @@ > Remove - +
- - + +
+
+ {{ verifiedUsers }}
-
{{ verifiedUsers }}
Get Username Verification Logs: @@ -1239,14 +1493,27 @@ > Fetch - +
    -
  • Time: {{ globalVars.convertTstampToDateOrTime(auditLog.TimestampNanos) }}
  • +
  • + Time: + {{ globalVars.convertTstampToDateOrTime(auditLog.TimestampNanos) }} +
    • -
    • VerifierPubKey: {{ auditLog.VerifierPublicKeyBase58Check }}
    • -
    • VerifierUsername: {{ auditLog.VerifierUsername }}
    • +
    • + VerifierPubKey: {{ auditLog.VerifierPublicKeyBase58Check }} +
    • +
    • + VerifierUsername: {{ auditLog.VerifierUsername }} +
    • VerificationRemoved: {{ auditLog.IsRemoval }}
@@ -1267,9 +1534,15 @@ (click)="updateUSDToDeSoReserveExchangeRate()" class="btn btn-outline-primary fs-15px ml-5px" > - Update + Update + + -
@@ -1291,39 +1564,70 @@ > Update - +
Remove nil posts from global feed:
- - +
-
+
-
+
-
+
diff --git a/src/app/admin/admin.component.spec.ts b/src/app/admin/admin.component.spec.ts index b5fdbe193..f0874e43f 100644 --- a/src/app/admin/admin.component.spec.ts +++ b/src/app/admin/admin.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminComponent } from "./admin.component"; +import { AdminComponent } from './admin.component'; -describe("AdminComponent", () => { +describe('AdminComponent', () => { let component: AdminComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("AdminComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/admin/admin.component.ts b/src/app/admin/admin.component.ts index 25f194662..d11c6a756 100644 --- a/src/app/admin/admin.component.ts +++ b/src/app/admin/admin.component.ts @@ -1,12 +1,15 @@ -import { Component, OnInit, Input } from "@angular/core"; -import { ActivatedRoute, Router } from "@angular/router"; -import { GlobalVarsService } from "../global-vars.service"; -import { BackendApiService, ProfileEntryResponse } from "../backend-api.service"; -import { sprintf } from "sprintf-js"; -import { SwalHelper } from "../../lib/helpers/swal-helper"; -import * as _ from "lodash"; -import { Title } from "@angular/platform-browser"; -import { environment } from "src/environments/environment"; +import { Component, OnInit, Input } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { GlobalVarsService } from '../global-vars.service'; +import { + BackendApiService, + ProfileEntryResponse, +} from '../backend-api.service'; +import { sprintf } from 'sprintf-js'; +import { SwalHelper } from '../../lib/helpers/swal-helper'; +import * as _ from 'lodash'; +import { Title } from '@angular/platform-browser'; +import { environment } from 'src/environments/environment'; class Messages { static INCORRECT_PASSWORD = `The password you entered was incorrect.`; @@ -18,9 +21,9 @@ class Messages { // TODO: Cleanup - separate this into multiple components @Component({ - selector: "admin", - templateUrl: "./admin.component.html", - styleUrls: ["./admin.component.scss"], + selector: 'admin', + templateUrl: './admin.component.html', + styleUrls: ['./admin.component.scss'], }) export class AdminComponent implements OnInit { globalVars: GlobalVarsService; @@ -37,15 +40,15 @@ export class AdminComponent implements OnInit { searchingForPostsByDESO = false; @Input() isMobile = false; - blacklistPubKeyOrUsername = ""; - graylistPubKeyOrUsername = ""; - unrestrictPubKeyOrUsername = ""; - whitelistPubKeyOrUsername = ""; - unwhitelistPubKeyOrUsername = ""; - removePhonePubKeyorUsername = ""; - removePhoneNum = ""; + blacklistPubKeyOrUsername = ''; + graylistPubKeyOrUsername = ''; + unrestrictPubKeyOrUsername = ''; + whitelistPubKeyOrUsername = ''; + unwhitelistPubKeyOrUsername = ''; + removePhonePubKeyorUsername = ''; + removePhoneNum = ''; - updateProfileSuccessType = ""; + updateProfileSuccessType = ''; whitelistUpdateSuccess = false; unwhitelistUpdateSuccess = false; @@ -53,7 +56,7 @@ export class AdminComponent implements OnInit { whitelistSuccessTimeout: any; unwhitelistSuccessTimeout: any; - submittingProfileUpdateType = ""; + submittingProfileUpdateType = ''; submittingBlacklistUpdate = false; submittingGraylistUpdate = false; submittingUnrestrictUpdate = false; @@ -83,11 +86,11 @@ export class AdminComponent implements OnInit { updatingMaxCopiesPerNFT = false; updatingCreateNFTFeeNanos = false; feeRateDeSoPerKB = (1000 / 1e9).toFixed(9); // Default fee rate. - bitcoinBlockHashOrHeight = ""; - evictBitcoinTxnHashes = ""; - usernameToVerify = ""; - usernameForWhomToRemoveVerification = ""; - usernameToFetchVerificationAuditLogs = ""; + bitcoinBlockHashOrHeight = ''; + evictBitcoinTxnHashes = ''; + usernameToVerify = ''; + usernameForWhomToRemoveVerification = ''; + usernameToFetchVerificationAuditLogs = ''; removingNilPosts = false; submittingReprocessRequest = false; submittingRemovalRequest = false; @@ -108,31 +111,31 @@ export class AdminComponent implements OnInit { loadingVerifiedUsers = false; loadingVerifiedUsersAuditLog = false; adminTabs = [ - "Posts", - "Hot Feed", - "Profiles", - "NFTs", - "Tutorial", - "Network", - "Mempool", - "Wyre", - "Jumio", - "Referral Program", + 'Posts', + 'Hot Feed', + 'Profiles', + 'NFTs', + 'Tutorial', + 'Network', + 'Mempool', + 'Wyre', + 'Jumio', + 'Referral Program', ]; - POSTS_TAB = "Posts"; - POSTS_BY_DESO_TAB = "Posts By DESO"; + POSTS_TAB = 'Posts'; + POSTS_BY_DESO_TAB = 'Posts By DESO'; adminPostTabs = [this.POSTS_TAB, this.POSTS_BY_DESO_TAB]; // Fields for SwapIdentity submittingSwapIdentity = false; - swapIdentityFromUsernameOrPublicKey = ""; - swapIdentityToUsernameOrPublicKey = ""; + swapIdentityFromUsernameOrPublicKey = ''; + swapIdentityToUsernameOrPublicKey = ''; // Fields for UpdateUsername submittingUpdateUsername = false; - changeUsernamePublicKey = ""; - usernameTarget = ""; + changeUsernamePublicKey = ''; + usernameTarget = ''; userMetadataToUpdate = null; userProfileEntryResponseToUpdate: ProfileEntryResponse = null; searchedForPubKey = false; @@ -140,16 +143,16 @@ export class AdminComponent implements OnInit { // These are the options used to populate the dropdown for selecting a time window over which we want to fetch // posts ordered by deso. timeWindowOptions = { - "15m": 15, - "30m": 30, - "60m": 60, + '15m': 15, + '30m': 30, + '60m': 60, }; // This is a variable to track the currently selected time window. selectedTimeWindow = 60; // Fields for getting user admin data submittingGetUserAdminData = false; - getUserAdminDataPublicKey = ""; + getUserAdminDataPublicKey = ''; getUserAdminDataResponse = null; // Hot feed. @@ -191,15 +194,15 @@ export class AdminComponent implements OnInit { ngOnInit() { if (this.globalVars.showSuperAdminTools()) { - this.adminTabs.push("Super"); - this.adminTabs.push("Node Fees"); + this.adminTabs.push('Super'); + this.adminTabs.push('Node Fees'); } this.route.queryParams.subscribe((queryParams) => { if (queryParams.adminTab) { this.activeTab = queryParams.adminTab; } else { - this.activeTab = "Posts"; + this.activeTab = 'Posts'; } }); // load data @@ -229,7 +232,12 @@ export class AdminComponent implements OnInit { return; } this.backendApi - .NodeControl(this.globalVars.localNode, this.globalVars.loggedInUser.PublicKeyBase58Check, "", "get_info") + .NodeControl( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + '', + 'get_info' + ) .subscribe( (res: any) => { if (res == null || res.DeSoStatus == null) { @@ -249,7 +257,7 @@ export class AdminComponent implements OnInit { this.router.navigate([], { relativeTo: this.route, queryParams: { adminTab: this.activeTab }, - queryParamsHandling: "merge", + queryParamsHandling: 'merge', }); } @@ -270,7 +278,7 @@ export class AdminComponent implements OnInit { _loadPostsByDESO() { this.loadingPostsByDESO = true; // Get the reader's public key for the request. - let readerPubKey = ""; + let readerPubKey = ''; if (this.globalVars.loggedInUser) { readerPubKey = this.globalVars.loggedInUser.PublicKeyBase58Check; } @@ -281,11 +289,11 @@ export class AdminComponent implements OnInit { this.backendApi .GetPostsStateless( this.globalVars.localNode, - "" /*PostHash*/, + '' /*PostHash*/, readerPubKey /*ReaderPublicKeyBase58Check*/, - "" /*OrderBy*/, + '' /*OrderBy*/, parseInt(this.globalVars.filterType) /*StartTstampSecs*/, - "", + '', 50 /*NumToFetch*/, false /*FetchSubcomments*/, false /*GetPostsForFollowFeed*/, @@ -304,7 +312,9 @@ export class AdminComponent implements OnInit { }, (err) => { console.error(err); - this.globalVars._alertError("Error loading posts: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error loading posts: ' + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -322,7 +332,10 @@ export class AdminComponent implements OnInit { (this.hotFeedInteractionCap === 0 || this.hotFeedTimeDecayBlocks === 0) ) { this.backendApi - .AdminGetHotFeedAlgorithm(this.globalVars.localNode, this.globalVars.loggedInUser.PublicKeyBase58Check) + .AdminGetHotFeedAlgorithm( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check + ) .subscribe( (res) => { this.hotFeedInteractionCap = res.InteractionCap / 1e9; @@ -333,7 +346,10 @@ export class AdminComponent implements OnInit { }, (err) => { console.error(err); - this.globalVars._alertError("Error getting hot feed constants: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error getting hot feed constants: ' + + this.backendApi.stringifyError(err) + ); } ); } @@ -353,12 +369,16 @@ export class AdminComponent implements OnInit { (res) => { this.hotFeedPosts = this.hotFeedPosts.concat(res.HotFeedPage); for (let ii = 0; ii < res.HotFeedPage?.length; ii++) { - this.hotFeedPostHashes = this.hotFeedPostHashes.concat(res.HotFeedPage[ii].PostHashHex); + this.hotFeedPostHashes = this.hotFeedPostHashes.concat( + res.HotFeedPage[ii].PostHashHex + ); } }, (err) => { console.error(err); - this.globalVars._alertError("Error loading hot feed: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error loading hot feed: ' + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -382,12 +402,15 @@ export class AdminComponent implements OnInit { .subscribe( (res) => { this.globalVars._alertSuccess( - "Successfully updated InteractionCap. The hot feed will take ~10s to recompute." + 'Successfully updated InteractionCap. The hot feed will take ~10s to recompute.' ); }, (err) => { console.error(err); - this.globalVars._alertError("Error updating InteractionCap: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error updating InteractionCap: ' + + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -410,12 +433,15 @@ export class AdminComponent implements OnInit { .subscribe( (res) => { this.globalVars._alertSuccess( - "Successfully updated Tag InteractionCap. The hot feed will take ~10s to recompute." + 'Successfully updated Tag InteractionCap. The hot feed will take ~10s to recompute.' ); }, (err) => { console.error(err); - this.globalVars._alertError("Error updating Tag InteractionCap: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error updating Tag InteractionCap: ' + + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -438,12 +464,15 @@ export class AdminComponent implements OnInit { .subscribe( (res) => { this.globalVars._alertSuccess( - "Successfully updated TimeDecayBlocks. The hot feed will take ~10s to recompute." + 'Successfully updated TimeDecayBlocks. The hot feed will take ~10s to recompute.' ); }, (err) => { console.error(err); - this.globalVars._alertError("Error updating hot TimeDecayBlocks: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error updating hot TimeDecayBlocks: ' + + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -466,12 +495,15 @@ export class AdminComponent implements OnInit { .subscribe( (res) => { this.globalVars._alertSuccess( - "Successfully updated tag TimeDecayBlocks. The hot feed will take ~10s to recompute." + 'Successfully updated tag TimeDecayBlocks. The hot feed will take ~10s to recompute.' ); }, (err) => { console.error(err); - this.globalVars._alertError("Error updating tag hot TimeDecayBlocks: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error updating tag hot TimeDecayBlocks: ' + + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -480,7 +512,9 @@ export class AdminComponent implements OnInit { } addMultiplierToTxnTypeMultiplier() { - this.hotFeedTxnTypeMultiplierMap[this.hotFeedTxnTypeMultiplierNewKey] = this.hotFeedTxnTypeMultiplierNewValue; + this.hotFeedTxnTypeMultiplierMap[ + this.hotFeedTxnTypeMultiplierNewKey + ] = this.hotFeedTxnTypeMultiplierNewValue; this.hotFeedTxnTypeMultiplierNewKey = null; this.hotFeedTxnTypeMultiplierNewValue = null; } @@ -500,12 +534,15 @@ export class AdminComponent implements OnInit { .subscribe( (res) => { this.globalVars._alertSuccess( - "Successfully updated txn type multiplier map. The hot feed will take ~10s to recompute." + 'Successfully updated txn type multiplier map. The hot feed will take ~10s to recompute.' ); }, (err) => { console.error(err); - this.globalVars._alertError("Error updating txn type multiplier map: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error updating txn type multiplier map: ' + + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -525,11 +562,16 @@ export class AdminComponent implements OnInit { ) .subscribe( (res) => { - this.globalVars._alertSuccess("Successfully updated posts multiplier."); + this.globalVars._alertSuccess( + 'Successfully updated posts multiplier.' + ); }, (err) => { console.error(err); - this.globalVars._alertError("Error updating posts multiplier: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error updating posts multiplier: ' + + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -549,11 +591,16 @@ export class AdminComponent implements OnInit { ) .subscribe( (res) => { - this.globalVars._alertSuccess("Successfully updated interaction multiplier."); + this.globalVars._alertSuccess( + 'Successfully updated interaction multiplier.' + ); }, (err) => { console.error(err); - this.globalVars._alertError("Error updating interaction multiplier: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error updating interaction multiplier: ' + + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -582,7 +629,10 @@ export class AdminComponent implements OnInit { }, (err) => { console.error(err); - this.globalVars._alertError("Error fetching user's multipliers: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + "Error fetching user's multipliers: " + + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -594,13 +644,13 @@ export class AdminComponent implements OnInit { this.loadingMorePosts = true; // Get the reader's public key for the request. - let readerPubKey = ""; + let readerPubKey = ''; if (this.globalVars.loggedInUser) { readerPubKey = this.globalVars.loggedInUser.PublicKeyBase58Check; } // Get the last post hash in case this is a "load more" request. - let lastPostHash = ""; + let lastPostHash = ''; if (this.adminPosts.length > 0) { lastPostHash = this.adminPosts[this.adminPosts.length - 1].PostHashHex; } @@ -609,9 +659,9 @@ export class AdminComponent implements OnInit { this.globalVars.localNode, lastPostHash /*PostHash*/, readerPubKey /*ReaderPublicKeyBase58Check*/, - "newest" /*OrderBy*/, + 'newest' /*OrderBy*/, parseInt(this.globalVars.filterType) /*StartTstampSecs*/, - "", + '', 50 /*NumToFetch*/, false /*FetchSubcomments*/, false /*GetPostsForFollowFeed*/, @@ -623,7 +673,7 @@ export class AdminComponent implements OnInit { ) .subscribe( (res) => { - if (lastPostHash != "") { + if (lastPostHash != '') { this.adminPosts = this.adminPosts.concat(res.PostsFound); } else { this.adminPosts = res.PostsFound; @@ -634,7 +684,9 @@ export class AdminComponent implements OnInit { }, (err) => { console.error(err); - this.globalVars._alertError("Error loading posts: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error loading posts: ' + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -644,19 +696,28 @@ export class AdminComponent implements OnInit { } _loadMempoolStats() { - console.log("Loading mempool stats..."); + console.log('Loading mempool stats...'); this.loadingMempoolStats = true; this.backendApi - .AdminGetMempoolStats(this.globalVars.localNode, this.globalVars.loggedInUser.PublicKeyBase58Check) + .AdminGetMempoolStats( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check + ) .subscribe( (res) => { this.mempoolSummaryStats = res.TransactionSummaryStats; - this.mempoolTxnCount = _.sumBy(Object.values(this.mempoolSummaryStats), (o) => { - return o["Count"]; - }); - this.mempoolTotalBytes = _.sumBy(Object.values(this.mempoolSummaryStats), (o) => { - return o["TotalBytes"]; - }); + this.mempoolTxnCount = _.sumBy( + Object.values(this.mempoolSummaryStats), + (o) => { + return o['Count']; + } + ); + this.mempoolTotalBytes = _.sumBy( + Object.values(this.mempoolSummaryStats), + (o) => { + return o['TotalBytes']; + } + ); }, (err) => { console.log(err); @@ -669,9 +730,12 @@ export class AdminComponent implements OnInit { _loadVerifiedUsers() { this.loadingVerifiedUsers = true; - console.log("Loading verified users..."); + console.log('Loading verified users...'); this.backendApi - .AdminGetVerifiedUsers(this.globalVars.localNode, this.globalVars.loggedInUser.PublicKeyBase58Check) + .AdminGetVerifiedUsers( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check + ) .subscribe( (res) => { this.verifiedUsers = res.VerifiedUsers; @@ -687,7 +751,7 @@ export class AdminComponent implements OnInit { _loadVerifiedUsersAuditLog() { this.loadingVerifiedUsersAuditLog = true; - console.log("Loading username verification audit log..."); + console.log('Loading username verification audit log...'); this.backendApi .AdminGetUsernameVerificationAuditLogs( this.globalVars.localNode, @@ -709,14 +773,14 @@ export class AdminComponent implements OnInit { } _loadNextBlockStats() { - console.log("Loading stats for next block..."); + console.log('Loading stats for next block...'); this.loadingNextBlockStats = true; // The GetBlockTemplate endpoint requires a username so we have two randomly // generated pub keys to use as dummies in main / test net. - let dummyPubKey = "BC1YLgqAkAJ4sX2YGD85j9rEpTqDrAkgLoXwv6oTzaCyZt3cDpqk8hy"; + let dummyPubKey = 'BC1YLgqAkAJ4sX2YGD85j9rEpTqDrAkgLoXwv6oTzaCyZt3cDpqk8hy'; if (this.globalVars.isTestnet) { - dummyPubKey = "tBCKYKKdGQpCUYaG2pGy6LcNDeydSXYRHV4phywuc6bZANavsx3Y5f"; + dummyPubKey = 'tBCKYKKdGQpCUYaG2pGy6LcNDeydSXYRHV4phywuc6bZANavsx3Y5f'; } this.backendApi @@ -737,7 +801,10 @@ export class AdminComponent implements OnInit { _loadGlobalParams() { this.loadingGlobalParams = true; this.backendApi - .GetGlobalParams(this.globalVars.localNode, this.globalVars.loggedInUser.PublicKeyBase58Check) + .GetGlobalParams( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check + ) .subscribe( (res) => { this.globalParams = { @@ -750,7 +817,9 @@ export class AdminComponent implements OnInit { this.updateGlobalParamsValues = this.globalParams; }, (err) => { - this.globalVars._alertError("Error global params: " + this.backendApi.stringifyError(err)); + this.globalVars._alertError( + 'Error global params: ' + this.backendApi.stringifyError(err) + ); } ) .add(() => { @@ -759,17 +828,22 @@ export class AdminComponent implements OnInit { } _loadBuyDeSoFeeRate(): void { - this.backendApi.GetBuyDeSoFeeBasisPoints(this.globalVars.localNode).subscribe( - (res) => (this.buyDeSoFeeRate = res.BuyDeSoFeeBasisPoints / 100), - (err) => console.log(err) - ); + this.backendApi + .GetBuyDeSoFeeBasisPoints(this.globalVars.localNode) + .subscribe( + (res) => (this.buyDeSoFeeRate = res.BuyDeSoFeeBasisPoints / 100), + (err) => console.log(err) + ); } _loadUSDToDeSoReserveExchangeRate(): void { - this.backendApi.GetUSDCentsToDeSoReserveExchangeRate(this.globalVars.localNode).subscribe( - (res) => (this.usdToDeSoReserveExchangeRate = res.USDCentsPerDeSo / 100), - (err) => console.log(err) - ); + this.backendApi + .GetUSDCentsToDeSoReserveExchangeRate(this.globalVars.localNode) + .subscribe( + (res) => + (this.usdToDeSoReserveExchangeRate = res.USDCentsPerDeSo / 100), + (err) => console.log(err) + ); } _toggleDbDetails() { @@ -812,7 +886,11 @@ export class AdminComponent implements OnInit { _removeNilPosts() { this.removingNilPosts = true; this.backendApi - .AdminRemoveNilPosts(this.globalVars.localNode, this.globalVars.loggedInUser.PublicKeyBase58Check, 1000) + .AdminRemoveNilPosts( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + 1000 + ) .subscribe( () => { this.removingNilPosts = false; @@ -824,35 +902,35 @@ export class AdminComponent implements OnInit { } updateProfileModerationLevel(level: string) { - let targetPubKeyOrUsername = ""; - let pubKey = ""; - let username = ""; + let targetPubKeyOrUsername = ''; + let pubKey = ''; + let username = ''; let removeEverywhere = false; let removeFromLeaderboard = false; - this.updateProfileSuccessType = ""; + this.updateProfileSuccessType = ''; clearTimeout(this.clearSuccessTimeout); // Determine what variables to set based on the button pressed. - if (level === "blacklist") { - console.log("Blacklisting Pub Key: " + this.blacklistPubKeyOrUsername); + if (level === 'blacklist') { + console.log('Blacklisting Pub Key: ' + this.blacklistPubKeyOrUsername); targetPubKeyOrUsername = this.blacklistPubKeyOrUsername; removeEverywhere = true; removeFromLeaderboard = true; this.submittingBlacklistUpdate = true; - } else if (level === "graylist") { - console.log("Graylisting Pub Key: " + this.graylistPubKeyOrUsername); + } else if (level === 'graylist') { + console.log('Graylisting Pub Key: ' + this.graylistPubKeyOrUsername); targetPubKeyOrUsername = this.graylistPubKeyOrUsername; removeEverywhere = false; removeFromLeaderboard = true; this.submittingGraylistUpdate = true; - } else if (level === "unrestrict") { - console.log("Unrestricting Pub Key: " + this.unrestrictPubKeyOrUsername); + } else if (level === 'unrestrict') { + console.log('Unrestricting Pub Key: ' + this.unrestrictPubKeyOrUsername); targetPubKeyOrUsername = this.unrestrictPubKeyOrUsername; removeEverywhere = false; removeFromLeaderboard = false; this.submittingUnrestrictUpdate = true; } else { - console.log("Cannot set moderation level to: " + level); + console.log('Cannot set moderation level to: ' + level); return; } @@ -882,7 +960,7 @@ export class AdminComponent implements OnInit { (res) => { this.updateProfileSuccessType = level; this.clearSuccessTimeout = setTimeout(() => { - this.updateProfileSuccessType = ""; + this.updateProfileSuccessType = ''; }, 1000); }, (err) => { @@ -890,22 +968,22 @@ export class AdminComponent implements OnInit { } ) .add(() => { - if (level === "blacklist") { + if (level === 'blacklist') { this.submittingBlacklistUpdate = false; - this.blacklistPubKeyOrUsername = ""; - } else if (level === "graylist") { + this.blacklistPubKeyOrUsername = ''; + } else if (level === 'graylist') { this.submittingGraylistUpdate = false; - this.graylistPubKeyOrUsername = ""; - } else if (level === "unrestrict") { + this.graylistPubKeyOrUsername = ''; + } else if (level === 'unrestrict') { this.submittingUnrestrictUpdate = false; - this.unrestrictPubKeyOrUsername = ""; + this.unrestrictPubKeyOrUsername = ''; } }); } whitelistClicked() { - let pubKey = ""; - let username = ""; + let pubKey = ''; + let username = ''; this.submittingWhitelistUpdate = true; clearTimeout(this.whitelistSuccessTimeout); @@ -942,13 +1020,13 @@ export class AdminComponent implements OnInit { ) .add(() => { this.submittingWhitelistUpdate = false; - this.whitelistPubKeyOrUsername = ""; + this.whitelistPubKeyOrUsername = ''; }); } unwhitelistClicked() { - let pubKey = ""; - let username = ""; + let pubKey = ''; + let username = ''; this.submittingUnwhitelistUpdate = true; clearTimeout(this.unwhitelistSuccessTimeout); @@ -985,7 +1063,7 @@ export class AdminComponent implements OnInit { ) .add(() => { this.submittingUnwhitelistUpdate = false; - this.unwhitelistPubKeyOrUsername = ""; + this.unwhitelistPubKeyOrUsername = ''; }); } @@ -1011,8 +1089,8 @@ export class AdminComponent implements OnInit { submitRemovePhoneNumber() { const targetPubKeyOrUsername = this.removePhonePubKeyorUsername; - let pubKey = ""; - let username = ""; + let pubKey = ''; + let username = ''; if (this.globalVars.isMaybePublicKey(targetPubKeyOrUsername)) { pubKey = targetPubKeyOrUsername; @@ -1049,9 +1127,9 @@ export class AdminComponent implements OnInit { } resetPhoneNumberSuccess(): void { - this.updateProfileSuccessType = "phone"; + this.updateProfileSuccessType = 'phone'; this.clearSuccessTimeout = setTimeout(() => { - this.updateProfileSuccessType = ""; + this.updateProfileSuccessType = ''; }, 1000); } @@ -1060,15 +1138,16 @@ export class AdminComponent implements OnInit { // Is it obvious yet that I'm not a frontend gal? // TODO: Error handling between BE and FE needs a major redesign. const rawError = err.error.error; - if (rawError.includes("password")) { + if (rawError.includes('password')) { return Messages.INCORRECT_PASSWORD; - } else if (rawError.includes("not sufficient")) { + } else if (rawError.includes('not sufficient')) { return Messages.INSUFFICIENT_BALANCE; - } else if (rawError.includes("RuleErrorTxnMustHaveAtLeastOneInput")) { + } else if (rawError.includes('RuleErrorTxnMustHaveAtLeastOneInput')) { return Messages.SEND_DESO_MIN; } else if ( - (rawError.includes("SendDeSo: Problem") && rawError.includes("Invalid input format")) || - rawError.includes("Checksum does not match") + (rawError.includes('SendDeSo: Problem') && + rawError.includes('Invalid input format')) || + rawError.includes('Checksum does not match') ) { return Messages.INVALID_PUBLIC_KEY; } else { @@ -1085,39 +1164,69 @@ export class AdminComponent implements OnInit { updateGlobalParamUSDPerBitcoin() { this.updatingUSDToBitcoin = true; - this.updateGlobalParams(this.updateGlobalParamsValues.USDPerBitcoin, -1, -1, -1, -1); + this.updateGlobalParams( + this.updateGlobalParamsValues.USDPerBitcoin, + -1, + -1, + -1, + -1 + ); } updateGlobalParamCreateProfileFee() { this.updatingCreateProfileFee = true; - this.updateGlobalParams(-1, this.updateGlobalParamsValues.CreateProfileFeeNanos, -1, -1, -1); + this.updateGlobalParams( + -1, + this.updateGlobalParamsValues.CreateProfileFeeNanos, + -1, + -1, + -1 + ); } updateGlobalParamMinimumNetworkFee() { this.updatingMinimumNetworkFee = true; - this.updateGlobalParams(-1, -1, this.updateGlobalParamsValues.MinimumNetworkFeeNanosPerKB, -1, -1); + this.updateGlobalParams( + -1, + -1, + this.updateGlobalParamsValues.MinimumNetworkFeeNanosPerKB, + -1, + -1 + ); } updateGlobalParamMaxCopiesPerNFT() { this.updatingMaxCopiesPerNFT = true; - this.updateGlobalParams(-1, -1, -1, this.updateGlobalParamsValues.MaxCopiesPerNFT, -1); + this.updateGlobalParams( + -1, + -1, + -1, + this.updateGlobalParamsValues.MaxCopiesPerNFT, + -1 + ); } updateGlobalParamCreateNFTFeeNanos() { this.updatingCreateNFTFeeNanos = true; - this.updateGlobalParams(-1, -1, -1, -1, this.updateGlobalParamsValues.CreateNFTFeeNanos); + this.updateGlobalParams( + -1, + -1, + -1, + -1, + this.updateGlobalParamsValues.CreateNFTFeeNanos + ); } updateUSDToDeSoReserveExchangeRate(): void { SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - title: "Are you ready?", + title: 'Are you ready?', html: `You are about to update the reserve exchange rate of USD to DeSo to be $${this.usdToDeSoReserveExchangeRate}`, showConfirmButton: true, showCancelButton: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, reverseButtons: true, }).then((res) => { @@ -1133,14 +1242,19 @@ export class AdminComponent implements OnInit { (res: any) => { console.log(res); this.globalVars._alertSuccess( - sprintf("Successfully updated the reserve exchange to $%d/DeSo", res.USDCentsPerDeSo / 100) + sprintf( + 'Successfully updated the reserve exchange to $%d/DeSo', + res.USDCentsPerDeSo / 100 + ) ); }, (err: any) => { this.globalVars._alertError(this.extractError(err)); } ) - .add(() => (this.submittingUSDToDeSoReserveExchangeRateUpdate = false)); + .add( + () => (this.submittingUSDToDeSoReserveExchangeRateUpdate = false) + ); } }); } @@ -1148,13 +1262,13 @@ export class AdminComponent implements OnInit { updateBuyDeSoFeeRate(): void { SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - title: "Are you ready?", + title: 'Are you ready?', html: `You are about to update the Buy DeSo Fee to be ${this.buyDeSoFeeRate}%`, showConfirmButton: true, showCancelButton: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, reverseButtons: true, }).then((res) => { @@ -1170,7 +1284,10 @@ export class AdminComponent implements OnInit { (res: any) => { console.log(res); this.globalVars._alertSuccess( - sprintf("Successfully updated the Buy DeSo Fee to %d%", res.USDCentsPerDeSo / 100) + sprintf( + 'Successfully updated the Buy DeSo Fee to %d%', + res.USDCentsPerDeSo / 100 + ) ); }, (err: any) => { @@ -1189,22 +1306,33 @@ export class AdminComponent implements OnInit { maxCopiesPerNFT: number, createNFTFeeNanos: number ) { - const updateBitcoinMessage = usdPerBitcoin >= 0 ? `Update Bitcoin to USD exchange rate: ${usdPerBitcoin}\n` : ""; + const updateBitcoinMessage = + usdPerBitcoin >= 0 + ? `Update Bitcoin to USD exchange rate: ${usdPerBitcoin}\n` + : ''; const createProfileFeeNanosMessage = - createProfileFeeNanos >= 0 ? `Create Profile Fee (in $DESO): ${createProfileFeeNanos}\n` : ""; + createProfileFeeNanos >= 0 + ? `Create Profile Fee (in $DESO): ${createProfileFeeNanos}\n` + : ''; const minimumNetworkFeeNanosPerKBMessage = - minimumNetworkFeeNanosPerKB >= 0 ? `Minimum Network Fee Nanos Per KB: ${minimumNetworkFeeNanosPerKB}\n` : ""; - const maxCopiesMessage = maxCopiesPerNFT >= 0 ? `Max Copies Per NFT: ${maxCopiesPerNFT}\n` : ""; - const createNFTFeeNanosMessage = createNFTFeeNanos >= 0 ? `Create NFT Fee (in $DESO): ${createNFTFeeNanos}\n` : ""; + minimumNetworkFeeNanosPerKB >= 0 + ? `Minimum Network Fee Nanos Per KB: ${minimumNetworkFeeNanosPerKB}\n` + : ''; + const maxCopiesMessage = + maxCopiesPerNFT >= 0 ? `Max Copies Per NFT: ${maxCopiesPerNFT}\n` : ''; + const createNFTFeeNanosMessage = + createNFTFeeNanos >= 0 + ? `Create NFT Fee (in $DESO): ${createNFTFeeNanos}\n` + : ''; SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - title: "Are you ready?", + title: 'Are you ready?', html: `${updateBitcoinMessage}${createProfileFeeNanosMessage}${minimumNetworkFeeNanosPerKBMessage}${maxCopiesMessage}${createNFTFeeNanosMessage}`, showConfirmButton: true, showCancelButton: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, reverseButtons: true, }) @@ -1218,7 +1346,9 @@ export class AdminComponent implements OnInit { this.globalVars.loggedInUser.PublicKeyBase58Check, usdPerBitcoin >= 0 ? usdPerBitcoin * 100 : -1, createProfileFeeNanos >= 0 ? createProfileFeeNanos * 1e9 : -1, - minimumNetworkFeeNanosPerKB >= 0 ? minimumNetworkFeeNanosPerKB : -1, + minimumNetworkFeeNanosPerKB >= 0 + ? minimumNetworkFeeNanosPerKB + : -1, maxCopiesPerNFT >= 0 ? maxCopiesPerNFT : -1, createNFTFeeNanos >= 0 ? createNFTFeeNanos * 1e9 : -1, minimumNetworkFeeNanosPerKB >= 0 @@ -1242,7 +1372,7 @@ export class AdminComponent implements OnInit { this.globalVars._alertSuccess( sprintf( - "Successfully updated global params rate. TxID: %s for a fee of %d DeSo", + 'Successfully updated global params rate. TxID: %s for a fee of %d DeSo', res.TransactionIDBase58Check, totalFeeDeSo ) @@ -1268,8 +1398,10 @@ export class AdminComponent implements OnInit { } reprocessBitcoinBlock() { - if (this.bitcoinBlockHashOrHeight === "") { - this.globalVars._alertError("Please enter either a Bitcoin block hash or a Bitcoin block height."); + if (this.bitcoinBlockHashOrHeight === '') { + this.globalVars._alertError( + 'Please enter either a Bitcoin block hash or a Bitcoin block height.' + ); return; } @@ -1286,7 +1418,7 @@ export class AdminComponent implements OnInit { this.globalVars._alertError(Messages.CONNECTION_PROBLEM); return null; } - this.bitcoinBlockHashOrHeight = ""; + this.bitcoinBlockHashOrHeight = ''; this.globalVars._alertSuccess(res.Message); }, (error) => { @@ -1302,13 +1434,13 @@ export class AdminComponent implements OnInit { evictBitcoinExchangeTxns(dryRun: boolean) { SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - title: "Are you ready?", + title: 'Are you ready?', html: `About to evict ${this.evictBitcoinTxnHashes} with DryRun=${dryRun}`, showConfirmButton: true, showCancelButton: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, reverseButtons: true, }) @@ -1319,7 +1451,7 @@ export class AdminComponent implements OnInit { .EvictUnminedBitcoinTxns( this.globalVars.localNode, this.globalVars.loggedInUser.PublicKeyBase58Check, - this.evictBitcoinTxnHashes.split(","), + this.evictBitcoinTxnHashes.split(','), dryRun ) .subscribe( @@ -1330,8 +1462,12 @@ export class AdminComponent implements OnInit { } this.globalVars._alertSuccess( - `Success! Lost ${res.TotalMempoolTxns - res.MempoolTxnsLeftAfterEviction} mempool - txns with ${res.TotalMempoolTxns} total txns in the mempool before eviction. + `Success! Lost ${ + res.TotalMempoolTxns - res.MempoolTxnsLeftAfterEviction + } mempool + txns with ${ + res.TotalMempoolTxns + } total txns in the mempool before eviction. Types: ${JSON.stringify(res.TxnTypesEvicted, null, 2)}. Check the response of this request in the browser's inspector for more information.` ); @@ -1352,8 +1488,8 @@ export class AdminComponent implements OnInit { } grantVerificationBadge() { - if (this.usernameToVerify === "") { - this.globalVars._alertError("Please enter a valid username."); + if (this.usernameToVerify === '') { + this.globalVars._alertError('Please enter a valid username.'); return; } @@ -1378,8 +1514,8 @@ export class AdminComponent implements OnInit { } getUserAdminDataClicked() { - if (this.getUserAdminDataPublicKey === "") { - this.globalVars._alertError("Please enter a valid username."); + if (this.getUserAdminDataPublicKey === '') { + this.globalVars._alertError('Please enter a valid username.'); return; } @@ -1404,8 +1540,8 @@ export class AdminComponent implements OnInit { } RemoveVerification() { - if (this.usernameForWhomToRemoveVerification === "") { - this.globalVars._alertError("Please enter a valid username."); + if (this.usernameForWhomToRemoveVerification === '') { + this.globalVars._alertError('Please enter a valid username.'); return; } @@ -1430,12 +1566,16 @@ export class AdminComponent implements OnInit { } swapIdentity() { - if (this.swapIdentityFromUsernameOrPublicKey === "") { - this.globalVars._alertError("Please enter the username or public key of the user you are swapping *from*"); + if (this.swapIdentityFromUsernameOrPublicKey === '') { + this.globalVars._alertError( + 'Please enter the username or public key of the user you are swapping *from*' + ); return; } - if (this.swapIdentityToUsernameOrPublicKey === "") { - this.globalVars._alertError("Please enter the username or public key of the user you are swapping *to*"); + if (this.swapIdentityToUsernameOrPublicKey === '') { + this.globalVars._alertError( + 'Please enter the username or public key of the user you are swapping *to*' + ); return; } @@ -1446,7 +1586,9 @@ export class AdminComponent implements OnInit { this.globalVars.loggedInUser.PublicKeyBase58Check, this.swapIdentityFromUsernameOrPublicKey, this.swapIdentityToUsernameOrPublicKey, - Math.floor(parseFloat(this.feeRateDeSoPerKB) * 1e9) /*MinFeeRateNanosPerKB*/ + Math.floor( + parseFloat(this.feeRateDeSoPerKB) * 1e9 + ) /*MinFeeRateNanosPerKB*/ ) .subscribe( (res: any) => { @@ -1454,7 +1596,7 @@ export class AdminComponent implements OnInit { this.globalVars._alertError(Messages.CONNECTION_PROBLEM); return null; } - this.globalVars._alertSuccess("Identities successfully swapped!"); + this.globalVars._alertSuccess('Identities successfully swapped!'); }, (error) => { console.error(error); @@ -1490,8 +1632,8 @@ export class AdminComponent implements OnInit { if (!this.searchedForPubKey) { return SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - icon: "warning", - title: "Search for public key before updating username", + icon: 'warning', + title: 'Search for public key before updating username', }); } const infoMsg = this.userProfileEntryResponseToUpdate @@ -1499,32 +1641,36 @@ export class AdminComponent implements OnInit { : `Set username to ${this.usernameTarget} for public key ${this.changeUsernamePublicKey}`; SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - icon: "info", + icon: 'info', title: `Updating Username`, html: infoMsg, showCancelButton: true, showConfirmButton: true, focusConfirm: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, reverseButtons: true, }).then((res: any) => { if (res.isConfirmed) { this.submittingUpdateUsername = true; - const creatorCoinBasisPoints = this.userProfileEntryResponseToUpdate?.CoinEntry?.CreatorBasisPoints || 10 * 100; + const creatorCoinBasisPoints = + this.userProfileEntryResponseToUpdate?.CoinEntry + ?.CreatorBasisPoints || 10 * 100; const stakeMultipleBasisPoints = - this.userProfileEntryResponseToUpdate?.StakeMultipleBasisPoints || 1.25 * 100 * 100; + this.userProfileEntryResponseToUpdate?.StakeMultipleBasisPoints || + 1.25 * 100 * 100; return this.backendApi .UpdateProfile( environment.verificationEndpointHostname, - this.globalVars.loggedInUser.PublicKeyBase58Check /*UpdaterPublicKeyBase58Check*/, + this.globalVars.loggedInUser + .PublicKeyBase58Check /*UpdaterPublicKeyBase58Check*/, this.changeUsernamePublicKey /*ProfilePublicKeyBase58Check*/, // Start params this.usernameTarget /*NewUsername*/, - "" /*NewDescription*/, - "" /*NewProfilePic*/, + '' /*NewDescription*/, + '' /*NewProfilePic*/, creatorCoinBasisPoints /*NewCreatorBasisPoints*/, stakeMultipleBasisPoints /*NewStakeMultipleBasisPoints*/, false /*IsHidden*/, @@ -1533,9 +1679,9 @@ export class AdminComponent implements OnInit { ) .subscribe( () => { - this.updateProfileSuccessType = "username"; + this.updateProfileSuccessType = 'username'; this.clearSuccessTimeout = setTimeout(() => { - this.updateProfileSuccessType = ""; + this.updateProfileSuccessType = ''; }, 1000); }, (err) => { diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 666c7f96a..36218e203 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,42 +1,42 @@ -import { NgModule } from "@angular/core"; -import { Routes, RouterModule, Router, Scroll } from "@angular/router"; - -import { ManageFollowsPageComponent } from "./manage-follows-page/manage-follows-page.component"; -import { NotFoundPageComponent } from "./not-found-page/not-found-page.component"; -import { BrowsePageComponent } from "./browse-page/browse-page.component"; -import { CreatorsLeaderboardPageComponent } from "./creators-leaderboard/creators-leaderboard-page/creators-leaderboard-page.component"; -import { BuyDeSoPageComponent } from "./buy-deso-page/buy-deso-page.component"; -import { MessagesPageComponent } from "./messages-page/messages-page.component"; -import { SettingsPageComponent } from "./settings-page/settings-page.component"; -import { CreatorProfilePageComponent } from "./creator-profile-page/creator-profile-page.component"; -import { TradeCreatorPageComponent } from "./trade-creator-page/trade-creator-page.component"; -import { UpdateProfilePageComponent } from "./update-profile-page/update-profile-page.component"; -import { NotificationsPageComponent } from "./notifications-page/notifications-page.component"; -import { PostThreadPageComponent } from "./post-thread-page/post-thread-page.component"; -import { TransferDeSoPageComponent } from "./transfer-deso-page/transfer-deso-page.component"; -import { CreatePostPageComponent } from "./create-post-page/create-post-page.component"; -import { TosPageComponent } from "./tos-page/tos-page.component"; -import { AdminPageComponent } from "./admin-page/admin-page.component"; -import { ViewportScroller } from "@angular/common"; -import { filter } from "rxjs/operators"; -import { LandingPageComponent } from "./landing-page/landing-page.component"; -import { GetStarterDeSoPageComponent } from "./get-starter-deso-page/get-starter-deso-page.component"; -import { SignUpComponent } from "./sign-up/sign-up.component"; -import { PickACoinPageComponent } from "./pick-a-coin-page/pick-a-coin-page.component"; -import { DiamondPostsPageComponent } from "./diamond-posts-page/diamond-posts-page.component"; -import { TrendsPageComponent } from "./trends-page/trends-page.component"; -import { NftPostPageComponent } from "./nft-post-page/nft-post-page.component"; -import { VerifyEmailComponent } from "./verify-email/verify-email.component"; -import { CreateProfileTutorialPageComponent } from "./tutorial/create-profile-tutorial-page/create-profile-tutorial-page.component"; -import { BuyCreatorCoinsTutorialPageComponent } from "./tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-tutorial-page.component"; -import { BuyCreatorCoinsConfirmTutorialComponent } from "./tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-confirm-tutorial/buy-creator-coins-confirm-tutorial.component"; -import { WalletPageComponent } from "./wallet/wallet-page/wallet-page.component"; -import { WalletTutorialPageComponent } from "./tutorial/wallet-tutorial-page/wallet-tutorial-page.component"; -import { SellCreatorCoinsTutorialComponent } from "./tutorial/sell-creator-coins-tutorial-page/sell-creator-coins-tutorial/sell-creator-coins-tutorial.component"; -import { DiamondTutorialPageComponent } from "./tutorial/diamond-tutorial-page/diamond-tutorial-page.component"; -import { CreatePostTutorialPageComponent } from "./tutorial/create-post-tutorial-page/create-post-tutorial-page.component"; -import { SupplyMonitoringStatsPageComponent } from "./supply-monitoring-stats-page/supply-monitoring-stats-page.component"; -import { DaoCoinsPageComponent } from "./dao-coins/dao-coins-page/dao-coins-page.component"; +import { NgModule } from '@angular/core'; +import { Routes, RouterModule, Router, Scroll } from '@angular/router'; + +import { ManageFollowsPageComponent } from './manage-follows-page/manage-follows-page.component'; +import { NotFoundPageComponent } from './not-found-page/not-found-page.component'; +import { BrowsePageComponent } from './browse-page/browse-page.component'; +import { CreatorsLeaderboardPageComponent } from './creators-leaderboard/creators-leaderboard-page/creators-leaderboard-page.component'; +import { BuyDeSoPageComponent } from './buy-deso-page/buy-deso-page.component'; +import { MessagesPageComponent } from './messages-page/messages-page.component'; +import { SettingsPageComponent } from './settings-page/settings-page.component'; +import { CreatorProfilePageComponent } from './creator-profile-page/creator-profile-page.component'; +import { TradeCreatorPageComponent } from './trade-creator-page/trade-creator-page.component'; +import { UpdateProfilePageComponent } from './update-profile-page/update-profile-page.component'; +import { NotificationsPageComponent } from './notifications-page/notifications-page.component'; +import { PostThreadPageComponent } from './post-thread-page/post-thread-page.component'; +import { TransferDeSoPageComponent } from './transfer-deso-page/transfer-deso-page.component'; +import { CreatePostPageComponent } from './create-post-page/create-post-page.component'; +import { TosPageComponent } from './tos-page/tos-page.component'; +import { AdminPageComponent } from './admin-page/admin-page.component'; +import { ViewportScroller } from '@angular/common'; +import { filter } from 'rxjs/operators'; +import { LandingPageComponent } from './landing-page/landing-page.component'; +import { GetStarterDeSoPageComponent } from './get-starter-deso-page/get-starter-deso-page.component'; +import { SignUpComponent } from './sign-up/sign-up.component'; +import { PickACoinPageComponent } from './pick-a-coin-page/pick-a-coin-page.component'; +import { DiamondPostsPageComponent } from './diamond-posts-page/diamond-posts-page.component'; +import { TrendsPageComponent } from './trends-page/trends-page.component'; +import { NftPostPageComponent } from './nft-post-page/nft-post-page.component'; +import { VerifyEmailComponent } from './verify-email/verify-email.component'; +import { CreateProfileTutorialPageComponent } from './tutorial/create-profile-tutorial-page/create-profile-tutorial-page.component'; +import { BuyCreatorCoinsTutorialPageComponent } from './tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-tutorial-page.component'; +import { BuyCreatorCoinsConfirmTutorialComponent } from './tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-confirm-tutorial/buy-creator-coins-confirm-tutorial.component'; +import { WalletPageComponent } from './wallet/wallet-page/wallet-page.component'; +import { WalletTutorialPageComponent } from './tutorial/wallet-tutorial-page/wallet-tutorial-page.component'; +import { SellCreatorCoinsTutorialComponent } from './tutorial/sell-creator-coins-tutorial-page/sell-creator-coins-tutorial/sell-creator-coins-tutorial.component'; +import { DiamondTutorialPageComponent } from './tutorial/diamond-tutorial-page/diamond-tutorial-page.component'; +import { CreatePostTutorialPageComponent } from './tutorial/create-post-tutorial-page/create-post-tutorial-page.component'; +import { SupplyMonitoringStatsPageComponent } from './supply-monitoring-stats-page/supply-monitoring-stats-page.component'; +import { DaoCoinsPageComponent } from './dao-coins/dao-coins-page/dao-coins-page.component'; class RouteNames { // Not sure if we should have a smarter schema for this, e.g. what happens if we have @@ -45,132 +45,226 @@ class RouteNames { // and we want to rename (1) but not (2) ? // /:username/following - public static FOLLOWING = "following"; + public static FOLLOWING = 'following'; // /:username/followers - public static FOLLOWERS = "followers"; - - public static BROWSE = "browse"; - public static CREATORS = "creators"; - public static BUY_DESO = "buy-deso"; - public static WALLET = "wallet"; - public static SETTINGS = "settings"; - public static USER_PREFIX = "u"; - public static INBOX_PREFIX = "inbox"; - public static TRANSFER_CREATOR = "transfer"; - public static PICK_A_COIN = "select-creator-coin"; - public static BUY_CREATOR = "buy"; - public static SELL_CREATOR = "sell"; - public static UPDATE_PROFILE = "update-profile"; - public static NOTIFICATIONS = "notifications"; - public static SIGN_UP = "sign-up"; - public static NOT_FOUND = "404"; - public static POSTS = "posts"; - public static SEND_DESO = "send-deso"; + public static FOLLOWERS = 'followers'; + + public static BROWSE = 'browse'; + public static CREATORS = 'creators'; + public static BUY_DESO = 'buy-deso'; + public static WALLET = 'wallet'; + public static SETTINGS = 'settings'; + public static USER_PREFIX = 'u'; + public static INBOX_PREFIX = 'inbox'; + public static TRANSFER_CREATOR = 'transfer'; + public static PICK_A_COIN = 'select-creator-coin'; + public static BUY_CREATOR = 'buy'; + public static SELL_CREATOR = 'sell'; + public static UPDATE_PROFILE = 'update-profile'; + public static NOTIFICATIONS = 'notifications'; + public static SIGN_UP = 'sign-up'; + public static NOT_FOUND = '404'; + public static POSTS = 'posts'; + public static SEND_DESO = 'send-deso'; // TODO: how do I make this /posts/new? - public static CREATE_POST = "posts/new"; - public static TOS = "terms-of-service"; - public static ADMIN = "admin"; - public static GET_STARTER_DESO = "get-starter-deso"; - public static LANDING = "/"; - public static DIAMONDS = "diamonds"; - public static TRENDS = "trends"; - public static NFT = "nft"; - public static VERIFY_EMAIL = "verify-email"; - - public static TUTORIAL = "tutorial"; - public static CREATE_PROFILE = "create-profile"; - public static INVEST = "invest"; - public static SUPPLY_STATS = "supply-stats"; - public static DAO = "dao"; + public static CREATE_POST = 'posts/new'; + public static TOS = 'terms-of-service'; + public static ADMIN = 'admin'; + public static GET_STARTER_DESO = 'get-starter-deso'; + public static LANDING = '/'; + public static DIAMONDS = 'diamonds'; + public static TRENDS = 'trends'; + public static NFT = 'nft'; + public static VERIFY_EMAIL = 'verify-email'; + + public static TUTORIAL = 'tutorial'; + public static CREATE_PROFILE = 'create-profile'; + public static INVEST = 'invest'; + public static SUPPLY_STATS = 'supply-stats'; + public static DAO = 'dao'; } const routes: Routes = [ - { path: "", component: LandingPageComponent, pathMatch: "full" }, - { path: RouteNames.BROWSE, component: BrowsePageComponent, pathMatch: "full" }, - { path: RouteNames.CREATORS, component: CreatorsLeaderboardPageComponent, pathMatch: "full" }, - { path: RouteNames.USER_PREFIX + "/:username", component: CreatorProfilePageComponent, pathMatch: "full" }, - { path: RouteNames.SETTINGS, component: SettingsPageComponent, pathMatch: "full" }, - { path: RouteNames.BUY_DESO, component: BuyDeSoPageComponent, pathMatch: "full" }, - { path: RouteNames.PICK_A_COIN, component: PickACoinPageComponent, pathMatch: "full" }, - { path: RouteNames.INBOX_PREFIX, component: MessagesPageComponent, pathMatch: "full" }, - { path: RouteNames.SIGN_UP, component: SignUpComponent, pathMatch: "full" }, - { path: RouteNames.WALLET, component: WalletPageComponent, pathMatch: "full" }, - { path: RouteNames.UPDATE_PROFILE, component: UpdateProfilePageComponent, pathMatch: "full" }, - { path: RouteNames.NOTIFICATIONS, component: NotificationsPageComponent, pathMatch: "full" }, - { path: RouteNames.NOT_FOUND, component: NotFoundPageComponent, pathMatch: "full" }, + { path: '', component: LandingPageComponent, pathMatch: 'full' }, + { + path: RouteNames.BROWSE, + component: BrowsePageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.CREATORS, + component: CreatorsLeaderboardPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.USER_PREFIX + '/:username', + component: CreatorProfilePageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.SETTINGS, + component: SettingsPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.BUY_DESO, + component: BuyDeSoPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.PICK_A_COIN, + component: PickACoinPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.INBOX_PREFIX, + component: MessagesPageComponent, + pathMatch: 'full', + }, + { path: RouteNames.SIGN_UP, component: SignUpComponent, pathMatch: 'full' }, + { + path: RouteNames.WALLET, + component: WalletPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.UPDATE_PROFILE, + component: UpdateProfilePageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.NOTIFICATIONS, + component: NotificationsPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.NOT_FOUND, + component: NotFoundPageComponent, + pathMatch: 'full', + }, // CREATE_POST needs to be above the POSTS route, since both involve the prefix /posts // if CREATOR_POST is second, then it's route (/posts/new/) will get matched to POSTS instead - { path: RouteNames.CREATE_POST, component: CreatePostPageComponent, pathMatch: "full" }, - { path: RouteNames.POSTS + "/:postHashHex", component: PostThreadPageComponent, pathMatch: "full" }, - { path: RouteNames.NFT + "/:postHashHex", component: NftPostPageComponent, pathMatch: "full" }, - { path: RouteNames.SEND_DESO, component: TransferDeSoPageComponent, pathMatch: "full" }, - { path: RouteNames.DAO, component: DaoCoinsPageComponent, pathMatch: "full" }, - { path: RouteNames.TOS, component: TosPageComponent, pathMatch: "full" }, - { path: "tos", component: TosPageComponent, pathMatch: "full" }, - { path: RouteNames.ADMIN, component: AdminPageComponent, pathMatch: "full" }, - { - path: RouteNames.USER_PREFIX + "/:username/" + RouteNames.FOLLOWERS, + { + path: RouteNames.CREATE_POST, + component: CreatePostPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.POSTS + '/:postHashHex', + component: PostThreadPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.NFT + '/:postHashHex', + component: NftPostPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.SEND_DESO, + component: TransferDeSoPageComponent, + pathMatch: 'full', + }, + { path: RouteNames.DAO, component: DaoCoinsPageComponent, pathMatch: 'full' }, + { path: RouteNames.TOS, component: TosPageComponent, pathMatch: 'full' }, + { path: 'tos', component: TosPageComponent, pathMatch: 'full' }, + { path: RouteNames.ADMIN, component: AdminPageComponent, pathMatch: 'full' }, + { + path: RouteNames.USER_PREFIX + '/:username/' + RouteNames.FOLLOWERS, component: ManageFollowsPageComponent, - pathMatch: "full", + pathMatch: 'full', }, { - path: RouteNames.USER_PREFIX + "/:username/" + RouteNames.FOLLOWING, + path: RouteNames.USER_PREFIX + '/:username/' + RouteNames.FOLLOWING, component: ManageFollowsPageComponent, - pathMatch: "full", + pathMatch: 'full', }, { - path: RouteNames.USER_PREFIX + "/:receiver/" + RouteNames.DIAMONDS + "/:sender", + path: + RouteNames.USER_PREFIX + '/:receiver/' + RouteNames.DIAMONDS + '/:sender', component: DiamondPostsPageComponent, - pathMatch: "full", + pathMatch: 'full', + }, + { + path: RouteNames.USER_PREFIX + '/:username/:tradeType', + component: TradeCreatorPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.GET_STARTER_DESO, + component: GetStarterDeSoPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.TRENDS, + component: TrendsPageComponent, + pathMatch: 'full', + }, + { + path: RouteNames.VERIFY_EMAIL + '/:publicKey/:emailHash', + component: VerifyEmailComponent, + pathMatch: 'full', }, - { path: RouteNames.USER_PREFIX + "/:username/:tradeType", component: TradeCreatorPageComponent, pathMatch: "full" }, - { path: RouteNames.GET_STARTER_DESO, component: GetStarterDeSoPageComponent, pathMatch: "full" }, - { path: RouteNames.TRENDS, component: TrendsPageComponent, pathMatch: "full" }, - { path: RouteNames.VERIFY_EMAIL + "/:publicKey/:emailHash", component: VerifyEmailComponent, pathMatch: "full" }, // TUTORIAL ROUTES { - path: RouteNames.TUTORIAL + "/" + RouteNames.CREATE_PROFILE, + path: RouteNames.TUTORIAL + '/' + RouteNames.CREATE_PROFILE, component: CreateProfileTutorialPageComponent, - pathMatch: "full", + pathMatch: 'full', }, { - path: RouteNames.TUTORIAL + "/" + RouteNames.INVEST + "/" + RouteNames.BUY_CREATOR, + path: + RouteNames.TUTORIAL + + '/' + + RouteNames.INVEST + + '/' + + RouteNames.BUY_CREATOR, component: BuyCreatorCoinsTutorialPageComponent, - pathMatch: "full", + pathMatch: 'full', }, { - path: RouteNames.TUTORIAL + "/" + RouteNames.INVEST + "/" + RouteNames.SELL_CREATOR + "/:username", + path: + RouteNames.TUTORIAL + + '/' + + RouteNames.INVEST + + '/' + + RouteNames.SELL_CREATOR + + '/:username', component: SellCreatorCoinsTutorialComponent, - pathMatch: "full", + pathMatch: 'full', }, { - path: RouteNames.TUTORIAL + "/" + RouteNames.INVEST + "/" + RouteNames.BUY_CREATOR + "/:username", + path: + RouteNames.TUTORIAL + + '/' + + RouteNames.INVEST + + '/' + + RouteNames.BUY_CREATOR + + '/:username', component: BuyCreatorCoinsConfirmTutorialComponent, - pathMatch: "full", + pathMatch: 'full', }, { - path: RouteNames.TUTORIAL + "/" + RouteNames.WALLET + "/:username", + path: RouteNames.TUTORIAL + '/' + RouteNames.WALLET + '/:username', component: WalletTutorialPageComponent, - pathMatch: "full", + pathMatch: 'full', }, { - path: RouteNames.TUTORIAL + "/" + RouteNames.DIAMONDS, + path: RouteNames.TUTORIAL + '/' + RouteNames.DIAMONDS, component: DiamondTutorialPageComponent, - pathMatch: "full", + pathMatch: 'full', }, { - path: RouteNames.TUTORIAL + "/" + RouteNames.CREATE_POST, + path: RouteNames.TUTORIAL + '/' + RouteNames.CREATE_POST, component: CreatePostTutorialPageComponent, - pathMatch: "full", + pathMatch: 'full', }, { path: RouteNames.SUPPLY_STATS, component: SupplyMonitoringStatsPageComponent, - pathMatch: "full", + pathMatch: 'full', }, // This NotFound route must be the last one as it catches all paths that were not matched above. - { path: "**", component: NotFoundPageComponent, pathMatch: "full" }, + { path: '**', component: NotFoundPageComponent, pathMatch: 'full' }, ]; @NgModule({ @@ -182,46 +276,61 @@ class AppRoutingModule { // we need the 100ms delay because it takes a hot sec to re-render the feed // angular doesn't handle scroll resuming correctly: https://github.com/angular/angular/issues/24547 constructor(router: Router, viewportScroller: ViewportScroller) { - router.events.pipe(filter((e): e is Scroll => e instanceof Scroll)).subscribe((e) => { - if (e.position) { - // backward navigation - setTimeout(() => viewportScroller.scrollToPosition(e.position), 100); - } else if (e.anchor) { - // anchor navigation - setTimeout(() => viewportScroller.scrollToAnchor(e.anchor), 100); - } else { - // forward navigation - setTimeout(() => viewportScroller.scrollToPosition([0, 0]), 100); - } - }); + router.events + .pipe(filter((e): e is Scroll => e instanceof Scroll)) + .subscribe((e) => { + if (e.position) { + // backward navigation + setTimeout(() => viewportScroller.scrollToPosition(e.position), 100); + } else if (e.anchor) { + // anchor navigation + setTimeout(() => viewportScroller.scrollToAnchor(e.anchor), 100); + } else { + // forward navigation + setTimeout(() => viewportScroller.scrollToPosition([0, 0]), 100); + } + }); } static transferCreatorPath(username: string): string { - return ["", RouteNames.USER_PREFIX, username, RouteNames.TRANSFER_CREATOR].join("/"); + return [ + '', + RouteNames.USER_PREFIX, + username, + RouteNames.TRANSFER_CREATOR, + ].join('/'); } static buyCreatorPath(username: string): string { - return ["", RouteNames.USER_PREFIX, username, RouteNames.BUY_CREATOR].join("/"); + return ['', RouteNames.USER_PREFIX, username, RouteNames.BUY_CREATOR].join( + '/' + ); } static sellCreatorPath(username: string): string { - return ["", RouteNames.USER_PREFIX, username, RouteNames.SELL_CREATOR].join("/"); + return ['', RouteNames.USER_PREFIX, username, RouteNames.SELL_CREATOR].join( + '/' + ); } static profilePath(username: string): string { - return ["", RouteNames.USER_PREFIX, username].join("/"); + return ['', RouteNames.USER_PREFIX, username].join('/'); } static userFollowingPath(username: string): string { - return ["", RouteNames.USER_PREFIX, username, RouteNames.FOLLOWING].join("/"); + return ['', RouteNames.USER_PREFIX, username, RouteNames.FOLLOWING].join( + '/' + ); } static userFollowersPath(username: string): string { - return ["", RouteNames.USER_PREFIX, username, RouteNames.FOLLOWERS].join("/"); + return ['', RouteNames.USER_PREFIX, username, RouteNames.FOLLOWERS].join( + '/' + ); } static postPath(postHashHex: string): string { - return ["", RouteNames.POSTS, postHashHex].join("/"); + return ['', RouteNames.POSTS, postHashHex].join('/'); } } diff --git a/src/app/app.component.html b/src/app/app.component.html index e43e989c4..3a7f19ce4 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -19,7 +19,9 @@ class="main global__container" [ngClass]="globalVars.userIsDragging ? 'unselectable' : ''" *ngIf="!globalVars.requestingStorageAccess" - > +> - +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index c32a08bd4..bf7f313d8 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,18 +1,23 @@ -import { ChangeDetectorRef, Component, HostListener, OnInit } from "@angular/core"; -import { BackendApiService, TutorialStatus, User } from "./backend-api.service"; -import { GlobalVarsService } from "./global-vars.service"; -import { ActivatedRoute, Router } from "@angular/router"; -import { IdentityService } from "./identity.service"; -import * as _ from "lodash"; -import { environment } from "../environments/environment"; -import { ThemeService } from "./theme/theme.service"; -import { of, Subscription, zip } from "rxjs"; -import { catchError } from "rxjs/operators"; +import { + ChangeDetectorRef, + Component, + HostListener, + OnInit, +} from '@angular/core'; +import { BackendApiService, TutorialStatus, User } from './backend-api.service'; +import { GlobalVarsService } from './global-vars.service'; +import { ActivatedRoute, Router } from '@angular/router'; +import { IdentityService } from './identity.service'; +import * as _ from 'lodash'; +import { environment } from '../environments/environment'; +import { ThemeService } from './theme/theme.service'; +import { of, Subscription, zip } from 'rxjs'; +import { catchError } from 'rxjs/operators'; @Component({ - selector: "app-root", - templateUrl: "./app.component.html", - styleUrls: ["./app.component.scss"], + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], }) export class AppComponent implements OnInit { constructor( @@ -37,22 +42,23 @@ export class AppComponent implements OnInit { // // TODO: I'm pretty sure all of this could fail on IE so we should make sure people // only use the app with chrome. - Object.defineProperty(document, "referrer", { + Object.defineProperty(document, 'referrer', { get() { - return ""; + return ''; }, }); - Object.defineProperty(document, "referer", { + Object.defineProperty(document, 'referer', { get() { - return ""; + return ''; }, }); } - static DYNAMICALLY_ADDED_ROUTER_LINK_CLASS = "js-app-component__dynamically-added-router-link-class"; + static DYNAMICALLY_ADDED_ROUTER_LINK_CLASS = + 'js-app-component__dynamically-added-router-link-class'; showUsernameTooltip = false; - desoToUSDExchangeRateToDisplay = "fetching..."; + desoToUSDExchangeRateToDisplay = 'fetching...'; // Throttle the calls to update the top-level data so they only happen after a // previous call has finished. @@ -64,23 +70,25 @@ export class AppComponent implements OnInit { // This is used to add router links dynamically. Feed posts use this // to turn @-mentions into links. // See https://stackoverflow.com/a/62783788 for more info - @HostListener("document:click", ["$event"]) + @HostListener('document:click', ['$event']) public handleClick(event: Event): void { if (event.target instanceof HTMLAnchorElement) { const element = event.target as HTMLAnchorElement; - if (element.className === AppComponent.DYNAMICALLY_ADDED_ROUTER_LINK_CLASS) { + if ( + element.className === AppComponent.DYNAMICALLY_ADDED_ROUTER_LINK_CLASS + ) { event.preventDefault(); if (!element) { return; } - const route = element.getAttribute("href"); + const route = element.getAttribute('href'); if (route) { // FYI, this seems to give a js error if the route isn't in our list // of routes, which should help prevent attackers from tricking users into // clicking misleading links - this.router.navigate([route], { queryParamsHandling: "merge" }); + this.router.navigate([route], { queryParamsHandling: 'merge' }); } } } @@ -106,21 +114,32 @@ export class AppComponent implements OnInit { // If we recently added a new public key, log in the user and clear the value if (this.identityService.identityServicePublicKeyAdded) { - loggedInUserPublicKey = this.identityService.identityServicePublicKeyAdded; + loggedInUserPublicKey = this.identityService + .identityServicePublicKeyAdded; this.identityService.identityServicePublicKeyAdded = null; } this.callingUpdateTopLevelData = true; return zip( - this.backendApi.GetUsersStateless(this.globalVars.localNode, [loggedInUserPublicKey], false), - environment.verificationEndpointHostname && !_.isNil(loggedInUserPublicKey) - ? this.backendApi.GetUserMetadata(environment.verificationEndpointHostname, loggedInUserPublicKey).pipe( - catchError((err) => { - console.error(err); - return of(null); - }) - ) + this.backendApi.GetUsersStateless( + this.globalVars.localNode, + [loggedInUserPublicKey], + false + ), + environment.verificationEndpointHostname && + !_.isNil(loggedInUserPublicKey) + ? this.backendApi + .GetUserMetadata( + environment.verificationEndpointHostname, + loggedInUserPublicKey + ) + .pipe( + catchError((err) => { + console.error(err); + return of(null); + }) + ) : of(null) ).subscribe( ([res, userMetadata]) => { @@ -147,7 +166,10 @@ export class AppComponent implements OnInit { loggedInUser.JumioFinishedTime = userMetadata.JumioFinishedTime; loggedInUser.JumioReturned = userMetadata.JumioReturned; // We can merge the blocked public key maps, which means we effectively block the union of public keys from both endpoints. - loggedInUser.BlockedPubKeys = { ...loggedInUser.BlockedPubKeys, ...userMetadata.BlockedPubKeys }; + loggedInUser.BlockedPubKeys = { + ...loggedInUser.BlockedPubKeys, + ...userMetadata.BlockedPubKeys, + }; // Even though we have EmailVerified and HasEmail, we don't overwrite email attributes since each app may want to gather emails on their own. } @@ -156,7 +178,10 @@ export class AppComponent implements OnInit { this.globalVars.userList.push(loggedInUser); } // Only call setLoggedInUser if logged in user has changed. - if (!_.isEqual(this.globalVars.loggedInUser, loggedInUser) && loggedInUserPublicKey) { + if ( + !_.isEqual(this.globalVars.loggedInUser, loggedInUser) && + loggedInUserPublicKey + ) { this.globalVars.setLoggedInUser(loggedInUser); } @@ -172,7 +197,8 @@ export class AppComponent implements OnInit { } if (res.DefaultFeeRateNanosPerKB > 0) { - this.globalVars.defaultFeeRateNanosPerKB = res.DefaultFeeRateNanosPerKB; + this.globalVars.defaultFeeRateNanosPerKB = + res.DefaultFeeRateNanosPerKB; } this.globalVars.paramUpdaters = res.ParamUpdaters; @@ -194,9 +220,13 @@ export class AppComponent implements OnInit { _updateAppState() { this.backendApi - .GetAppState(this.globalVars.localNode, this.globalVars.loggedInUser?.PublicKeyBase58Check) + .GetAppState( + this.globalVars.localNode, + this.globalVars.loggedInUser?.PublicKeyBase58Check + ) .subscribe((res: any) => { - this.globalVars.minSatoshisBurnedForProfileCreation = res.MinSatoshisBurnedForProfileCreation; + this.globalVars.minSatoshisBurnedForProfileCreation = + res.MinSatoshisBurnedForProfileCreation; this.globalVars.diamondLevelMap = res.DiamondLevelMap; this.globalVars.showBuyWithUSD = res.HasWyreIntegration; this.globalVars.showBuyWithETH = res.BuyWithETH; @@ -206,9 +236,12 @@ export class AppComponent implements OnInit { this.globalVars.jumioKickbackUSDCents = res.JumioKickbackUSDCents; this.globalVars.isTestnet = res.IsTestnet; this.identityService.isTestnet = res.IsTestnet; - this.globalVars.showPhoneNumberVerification = res.HasTwilioAPIKey && res.HasStarterDeSoSeed; + this.globalVars.showPhoneNumberVerification = + res.HasTwilioAPIKey && res.HasStarterDeSoSeed; this.globalVars.createProfileFeeNanos = res.CreateProfileFeeNanos; - this.globalVars.isCompProfileCreation = this.globalVars.showPhoneNumberVerification && res.CompProfileCreation; + this.globalVars.isCompProfileCreation = + this.globalVars.showPhoneNumberVerification && + res.CompProfileCreation; this.globalVars.buyETHAddress = res.BuyETHAddress; this.globalVars.nodes = res.Nodes; @@ -216,7 +249,9 @@ export class AppComponent implements OnInit { // Calculate max fee for display in frontend // Sort so highest fee is at the top - const simpleFeeMap: { txnType: string; fees: number }[] = Object.keys(res.TransactionFeeMap) + const simpleFeeMap: { txnType: string; fees: number }[] = Object.keys( + res.TransactionFeeMap + ) .map((k) => { if (res.TransactionFeeMap[k] !== null) { // only return for non empty transactions @@ -225,10 +260,13 @@ export class AppComponent implements OnInit { .map((f) => f.AmountNanos) .reduce((partial_sum, a) => partial_sum + a, 0); // Capitalize and use spaces in Txn type - const txnType = (" " + k) - .replace(/_/g, " ") + const txnType = (' ' + k) + .replace(/_/g, ' ') .toLowerCase() - .replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => " " + chr.toUpperCase()) + .replace( + /[^a-zA-Z0-9]+(.)/g, + (m, chr) => ' ' + chr.toUpperCase() + ) .trim(); return { txnType: txnType, fees: sumOfFees }; } @@ -237,23 +275,27 @@ export class AppComponent implements OnInit { .sort((a, b) => b.fees - a.fees); //Get the max of all fees - this.globalVars.transactionFeeMax = Math.max(...simpleFeeMap.map((k) => k.fees)); + this.globalVars.transactionFeeMax = Math.max( + ...simpleFeeMap.map((k) => k.fees) + ); //Prepare text detailed info of fees and join with newlines this.globalVars.transactionFeeInfo = simpleFeeMap .map((k) => `${k.txnType}: ${this.globalVars.nanosToUSD(k.fees, 4)}`) - .join("\n"); + .join('\n'); }); } _updateEverything = ( - waitTxn: string = "", + waitTxn: string = '', successCallback: (comp: any) => void = () => {}, errorCallback: (comp: any) => void = () => {}, - comp: any = "" + comp: any = '' ) => { // Refresh the messageMeta periodically. - this.globalVars.messageMeta = this.backendApi.GetStorage(this.backendApi.MessageMetaKey); + this.globalVars.messageMeta = this.backendApi.GetStorage( + this.backendApi.MessageMetaKey + ); if (!this.globalVars.messageMeta) { this.globalVars.messageMeta = { decryptedMessgesMap: {}, @@ -263,7 +305,7 @@ export class AppComponent implements OnInit { // If we have a transaction to wait for, we do a GetTxn call for a maximum of 10s (250ms * 40). // There is a success and error callback so that the caller gets feedback on the polling. - if (waitTxn !== "") { + if (waitTxn !== '') { let attempts = 0; let numTries = 160; let timeoutMillis = 750; @@ -330,7 +372,9 @@ export class AppComponent implements OnInit { return; } - const isLoggedIn = this.backendApi.GetStorage(this.backendApi.LastLoggedInUserKey); + const isLoggedIn = this.backendApi.GetStorage( + this.backendApi.LastLoggedInUserKey + ); if (res.hasStorageAccess || !isLoggedIn) { this.loadApp(); } else { @@ -347,7 +391,8 @@ export class AppComponent implements OnInit { } loadApp() { - this.identityService.identityServiceUsers = this.backendApi.GetStorage(this.backendApi.IdentityUsersKey) || {}; + this.identityService.identityServiceUsers = + this.backendApi.GetStorage(this.backendApi.IdentityUsersKey) || {}; // Filter out invalid public keys const publicKeys = Object.keys(this.identityService.identityServiceUsers); for (const publicKey of publicKeys) { @@ -355,14 +400,19 @@ export class AppComponent implements OnInit { delete this.identityService.identityServiceUsers[publicKey]; } } - this.backendApi.SetStorage(this.backendApi.IdentityUsersKey, this.identityService.identityServiceUsers); + this.backendApi.SetStorage( + this.backendApi.IdentityUsersKey, + this.identityService.identityServiceUsers + ); - this.backendApi.GetUsersStateless(this.globalVars.localNode, publicKeys, true).subscribe((res) => { - if (!_.isEqual(this.globalVars.userList, res.UserList)) { - this.globalVars.userList = res.UserList || []; - } - this.globalVars.updateEverything(); - }); + this.backendApi + .GetUsersStateless(this.globalVars.localNode, publicKeys, true) + .subscribe((res) => { + if (!_.isEqual(this.globalVars.userList, res.UserList)) { + this.globalVars.userList = res.UserList || []; + } + this.globalVars.updateEverything(); + }); // Clean up legacy seedinfo storage. only called when a user visits the site again after a successful import this.backendApi.DeleteIdentities(this.globalVars.localNode).subscribe(); @@ -381,8 +431,8 @@ export class AppComponent implements OnInit { // @ts-ignore window.ddoptions = { ajaxListenerPath, endpoint }; - const datadomeScript = document.createElement("script"); - const firstScript = document.getElementsByTagName("script")[0]; + const datadomeScript = document.createElement('script'); + const firstScript = document.getElementsByTagName('script')[0]; datadomeScript.async = true; datadomeScript.src = jsPath; firstScript.parentNode.insertBefore(datadomeScript, firstScript); @@ -394,13 +444,13 @@ export class AppComponent implements OnInit { return; } - this.globalVars.amplitude = require("amplitude-js"); + this.globalVars.amplitude = require('amplitude-js'); this.globalVars.amplitude.init(key, null, { apiEndpoint: domain, }); // Track initial app load event so we are aware of every user // who visits our site (and not just those who click a button) - this.globalVars.logEvent("app : load"); + this.globalVars.logEvent('app : load'); } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index acbc0fee1..80eaf0228 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,183 +1,183 @@ -import { BrowserModule } from "@angular/platform-browser"; -import { NgModule } from "@angular/core"; -import { FormsModule, ReactiveFormsModule } from "@angular/forms"; -import { MatSelectModule } from "@angular/material/select"; -import { MatFormFieldModule } from "@angular/material/form-field"; -import { MatProgressBarModule } from "@angular/material/progress-bar"; -import { HttpClientModule } from "@angular/common/http"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { TextFieldModule } from "@angular/cdk/text-field"; +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatSelectModule } from '@angular/material/select'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { HttpClientModule } from '@angular/common/http'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { TextFieldModule } from '@angular/cdk/text-field'; -import { AppRoutingModule } from "./app-routing.module"; -import { AppComponent } from "./app.component"; -import { BackendApiService } from "./backend-api.service"; -import { GlobalVarsService } from "./global-vars.service"; -import { IdentityService } from "./identity.service"; -import { TermsOfServiceComponent } from "./terms-of-service/terms-of-service.component"; -import { ManageFollowsComponent } from "./manage-follows-page/manage-follows/manage-follows.component"; -import { ManageFollowsPageComponent } from "./manage-follows-page/manage-follows-page.component"; -import { FollowButtonComponent } from "./follow-button/follow-button.component"; -import { NotFoundPageComponent } from "./not-found-page/not-found-page.component"; -import { BrowsePageComponent } from "./browse-page/browse-page.component"; -import { FeedComponent } from "./feed/feed.component"; -import { LeftBarComponent } from "./left-bar/left-bar.component"; -import { RightBarCreatorsComponent } from "./right-bar-creators/right-bar-creators.component"; -import { FeedCreatePostComponent } from "./feed/feed-create-post/feed-create-post.component"; -import { FeedPostComponent } from "./feed/feed-post/feed-post.component"; -import { FeedPostDropdownComponent } from "./feed/feed-post-dropdown/feed-post-dropdown.component"; -import { FeedPostIconRowComponent } from "./feed/feed-post-icon-row/feed-post-icon-row.component"; -import { CreatorsLeaderboardPageComponent } from "./creators-leaderboard/creators-leaderboard-page/creators-leaderboard-page.component"; -import { CreatorsLeaderboardComponent } from "./creators-leaderboard/creators-leaderboard/creators-leaderboard.component"; -import { BuyDeSoPageComponent } from "./buy-deso-page/buy-deso-page.component"; -import { MessagesPageComponent } from "./messages-page/messages-page.component"; -import { SettingsPageComponent } from "./settings-page/settings-page.component"; -import { CreatorProfilePageComponent } from "./creator-profile-page/creator-profile-page.component"; -import { CreatorProfileDetailsComponent } from "./creator-profile-page/creator-profile-details/creator-profile-details.component"; -import { CreatorProfileHodlersComponent } from "./creator-profile-page/creator-profile-hodlers/creator-profile-hodlers.component"; -import { CreatorProfilePostsComponent } from "./creator-profile-page/creator-profile-posts/creator-profile-posts.component"; -import { TabSelectorComponent } from "./tab-selector/tab-selector.component"; -import { CreatorProfileTopCardComponent } from "./creator-profile-page/creator-profile-top-card/creator-profile-top-card.component"; -import { LeftBarButtonComponent } from "./left-bar/left-bar-button/left-bar-button.component"; -import { TradeCreatorPageComponent } from "./trade-creator-page/trade-creator-page.component"; -import { TradeCreatorComponent } from "./trade-creator-page/trade-creator/trade-creator.component"; -import { BuyDeSoComponent } from "./buy-deso-page/buy-deso/buy-deso.component"; -import { BuyDeSoUSDComponent } from "./buy-deso-page/buy-deso-usd/buy-deso-usd.component"; -import { TradeCreatorFormComponent } from "./trade-creator-page/trade-creator-form/trade-creator-form.component"; -import { TradeCreatorPreviewComponent } from "./trade-creator-page/trade-creator-preview/trade-creator-preview.component"; -import { TradeCreatorCompleteComponent } from "./trade-creator-page/trade-creator-complete/trade-creator-complete.component"; -import { UpdateProfilePageComponent } from "./update-profile-page/update-profile-page.component"; -import { NotificationsPageComponent } from "./notifications-page/notifications-page.component"; -import { SearchBarComponent } from "./search-bar/search-bar.component"; -import { SimpleCenterLoaderComponent } from "./simple-center-loader/simple-center-loader.component"; -import { ChangeAccountSelectorComponent } from "./change-account-selector/change-account-selector.component"; -import { RightBarSignupComponent } from "./right-bar-signup/right-bar-signup.component"; -import { TradeCreatorTableComponent } from "./trade-creator-page/trade-creator-table/trade-creator-table.component"; -import { PostThreadPageComponent } from "./post-thread-page/post-thread-page.component"; -import { PostThreadComponent } from "./post-thread-page/post-thread/post-thread.component"; -import { UpdateProfileComponent } from "./update-profile-page/update-profile/update-profile.component"; -import { RightBarCreatorsLeaderboardComponent } from "./right-bar-creators/right-bar-creators-leaderboard/right-bar-creators-leaderboard.component"; -import { BottomBarMobileComponent } from "./bottom-bar-mobile/bottom-bar-mobile.component"; -import { LeftBarMobileComponent } from "./left-bar-mobile/left-bar-mobile.component"; -import { TransferDeSoPageComponent } from "./transfer-deso-page/transfer-deso-page.component"; -import { TransferDeSoComponent } from "./transfer-deso/transfer-deso.component"; -import { BuyDeSoLoggedOutComponent } from "./buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component"; -import { BuyDeSoCompleteComponent } from "./buy-deso-page/buy-deso-complete/buy-deso-complete.component"; -import { MessagesInboxComponent } from "./messages-page/messages-inbox/messages-inbox.component"; -import { MessagesThreadComponent } from "./messages-page/messages-thread/messages-thread.component"; -import { MessageComponent } from "./messages-page/message/message.component"; -import { MessagesThreadViewComponent } from "./messages-page/messages-thread-view/messages-thread-view.component"; -import { TopBarMobileNavigationControlComponent } from "./top-bar-mobile/top-bar-mobile-navigation-control/top-bar-mobile-navigation-control.component"; -import { BottomBarMobileTabComponent } from "./bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component"; -import { NotFoundComponent } from "./not-found-page/not-found/not-found.component"; -import { CreatePostPageComponent } from "./create-post-page/create-post-page.component"; -import { CreatePostFormComponent } from "./create-post-page/create-post-form/create-post-form.component"; -import { TopBarMobileLogInOrSignUpComponent } from "./top-bar-mobile/top-bar-mobile-log-in-or-sign-up/top-bar-mobile-log-in-or-sign-up.component"; -import { TopBarMobileHamburgerMenuComponent } from "./top-bar-mobile/top-bar-mobile-hamburger-menu/top-bar-mobile-hamburger-menu.component"; -import { TradeCreatorLoggedOutComponent } from "./trade-creator-page/trade-creator-logged-out/trade-creator-logged-out.component"; -import { TosPageComponent } from "./tos-page/tos-page.component"; -import { MatTooltipModule } from "@angular/material/tooltip"; -import { AdminPageComponent } from "./admin-page/admin-page.component"; -import { AdminComponent } from "./admin/admin.component"; -import { AdminWyreComponent } from "./admin/admin-wyre/admin-wyre.component"; -import { NetworkInfoComponent } from "./network-info/network-info.component"; -import { SanitizeAndAutoLinkPipe } from "../lib/pipes/sanitize-and-auto-link-pipe"; -import { SanitizeEmbedPipe } from "../lib/pipes/sanitize-embed-pipe"; -import { SettingsComponent } from "./settings/settings.component"; -import { NotificationsListComponent } from "./notifications-page/notifications-list/notifications-list.component"; -import { UiScrollModule } from "ngx-ui-scroll"; -import { PageComponent } from "./page/page.component"; -import { BsModalService } from "ngx-bootstrap/modal"; -import { BsDropdownModule } from "ngx-bootstrap/dropdown"; -import { PopoverModule } from "ngx-bootstrap/popover"; -import { RatingModule } from "ngx-bootstrap/rating"; -import { BsDatepickerModule } from "ngx-bootstrap/datepicker"; -import { TimepickerModule } from "ngx-bootstrap/timepicker"; -import { CollapseModule } from "ngx-bootstrap/collapse"; -import { LandingPageComponent } from "./landing-page/landing-page.component"; -import { AnimateOnScrollModule } from "ng2-animate-on-scroll"; -import { SignUpGetStarterDeSoComponent } from "./sign-up/sign-up-get-starter-deso/sign-up-get-starter-deso.component"; -import { UpdateProfileGetStarterDeSoComponent } from "./update-profile-page/update-profile-get-starter-deso/update-profile-get-starter-deso.component"; -import { GetStarterDeSoPageComponent } from "./get-starter-deso-page/get-starter-deso-page.component"; -import { GetStarterDeSoComponent } from "./get-starter-deso-page/get-starter-deso/get-starter-deso.component"; -import { CommentModalComponent } from "./comment-modal/comment-modal.component"; -import { WalletComponent } from "./wallet/wallet.component"; -import { Toast, ToastrModule } from "ngx-toastr"; -import { SignUpComponent } from "./sign-up/sign-up.component"; -import { WalletActionsDropdownComponent } from "./wallet/wallet-actions-dropdown/wallet-actions-dropdown.component"; -import { PickACoinPageComponent } from "./pick-a-coin-page/pick-a-coin-page.component"; -import { DiamondsModalComponent } from "./diamonds-modal/diamonds-modal.component"; -import { RepostsModalComponent } from "./reposts-modal/reposts-modal.component"; -import { QuoteRepostsModalComponent } from "./quote-reposts-modal/quote-reposts-modal.component"; -import { LikesModalComponent } from "./likes-modal/likes-modal.component"; -import { SimpleProfileCardComponent } from "./simple-profile-card/simple-profile-card.component"; -import { CreatorDiamondsComponent } from "./creator-profile-page/creator-diamonds/creator-diamonds.component"; -import { DiamondPostsPageComponent } from "./diamond-posts-page/diamond-posts-page.component"; -import { DiamondPostsComponent } from "./diamond-posts-page/diamond-posts/diamond-posts.component"; -import { MessagesFilterMenuComponent } from "./messages-page/messages-inbox/messages-filter-menu/messages-filter-menu.component"; -import { CountdownTimerComponent } from "./countdown-timer/countdown-timer.component"; -import { AvatarDirective } from "./avatar/avatar.directive"; -import { TrendsPageComponent } from "./trends-page/trends-page.component"; -import { TrendsComponent } from "./trends-page/trends/trends.component"; -import { UploadDirective } from "./directives/upload.directive"; -import { SanitizeQRCodePipe } from "../lib/pipes/sanitize-qrcode-pipe"; -import { MintNftModalComponent } from "./mint-nft-modal/mint-nft-modal.component"; -import { CreateNftAuctionModalComponent } from "./create-nft-auction-modal/create-nft-auction-modal.component"; -import { BidPlacedModalComponent } from "./bid-placed-modal/bid-placed-modal.component"; -import { PlaceBidModalComponent } from "./place-bid-modal/place-bid-modal.component"; -import { NftSoldModalComponent } from "./nft-sold-modal/nft-sold-modal.component"; -import { NftModalHeaderComponent } from "./nft-modal-header/nft-modal-header.component"; -import { CloseNftAuctionModalComponent } from "./close-nft-auction-modal/close-nft-auction-modal.component"; -import { SellNftModalComponent } from "./sell-nft-modal/sell-nft-modal.component"; -import { AddUnlockableModalComponent } from "./add-unlockable-modal/add-unlockable-modal.component"; -import { NftPostPageComponent } from "./nft-post-page/nft-post-page.component"; -import { NftPostComponent } from "./nft-post-page/nft-post/nft-post.component"; -import { CreatorProfileNftsComponent } from "./creator-profile-page/creator-profile-nfts/creator-profile-nfts.component"; -import { NftDropMgrComponent } from "./nft-drop-mgr/nft-drop-mgr.component"; -import { NftShowcaseComponent } from "./nft-showcase/nft-showcase.component"; -import { VerifyEmailComponent } from "./verify-email/verify-email.component"; -import { AdminJumioComponent } from "./admin/admin-jumio/admin-jumio.component"; -import { AdminJumioEditCountrySignUpBonusComponent } from "./admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component"; -import { JumioStatusComponent } from "./jumio-status/jumio-status.component"; -import { AdminTutorialComponent } from "./admin/admin-tutorial/admin-tutorial.component"; -import { CreateProfileTutorialPageComponent } from "./tutorial/create-profile-tutorial-page/create-profile-tutorial-page.component"; -import { BuyCreatorCoinsTutorialComponent } from "./tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-tutorial/buy-creator-coins-tutorial.component"; -import { BuyCreatorCoinsTutorialPageComponent } from "./tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-tutorial-page.component"; -import { BuyCreatorCoinsConfirmTutorialComponent } from "./tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-confirm-tutorial/buy-creator-coins-confirm-tutorial.component"; -import { WalletPageComponent } from "./wallet/wallet-page/wallet-page.component"; -import { WalletTutorialPageComponent } from "./tutorial/wallet-tutorial-page/wallet-tutorial-page.component"; -import { SellCreatorCoinsTutorialComponent } from "./tutorial/sell-creator-coins-tutorial-page/sell-creator-coins-tutorial/sell-creator-coins-tutorial.component"; -import { DiamondTutorialPageComponent } from "./tutorial/diamond-tutorial-page/diamond-tutorial-page.component"; -import { DiamondTutorialComponent } from "./tutorial/diamond-tutorial-page/diamond-tutorial/diamond-tutorial.component"; -import { CreatePostTutorialPageComponent } from "./tutorial/create-post-tutorial-page/create-post-tutorial-page.component"; -import { DragDropModule } from "@angular/cdk/drag-drop"; -import { ReferralProgramMgrComponent } from "./referral-program-mgr/referral-program-mgr.component"; -import { ReferralsComponent } from "./referrals/referrals.component"; -import { BuyDeSoEthComponent } from "./buy-deso-page/buy-deso-eth/buy-deso-eth.component"; -import { SanitizeVideoUrlPipe } from "../lib/pipes/sanitize-video-url-pipe"; -import { AdminNodeFeesComponent } from "./admin/admin-node-fees/admin-node-fees.component"; -import { AdminNodeAddFeesComponent } from "./admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component"; -import { FreeDesoMessageComponent } from "./free-deso-message/free-deso-message.component"; -import { SupplyMonitoringStatsPageComponent } from "./supply-monitoring-stats-page/supply-monitoring-stats-page.component"; -import { SupplyMonitoringStatsComponent } from "./supply-monitoring-stats-page/supply-monitoring-stats/supply-monitoring-stats.component"; -import { TransferNftModalComponent } from "./transfer-nft-modal/transfer-nft-modal.component"; -import { TransferNftAcceptModalComponent } from "./transfer-nft-accept-modal/transfer-nft-accept-modal.component"; -import { NftBurnModalComponent } from "./nft-burn-modal/nft-burn-modal.component"; -import { NftSelectSerialNumberComponent } from "./nft-select-serial-number/nft-select-serial-number.component"; -import { DaoCoinsComponent } from "./dao-coins/dao-coins.component"; -import { DaoCoinsPageComponent } from "./dao-coins/dao-coins-page/dao-coins-page.component"; -import { TransferDAOCoinModalComponent } from "./dao-coins/transfer-dao-coin-modal/transfer-dao-coin-modal.component"; -import { BurnDaoCoinModalComponent } from "./dao-coins/burn-dao-coin-modal/burn-dao-coin-modal.component"; +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; +import { BackendApiService } from './backend-api.service'; +import { GlobalVarsService } from './global-vars.service'; +import { IdentityService } from './identity.service'; +import { TermsOfServiceComponent } from './terms-of-service/terms-of-service.component'; +import { ManageFollowsComponent } from './manage-follows-page/manage-follows/manage-follows.component'; +import { ManageFollowsPageComponent } from './manage-follows-page/manage-follows-page.component'; +import { FollowButtonComponent } from './follow-button/follow-button.component'; +import { NotFoundPageComponent } from './not-found-page/not-found-page.component'; +import { BrowsePageComponent } from './browse-page/browse-page.component'; +import { FeedComponent } from './feed/feed.component'; +import { LeftBarComponent } from './left-bar/left-bar.component'; +import { RightBarCreatorsComponent } from './right-bar-creators/right-bar-creators.component'; +import { FeedCreatePostComponent } from './feed/feed-create-post/feed-create-post.component'; +import { FeedPostComponent } from './feed/feed-post/feed-post.component'; +import { FeedPostDropdownComponent } from './feed/feed-post-dropdown/feed-post-dropdown.component'; +import { FeedPostIconRowComponent } from './feed/feed-post-icon-row/feed-post-icon-row.component'; +import { CreatorsLeaderboardPageComponent } from './creators-leaderboard/creators-leaderboard-page/creators-leaderboard-page.component'; +import { CreatorsLeaderboardComponent } from './creators-leaderboard/creators-leaderboard/creators-leaderboard.component'; +import { BuyDeSoPageComponent } from './buy-deso-page/buy-deso-page.component'; +import { MessagesPageComponent } from './messages-page/messages-page.component'; +import { SettingsPageComponent } from './settings-page/settings-page.component'; +import { CreatorProfilePageComponent } from './creator-profile-page/creator-profile-page.component'; +import { CreatorProfileDetailsComponent } from './creator-profile-page/creator-profile-details/creator-profile-details.component'; +import { CreatorProfileHodlersComponent } from './creator-profile-page/creator-profile-hodlers/creator-profile-hodlers.component'; +import { CreatorProfilePostsComponent } from './creator-profile-page/creator-profile-posts/creator-profile-posts.component'; +import { TabSelectorComponent } from './tab-selector/tab-selector.component'; +import { CreatorProfileTopCardComponent } from './creator-profile-page/creator-profile-top-card/creator-profile-top-card.component'; +import { LeftBarButtonComponent } from './left-bar/left-bar-button/left-bar-button.component'; +import { TradeCreatorPageComponent } from './trade-creator-page/trade-creator-page.component'; +import { TradeCreatorComponent } from './trade-creator-page/trade-creator/trade-creator.component'; +import { BuyDeSoComponent } from './buy-deso-page/buy-deso/buy-deso.component'; +import { BuyDeSoUSDComponent } from './buy-deso-page/buy-deso-usd/buy-deso-usd.component'; +import { TradeCreatorFormComponent } from './trade-creator-page/trade-creator-form/trade-creator-form.component'; +import { TradeCreatorPreviewComponent } from './trade-creator-page/trade-creator-preview/trade-creator-preview.component'; +import { TradeCreatorCompleteComponent } from './trade-creator-page/trade-creator-complete/trade-creator-complete.component'; +import { UpdateProfilePageComponent } from './update-profile-page/update-profile-page.component'; +import { NotificationsPageComponent } from './notifications-page/notifications-page.component'; +import { SearchBarComponent } from './search-bar/search-bar.component'; +import { SimpleCenterLoaderComponent } from './simple-center-loader/simple-center-loader.component'; +import { ChangeAccountSelectorComponent } from './change-account-selector/change-account-selector.component'; +import { RightBarSignupComponent } from './right-bar-signup/right-bar-signup.component'; +import { TradeCreatorTableComponent } from './trade-creator-page/trade-creator-table/trade-creator-table.component'; +import { PostThreadPageComponent } from './post-thread-page/post-thread-page.component'; +import { PostThreadComponent } from './post-thread-page/post-thread/post-thread.component'; +import { UpdateProfileComponent } from './update-profile-page/update-profile/update-profile.component'; +import { RightBarCreatorsLeaderboardComponent } from './right-bar-creators/right-bar-creators-leaderboard/right-bar-creators-leaderboard.component'; +import { BottomBarMobileComponent } from './bottom-bar-mobile/bottom-bar-mobile.component'; +import { LeftBarMobileComponent } from './left-bar-mobile/left-bar-mobile.component'; +import { TransferDeSoPageComponent } from './transfer-deso-page/transfer-deso-page.component'; +import { TransferDeSoComponent } from './transfer-deso/transfer-deso.component'; +import { BuyDeSoLoggedOutComponent } from './buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component'; +import { BuyDeSoCompleteComponent } from './buy-deso-page/buy-deso-complete/buy-deso-complete.component'; +import { MessagesInboxComponent } from './messages-page/messages-inbox/messages-inbox.component'; +import { MessagesThreadComponent } from './messages-page/messages-thread/messages-thread.component'; +import { MessageComponent } from './messages-page/message/message.component'; +import { MessagesThreadViewComponent } from './messages-page/messages-thread-view/messages-thread-view.component'; +import { TopBarMobileNavigationControlComponent } from './top-bar-mobile/top-bar-mobile-navigation-control/top-bar-mobile-navigation-control.component'; +import { BottomBarMobileTabComponent } from './bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component'; +import { NotFoundComponent } from './not-found-page/not-found/not-found.component'; +import { CreatePostPageComponent } from './create-post-page/create-post-page.component'; +import { CreatePostFormComponent } from './create-post-page/create-post-form/create-post-form.component'; +import { TopBarMobileLogInOrSignUpComponent } from './top-bar-mobile/top-bar-mobile-log-in-or-sign-up/top-bar-mobile-log-in-or-sign-up.component'; +import { TopBarMobileHamburgerMenuComponent } from './top-bar-mobile/top-bar-mobile-hamburger-menu/top-bar-mobile-hamburger-menu.component'; +import { TradeCreatorLoggedOutComponent } from './trade-creator-page/trade-creator-logged-out/trade-creator-logged-out.component'; +import { TosPageComponent } from './tos-page/tos-page.component'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { AdminPageComponent } from './admin-page/admin-page.component'; +import { AdminComponent } from './admin/admin.component'; +import { AdminWyreComponent } from './admin/admin-wyre/admin-wyre.component'; +import { NetworkInfoComponent } from './network-info/network-info.component'; +import { SanitizeAndAutoLinkPipe } from '../lib/pipes/sanitize-and-auto-link-pipe'; +import { SanitizeEmbedPipe } from '../lib/pipes/sanitize-embed-pipe'; +import { SettingsComponent } from './settings/settings.component'; +import { NotificationsListComponent } from './notifications-page/notifications-list/notifications-list.component'; +import { UiScrollModule } from 'ngx-ui-scroll'; +import { PageComponent } from './page/page.component'; +import { BsModalService } from 'ngx-bootstrap/modal'; +import { BsDropdownModule } from 'ngx-bootstrap/dropdown'; +import { PopoverModule } from 'ngx-bootstrap/popover'; +import { RatingModule } from 'ngx-bootstrap/rating'; +import { BsDatepickerModule } from 'ngx-bootstrap/datepicker'; +import { TimepickerModule } from 'ngx-bootstrap/timepicker'; +import { CollapseModule } from 'ngx-bootstrap/collapse'; +import { LandingPageComponent } from './landing-page/landing-page.component'; +import { AnimateOnScrollModule } from 'ng2-animate-on-scroll'; +import { SignUpGetStarterDeSoComponent } from './sign-up/sign-up-get-starter-deso/sign-up-get-starter-deso.component'; +import { UpdateProfileGetStarterDeSoComponent } from './update-profile-page/update-profile-get-starter-deso/update-profile-get-starter-deso.component'; +import { GetStarterDeSoPageComponent } from './get-starter-deso-page/get-starter-deso-page.component'; +import { GetStarterDeSoComponent } from './get-starter-deso-page/get-starter-deso/get-starter-deso.component'; +import { CommentModalComponent } from './comment-modal/comment-modal.component'; +import { WalletComponent } from './wallet/wallet.component'; +import { Toast, ToastrModule } from 'ngx-toastr'; +import { SignUpComponent } from './sign-up/sign-up.component'; +import { WalletActionsDropdownComponent } from './wallet/wallet-actions-dropdown/wallet-actions-dropdown.component'; +import { PickACoinPageComponent } from './pick-a-coin-page/pick-a-coin-page.component'; +import { DiamondsModalComponent } from './diamonds-modal/diamonds-modal.component'; +import { RepostsModalComponent } from './reposts-modal/reposts-modal.component'; +import { QuoteRepostsModalComponent } from './quote-reposts-modal/quote-reposts-modal.component'; +import { LikesModalComponent } from './likes-modal/likes-modal.component'; +import { SimpleProfileCardComponent } from './simple-profile-card/simple-profile-card.component'; +import { CreatorDiamondsComponent } from './creator-profile-page/creator-diamonds/creator-diamonds.component'; +import { DiamondPostsPageComponent } from './diamond-posts-page/diamond-posts-page.component'; +import { DiamondPostsComponent } from './diamond-posts-page/diamond-posts/diamond-posts.component'; +import { MessagesFilterMenuComponent } from './messages-page/messages-inbox/messages-filter-menu/messages-filter-menu.component'; +import { CountdownTimerComponent } from './countdown-timer/countdown-timer.component'; +import { AvatarDirective } from './avatar/avatar.directive'; +import { TrendsPageComponent } from './trends-page/trends-page.component'; +import { TrendsComponent } from './trends-page/trends/trends.component'; +import { UploadDirective } from './directives/upload.directive'; +import { SanitizeQRCodePipe } from '../lib/pipes/sanitize-qrcode-pipe'; +import { MintNftModalComponent } from './mint-nft-modal/mint-nft-modal.component'; +import { CreateNftAuctionModalComponent } from './create-nft-auction-modal/create-nft-auction-modal.component'; +import { BidPlacedModalComponent } from './bid-placed-modal/bid-placed-modal.component'; +import { PlaceBidModalComponent } from './place-bid-modal/place-bid-modal.component'; +import { NftSoldModalComponent } from './nft-sold-modal/nft-sold-modal.component'; +import { NftModalHeaderComponent } from './nft-modal-header/nft-modal-header.component'; +import { CloseNftAuctionModalComponent } from './close-nft-auction-modal/close-nft-auction-modal.component'; +import { SellNftModalComponent } from './sell-nft-modal/sell-nft-modal.component'; +import { AddUnlockableModalComponent } from './add-unlockable-modal/add-unlockable-modal.component'; +import { NftPostPageComponent } from './nft-post-page/nft-post-page.component'; +import { NftPostComponent } from './nft-post-page/nft-post/nft-post.component'; +import { CreatorProfileNftsComponent } from './creator-profile-page/creator-profile-nfts/creator-profile-nfts.component'; +import { NftDropMgrComponent } from './nft-drop-mgr/nft-drop-mgr.component'; +import { NftShowcaseComponent } from './nft-showcase/nft-showcase.component'; +import { VerifyEmailComponent } from './verify-email/verify-email.component'; +import { AdminJumioComponent } from './admin/admin-jumio/admin-jumio.component'; +import { AdminJumioEditCountrySignUpBonusComponent } from './admin/admin-jumio/admin-jumio-edit-country-sign-up-bonus/admin-jumio-edit-country-sign-up-bonus.component'; +import { JumioStatusComponent } from './jumio-status/jumio-status.component'; +import { AdminTutorialComponent } from './admin/admin-tutorial/admin-tutorial.component'; +import { CreateProfileTutorialPageComponent } from './tutorial/create-profile-tutorial-page/create-profile-tutorial-page.component'; +import { BuyCreatorCoinsTutorialComponent } from './tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-tutorial/buy-creator-coins-tutorial.component'; +import { BuyCreatorCoinsTutorialPageComponent } from './tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-tutorial-page.component'; +import { BuyCreatorCoinsConfirmTutorialComponent } from './tutorial/buy-creator-coins-tutorial-page/buy-creator-coins-confirm-tutorial/buy-creator-coins-confirm-tutorial.component'; +import { WalletPageComponent } from './wallet/wallet-page/wallet-page.component'; +import { WalletTutorialPageComponent } from './tutorial/wallet-tutorial-page/wallet-tutorial-page.component'; +import { SellCreatorCoinsTutorialComponent } from './tutorial/sell-creator-coins-tutorial-page/sell-creator-coins-tutorial/sell-creator-coins-tutorial.component'; +import { DiamondTutorialPageComponent } from './tutorial/diamond-tutorial-page/diamond-tutorial-page.component'; +import { DiamondTutorialComponent } from './tutorial/diamond-tutorial-page/diamond-tutorial/diamond-tutorial.component'; +import { CreatePostTutorialPageComponent } from './tutorial/create-post-tutorial-page/create-post-tutorial-page.component'; +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { ReferralProgramMgrComponent } from './referral-program-mgr/referral-program-mgr.component'; +import { ReferralsComponent } from './referrals/referrals.component'; +import { BuyDeSoEthComponent } from './buy-deso-page/buy-deso-eth/buy-deso-eth.component'; +import { SanitizeVideoUrlPipe } from '../lib/pipes/sanitize-video-url-pipe'; +import { AdminNodeFeesComponent } from './admin/admin-node-fees/admin-node-fees.component'; +import { AdminNodeAddFeesComponent } from './admin/admin-node-fees/admin-node-add-fee/admin-node-add-fees.component'; +import { FreeDesoMessageComponent } from './free-deso-message/free-deso-message.component'; +import { SupplyMonitoringStatsPageComponent } from './supply-monitoring-stats-page/supply-monitoring-stats-page.component'; +import { SupplyMonitoringStatsComponent } from './supply-monitoring-stats-page/supply-monitoring-stats/supply-monitoring-stats.component'; +import { TransferNftModalComponent } from './transfer-nft-modal/transfer-nft-modal.component'; +import { TransferNftAcceptModalComponent } from './transfer-nft-accept-modal/transfer-nft-accept-modal.component'; +import { NftBurnModalComponent } from './nft-burn-modal/nft-burn-modal.component'; +import { NftSelectSerialNumberComponent } from './nft-select-serial-number/nft-select-serial-number.component'; +import { DaoCoinsComponent } from './dao-coins/dao-coins.component'; +import { DaoCoinsPageComponent } from './dao-coins/dao-coins-page/dao-coins-page.component'; +import { TransferDAOCoinModalComponent } from './dao-coins/transfer-dao-coin-modal/transfer-dao-coin-modal.component'; +import { BurnDaoCoinModalComponent } from './dao-coins/burn-dao-coin-modal/burn-dao-coin-modal.component'; // Modular Themes for DeSo by Carsen Klock @carsenk -import { ThemeModule } from "./theme/theme.module"; -import { Theme } from "./theme/symbols"; -import {PostMultiplierComponent} from "./feed/feed-post-dropdown/post-multiplier/post-multiplier.component"; -const lightTheme: Theme = { key: "light", name: "Light Theme" }; -const darkTheme: Theme = { key: "dark", name: "Dark Theme" }; -const icydarkTheme: Theme = { key: "icydark", name: "Icy Dark Theme" }; -const legendsTheme: Theme = { key: "legends", name: "Legends Theme" }; -const cakeTheme: Theme = { key: "cake", name: "Cake Theme" }; -const greenishTheme: Theme = { key: "greenish", name: "Green Theme" }; +import { ThemeModule } from './theme/theme.module'; +import { Theme } from './theme/symbols'; +import { PostMultiplierComponent } from './feed/feed-post-dropdown/post-multiplier/post-multiplier.component'; +const lightTheme: Theme = { key: 'light', name: 'Light Theme' }; +const darkTheme: Theme = { key: 'dark', name: 'Dark Theme' }; +const icydarkTheme: Theme = { key: 'icydark', name: 'Icy Dark Theme' }; +const legendsTheme: Theme = { key: 'legends', name: 'Legends Theme' }; +const cakeTheme: Theme = { key: 'cake', name: 'Cake Theme' }; +const greenishTheme: Theme = { key: 'greenish', name: 'Green Theme' }; @NgModule({ declarations: [ @@ -349,13 +349,27 @@ const greenishTheme: Theme = { key: "greenish", name: "Green Theme" }; TimepickerModule.forRoot(), CollapseModule.forRoot(), ThemeModule.forRoot({ - themes: [lightTheme, darkTheme, icydarkTheme, legendsTheme, cakeTheme, greenishTheme], + themes: [ + lightTheme, + darkTheme, + icydarkTheme, + legendsTheme, + cakeTheme, + greenishTheme, + ], active: - localStorage.getItem("theme") || - (window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark"), + localStorage.getItem('theme') || + (window.matchMedia('(prefers-color-scheme: light)').matches + ? 'light' + : 'dark'), }), ], - providers: [BackendApiService, GlobalVarsService, BsModalService, IdentityService], + providers: [ + BackendApiService, + GlobalVarsService, + BsModalService, + IdentityService, + ], bootstrap: [AppComponent], }) export class AppModule {} diff --git a/src/app/avatar/avatar.directive.ts b/src/app/avatar/avatar.directive.ts index e35223424..84a5a5d2d 100644 --- a/src/app/avatar/avatar.directive.ts +++ b/src/app/avatar/avatar.directive.ts @@ -1,27 +1,35 @@ -import { Directive, ElementRef, Input, OnChanges } from "@angular/core"; -import { GlobalVarsService } from "../global-vars.service"; -import { BackendApiService } from "../backend-api.service"; -import * as _ from "lodash"; +import { Directive, ElementRef, Input, OnChanges } from '@angular/core'; +import { GlobalVarsService } from '../global-vars.service'; +import { BackendApiService } from '../backend-api.service'; +import * as _ from 'lodash'; @Directive({ - selector: "[avatar]", + selector: '[avatar]', }) export class AvatarDirective implements OnChanges { - @Input() avatar: string = ""; + @Input() avatar: string = ''; - constructor(private globalVars: GlobalVarsService, private backendApi: BackendApiService, private el: ElementRef) {} + constructor( + private globalVars: GlobalVarsService, + private backendApi: BackendApiService, + private el: ElementRef + ) {} setAvatar() { if (!this.avatar) { - this.setURLOnElement(this.backendApi.GetDefaultProfilePictureURL(window.location.host)); + this.setURLOnElement( + this.backendApi.GetDefaultProfilePictureURL(window.location.host) + ); return; } // The fallback route is the route to the pic we use if we can't find an avatar for the user. - let fallbackRoute = `fallback=${this.backendApi.GetDefaultProfilePictureURL(window.location.host)}`; + let fallbackRoute = `fallback=${this.backendApi.GetDefaultProfilePictureURL( + window.location.host + )}`; // If fetching the avatar for the current user, use the last timestamp of profile update to bust // the cache so we get the updated avatar. - let cacheBuster = ""; + let cacheBuster = ''; if ( this.globalVars?.loggedInUser && this.avatar === this.globalVars.loggedInUser?.PublicKeyBase58Check && @@ -33,7 +41,11 @@ export class AvatarDirective implements OnChanges { // Although it would be hard for an attacker to inject a malformed public key into the app, // we do a basic _.escape anyways just to be extra safe. const profPicURL = _.escape( - this.backendApi.GetSingleProfilePictureURL(this.globalVars.localNode, this.avatar, fallbackRoute) + this.backendApi.GetSingleProfilePictureURL( + this.globalVars.localNode, + this.avatar, + fallbackRoute + ) ); // Set the URL on the element. diff --git a/src/app/backend-api.service.spec.ts b/src/app/backend-api.service.spec.ts index 67d356183..9150bb728 100644 --- a/src/app/backend-api.service.spec.ts +++ b/src/app/backend-api.service.spec.ts @@ -1,11 +1,11 @@ -import { TestBed } from "@angular/core/testing"; +import { TestBed } from '@angular/core/testing'; -import { BackendApiService } from "./backend-api.service"; +import { BackendApiService } from './backend-api.service'; -describe("BackendApiService", () => { +describe('BackendApiService', () => { beforeEach(() => TestBed.configureTestingModule({})); - it("should be created", () => { + it('should be created', () => { const service: BackendApiService = TestBed.inject(BackendApiService); expect(service).toBeTruthy(); }); diff --git a/src/app/backend-api.service.ts b/src/app/backend-api.service.ts index aa278a295..62136da54 100644 --- a/src/app/backend-api.service.ts +++ b/src/app/backend-api.service.ts @@ -2,179 +2,236 @@ // needs the seed phrase) needs the {withCredentials: true} option. It may also needed to // get the browser to save the cookie in the response. // https://github.com/github/fetch#sending-cookies -import { Injectable } from "@angular/core"; -import { interval, Observable, of, throwError, zip } from "rxjs"; -import { map, switchMap, catchError, filter, take, concatMap } from "rxjs/operators"; -import { HttpClient, HttpErrorResponse } from "@angular/common/http"; -import { IdentityService } from "./identity.service"; -import { environment } from "src/environments/environment"; -import { Hex } from "web3-utils/types"; +import { Injectable } from '@angular/core'; +import { interval, Observable, of, throwError, zip } from 'rxjs'; +import { + map, + switchMap, + catchError, + filter, + take, + concatMap, +} from 'rxjs/operators'; +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; +import { IdentityService } from './identity.service'; +import { environment } from 'src/environments/environment'; +import { Hex } from 'web3-utils/types'; export class BackendRoutes { - static ExchangeRateRoute = "/api/v0/get-exchange-rate"; - static ExchangeBitcoinRoute = "/api/v0/exchange-bitcoin"; - static SendDeSoRoute = "/api/v0/send-deso"; - static MinerControlRoute = "/api/v0/miner-control"; - - static GetUsersStatelessRoute = "/api/v0/get-users-stateless"; - static RoutePathSubmitPost = "/api/v0/submit-post"; - static RoutePathUploadImage = "/api/v0/upload-image"; - static RoutePathSubmitTransaction = "/api/v0/submit-transaction"; - static RoutePathUpdateProfile = "/api/v0/update-profile"; - static RoutePathGetPostsStateless = "/api/v0/get-posts-stateless"; - static RoutePathGetHotFeed = "/api/v0/get-hot-feed"; - static RoutePathGetProfiles = "/api/v0/get-profiles"; - static RoutePathGetSingleProfile = "/api/v0/get-single-profile"; - static RoutePathGetSingleProfilePicture = "/api/v0/get-single-profile-picture"; - static RoutePathGetPostsForPublicKey = "/api/v0/get-posts-for-public-key"; - static RoutePathGetDiamondedPosts = "/api/v0/get-diamonded-posts"; - static RoutePathGetHodlersForPublicKey = "/api/v0/get-hodlers-for-public-key"; - static RoutePathIsHodlingPublicKey = "/api/v0/is-hodling-public-key"; - static RoutePathSendMessageStateless = "/api/v0/send-message-stateless"; - static RoutePathGetMessagesStateless = "/api/v0/get-messages-stateless"; - static RoutePathCheckPartyMessagingKeys = "/api/v0/check-party-messaging-keys"; - static RoutePathMarkContactMessagesRead = "/api/v0/mark-contact-messages-read"; - static RoutePathMarkAllMessagesRead = "/api/v0/mark-all-messages-read"; - static RoutePathGetFollowsStateless = "/api/v0/get-follows-stateless"; - static RoutePathCreateFollowTxnStateless = "/api/v0/create-follow-txn-stateless"; - static RoutePathCreateLikeStateless = "/api/v0/create-like-stateless"; - static RoutePathBuyOrSellCreatorCoin = "/api/v0/buy-or-sell-creator-coin"; - static RoutePathTransferCreatorCoin = "/api/v0/transfer-creator-coin"; - static RoutePathUpdateUserGlobalMetadata = "/api/v0/update-user-global-metadata"; - static RoutePathGetUserGlobalMetadata = "/api/v0/get-user-global-metadata"; - static RoutePathGetNotifications = "/api/v0/get-notifications"; - static RoutePathGetAppState = "/api/v0/get-app-state"; - static RoutePathGetSinglePost = "/api/v0/get-single-post"; - static RoutePathSendPhoneNumberVerificationText = "/api/v0/send-phone-number-verification-text"; - static RoutePathSubmitPhoneNumberVerificationCode = "/api/v0/submit-phone-number-verification-code"; - static RoutePathBlockPublicKey = "/api/v0/block-public-key"; - static RoutePathGetBlockTemplate = "/api/v0/get-block-template"; - static RoutePathGetTxn = "/api/v0/get-txn"; - static RoutePathDeleteIdentities = "/api/v0/delete-identities"; - static RoutePathSendDiamonds = "/api/v0/send-diamonds"; - static RoutePathGetDiamondsForPublicKey = "/api/v0/get-diamonds-for-public-key"; - static RoutePathGetLikesForPost = "/api/v0/get-likes-for-post"; - static RoutePathGetDiamondsForPost = "/api/v0/get-diamonds-for-post"; - static RoutePathGetRepostsForPost = "/api/v0/get-reposts-for-post"; - static RoutePathGetQuoteRepostsForPost = "/api/v0/get-quote-reposts-for-post"; - static RoutePathGetJumioStatusForPublicKey = "/api/v0/get-jumio-status-for-public-key"; - static RoutePathGetUserMetadata = "/api/v0/get-user-metadata"; - static RoutePathGetUsernameForPublicKey = "/api/v0/get-user-name-for-public-key"; - static RoutePathGetPublicKeyForUsername = "/api/v0/get-public-key-for-user-name"; + static ExchangeRateRoute = '/api/v0/get-exchange-rate'; + static ExchangeBitcoinRoute = '/api/v0/exchange-bitcoin'; + static SendDeSoRoute = '/api/v0/send-deso'; + static MinerControlRoute = '/api/v0/miner-control'; + + static GetUsersStatelessRoute = '/api/v0/get-users-stateless'; + static RoutePathSubmitPost = '/api/v0/submit-post'; + static RoutePathUploadImage = '/api/v0/upload-image'; + static RoutePathSubmitTransaction = '/api/v0/submit-transaction'; + static RoutePathUpdateProfile = '/api/v0/update-profile'; + static RoutePathGetPostsStateless = '/api/v0/get-posts-stateless'; + static RoutePathGetHotFeed = '/api/v0/get-hot-feed'; + static RoutePathGetProfiles = '/api/v0/get-profiles'; + static RoutePathGetSingleProfile = '/api/v0/get-single-profile'; + static RoutePathGetSingleProfilePicture = + '/api/v0/get-single-profile-picture'; + static RoutePathGetPostsForPublicKey = '/api/v0/get-posts-for-public-key'; + static RoutePathGetDiamondedPosts = '/api/v0/get-diamonded-posts'; + static RoutePathGetHodlersForPublicKey = '/api/v0/get-hodlers-for-public-key'; + static RoutePathIsHodlingPublicKey = '/api/v0/is-hodling-public-key'; + static RoutePathSendMessageStateless = '/api/v0/send-message-stateless'; + static RoutePathGetMessagesStateless = '/api/v0/get-messages-stateless'; + static RoutePathCheckPartyMessagingKeys = + '/api/v0/check-party-messaging-keys'; + static RoutePathMarkContactMessagesRead = + '/api/v0/mark-contact-messages-read'; + static RoutePathMarkAllMessagesRead = '/api/v0/mark-all-messages-read'; + static RoutePathGetFollowsStateless = '/api/v0/get-follows-stateless'; + static RoutePathCreateFollowTxnStateless = + '/api/v0/create-follow-txn-stateless'; + static RoutePathCreateLikeStateless = '/api/v0/create-like-stateless'; + static RoutePathBuyOrSellCreatorCoin = '/api/v0/buy-or-sell-creator-coin'; + static RoutePathTransferCreatorCoin = '/api/v0/transfer-creator-coin'; + static RoutePathUpdateUserGlobalMetadata = + '/api/v0/update-user-global-metadata'; + static RoutePathGetUserGlobalMetadata = '/api/v0/get-user-global-metadata'; + static RoutePathGetNotifications = '/api/v0/get-notifications'; + static RoutePathGetAppState = '/api/v0/get-app-state'; + static RoutePathGetSinglePost = '/api/v0/get-single-post'; + static RoutePathSendPhoneNumberVerificationText = + '/api/v0/send-phone-number-verification-text'; + static RoutePathSubmitPhoneNumberVerificationCode = + '/api/v0/submit-phone-number-verification-code'; + static RoutePathBlockPublicKey = '/api/v0/block-public-key'; + static RoutePathGetBlockTemplate = '/api/v0/get-block-template'; + static RoutePathGetTxn = '/api/v0/get-txn'; + static RoutePathDeleteIdentities = '/api/v0/delete-identities'; + static RoutePathSendDiamonds = '/api/v0/send-diamonds'; + static RoutePathGetDiamondsForPublicKey = + '/api/v0/get-diamonds-for-public-key'; + static RoutePathGetLikesForPost = '/api/v0/get-likes-for-post'; + static RoutePathGetDiamondsForPost = '/api/v0/get-diamonds-for-post'; + static RoutePathGetRepostsForPost = '/api/v0/get-reposts-for-post'; + static RoutePathGetQuoteRepostsForPost = '/api/v0/get-quote-reposts-for-post'; + static RoutePathGetJumioStatusForPublicKey = + '/api/v0/get-jumio-status-for-public-key'; + static RoutePathGetUserMetadata = '/api/v0/get-user-metadata'; + static RoutePathGetUsernameForPublicKey = + '/api/v0/get-user-name-for-public-key'; + static RoutePathGetPublicKeyForUsername = + '/api/v0/get-public-key-for-user-name'; // Verify - static RoutePathVerifyEmail = "/api/v0/verify-email"; - static RoutePathResendVerifyEmail = "/api/v0/resend-verify-email"; + static RoutePathVerifyEmail = '/api/v0/verify-email'; + static RoutePathResendVerifyEmail = '/api/v0/resend-verify-email'; // Delete PII - static RoutePathDeletePII = "/api/v0/delete-pii"; + static RoutePathDeletePII = '/api/v0/delete-pii'; // Tutorial - static RoutePathStartOrSkipTutorial = "/api/v0/start-or-skip-tutorial"; - static RoutePathCompleteTutorial = "/api/v0/complete-tutorial"; - static RoutePathGetTutorialCreators = "/api/v0/get-tutorial-creators"; + static RoutePathStartOrSkipTutorial = '/api/v0/start-or-skip-tutorial'; + static RoutePathCompleteTutorial = '/api/v0/complete-tutorial'; + static RoutePathGetTutorialCreators = '/api/v0/get-tutorial-creators'; // Media - static RoutePathUploadVideo = "/api/v0/upload-video"; - static RoutePathGetVideoStatus = "/api/v0/get-video-status"; + static RoutePathUploadVideo = '/api/v0/upload-video'; + static RoutePathGetVideoStatus = '/api/v0/get-video-status'; // NFT routes. - static RoutePathCreateNft = "/api/v0/create-nft"; - static RoutePathUpdateNFT = "/api/v0/update-nft"; - static RoutePathCreateNFTBid = "/api/v0/create-nft-bid"; - static RoutePathAcceptNFTBid = "/api/v0/accept-nft-bid"; - static RoutePathGetNFTBidsForNFTPost = "/api/v0/get-nft-bids-for-nft-post"; - static RoutePathGetNFTsForUser = "/api/v0/get-nfts-for-user"; - static RoutePathGetNFTBidsForUser = "/api/v0/get-nft-bids-for-user"; - static RoutePathGetNFTShowcase = "/api/v0/get-nft-showcase"; - static RoutePathGetNextNFTShowcase = "/api/v0/get-next-nft-showcase"; - static RoutePathGetNFTCollectionSummary = "/api/v0/get-nft-collection-summary"; - static RoutePathGetNFTEntriesForPostHash = "/api/v0/get-nft-entries-for-nft-post"; - static RoutePathTransferNFT = "/api/v0/transfer-nft"; - static RoutePathAcceptNFTTransfer = "/api/v0/accept-nft-transfer"; - static RoutePathBurnNFT = "/api/v0/burn-nft"; + static RoutePathCreateNft = '/api/v0/create-nft'; + static RoutePathUpdateNFT = '/api/v0/update-nft'; + static RoutePathCreateNFTBid = '/api/v0/create-nft-bid'; + static RoutePathAcceptNFTBid = '/api/v0/accept-nft-bid'; + static RoutePathGetNFTBidsForNFTPost = '/api/v0/get-nft-bids-for-nft-post'; + static RoutePathGetNFTsForUser = '/api/v0/get-nfts-for-user'; + static RoutePathGetNFTBidsForUser = '/api/v0/get-nft-bids-for-user'; + static RoutePathGetNFTShowcase = '/api/v0/get-nft-showcase'; + static RoutePathGetNextNFTShowcase = '/api/v0/get-next-nft-showcase'; + static RoutePathGetNFTCollectionSummary = + '/api/v0/get-nft-collection-summary'; + static RoutePathGetNFTEntriesForPostHash = + '/api/v0/get-nft-entries-for-nft-post'; + static RoutePathTransferNFT = '/api/v0/transfer-nft'; + static RoutePathAcceptNFTTransfer = '/api/v0/accept-nft-transfer'; + static RoutePathBurnNFT = '/api/v0/burn-nft'; // DAO routes - static RoutePathDAOCoin = "/api/v0/dao-coin"; - static RoutePathTransferDAOCoin = "/api/v0/transfer-dao-coin"; + static RoutePathDAOCoin = '/api/v0/dao-coin'; + static RoutePathTransferDAOCoin = '/api/v0/transfer-dao-coin'; // ETH - static RoutePathSubmitETHTx = "/api/v0/submit-eth-tx"; - static RoutePathQueryETHRPC = "/api/v0/query-eth-rpc"; + static RoutePathSubmitETHTx = '/api/v0/submit-eth-tx'; + static RoutePathQueryETHRPC = '/api/v0/query-eth-rpc'; // Admin routes. - static NodeControlRoute = "/api/v0/admin/node-control"; - static ReprocessBitcoinBlockRoute = "/api/v0/admin/reprocess-bitcoin-block"; - static RoutePathSwapIdentity = "/api/v0/admin/swap-identity"; - static RoutePathAdminUpdateUserGlobalMetadata = "/api/v0/admin/update-user-global-metadata"; - static RoutePathAdminResetPhoneNumber = "/api/v0/admin/reset-phone-number"; - static RoutePathAdminGetAllUserGlobalMetadata = "/api/v0/admin/get-all-user-global-metadata"; - static RoutePathAdminGetUserGlobalMetadata = "/api/v0/admin/get-user-global-metadata"; - static RoutePathAdminUpdateGlobalFeed = "/api/v0/admin/update-global-feed"; - static RoutePathAdminPinPost = "/api/v0/admin/pin-post"; - static RoutePathAdminRemoveNilPosts = "/api/v0/admin/remove-nil-posts"; - static RoutePathAdminGetMempoolStats = "/api/v0/admin/get-mempool-stats"; - static RoutePathAdminGrantVerificationBadge = "/api/v0/admin/grant-verification-badge"; - static RoutePathAdminRemoveVerificationBadge = "/api/v0/admin/remove-verification-badge"; - static RoutePathAdminGetVerifiedUsers = "/api/v0/admin/get-verified-users"; - static RoutePathAdminGetUserAdminData = "/api/v0/admin/get-user-admin-data"; - static RoutePathAdminGetUsernameVerificationAuditLogs = "/api/v0/admin/get-username-verification-audit-logs"; - static RoutePathUpdateGlobalParams = "/api/v0/admin/update-global-params"; - static RoutePathSetUSDCentsToDeSoReserveExchangeRate = "/api/v0/admin/set-usd-cents-to-deso-reserve-exchange-rate"; - static RoutePathGetUSDCentsToDeSoReserveExchangeRate = "/api/v0/admin/get-usd-cents-to-deso-reserve-exchange-rate"; - static RoutePathSetBuyDeSoFeeBasisPoints = "/api/v0/admin/set-buy-deso-fee-basis-points"; - static RoutePathGetBuyDeSoFeeBasisPoints = "/api/v0/admin/get-buy-deso-fee-basis-points"; - static RoutePathAdminGetGlobalParams = "/api/v0/admin/get-global-params"; - static RoutePathGetGlobalParams = "/api/v0/get-global-params"; - static RoutePathEvictUnminedBitcoinTxns = "/api/v0/admin/evict-unmined-bitcoin-txns"; - static RoutePathGetWyreWalletOrdersForPublicKey = "/api/v0/admin/get-wyre-wallet-orders-for-public-key"; - static RoutePathAdminGetNFTDrop = "/api/v0/admin/get-nft-drop"; - static RoutePathAdminUpdateNFTDrop = "/api/v0/admin/update-nft-drop"; - static RoutePathAdminResetJumioForPublicKey = "/api/v0/admin/reset-jumio-for-public-key"; - static RoutePathAdminUpdateJumioDeSo = "/api/v0/admin/update-jumio-deso"; - static RoutePathAdminUpdateTutorialCreators = "/api/v0/admin/update-tutorial-creators"; - static RoutePathAdminResetTutorialStatus = "/api/v0/admin/reset-tutorial-status"; - static RoutePathAdminGetTutorialCreators = "/api/v0/admin/get-tutorial-creators"; - static RoutePathAdminJumioCallback = "/api/v0/admin/jumio-callback"; - static RoutePathAdminGetAllCountryLevelSignUpBonuses = "/api/v0/admin/get-all-country-level-sign-up-bonuses"; - static RoutePathAdminUpdateJumioCountrySignUpBonus = "/api/v0/admin/update-jumio-country-sign-up-bonus"; - static RoutePathAdminUpdateJumioUSDCents = "/api/v0/admin/update-jumio-usd-cents"; - static RoutePathAdminUpdateJumioKickbackUSDCents = "/api/v0/admin/update-jumio-kickback-usd-cents"; - static RoutePathAdminGetUnfilteredHotFeed = "/api/v0/admin/get-unfiltered-hot-feed"; - static RoutePathAdminGetHotFeedAlgorithm = "/api/v0/admin/get-hot-feed-algorithm"; - static RoutePathAdminUpdateHotFeedAlgorithm = "/api/v0/admin/update-hot-feed-algorithm"; - static RoutePathAdminUpdateHotFeedPostMultiplier = "/api/v0/admin/update-hot-feed-post-multiplier"; - static RoutePathAdminUpdateHotFeedUserMultiplier = "/api/v0/admin/update-hot-feed-user-multiplier"; - static RoutePathAdminGetHotFeedUserMultiplier = "/api/v0/admin/get-hot-feed-user-multiplier"; + static NodeControlRoute = '/api/v0/admin/node-control'; + static ReprocessBitcoinBlockRoute = '/api/v0/admin/reprocess-bitcoin-block'; + static RoutePathSwapIdentity = '/api/v0/admin/swap-identity'; + static RoutePathAdminUpdateUserGlobalMetadata = + '/api/v0/admin/update-user-global-metadata'; + static RoutePathAdminResetPhoneNumber = '/api/v0/admin/reset-phone-number'; + static RoutePathAdminGetAllUserGlobalMetadata = + '/api/v0/admin/get-all-user-global-metadata'; + static RoutePathAdminGetUserGlobalMetadata = + '/api/v0/admin/get-user-global-metadata'; + static RoutePathAdminUpdateGlobalFeed = '/api/v0/admin/update-global-feed'; + static RoutePathAdminPinPost = '/api/v0/admin/pin-post'; + static RoutePathAdminRemoveNilPosts = '/api/v0/admin/remove-nil-posts'; + static RoutePathAdminGetMempoolStats = '/api/v0/admin/get-mempool-stats'; + static RoutePathAdminGrantVerificationBadge = + '/api/v0/admin/grant-verification-badge'; + static RoutePathAdminRemoveVerificationBadge = + '/api/v0/admin/remove-verification-badge'; + static RoutePathAdminGetVerifiedUsers = '/api/v0/admin/get-verified-users'; + static RoutePathAdminGetUserAdminData = '/api/v0/admin/get-user-admin-data'; + static RoutePathAdminGetUsernameVerificationAuditLogs = + '/api/v0/admin/get-username-verification-audit-logs'; + static RoutePathUpdateGlobalParams = '/api/v0/admin/update-global-params'; + static RoutePathSetUSDCentsToDeSoReserveExchangeRate = + '/api/v0/admin/set-usd-cents-to-deso-reserve-exchange-rate'; + static RoutePathGetUSDCentsToDeSoReserveExchangeRate = + '/api/v0/admin/get-usd-cents-to-deso-reserve-exchange-rate'; + static RoutePathSetBuyDeSoFeeBasisPoints = + '/api/v0/admin/set-buy-deso-fee-basis-points'; + static RoutePathGetBuyDeSoFeeBasisPoints = + '/api/v0/admin/get-buy-deso-fee-basis-points'; + static RoutePathAdminGetGlobalParams = '/api/v0/admin/get-global-params'; + static RoutePathGetGlobalParams = '/api/v0/get-global-params'; + static RoutePathEvictUnminedBitcoinTxns = + '/api/v0/admin/evict-unmined-bitcoin-txns'; + static RoutePathGetWyreWalletOrdersForPublicKey = + '/api/v0/admin/get-wyre-wallet-orders-for-public-key'; + static RoutePathAdminGetNFTDrop = '/api/v0/admin/get-nft-drop'; + static RoutePathAdminUpdateNFTDrop = '/api/v0/admin/update-nft-drop'; + static RoutePathAdminResetJumioForPublicKey = + '/api/v0/admin/reset-jumio-for-public-key'; + static RoutePathAdminUpdateJumioDeSo = '/api/v0/admin/update-jumio-deso'; + static RoutePathAdminUpdateTutorialCreators = + '/api/v0/admin/update-tutorial-creators'; + static RoutePathAdminResetTutorialStatus = + '/api/v0/admin/reset-tutorial-status'; + static RoutePathAdminGetTutorialCreators = + '/api/v0/admin/get-tutorial-creators'; + static RoutePathAdminJumioCallback = '/api/v0/admin/jumio-callback'; + static RoutePathAdminGetAllCountryLevelSignUpBonuses = + '/api/v0/admin/get-all-country-level-sign-up-bonuses'; + static RoutePathAdminUpdateJumioCountrySignUpBonus = + '/api/v0/admin/update-jumio-country-sign-up-bonus'; + static RoutePathAdminUpdateJumioUSDCents = + '/api/v0/admin/update-jumio-usd-cents'; + static RoutePathAdminUpdateJumioKickbackUSDCents = + '/api/v0/admin/update-jumio-kickback-usd-cents'; + static RoutePathAdminGetUnfilteredHotFeed = + '/api/v0/admin/get-unfiltered-hot-feed'; + static RoutePathAdminGetHotFeedAlgorithm = + '/api/v0/admin/get-hot-feed-algorithm'; + static RoutePathAdminUpdateHotFeedAlgorithm = + '/api/v0/admin/update-hot-feed-algorithm'; + static RoutePathAdminUpdateHotFeedPostMultiplier = + '/api/v0/admin/update-hot-feed-post-multiplier'; + static RoutePathAdminUpdateHotFeedUserMultiplier = + '/api/v0/admin/update-hot-feed-user-multiplier'; + static RoutePathAdminGetHotFeedUserMultiplier = + '/api/v0/admin/get-hot-feed-user-multiplier'; // Referral program admin routes. - static RoutePathAdminCreateReferralHash = "/api/v0/admin/create-referral-hash"; - static RoutePathAdminGetAllReferralInfoForUser = "/api/v0/admin/get-all-referral-info-for-user"; - static RoutePathAdminUpdateReferralHash = "/api/v0/admin/update-referral-hash"; - static RoutePathAdminDownloadReferralCSV = "/api/v0/admin/download-referral-csv"; - static RoutePathAdminUploadReferralCSV = "/api/v0/admin/upload-referral-csv"; + static RoutePathAdminCreateReferralHash = + '/api/v0/admin/create-referral-hash'; + static RoutePathAdminGetAllReferralInfoForUser = + '/api/v0/admin/get-all-referral-info-for-user'; + static RoutePathAdminUpdateReferralHash = + '/api/v0/admin/update-referral-hash'; + static RoutePathAdminDownloadReferralCSV = + '/api/v0/admin/download-referral-csv'; + static RoutePathAdminUploadReferralCSV = '/api/v0/admin/upload-referral-csv'; // Referral program non-admin routes - static RoutePathGetReferralInfoForUser = "/api/v0/get-referral-info-for-user"; - static RoutePathGetReferralInfoForReferralHash = "/api/v0/get-referral-info-for-referral-hash"; + static RoutePathGetReferralInfoForUser = '/api/v0/get-referral-info-for-user'; + static RoutePathGetReferralInfoForReferralHash = + '/api/v0/get-referral-info-for-referral-hash'; - static RoutePathGetFullTikTokURL = "/api/v0/get-full-tiktok-url"; + static RoutePathGetFullTikTokURL = '/api/v0/get-full-tiktok-url'; // Wyre routes. - static RoutePathGetWyreWalletOrderQuotation = "/api/v0/get-wyre-wallet-order-quotation"; - static RoutePathGetWyreWalletOrderReservation = "/api/v0/get-wyre-wallet-order-reservation"; + static RoutePathGetWyreWalletOrderQuotation = + '/api/v0/get-wyre-wallet-order-quotation'; + static RoutePathGetWyreWalletOrderReservation = + '/api/v0/get-wyre-wallet-order-reservation'; // Admin Node Fee routes - static RoutePathAdminSetTransactionFeeForTransactionType = "/api/v0/admin/set-txn-fee-for-txn-type"; - static RoutePathAdminSetAllTransactionFees = "/api/v0/admin/set-all-txn-fees"; - static RoutePathAdminGetTransactionFeeMap = "/api/v0/admin/get-transaction-fee-map"; - static RoutePathAdminAddExemptPublicKey = "/api/v0/admin/add-exempt-public-key"; - static RoutePathAdminGetExemptPublicKeys = "/api/v0/admin/get-exempt-public-keys"; + static RoutePathAdminSetTransactionFeeForTransactionType = + '/api/v0/admin/set-txn-fee-for-txn-type'; + static RoutePathAdminSetAllTransactionFees = '/api/v0/admin/set-all-txn-fees'; + static RoutePathAdminGetTransactionFeeMap = + '/api/v0/admin/get-transaction-fee-map'; + static RoutePathAdminAddExemptPublicKey = + '/api/v0/admin/add-exempt-public-key'; + static RoutePathAdminGetExemptPublicKeys = + '/api/v0/admin/get-exempt-public-keys'; // Supply Monitoring endpoints - static RoutePathGetTotalSupply = "/api/v0/total-supply"; - static RoutePathGetRichList = "/api/v0/rich-list"; - static RoutePathGetCountKeysWithDESO = "/api/v0/count-keys-with-deso"; + static RoutePathGetTotalSupply = '/api/v0/total-supply'; + static RoutePathGetRichList = '/api/v0/rich-list'; + static RoutePathGetCountKeysWithDESO = '/api/v0/count-keys-with-deso'; } export class Transaction { @@ -220,15 +277,15 @@ export class ProfileEntryResponse { } export enum TutorialStatus { - EMPTY = "", - STARTED = "TutorialStarted", - SKIPPED = "TutorialSkipped", - CREATE_PROFILE = "TutorialCreateProfileComplete", - INVEST_OTHERS_BUY = "InvestInOthersBuyComplete", - INVEST_OTHERS_SELL = "InvestInOthersSellComplete", - INVEST_SELF = "InvestInYourselfComplete", - DIAMOND = "GiveADiamondComplete", - COMPLETE = "TutorialComplete", + EMPTY = '', + STARTED = 'TutorialStarted', + SKIPPED = 'TutorialSkipped', + CREATE_PROFILE = 'TutorialCreateProfileComplete', + INVEST_OTHERS_BUY = 'InvestInOthersBuyComplete', + INVEST_OTHERS_SELL = 'InvestInOthersSellComplete', + INVEST_SELF = 'InvestInYourselfComplete', + DIAMOND = 'GiveADiamondComplete', + COMPLETE = 'TutorialComplete', } export class User { @@ -468,57 +525,63 @@ export type CountryLevelSignUpBonusResponse = { }; export enum DAOCoinOperationTypeString { - MINT = "mint", - BURN = "burn", - UPDATE_TRANSFER_RESTRICTION_STATUS = "update_transfer_restriction_status", - DISABLE_MINTING = "disable_minting", + MINT = 'mint', + BURN = 'burn', + UPDATE_TRANSFER_RESTRICTION_STATUS = 'update_transfer_restriction_status', + DISABLE_MINTING = 'disable_minting', } export enum TransferRestrictionStatusString { - UNRESTRICTED = "unrestricted", - PROFILE_OWNER_ONLY = "profile_owner_only", - DAO_MEMBERS_ONLY = "dao_members_only", - PERMANENTLY_UNRESTRICTED = "permanently_unrestricted", + UNRESTRICTED = 'unrestricted', + PROFILE_OWNER_ONLY = 'profile_owner_only', + DAO_MEMBERS_ONLY = 'dao_members_only', + PERMANENTLY_UNRESTRICTED = 'permanently_unrestricted', } @Injectable({ - providedIn: "root", + providedIn: 'root', }) export class BackendApiService { - constructor(private httpClient: HttpClient, private identityService: IdentityService) {} + constructor( + private httpClient: HttpClient, + private identityService: IdentityService + ) {} - static GET_PROFILES_ORDER_BY_INFLUENCER_COIN_PRICE = "influencer_coin_price"; - static BUY_CREATOR_COIN_OPERATION_TYPE = "buy"; - static SELL_CREATOR_COIN_OPERATION_TYPE = "sell"; + static GET_PROFILES_ORDER_BY_INFLUENCER_COIN_PRICE = 'influencer_coin_price'; + static BUY_CREATOR_COIN_OPERATION_TYPE = 'buy'; + static SELL_CREATOR_COIN_OPERATION_TYPE = 'sell'; // TODO: Cleanup - this should be a configurable value on the node. Leaving it in the frontend // is fine for now because BlockCypher has strong anti-abuse measures in place. - blockCypherToken = "cd455c8a5d404bb0a23880b72f56aa86"; + blockCypherToken = 'cd455c8a5d404bb0a23880b72f56aa86'; // Store sent messages and associated metadata in localStorage - MessageMetaKey = "messageMetaKey"; + MessageMetaKey = 'messageMetaKey'; // Store the identity users in localStorage - IdentityUsersKey = "identityUsersV2"; + IdentityUsersKey = 'identityUsersV2'; // Store last local node URL in localStorage - LastLocalNodeKey = "lastLocalNodeV2"; + LastLocalNodeKey = 'lastLocalNodeV2'; // Store last logged in user public key in localStorage - LastLoggedInUserKey = "lastLoggedInUserV2"; + LastLoggedInUserKey = 'lastLoggedInUserV2'; // Store the last identity service URL in localStorage - LastIdentityServiceKey = "lastIdentityServiceURLV2"; + LastIdentityServiceKey = 'lastIdentityServiceURLV2'; // Messaging V3 default key name. - DefaultKey = "default-key"; + DefaultKey = 'default-key'; // TODO: Wipe all this data when transition is complete - LegacyUserListKey = "userList"; - LegacySeedListKey = "seedList"; + LegacyUserListKey = 'userList'; + LegacySeedListKey = 'seedList'; SetStorage(key: string, value: any) { - localStorage.setItem(key, value || value === false ? JSON.stringify(value) : ""); + localStorage.setItem( + key, + value || value === false ? JSON.stringify(value) : '' + ); } RemoveStorage(key: string) { @@ -527,7 +590,7 @@ export class BackendApiService { GetStorage(key: string) { const data = localStorage.getItem(key); - if (data === "") { + if (data === '') { return null; } @@ -535,10 +598,14 @@ export class BackendApiService { } // Assemble a URL to hit the BE with. - _makeRequestURL(endpoint: string, routeName: string, adminPublicKey?: string): string { - let queryURL = location.protocol + "//" + endpoint + routeName; + _makeRequestURL( + endpoint: string, + routeName: string, + adminPublicKey?: string + ): string { + let queryURL = location.protocol + '//' + endpoint + routeName; // If the protocol is specified within the endpoint then use that. - if (endpoint.startsWith("http")) { + if (endpoint.startsWith('http')) { queryURL = endpoint + routeName; } if (adminPublicKey) { @@ -550,11 +617,14 @@ export class BackendApiService { _handleError(error: HttpErrorResponse) { if (error.error instanceof ErrorEvent) { // A client-side or network error occurred. Handle it accordingly. - console.error("An error occurred:", error.error.message); + console.error('An error occurred:', error.error.message); } else { // The backend returned an unsuccessful response code. // The response body may contain clues as to what went wrong, - console.error(`Backend returned code ${error.status}, ` + `body was: ${JSON.stringify(error.error)}`); + console.error( + `Backend returned code ${error.status}, ` + + `body was: ${JSON.stringify(error.error)}` + ); } // return an observable with a user-facing error message return throwError(error); @@ -567,20 +637,26 @@ export class BackendApiService { this.identityService.identityServicePublicKeyAdded = publicKeyAdded; } - signAndSubmitTransaction(endpoint: string, request: Observable, PublicKeyBase58Check: string): Observable { + signAndSubmitTransaction( + endpoint: string, + request: Observable, + PublicKeyBase58Check: string + ): Observable { return request .pipe( switchMap((res) => this.identityService .sign({ transactionHex: res.TransactionHex, - ...this.identityService.identityServiceParamsForKey(PublicKeyBase58Check), + ...this.identityService.identityServiceParamsForKey( + PublicKeyBase58Check + ), }) .pipe( switchMap((signed) => { if (signed.approvalRequired) { return this.identityService - .launch("/approve", { + .launch('/approve', { tx: res.TransactionHex, }) .pipe( @@ -607,14 +683,23 @@ export class BackendApiService { } get(endpoint: string, path: string) { - return this.httpClient.get(this._makeRequestURL(endpoint, path)).pipe(catchError(this._handleError)); + return this.httpClient + .get(this._makeRequestURL(endpoint, path)) + .pipe(catchError(this._handleError)); } post(endpoint: string, path: string, body: any): Observable { - return this.httpClient.post(this._makeRequestURL(endpoint, path), body).pipe(catchError(this._handleError)); + return this.httpClient + .post(this._makeRequestURL(endpoint, path), body) + .pipe(catchError(this._handleError)); } - jwtPost(endpoint: string, path: string, publicKey: string, body: any): Observable { + jwtPost( + endpoint: string, + path: string, + publicKey: string, + body: any + ): Observable { const request = this.identityService.jwt({ ...this.identityService.identityServiceParamsForKey(publicKey), }); @@ -626,7 +711,9 @@ export class BackendApiService { ...body, }; - return this.post(endpoint, path, body).pipe(map((res) => ({ ...res, ...signed }))); + return this.post(endpoint, path, body).pipe( + map((res) => ({ ...res, ...signed })) + ); }) ); } @@ -637,7 +724,9 @@ export class BackendApiService { // Use empty string to return all top categories. GetBitcoinFeeRateSatoshisPerKB(): Observable { - return this.httpClient.get("https://api.blockchain.com/mempool/fees").pipe(catchError(this._handleError)); + return this.httpClient + .get('https://api.blockchain.com/mempool/fees') + .pipe(catchError(this._handleError)); } SendPhoneNumberVerificationText( @@ -646,11 +735,16 @@ export class BackendApiService { PhoneNumber: string, PhoneNumberCountryCode: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathSendPhoneNumberVerificationText, PublicKeyBase58Check, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathSendPhoneNumberVerificationText, PublicKeyBase58Check, - PhoneNumber, - PhoneNumberCountryCode, - }); + { + PublicKeyBase58Check, + PhoneNumber, + PhoneNumberCountryCode, + } + ); } SubmitPhoneNumberVerificationCode( @@ -660,15 +754,23 @@ export class BackendApiService { PhoneNumberCountryCode: string, VerificationCode: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathSubmitPhoneNumberVerificationCode, PublicKeyBase58Check, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathSubmitPhoneNumberVerificationCode, PublicKeyBase58Check, - PhoneNumber, - PhoneNumberCountryCode, - VerificationCode, - }); + { + PublicKeyBase58Check, + PhoneNumber, + PhoneNumberCountryCode, + VerificationCode, + } + ); } - GetBlockTemplate(endpoint: string, PublicKeyBase58Check: string): Observable { + GetBlockTemplate( + endpoint: string, + PublicKeyBase58Check: string + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetBlockTemplate, { PublicKeyBase58Check, HeaderVersion: 1, @@ -683,7 +785,11 @@ export class BackendApiService { DeleteIdentities(endpoint: string): Observable { return this.httpClient - .post(this._makeRequestURL(endpoint, BackendRoutes.RoutePathDeleteIdentities), {}, { withCredentials: true }) + .post( + this._makeRequestURL(endpoint, BackendRoutes.RoutePathDeleteIdentities), + {}, + { withCredentials: true } + ) .pipe(catchError(this._handleError)); } @@ -710,7 +816,9 @@ export class BackendApiService { switchMap((res) => this.identityService .burn({ - ...this.identityService.identityServiceParamsForKey(PublicKeyBase58Check), + ...this.identityService.identityServiceParamsForKey( + PublicKeyBase58Check + ), unsignedHashes: res.UnsignedHashes, }) .pipe(map((signed) => ({ ...res, ...signed }))) @@ -766,7 +874,11 @@ export class BackendApiService { MinFeeRateNanosPerKB ); - return this.signAndSubmitTransaction(endpoint, request, SenderPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + SenderPublicKeyBase58Check + ); } SubmitTransaction(endpoint: string, TransactionHex: string): Observable { @@ -786,18 +898,25 @@ export class BackendApiService { // In V3 messages, we expect users to migrate to the V3 messages, which means they'll have the default // key registered on-chain. We want to automatically send messages to this default key is it's registered. // To check the messaging key we call the RoutePathCheckPartyMessaging keys backend API route. - let req = this.post(endpoint, BackendRoutes.RoutePathCheckPartyMessagingKeys, { - SenderPublicKeyBase58Check, - SenderMessagingKeyName: this.DefaultKey, - RecipientPublicKeyBase58Check, - RecipientMessagingKeyName: this.DefaultKey, - }).pipe( + let req = this.post( + endpoint, + BackendRoutes.RoutePathCheckPartyMessagingKeys, + { + SenderPublicKeyBase58Check, + SenderMessagingKeyName: this.DefaultKey, + RecipientPublicKeyBase58Check, + RecipientMessagingKeyName: this.DefaultKey, + } + ).pipe( switchMap((partyMessagingKeys) => { // Once we determine the messaging keys of the parties, we will then encrypt a message based on the keys. return this.identityService .encrypt({ - ...this.identityService.identityServiceParamsForKey(SenderPublicKeyBase58Check), - recipientPublicKey: partyMessagingKeys.RecipientMessagingPublicKeyBase58Check, + ...this.identityService.identityServiceParamsForKey( + SenderPublicKeyBase58Check + ), + recipientPublicKey: + partyMessagingKeys.RecipientMessagingPublicKeyBase58Check, senderGroupKeyName: partyMessagingKeys.SenderMessagingKeyName, message: MessageText, }) @@ -808,17 +927,25 @@ export class BackendApiService { const EncryptedMessageText = encrypted.encryptedMessage; // Determine whether to use V3 messaging group key names for sender or recipient. const senderV3 = partyMessagingKeys.IsSenderMessagingKey; - const SenderMessagingGroupKeyName = senderV3 ? partyMessagingKeys.SenderMessagingKeyName : ""; + const SenderMessagingGroupKeyName = senderV3 + ? partyMessagingKeys.SenderMessagingKeyName + : ''; const recipientV3 = partyMessagingKeys.IsRecipientMessagingKey; - const RecipientMessagingGroupKeyName = recipientV3 ? partyMessagingKeys.RecipientMessagingKeyName : ""; - return this.post(endpoint, BackendRoutes.RoutePathSendMessageStateless, { - SenderPublicKeyBase58Check, - RecipientPublicKeyBase58Check, - EncryptedMessageText, - SenderMessagingGroupKeyName, - RecipientMessagingGroupKeyName, - MinFeeRateNanosPerKB, - }).pipe( + const RecipientMessagingGroupKeyName = recipientV3 + ? partyMessagingKeys.RecipientMessagingKeyName + : ''; + return this.post( + endpoint, + BackendRoutes.RoutePathSendMessageStateless, + { + SenderPublicKeyBase58Check, + RecipientPublicKeyBase58Check, + EncryptedMessageText, + SenderMessagingGroupKeyName, + RecipientMessagingGroupKeyName, + MinFeeRateNanosPerKB, + } + ).pipe( map((request) => { return { ...request }; }) @@ -827,7 +954,11 @@ export class BackendApiService { ); }) ); - return this.signAndSubmitTransaction(endpoint, req, SenderPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + req, + SenderPublicKeyBase58Check + ); } // User-related functions. @@ -931,18 +1062,28 @@ export class BackendApiService { ); } - UploadImage(endpoint: string, UserPublicKeyBase58Check: string, file: File): Observable { + UploadImage( + endpoint: string, + UserPublicKeyBase58Check: string, + file: File + ): Observable { const request = this.identityService.jwt({ - ...this.identityService.identityServiceParamsForKey(UserPublicKeyBase58Check), + ...this.identityService.identityServiceParamsForKey( + UserPublicKeyBase58Check + ), }); return request.pipe( switchMap((signed) => { const formData = new FormData(); - formData.append("file", file); - formData.append("UserPublicKeyBase58Check", UserPublicKeyBase58Check); - formData.append("JWT", signed.jwt); - - return this.post(endpoint, BackendRoutes.RoutePathUploadImage, formData); + formData.append('file', file); + formData.append('UserPublicKeyBase58Check', UserPublicKeyBase58Check); + formData.append('JWT', signed.jwt); + + return this.post( + endpoint, + BackendRoutes.RoutePathUploadImage, + formData + ); }) ); } @@ -979,7 +1120,11 @@ export class BackendApiService { MinFeeRateNanosPerKB, }); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } UpdateNFT( @@ -1004,7 +1149,11 @@ export class BackendApiService { MinFeeRateNanosPerKB, }); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } CreateNFTBid( @@ -1022,7 +1171,11 @@ export class BackendApiService { BidAmountNanos, MinFeeRateNanosPerKB, }); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } AcceptNFTBid( @@ -1037,12 +1190,14 @@ export class BackendApiService { ): Observable { let request = UnencryptedUnlockableText ? this.identityService.encrypt({ - ...this.identityService.identityServiceParamsForKey(UpdaterPublicKeyBase58Check), + ...this.identityService.identityServiceParamsForKey( + UpdaterPublicKeyBase58Check + ), recipientPublicKey: BidderPublicKeyBase58Check, - senderGroupKeyName: "", + senderGroupKeyName: '', message: UnencryptedUnlockableText, }) - : of({ encryptedMessage: "" }); + : of({ encryptedMessage: '' }); request = request.pipe( switchMap((encrypted) => { const EncryptedMessageText = encrypted.encryptedMessage; @@ -1061,7 +1216,11 @@ export class BackendApiService { ); }) ); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } TransferNFT( @@ -1075,12 +1234,14 @@ export class BackendApiService { ): Observable { let request = UnencryptedUnlockableText ? this.identityService.encrypt({ - ...this.identityService.identityServiceParamsForKey(SenderPublicKeyBase58Check), + ...this.identityService.identityServiceParamsForKey( + SenderPublicKeyBase58Check + ), recipientPublicKey: ReceiverPublicKeyBase58Check, - senderGroupKeyName: "", + senderGroupKeyName: '', message: UnencryptedUnlockableText, }) - : of({ encryptedMessage: "" }); + : of({ encryptedMessage: '' }); request = request.pipe( switchMap((encrypted) => { const EncryptedUnlockableText = encrypted.encryptedMessage; @@ -1099,7 +1260,11 @@ export class BackendApiService { }) ); - return this.signAndSubmitTransaction(endpoint, request, SenderPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + SenderPublicKeyBase58Check + ); } AcceptNFTTransfer( @@ -1109,13 +1274,21 @@ export class BackendApiService { SerialNumber: number, MinFeeRateNanosPerKB: number ): Observable { - const request = this.post(endpoint, BackendRoutes.RoutePathAcceptNFTTransfer, { - UpdaterPublicKeyBase58Check, - NFTPostHashHex, - SerialNumber, - MinFeeRateNanosPerKB, - }); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + const request = this.post( + endpoint, + BackendRoutes.RoutePathAcceptNFTTransfer, + { + UpdaterPublicKeyBase58Check, + NFTPostHashHex, + SerialNumber, + MinFeeRateNanosPerKB, + } + ); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } BurnNFT( @@ -1131,7 +1304,11 @@ export class BackendApiService { SerialNumber, MinFeeRateNanosPerKB, }); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } DecryptUnlockableTexts( @@ -1140,17 +1317,24 @@ export class BackendApiService { ): Observable { return this.identityService .decrypt({ - ...this.identityService.identityServiceParamsForKey(ReaderPublicKeyBase58Check), - encryptedMessages: UnlockableNFTEntryResponses.map((unlockableNFTEntryResponses) => ({ - EncryptedHex: unlockableNFTEntryResponses.EncryptedUnlockableText, - PublicKey: unlockableNFTEntryResponses.LastOwnerPublicKeyBase58Check, - })), + ...this.identityService.identityServiceParamsForKey( + ReaderPublicKeyBase58Check + ), + encryptedMessages: UnlockableNFTEntryResponses.map( + (unlockableNFTEntryResponses) => ({ + EncryptedHex: unlockableNFTEntryResponses.EncryptedUnlockableText, + PublicKey: + unlockableNFTEntryResponses.LastOwnerPublicKeyBase58Check, + }) + ), }) .pipe( map((decrypted) => { for (const unlockableNFTEntryResponse of UnlockableNFTEntryResponses) { unlockableNFTEntryResponse.DecryptedUnlockableText = - decrypted.decryptedHexes[unlockableNFTEntryResponse.EncryptedUnlockableText]; + decrypted.decryptedHexes[ + unlockableNFTEntryResponse.EncryptedUnlockableText + ]; } return UnlockableNFTEntryResponses; }) @@ -1206,24 +1390,39 @@ export class BackendApiService { }); } - GetNextNFTShowcase(endpoint: string, UserPublicKeyBase58Check: string): Observable { + GetNextNFTShowcase( + endpoint: string, + UserPublicKeyBase58Check: string + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetNextNFTShowcase, { UserPublicKeyBase58Check, }); } - GetNFTCollectionSummary(endpoint: string, ReaderPublicKeyBase58Check: string, PostHashHex: string): Observable { + GetNFTCollectionSummary( + endpoint: string, + ReaderPublicKeyBase58Check: string, + PostHashHex: string + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetNFTCollectionSummary, { ReaderPublicKeyBase58Check, PostHashHex, }); } - GetNFTEntriesForNFTPost(endpoint: string, ReaderPublicKeyBase58Check: string, PostHashHex: string): Observable { - return this.post(endpoint, BackendRoutes.RoutePathGetNFTEntriesForPostHash, { - ReaderPublicKeyBase58Check, - PostHashHex, - }); + GetNFTEntriesForNFTPost( + endpoint: string, + ReaderPublicKeyBase58Check: string, + PostHashHex: string + ): Observable { + return this.post( + endpoint, + BackendRoutes.RoutePathGetNFTEntriesForPostHash, + { + ReaderPublicKeyBase58Check, + PostHashHex, + } + ); } SubmitPost( @@ -1254,10 +1453,19 @@ export class BackendApiService { InTutorial, }); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } - GetHotFeed(endpoint: string, ReaderPublicKeyBase58Check: string, SeenPosts, ResponseLimit): Observable { + GetHotFeed( + endpoint: string, + ReaderPublicKeyBase58Check: string, + SeenPosts, + ResponseLimit + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetHotFeed, { ReaderPublicKeyBase58Check, SeenPosts, @@ -1344,7 +1552,11 @@ export class BackendApiService { AddGlobalFeedBool, }); } - GetSingleProfile(endpoint: string, PublicKeyBase58Check: string, Username: string): Observable { + GetSingleProfile( + endpoint: string, + PublicKeyBase58Check: string, + Username: string + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetSingleProfile, { PublicKeyBase58Check, Username, @@ -1352,20 +1564,42 @@ export class BackendApiService { } // We add a ts-ignore here as typescript does not expect responseType to be anything but "json". - GetSingleProfilePicture(endpoint: string, PublicKeyBase58Check: string, bustCache: string = ""): Observable { - return this.httpClient.get(this.GetSingleProfilePictureURL(endpoint, PublicKeyBase58Check, bustCache), { - // @ts-ignore - responseType: "blob", - }); + GetSingleProfilePicture( + endpoint: string, + PublicKeyBase58Check: string, + bustCache: string = '' + ): Observable { + return this.httpClient.get( + this.GetSingleProfilePictureURL( + endpoint, + PublicKeyBase58Check, + bustCache + ), + { + // @ts-ignore + responseType: 'blob', + } + ); } - GetSingleProfilePictureURL(endpoint: string, PublicKeyBase58Check: string, fallback): string { + GetSingleProfilePictureURL( + endpoint: string, + PublicKeyBase58Check: string, + fallback + ): string { return this._makeRequestURL( endpoint, - BackendRoutes.RoutePathGetSingleProfilePicture + "/" + PublicKeyBase58Check + "?" + fallback + BackendRoutes.RoutePathGetSingleProfilePicture + + '/' + + PublicKeyBase58Check + + '?' + + fallback ); } GetDefaultProfilePictureURL(endpoint: string): string { - return this._makeRequestURL(endpoint, "/assets/img/default_profile_pic.png"); + return this._makeRequestURL( + endpoint, + '/assets/img/default_profile_pic.png' + ); } GetPostsForPublicKey( @@ -1417,7 +1651,10 @@ export class BackendApiService { FetchHodlings: boolean = false, FetchAll: boolean = false, IsDAOCoin: boolean = false - ): Observable<{ Hodlers: BalanceEntryResponse[]; LastPublicKeyBase58Check: string }> { + ): Observable<{ + Hodlers: BalanceEntryResponse[]; + LastPublicKeyBase58Check: string; + }> { return this.post(endpoint, BackendRoutes.RoutePathGetHodlersForPublicKey, { PublicKeyBase58Check, Username, @@ -1476,9 +1713,18 @@ export class BackendApiService { if (res.CompProfileCreationTxnHashHex) { return interval(500) .pipe( - concatMap((iteration) => zip(this.GetTxn(endpoint, res.CompProfileCreationTxnHashHex), of(iteration))) + concatMap((iteration) => + zip( + this.GetTxn(endpoint, res.CompProfileCreationTxnHashHex), + of(iteration) + ) + ) + ) + .pipe( + filter( + ([txFound, iteration]) => txFound.TxnFound || iteration > 120 + ) ) - .pipe(filter(([txFound, iteration]) => txFound.TxnFound || iteration > 120)) .pipe(take(1)) .pipe(switchMap(() => of(res))); } else { @@ -1487,7 +1733,11 @@ export class BackendApiService { }) ); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } GetFollows( @@ -1495,7 +1745,7 @@ export class BackendApiService { Username: string, PublicKeyBase58Check: string, GetEntriesFollowingUsername: boolean, - LastPublicKeyBase58Check: string = "", + LastPublicKeyBase58Check: string = '', NumToFetch: number = 50 ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetFollowsStateless, { @@ -1514,55 +1764,73 @@ export class BackendApiService { IsUnfollow: boolean, MinFeeRateNanosPerKB: number ): Observable { - const request = this.post(endpoint, BackendRoutes.RoutePathCreateFollowTxnStateless, { - FollowerPublicKeyBase58Check, - FollowedPublicKeyBase58Check, - IsUnfollow, - MinFeeRateNanosPerKB, - }); + const request = this.post( + endpoint, + BackendRoutes.RoutePathCreateFollowTxnStateless, + { + FollowerPublicKeyBase58Check, + FollowedPublicKeyBase58Check, + IsUnfollow, + MinFeeRateNanosPerKB, + } + ); - return this.signAndSubmitTransaction(endpoint, request, FollowerPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + FollowerPublicKeyBase58Check + ); } GetMessages( endpoint: string, PublicKeyBase58Check: string, - FetchAfterPublicKeyBase58Check: string = "", + FetchAfterPublicKeyBase58Check: string = '', NumToFetch: number = 25, HoldersOnly: boolean = false, HoldingsOnly: boolean = false, FollowersOnly: boolean = false, FollowingOnly: boolean = false, - SortAlgorithm: string = "time" + SortAlgorithm: string = 'time' ): Observable { - let req = this.httpClient.post(this._makeRequestURL(endpoint, BackendRoutes.RoutePathGetMessagesStateless), { - PublicKeyBase58Check, - FetchAfterPublicKeyBase58Check, - NumToFetch, - HoldersOnly, - HoldingsOnly, - FollowersOnly, - FollowingOnly, - SortAlgorithm, - }); + let req = this.httpClient.post( + this._makeRequestURL( + endpoint, + BackendRoutes.RoutePathGetMessagesStateless + ), + { + PublicKeyBase58Check, + FetchAfterPublicKeyBase58Check, + NumToFetch, + HoldersOnly, + HoldingsOnly, + FollowersOnly, + FollowingOnly, + SortAlgorithm, + } + ); // create an array of messages to decrypt req = req.pipe( map((res) => { // This array contains encrypted messages with public keys // Public keys of the other party involved in the correspondence - const encryptedMessages = res.OrderedContactsWithMessages.flatMap((thread) => - thread.Messages.flatMap((message) => ({ - EncryptedHex: message.EncryptedText, - PublicKey: message.IsSender ? message.RecipientPublicKeyBase58Check : message.SenderPublicKeyBase58Check, - IsSender: message.IsSender, - Legacy: !message.V2 && (!message.Version || message.Version < 2), - Version: message.Version, - SenderMessagingPublicKey: message.SenderMessagingPublicKey, - SenderMessagingGroupKeyName: message.SenderMessagingGroupKeyName, - RecipientMessagingPublicKey: message.RecipientMessagingPublicKey, - RecipientMessagingGroupKeyName: message.RecipientMessagingGroupKeyName, - })) + const encryptedMessages = res.OrderedContactsWithMessages.flatMap( + (thread) => + thread.Messages.flatMap((message) => ({ + EncryptedHex: message.EncryptedText, + PublicKey: message.IsSender + ? message.RecipientPublicKeyBase58Check + : message.SenderPublicKeyBase58Check, + IsSender: message.IsSender, + Legacy: !message.V2 && (!message.Version || message.Version < 2), + Version: message.Version, + SenderMessagingPublicKey: message.SenderMessagingPublicKey, + SenderMessagingGroupKeyName: message.SenderMessagingGroupKeyName, + RecipientMessagingPublicKey: message.RecipientMessagingPublicKey, + RecipientMessagingGroupKeyName: + message.RecipientMessagingGroupKeyName, + })) ); return { ...res, encryptedMessages }; }) @@ -1573,14 +1841,18 @@ export class BackendApiService { switchMap((res) => { return this.identityService .decrypt({ - ...this.identityService.identityServiceParamsForKey(PublicKeyBase58Check), + ...this.identityService.identityServiceParamsForKey( + PublicKeyBase58Check + ), encryptedMessages: res.encryptedMessages, }) .pipe( map((decrypted) => { res.OrderedContactsWithMessages.forEach((threads) => threads.Messages.forEach( - (message) => (message.DecryptedText = decrypted.decryptedHexes[message.EncryptedText]) + (message) => + (message.DecryptedText = + decrypted.decryptedHexes[message.EncryptedText]) ) ); return { ...res, ...decrypted }; @@ -1599,14 +1871,22 @@ export class BackendApiService { IsUnlike: boolean, MinFeeRateNanosPerKB: number ): Observable { - const request = this.post(endpoint, BackendRoutes.RoutePathCreateLikeStateless, { - ReaderPublicKeyBase58Check, - LikedPostHashHex, - IsUnlike, - MinFeeRateNanosPerKB, - }); + const request = this.post( + endpoint, + BackendRoutes.RoutePathCreateLikeStateless, + { + ReaderPublicKeyBase58Check, + LikedPostHashHex, + IsUnlike, + MinFeeRateNanosPerKB, + } + ); - return this.signAndSubmitTransaction(endpoint, request, ReaderPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + ReaderPublicKeyBase58Check + ); } SendDiamonds( @@ -1627,7 +1907,11 @@ export class BackendApiService { InTutorial, }); - return this.signAndSubmitTransaction(endpoint, request, SenderPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + SenderPublicKeyBase58Check + ); } GetDiamondsForPublicKey( @@ -1738,22 +2022,30 @@ export class BackendApiService { MinDeSoExpectedNanos = Math.floor(MinDeSoExpectedNanos); MinCreatorCoinExpectedNanos = Math.floor(MinCreatorCoinExpectedNanos); - let request = this.post(endpoint, BackendRoutes.RoutePathBuyOrSellCreatorCoin, { - UpdaterPublicKeyBase58Check, - CreatorPublicKeyBase58Check, - OperationType, - DeSoToSellNanos, - CreatorCoinToSellNanos, - DeSoToAddNanos, - MinDeSoExpectedNanos, - MinCreatorCoinExpectedNanos, - MinFeeRateNanosPerKB, - // If we are not broadcasting the transaction, InTutorial should always be false so we don't update the TutorialStatus of the user. - InTutorial: Broadcast ? InTutorial : false, - }); + let request = this.post( + endpoint, + BackendRoutes.RoutePathBuyOrSellCreatorCoin, + { + UpdaterPublicKeyBase58Check, + CreatorPublicKeyBase58Check, + OperationType, + DeSoToSellNanos, + CreatorCoinToSellNanos, + DeSoToAddNanos, + MinDeSoExpectedNanos, + MinCreatorCoinExpectedNanos, + MinFeeRateNanosPerKB, + // If we are not broadcasting the transaction, InTutorial should always be false so we don't update the TutorialStatus of the user. + InTutorial: Broadcast ? InTutorial : false, + } + ); if (Broadcast) { - request = this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + request = this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } return request; @@ -1780,7 +2072,11 @@ export class BackendApiService { }); if (Broadcast) { - request = this.signAndSubmitTransaction(endpoint, request, SenderPublicKeyBase58Check); + request = this.signAndSubmitTransaction( + endpoint, + request, + SenderPublicKeyBase58Check + ); } return request; @@ -1805,7 +2101,11 @@ export class BackendApiService { TransferRestrictionStatus, MinFeeRateNanosPerKB, }); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } TransferDAOCoin( @@ -1816,14 +2116,22 @@ export class BackendApiService { DAOCoinToTransferNanos: Hex, MinFeeRateNanosPerKB: number ): Observable { - const request = this.post(endpoint, BackendRoutes.RoutePathTransferDAOCoin, { - SenderPublicKeyBase58Check, - ProfilePublicKeyBase58CheckOrUsername, - ReceiverPublicKeyBase58CheckOrUsername, - DAOCoinToTransferNanos, - MinFeeRateNanosPerKB, - }); - return this.signAndSubmitTransaction(endpoint, request, SenderPublicKeyBase58Check); + const request = this.post( + endpoint, + BackendRoutes.RoutePathTransferDAOCoin, + { + SenderPublicKeyBase58Check, + ProfilePublicKeyBase58CheckOrUsername, + ReceiverPublicKeyBase58CheckOrUsername, + DAOCoinToTransferNanos, + MinFeeRateNanosPerKB, + } + ); + return this.signAndSubmitTransaction( + endpoint, + request, + SenderPublicKeyBase58Check + ); } BlockPublicKey( @@ -1832,11 +2140,16 @@ export class BackendApiService { BlockPublicKeyBase58Check: string, Unblock: boolean = false ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathBlockPublicKey, PublicKeyBase58Check, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathBlockPublicKey, PublicKeyBase58Check, - BlockPublicKeyBase58Check, - Unblock, - }); + { + PublicKeyBase58Check, + BlockPublicKeyBase58Check, + Unblock, + } + ); } MarkContactMessagesRead( @@ -1844,16 +2157,29 @@ export class BackendApiService { UserPublicKeyBase58Check: string, ContactPublicKeyBase58Check: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathMarkContactMessagesRead, UserPublicKeyBase58Check, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathMarkContactMessagesRead, UserPublicKeyBase58Check, - ContactPublicKeyBase58Check, - }); + { + UserPublicKeyBase58Check, + ContactPublicKeyBase58Check, + } + ); } - MarkAllMessagesRead(endpoint: string, UserPublicKeyBase58Check: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathMarkAllMessagesRead, UserPublicKeyBase58Check, { + MarkAllMessagesRead( + endpoint: string, + UserPublicKeyBase58Check: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathMarkAllMessagesRead, UserPublicKeyBase58Check, - }); + { + UserPublicKeyBase58Check, + } + ); } // Note that FetchStartIndex < 0 means "fetch me the latest notifications." @@ -1886,11 +2212,16 @@ export class BackendApiService { Email: string, MessageReadStateUpdatesByContact: any ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathUpdateUserGlobalMetadata, UserPublicKeyBase58Check, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathUpdateUserGlobalMetadata, UserPublicKeyBase58Check, - Email, - MessageReadStateUpdatesByContact, - }); + { + UserPublicKeyBase58Check, + Email, + MessageReadStateUpdatesByContact, + } + ); } GetUserGlobalMetadata( @@ -1899,18 +2230,32 @@ export class BackendApiService { // The public key of the user to update. UserPublicKeyBase58Check: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathGetUserGlobalMetadata, UserPublicKeyBase58Check, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathGetUserGlobalMetadata, UserPublicKeyBase58Check, - }); + { + UserPublicKeyBase58Check, + } + ); } ResendVerifyEmail(endpoint: string, PublicKey: string) { - return this.jwtPost(endpoint, BackendRoutes.RoutePathResendVerifyEmail, PublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathResendVerifyEmail, PublicKey, - }); + { + PublicKey, + } + ); } - VerifyEmail(endpoint: string, PublicKey: string, EmailHash: string): Observable { + VerifyEmail( + endpoint: string, + PublicKey: string, + EmailHash: string + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathVerifyEmail, { PublicKey, EmailHash, @@ -1918,27 +2263,60 @@ export class BackendApiService { } DeletePII(endpoint: string, PublicKeyBase58Check: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathDeletePII, PublicKeyBase58Check, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathDeletePII, PublicKeyBase58Check, - }); + { + PublicKeyBase58Check, + } + ); } - GetUserMetadata(endpoint: string, PublicKeyBase58Check: string): Observable { - return this.get(endpoint, BackendRoutes.RoutePathGetUserMetadata + "/" + PublicKeyBase58Check); + GetUserMetadata( + endpoint: string, + PublicKeyBase58Check: string + ): Observable { + return this.get( + endpoint, + BackendRoutes.RoutePathGetUserMetadata + '/' + PublicKeyBase58Check + ); } - GetUsernameForPublicKey(endpoint: string, PublicKeyBase58Check: string): Observable { - return this.get(endpoint, BackendRoutes.RoutePathGetUsernameForPublicKey + "/" + PublicKeyBase58Check); + GetUsernameForPublicKey( + endpoint: string, + PublicKeyBase58Check: string + ): Observable { + return this.get( + endpoint, + BackendRoutes.RoutePathGetUsernameForPublicKey + + '/' + + PublicKeyBase58Check + ); } - GetPublicKeyForUsername(endpoint: string, Username: string): Observable { - return this.get(endpoint, BackendRoutes.RoutePathGetPublicKeyForUsername + "/" + Username); + GetPublicKeyForUsername( + endpoint: string, + Username: string + ): Observable { + return this.get( + endpoint, + BackendRoutes.RoutePathGetPublicKeyForUsername + '/' + Username + ); } - GetJumioStatusForPublicKey(endpoint: string, PublicKeyBase58Check: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathGetJumioStatusForPublicKey, PublicKeyBase58Check, { + GetJumioStatusForPublicKey( + endpoint: string, + PublicKeyBase58Check: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathGetJumioStatusForPublicKey, PublicKeyBase58Check, - }); + { + PublicKeyBase58Check, + } + ); } SubmitETHTx( @@ -1956,65 +2334,128 @@ export class BackendApiService { }); } - QueryETHRPC(endpoint: string, Method: string, Params: string[]): Observable { + QueryETHRPC( + endpoint: string, + Method: string, + Params: string[] + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathQueryETHRPC, { Method, Params, }); } - AdminGetVerifiedUsers(endpoint: string, AdminPublicKey: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetVerifiedUsers, AdminPublicKey, { - AdminPublicKey, - }); - } - - AdminGetUsernameVerificationAuditLogs(endpoint: string, AdminPublicKey: string, Username: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetUsernameVerificationAuditLogs, AdminPublicKey, { + AdminGetVerifiedUsers( + endpoint: string, + AdminPublicKey: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetVerifiedUsers, AdminPublicKey, - Username, - }); + { + AdminPublicKey, + } + ); } - AdminGrantVerificationBadge(endpoint: string, AdminPublicKey: string, UsernameToVerify: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGrantVerificationBadge, AdminPublicKey, { + AdminGetUsernameVerificationAuditLogs( + endpoint: string, + AdminPublicKey: string, + Username: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetUsernameVerificationAuditLogs, AdminPublicKey, - UsernameToVerify, - }); + { + AdminPublicKey, + Username, + } + ); } - AdminRemoveVerificationBadge( + AdminGrantVerificationBadge( endpoint: string, AdminPublicKey: string, - UsernameForWhomToRemoveVerification: string + UsernameToVerify: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminRemoveVerificationBadge, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGrantVerificationBadge, AdminPublicKey, - UsernameForWhomToRemoveVerification, - }); + { + AdminPublicKey, + UsernameToVerify, + } + ); } - AdminGetUserAdminData(endpoint: string, AdminPublicKey: string, UserPublicKeyBase58Check: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetUserAdminData, AdminPublicKey, { + AdminRemoveVerificationBadge( + endpoint: string, + AdminPublicKey: string, + UsernameForWhomToRemoveVerification: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminRemoveVerificationBadge, AdminPublicKey, - UserPublicKeyBase58Check, - }); + { + AdminPublicKey, + UsernameForWhomToRemoveVerification, + } + ); } - NodeControl(endpoint: string, AdminPublicKey: string, Address: string, OperationType: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.NodeControlRoute, AdminPublicKey, { + AdminGetUserAdminData( + endpoint: string, + AdminPublicKey: string, + UserPublicKeyBase58Check: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetUserAdminData, AdminPublicKey, - Address, - OperationType, - }); + { + AdminPublicKey, + UserPublicKeyBase58Check, + } + ); } - UpdateMiner(endpoint: string, AdminPublicKey: string, MinerPublicKeys: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.NodeControlRoute, AdminPublicKey, { + NodeControl( + endpoint: string, + AdminPublicKey: string, + Address: string, + OperationType: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.NodeControlRoute, AdminPublicKey, - MinerPublicKeys, - OperationType: "update_miner", - }); + { + AdminPublicKey, + Address, + OperationType, + } + ); + } + + UpdateMiner( + endpoint: string, + AdminPublicKey: string, + MinerPublicKeys: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.NodeControlRoute, + AdminPublicKey, + { + AdminPublicKey, + MinerPublicKeys, + OperationType: 'update_miner', + } + ); } AdminGetUserGlobalMetadata( @@ -2024,10 +2465,15 @@ export class BackendApiService { // The public key of the user for whom we'd like to get global metadata UserPublicKeyBase58Check: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetUserGlobalMetadata, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetUserGlobalMetadata, AdminPublicKey, - UserPublicKeyBase58Check, - }); + { + AdminPublicKey, + UserPublicKeyBase58Check, + } + ); } AdminUpdateUserGlobalMetadata( @@ -2044,39 +2490,72 @@ export class BackendApiService { WhitelistPosts: boolean, RemovePhoneNumberMetadata: boolean ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateUserGlobalMetadata, AdminPublicKey, { - UserPublicKeyBase58Check, - Username, - IsBlacklistUpdate, - RemoveEverywhere, - RemoveFromLeaderboard, - IsWhitelistUpdate, - WhitelistPosts, - RemovePhoneNumberMetadata, + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateUserGlobalMetadata, AdminPublicKey, - }); + { + UserPublicKeyBase58Check, + Username, + IsBlacklistUpdate, + RemoveEverywhere, + RemoveFromLeaderboard, + IsWhitelistUpdate, + WhitelistPosts, + RemovePhoneNumberMetadata, + AdminPublicKey, + } + ); } - AdminResetPhoneNumber(endpoint: string, AdminPublicKey: string, PhoneNumber: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminResetPhoneNumber, AdminPublicKey, { - PhoneNumber, + AdminResetPhoneNumber( + endpoint: string, + AdminPublicKey: string, + PhoneNumber: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminResetPhoneNumber, AdminPublicKey, - }); + { + PhoneNumber, + AdminPublicKey, + } + ); } - AdminGetAllUserGlobalMetadata(endpoint: string, AdminPublicKey: string, NumToFetch: number): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetAllUserGlobalMetadata, AdminPublicKey, { + AdminGetAllUserGlobalMetadata( + endpoint: string, + AdminPublicKey: string, + NumToFetch: number + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetAllUserGlobalMetadata, AdminPublicKey, - NumToFetch, - }); + { + AdminPublicKey, + NumToFetch, + } + ); } - AdminPinPost(endpoint: string, AdminPublicKey: string, PostHashHex: string, UnpinPost: boolean): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminPinPost, AdminPublicKey, { + AdminPinPost( + endpoint: string, + AdminPublicKey: string, + PostHashHex: string, + UnpinPost: boolean + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminPinPost, AdminPublicKey, - PostHashHex, - UnpinPost, - }); + { + AdminPublicKey, + PostHashHex, + UnpinPost, + } + ); } AdminUpdateGlobalFeed( @@ -2085,18 +2564,32 @@ export class BackendApiService { PostHashHex: string, RemoveFromGlobalFeed: boolean ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateGlobalFeed, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateGlobalFeed, AdminPublicKey, - PostHashHex, - RemoveFromGlobalFeed, - }); + { + AdminPublicKey, + PostHashHex, + RemoveFromGlobalFeed, + } + ); } - AdminRemoveNilPosts(endpoint: string, AdminPublicKey: string, NumPostsToSearch: number = 1000): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminRemoveNilPosts, AdminPublicKey, { + AdminRemoveNilPosts( + endpoint: string, + AdminPublicKey: string, + NumPostsToSearch: number = 1000 + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminRemoveNilPosts, AdminPublicKey, - NumPostsToSearch, - }); + { + AdminPublicKey, + NumPostsToSearch, + } + ); } AdminReprocessBitcoinBlock( @@ -2114,10 +2607,18 @@ export class BackendApiService { ); } - AdminGetMempoolStats(endpoint: string, AdminPublicKey: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetMempoolStats, AdminPublicKey, { + AdminGetMempoolStats( + endpoint: string, + AdminPublicKey: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetMempoolStats, AdminPublicKey, - }); + { + AdminPublicKey, + } + ); } AdminGetUnfilteredHotFeed( @@ -2126,17 +2627,30 @@ export class BackendApiService { ResponseLimit: number, SeenPosts: Array ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetUnfilteredHotFeed, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetUnfilteredHotFeed, AdminPublicKey, - ResponseLimit, - SeenPosts, - }); + { + AdminPublicKey, + ResponseLimit, + SeenPosts, + } + ); } - AdminGetHotFeedAlgorithm(endpoint: string, AdminPublicKey: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetHotFeedAlgorithm, AdminPublicKey, { + AdminGetHotFeedAlgorithm( + endpoint: string, + AdminPublicKey: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetHotFeedAlgorithm, AdminPublicKey, - }); + { + AdminPublicKey, + } + ); } AdminUpdateHotFeedAlgorithm( @@ -2148,14 +2662,19 @@ export class BackendApiService { TimeDecayBlocksTag: number, TxnTypeMultiplierMap: { [txnType: number]: number } ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateHotFeedAlgorithm, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateHotFeedAlgorithm, AdminPublicKey, - InteractionCap, - InteractionCapTag, - TimeDecayBlocks, - TimeDecayBlocksTag, - TxnTypeMultiplierMap, - }); + { + AdminPublicKey, + InteractionCap, + InteractionCapTag, + TimeDecayBlocks, + TimeDecayBlocksTag, + TxnTypeMultiplierMap, + } + ); } AdminUpdateHotFeedPostMultiplier( @@ -2164,11 +2683,16 @@ export class BackendApiService { PostHashHex: string, Multiplier: number ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateHotFeedPostMultiplier, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateHotFeedPostMultiplier, AdminPublicKey, - PostHashHex, - Multiplier, - }); + { + AdminPublicKey, + PostHashHex, + Multiplier, + } + ); } AdminUpdateHotFeedUserMultiplier( @@ -2178,19 +2702,33 @@ export class BackendApiService { InteractionMultiplier: number, PostsMultiplier: number ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateHotFeedUserMultiplier, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateHotFeedUserMultiplier, AdminPublicKey, - Username, - InteractionMultiplier, - PostsMultiplier, - }); + { + AdminPublicKey, + Username, + InteractionMultiplier, + PostsMultiplier, + } + ); } - AdminGetHotFeedUserMultiplier(endpoint: string, AdminPublicKey: string, Username: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetHotFeedUserMultiplier, AdminPublicKey, { + AdminGetHotFeedUserMultiplier( + endpoint: string, + AdminPublicKey: string, + Username: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetHotFeedUserMultiplier, AdminPublicKey, - Username, - }); + { + AdminPublicKey, + Username, + } + ); } SwapIdentity( @@ -2200,15 +2738,24 @@ export class BackendApiService { ToUsernameOrPublicKeyBase58Check: string, MinFeeRateNanosPerKB: number ): Observable { - const request = this.jwtPost(endpoint, BackendRoutes.RoutePathSwapIdentity, UpdaterPublicKeyBase58Check, { + const request = this.jwtPost( + endpoint, + BackendRoutes.RoutePathSwapIdentity, UpdaterPublicKeyBase58Check, - FromUsernameOrPublicKeyBase58Check, - ToUsernameOrPublicKeyBase58Check, - MinFeeRateNanosPerKB, - AdminPublicKey: UpdaterPublicKeyBase58Check, - }); + { + UpdaterPublicKeyBase58Check, + FromUsernameOrPublicKeyBase58Check, + ToUsernameOrPublicKeyBase58Check, + MinFeeRateNanosPerKB, + AdminPublicKey: UpdaterPublicKeyBase58Check, + } + ); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } SetUSDCentsToDeSoReserveExchangeRate( @@ -2216,21 +2763,38 @@ export class BackendApiService { AdminPublicKey: string, USDCentsPerDeSo: number ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathSetUSDCentsToDeSoReserveExchangeRate, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathSetUSDCentsToDeSoReserveExchangeRate, AdminPublicKey, - USDCentsPerDeSo, - }); + { + AdminPublicKey, + USDCentsPerDeSo, + } + ); } GetUSDCentsToDeSoReserveExchangeRate(endpoint: string): Observable { - return this.get(endpoint, BackendRoutes.RoutePathGetUSDCentsToDeSoReserveExchangeRate); + return this.get( + endpoint, + BackendRoutes.RoutePathGetUSDCentsToDeSoReserveExchangeRate + ); } - SetBuyDeSoFeeBasisPoints(endpoint: string, AdminPublicKey: string, BuyDeSoFeeBasisPoints: number): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathSetBuyDeSoFeeBasisPoints, AdminPublicKey, { + SetBuyDeSoFeeBasisPoints( + endpoint: string, + AdminPublicKey: string, + BuyDeSoFeeBasisPoints: number + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathSetBuyDeSoFeeBasisPoints, AdminPublicKey, - BuyDeSoFeeBasisPoints, - }); + { + AdminPublicKey, + BuyDeSoFeeBasisPoints, + } + ); } GetBuyDeSoFeeBasisPoints(endpoint: string): Observable { @@ -2247,30 +2811,51 @@ export class BackendApiService { CreateNFTFeeNanos: number, MinFeeRateNanosPerKB: number ): Observable { - const request = this.jwtPost(endpoint, BackendRoutes.RoutePathUpdateGlobalParams, UpdaterPublicKeyBase58Check, { + const request = this.jwtPost( + endpoint, + BackendRoutes.RoutePathUpdateGlobalParams, UpdaterPublicKeyBase58Check, - USDCentsPerBitcoin, - CreateProfileFeeNanos, - MaxCopiesPerNFT, - CreateNFTFeeNanos, - MinimumNetworkFeeNanosPerKB, - MinFeeRateNanosPerKB, - AdminPublicKey: UpdaterPublicKeyBase58Check, - }); - return this.signAndSubmitTransaction(endpoint, request, UpdaterPublicKeyBase58Check); + { + UpdaterPublicKeyBase58Check, + USDCentsPerBitcoin, + CreateProfileFeeNanos, + MaxCopiesPerNFT, + CreateNFTFeeNanos, + MinimumNetworkFeeNanosPerKB, + MinFeeRateNanosPerKB, + AdminPublicKey: UpdaterPublicKeyBase58Check, + } + ); + return this.signAndSubmitTransaction( + endpoint, + request, + UpdaterPublicKeyBase58Check + ); } - GetGlobalParams(endpoint: string, UpdaterPublicKeyBase58Check: string): Observable { + GetGlobalParams( + endpoint: string, + UpdaterPublicKeyBase58Check: string + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetGlobalParams, { UpdaterPublicKeyBase58Check, }); } - AdminGetNFTDrop(endpoint: string, UpdaterPublicKeyBase58Check: string, DropNumber: number): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetNFTDrop, UpdaterPublicKeyBase58Check, { - DropNumber, - AdminPublicKey: UpdaterPublicKeyBase58Check, - }); + AdminGetNFTDrop( + endpoint: string, + UpdaterPublicKeyBase58Check: string, + DropNumber: number + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetNFTDrop, + UpdaterPublicKeyBase58Check, + { + DropNumber, + AdminPublicKey: UpdaterPublicKeyBase58Check, + } + ); } AdminUpdateNFTDrop( @@ -2282,14 +2867,19 @@ export class BackendApiService { NFTHashHexToAdd: string, NFTHashHexToRemove: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateNFTDrop, UpdaterPublicKeyBase58Check, { - DropNumber, - DropTstampNanos, - IsActive, - NFTHashHexToAdd, - NFTHashHexToRemove, - AdminPublicKey: UpdaterPublicKeyBase58Check, - }); + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateNFTDrop, + UpdaterPublicKeyBase58Check, + { + DropNumber, + DropTstampNanos, + IsActive, + NFTHashHexToAdd, + NFTHashHexToRemove, + AdminPublicKey: UpdaterPublicKeyBase58Check, + } + ); } EvictUnminedBitcoinTxns( @@ -2298,14 +2888,22 @@ export class BackendApiService { BitcoinTxnHashes: string[], DryRun: boolean ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathEvictUnminedBitcoinTxns, UpdaterPublicKeyBase58Check, { - BitcoinTxnHashes, - DryRun, - AdminPublicKey: UpdaterPublicKeyBase58Check, - }); + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathEvictUnminedBitcoinTxns, + UpdaterPublicKeyBase58Check, + { + BitcoinTxnHashes, + DryRun, + AdminPublicKey: UpdaterPublicKeyBase58Check, + } + ); } - GetFullTikTokURL(endpoint: string, TikTokShortVideoID: string): Observable { + GetFullTikTokURL( + endpoint: string, + TikTokShortVideoID: string + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetFullTikTokURL, { TikTokShortVideoID, }).pipe( @@ -2321,32 +2919,64 @@ export class BackendApiService { PublicKeyBase58Check: string, Username: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminResetJumioForPublicKey, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminResetJumioForPublicKey, AdminPublicKey, - PublicKeyBase58Check, - Username, - }); + { + AdminPublicKey, + PublicKeyBase58Check, + Username, + } + ); } - AdminUpdateJumioDeSo(endpoint: string, AdminPublicKey: string, DeSoNanos: number): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateJumioDeSo, AdminPublicKey, { - DeSoNanos, + AdminUpdateJumioDeSo( + endpoint: string, + AdminPublicKey: string, + DeSoNanos: number + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateJumioDeSo, AdminPublicKey, - }); + { + DeSoNanos, + AdminPublicKey, + } + ); } - AdminUpdateJumioUSDCents(endpoint: string, AdminPublicKey: string, USDCents: number): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateJumioUSDCents, AdminPublicKey, { + AdminUpdateJumioUSDCents( + endpoint: string, + AdminPublicKey: string, + USDCents: number + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateJumioUSDCents, AdminPublicKey, - USDCents, - }); + { + AdminPublicKey, + USDCents, + } + ); } - AdminUpdateJumioKickbackUSDCents(endpoint: string, AdminPublicKey: string, USDCents: number): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateJumioKickbackUSDCents, AdminPublicKey, { + AdminUpdateJumioKickbackUSDCents( + endpoint: string, + AdminPublicKey: string, + USDCents: number + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateJumioKickbackUSDCents, AdminPublicKey, - USDCents, - }); + { + AdminPublicKey, + USDCents, + } + ); } AdminJumioCallback( @@ -2354,14 +2984,19 @@ export class BackendApiService { AdminPublicKey: string, PublicKeyBase58Check: string, Username: string, - CountryAlpha3: string = "" + CountryAlpha3: string = '' ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminJumioCallback, AdminPublicKey, { - PublicKeyBase58Check, - Username, + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminJumioCallback, AdminPublicKey, - CountryAlpha3, - }); + { + PublicKeyBase58Check, + Username, + AdminPublicKey, + CountryAlpha3, + } + ); } AdminGetAllCountryLevelSignUpBonuses( @@ -2371,9 +3006,14 @@ export class BackendApiService { SignUpBonusMetadata: { [k: string]: CountryLevelSignUpBonusResponse }; DefaultSignUpBonusMetadata: CountryLevelSignUpBonus; }> { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetAllCountryLevelSignUpBonuses, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetAllCountryLevelSignUpBonuses, AdminPublicKey, - }); + { + AdminPublicKey, + } + ); } AdminUpdateJumioCountrySignUpBonus( @@ -2382,11 +3022,16 @@ export class BackendApiService { CountryCode: string, CountryLevelSignUpBonus: CountryLevelSignUpBonus ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateJumioCountrySignUpBonus, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateJumioCountrySignUpBonus, AdminPublicKey, - CountryCode, - CountryLevelSignUpBonus, - }); + { + AdminPublicKey, + CountryCode, + CountryLevelSignUpBonus, + } + ); } AdminCreateReferralHash( @@ -2399,15 +3044,20 @@ export class BackendApiService { MaxReferrals: number, RequiresJumio: boolean ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminCreateReferralHash, AdminPublicKey, { - UserPublicKeyBase58Check, - Username, - ReferrerAmountUSDCents, - RefereeAmountUSDCents, - MaxReferrals, - RequiresJumio, + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminCreateReferralHash, AdminPublicKey, - }); + { + UserPublicKeyBase58Check, + Username, + ReferrerAmountUSDCents, + RefereeAmountUSDCents, + MaxReferrals, + RequiresJumio, + AdminPublicKey, + } + ); } AdminUpdateReferralHash( @@ -2420,15 +3070,20 @@ export class BackendApiService { RequiresJumio: boolean, IsActive: boolean ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateReferralHash, AdminPublicKey, { - ReferralHashBase58, - ReferrerAmountUSDCents, - RefereeAmountUSDCents, - MaxReferrals, - RequiresJumio, - IsActive, + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateReferralHash, AdminPublicKey, - }); + { + ReferralHashBase58, + ReferrerAmountUSDCents, + RefereeAmountUSDCents, + MaxReferrals, + RequiresJumio, + IsActive, + AdminPublicKey, + } + ); } AdminGetAllReferralInfoForUser( @@ -2437,55 +3092,100 @@ export class BackendApiService { UserPublicKeyBase58Check: string, Username: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetAllReferralInfoForUser, AdminPublicKey, { - UserPublicKeyBase58Check, - Username, + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetAllReferralInfoForUser, AdminPublicKey, - }); + { + UserPublicKeyBase58Check, + Username, + AdminPublicKey, + } + ); } - AdminDownloadReferralCSV(endpoint: string, AdminPublicKey: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminDownloadReferralCSV, AdminPublicKey, { + AdminDownloadReferralCSV( + endpoint: string, + AdminPublicKey: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminDownloadReferralCSV, AdminPublicKey, - }); + { + AdminPublicKey, + } + ); } - AdminUploadReferralCSV(endpoint: string, AdminPublicKey: string, file: File): Observable { + AdminUploadReferralCSV( + endpoint: string, + AdminPublicKey: string, + file: File + ): Observable { const request = this.identityService.jwt({ ...this.identityService.identityServiceParamsForKey(AdminPublicKey), }); return request.pipe( switchMap((signed) => { const formData = new FormData(); - formData.append("file", file); - formData.append("UserPublicKeyBase58Check", AdminPublicKey); - formData.append("JWT", signed.jwt); - - return this.post(endpoint, BackendRoutes.RoutePathAdminUploadReferralCSV, formData); + formData.append('file', file); + formData.append('UserPublicKeyBase58Check', AdminPublicKey); + formData.append('JWT', signed.jwt); + + return this.post( + endpoint, + BackendRoutes.RoutePathAdminUploadReferralCSV, + formData + ); }) ); } - GetReferralInfoForUser(endpoint: string, PublicKeyBase58Check: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathGetReferralInfoForUser, PublicKeyBase58Check, { + GetReferralInfoForUser( + endpoint: string, + PublicKeyBase58Check: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathGetReferralInfoForUser, PublicKeyBase58Check, - }); + { + PublicKeyBase58Check, + } + ); } GetReferralInfoForReferralHash( endpoint: string, ReferralHash: string - ): Observable<{ ReferralInfoResponse: any; CountrySignUpBonus: CountryLevelSignUpBonus }> { - return this.post(endpoint, BackendRoutes.RoutePathGetReferralInfoForReferralHash, { - ReferralHash, - }); + ): Observable<{ + ReferralInfoResponse: any; + CountrySignUpBonus: CountryLevelSignUpBonus; + }> { + return this.post( + endpoint, + BackendRoutes.RoutePathGetReferralInfoForReferralHash, + { + ReferralHash, + } + ); } - AdminResetTutorialStatus(endpoint: string, AdminPublicKey: string, PublicKeyBase58Check: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminResetTutorialStatus, AdminPublicKey, { - PublicKeyBase58Check, + AdminResetTutorialStatus( + endpoint: string, + AdminPublicKey: string, + PublicKeyBase58Check: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminResetTutorialStatus, AdminPublicKey, - }); + { + PublicKeyBase58Check, + AdminPublicKey, + } + ); } AdminUpdateTutorialCreators( @@ -2495,27 +3195,45 @@ export class BackendApiService { IsRemoval: boolean, IsWellKnown: boolean ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateTutorialCreators, AdminPublicKey, { - PublicKeyBase58Check, - IsRemoval, - IsWellKnown, + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminUpdateTutorialCreators, AdminPublicKey, - }); + { + PublicKeyBase58Check, + IsRemoval, + IsWellKnown, + AdminPublicKey, + } + ); } - GetTutorialCreators(endpoint: string, PublicKeyBase58Check: string, ResponseLimit: number): Observable { + GetTutorialCreators( + endpoint: string, + PublicKeyBase58Check: string, + ResponseLimit: number + ): Observable { return this.post(endpoint, BackendRoutes.RoutePathGetTutorialCreators, { ResponseLimit, PublicKeyBase58Check, }); } - AdminGetTutorialCreators(endpoint: string, PublicKeyBase58Check: string, ResponseLimit: number): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetTutorialCreators, PublicKeyBase58Check, { - ResponseLimit, + AdminGetTutorialCreators( + endpoint: string, + PublicKeyBase58Check: string, + ResponseLimit: number + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetTutorialCreators, PublicKeyBase58Check, - AdminPublicKey: PublicKeyBase58Check, - }); + { + ResponseLimit, + PublicKeyBase58Check, + AdminPublicKey: PublicKeyBase58Check, + } + ); } GetWyreWalletOrderForPublicKey( @@ -2524,11 +3242,16 @@ export class BackendApiService { PublicKeyBase58Check: string, Username: string ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathGetWyreWalletOrdersForPublicKey, AdminPublicKeyBase58Check, { - AdminPublicKey: AdminPublicKeyBase58Check, - PublicKeyBase58Check, - Username, - }); + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathGetWyreWalletOrdersForPublicKey, + AdminPublicKeyBase58Check, + { + AdminPublicKey: AdminPublicKeyBase58Check, + PublicKeyBase58Check, + Username, + } + ); } // Wyre @@ -2538,11 +3261,15 @@ export class BackendApiService { Country: string, SourceCurrency: string ): Observable { - return this.post(endpoint, BackendRoutes.RoutePathGetWyreWalletOrderQuotation, { - SourceAmount, - Country, - SourceCurrency, - }); + return this.post( + endpoint, + BackendRoutes.RoutePathGetWyreWalletOrderQuotation, + { + SourceAmount, + Country, + SourceCurrency, + } + ); } GetWyreWalletOrderReservation( @@ -2552,12 +3279,16 @@ export class BackendApiService { Country: string, SourceCurrency: string ): Observable { - return this.post(endpoint, BackendRoutes.RoutePathGetWyreWalletOrderReservation, { - ReferenceId, - SourceAmount, - Country, - SourceCurrency, - }); + return this.post( + endpoint, + BackendRoutes.RoutePathGetWyreWalletOrderReservation, + { + ReferenceId, + SourceAmount, + Country, + SourceCurrency, + } + ); } // Admin Node Fee Endpoints @@ -2567,11 +3298,16 @@ export class BackendApiService { TransactionType: string, NewTransactionFees: TransactionFee[] ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminSetTransactionFeeForTransactionType, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminSetTransactionFeeForTransactionType, AdminPublicKey, - TransactionType, - NewTransactionFees, - }); + { + AdminPublicKey, + TransactionType, + NewTransactionFees, + } + ); } AdminSetAllTransactionFees( @@ -2579,16 +3315,29 @@ export class BackendApiService { AdminPublicKey: string, NewTransactionFees: TransactionFee[] ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminSetAllTransactionFees, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminSetAllTransactionFees, AdminPublicKey, - NewTransactionFees, - }); + { + AdminPublicKey, + NewTransactionFees, + } + ); } - AdminGetTransactionFeeMap(endpoint: string, AdminPublicKey: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetTransactionFeeMap, AdminPublicKey, { + AdminGetTransactionFeeMap( + endpoint: string, + AdminPublicKey: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetTransactionFeeMap, AdminPublicKey, - }); + { + AdminPublicKey, + } + ); } AdminAddExemptPublicKey( @@ -2597,35 +3346,68 @@ export class BackendApiService { PublicKeyBase58Check: string, IsRemoval: boolean ): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminAddExemptPublicKey, AdminPublicKey, { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminAddExemptPublicKey, AdminPublicKey, - PublicKeyBase58Check, - IsRemoval, - }); + { + AdminPublicKey, + PublicKeyBase58Check, + IsRemoval, + } + ); } - AdminGetExemptPublicKeys(endpoint: string, AdminPublicKey: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetExemptPublicKeys, AdminPublicKey, { + AdminGetExemptPublicKeys( + endpoint: string, + AdminPublicKey: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathAdminGetExemptPublicKeys, AdminPublicKey, - }); + { + AdminPublicKey, + } + ); } // Tutorial Endpoints - StartOrSkipTutorial(endpoint: string, PublicKeyBase58Check: string, IsSkip: boolean): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathStartOrSkipTutorial, PublicKeyBase58Check, { + StartOrSkipTutorial( + endpoint: string, + PublicKeyBase58Check: string, + IsSkip: boolean + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathStartOrSkipTutorial, PublicKeyBase58Check, - IsSkip, - }); + { + PublicKeyBase58Check, + IsSkip, + } + ); } - CompleteTutorial(endpoint: string, PublicKeyBase58Check: string): Observable { - return this.jwtPost(endpoint, BackendRoutes.RoutePathCompleteTutorial, PublicKeyBase58Check, { + CompleteTutorial( + endpoint: string, + PublicKeyBase58Check: string + ): Observable { + return this.jwtPost( + endpoint, + BackendRoutes.RoutePathCompleteTutorial, PublicKeyBase58Check, - }); + { + PublicKeyBase58Check, + } + ); } GetVideoStatus(endpoint: string, videoId: string): Observable { - return this.get(endpoint, `${BackendRoutes.RoutePathGetVideoStatus}/${videoId}`); + return this.get( + endpoint, + `${BackendRoutes.RoutePathGetVideoStatus}/${videoId}` + ); } GetTotalSupply(endpoint: string): Observable { @@ -2657,14 +3439,17 @@ export class BackendApiService { let errorMessage = JSON.stringify(err); if (err && err.error && err.error.error) { errorMessage = err.error.error; - if (errorMessage.indexOf("not sufficient") >= 0) { + if (errorMessage.indexOf('not sufficient') >= 0) { errorMessage = `Your balance is insufficient.`; - } else if (errorMessage.indexOf("with password") >= 0) { - errorMessage = "The password you entered was incorrect."; - } else if (errorMessage.indexOf("RuleErrorExistingStakeExceedsMaxAllowed") >= 0) { - errorMessage = "Another staker staked to this post right before you. Please try again."; - } else if (errorMessage.indexOf("already has stake") >= 0) { - errorMessage = "You cannot stake to the same post more than once."; + } else if (errorMessage.indexOf('with password') >= 0) { + errorMessage = 'The password you entered was incorrect.'; + } else if ( + errorMessage.indexOf('RuleErrorExistingStakeExceedsMaxAllowed') >= 0 + ) { + errorMessage = + 'Another staker staked to this post right before you. Please try again.'; + } else if (errorMessage.indexOf('already has stake') >= 0) { + errorMessage = 'You cannot stake to the same post more than once.'; } } return errorMessage; @@ -2678,30 +3463,48 @@ export class BackendApiService { let errorMessage = JSON.stringify(err); if (err && err.error && err.error.error) { errorMessage = err.error.error; - if (errorMessage.indexOf("not sufficient") >= 0) { + if (errorMessage.indexOf('not sufficient') >= 0) { errorMessage = `Your balance is insufficient.`; - } else if (errorMessage.indexOf("with password") >= 0) { - errorMessage = "The password you entered was incorrect."; - } else if (errorMessage.indexOf("RuleErrorExistingStakeExceedsMaxAllowed") >= 0) { - errorMessage = "Another staker staked to this profile right before you. Please try again."; - } else if (errorMessage.indexOf("already has stake") >= 0) { - errorMessage = "You cannot stake to the same profile more than once."; - } else if (errorMessage.indexOf("RuleErrorProfileUsernameExists") >= 0) { - errorMessage = "Sorry, someone has already taken this username."; - } else if (errorMessage.indexOf("RuleErrorUserDescriptionLen") >= 0) { - errorMessage = "Your description is too long."; - } else if (errorMessage.indexOf("RuleErrorProfileUsernameTooLong") >= 0) { - errorMessage = "Your username is too long."; - } else if (errorMessage.indexOf("RuleErrorInvalidUsername") >= 0) { + } else if (errorMessage.indexOf('with password') >= 0) { + errorMessage = 'The password you entered was incorrect.'; + } else if ( + errorMessage.indexOf('RuleErrorExistingStakeExceedsMaxAllowed') >= 0 + ) { + errorMessage = + 'Another staker staked to this profile right before you. Please try again.'; + } else if (errorMessage.indexOf('already has stake') >= 0) { + errorMessage = 'You cannot stake to the same profile more than once.'; + } else if (errorMessage.indexOf('RuleErrorProfileUsernameExists') >= 0) { + errorMessage = 'Sorry, someone has already taken this username.'; + } else if (errorMessage.indexOf('RuleErrorUserDescriptionLen') >= 0) { + errorMessage = 'Your description is too long.'; + } else if (errorMessage.indexOf('RuleErrorProfileUsernameTooLong') >= 0) { + errorMessage = 'Your username is too long.'; + } else if (errorMessage.indexOf('RuleErrorInvalidUsername') >= 0) { + errorMessage = + 'Your username contains invalid characters. Usernames can only numbers, English letters, and underscores.'; + } else if ( + errorMessage.indexOf('RuleErrorCreatorCoinTransferInsufficientCoins') >= + 0 + ) { + errorMessage = + 'You need more of your own creator coin to give a diamond of this level.'; + } else if ( + errorMessage.indexOf('RuleErrorInputSpendsPreviouslySpentOutput') >= 0 + ) { errorMessage = - "Your username contains invalid characters. Usernames can only numbers, English letters, and underscores."; - } else if (errorMessage.indexOf("RuleErrorCreatorCoinTransferInsufficientCoins") >= 0) { - errorMessage = "You need more of your own creator coin to give a diamond of this level."; - } else if (errorMessage.indexOf("RuleErrorInputSpendsPreviouslySpentOutput") >= 0) { - errorMessage = "You're doing that a bit too quickly. Please wait a second or two and try again."; - } else if (errorMessage.indexOf("RuleErrorCreatorCoinTransferBalanceEntryDoesNotExist") >= 0) { - errorMessage = "You must own this creator coin before transferring it."; - } else if (errorMessage.indexOf("RuleErrorCreatorCoinBuyMustTradeNonZeroDeSoAfterFounderReward") >= 0) { + "You're doing that a bit too quickly. Please wait a second or two and try again."; + } else if ( + errorMessage.indexOf( + 'RuleErrorCreatorCoinTransferBalanceEntryDoesNotExist' + ) >= 0 + ) { + errorMessage = 'You must own this creator coin before transferring it.'; + } else if ( + errorMessage.indexOf( + 'RuleErrorCreatorCoinBuyMustTradeNonZeroDeSoAfterFounderReward' + ) >= 0 + ) { errorMessage = "This creator has set their founder's reward to 100%. " + "You cannot buy creators that have set their founder's reward to 100%."; @@ -2718,13 +3521,17 @@ export class BackendApiService { let errorMessage = JSON.stringify(err); if (err && err.error && err.error.error) { errorMessage = err.error.error; - if (errorMessage.indexOf("not sufficient") >= 0) { + if (errorMessage.indexOf('not sufficient') >= 0) { errorMessage = `Your balance is insufficient.`; - } else if (errorMessage.indexOf("with password") >= 0) { - errorMessage = "The password you entered was incorrect."; - } else if (errorMessage.indexOf("RuleErrorPrivateMessageSenderPublicKeyEqualsRecipientPublicKey") >= 0) { + } else if (errorMessage.indexOf('with password') >= 0) { + errorMessage = 'The password you entered was incorrect.'; + } else if ( + errorMessage.indexOf( + 'RuleErrorPrivateMessageSenderPublicKeyEqualsRecipientPublicKey' + ) >= 0 + ) { errorMessage = `You can't message yourself.`; - } else if (errorMessage.indexOf("Problem decoding recipient") >= 0) { + } else if (errorMessage.indexOf('Problem decoding recipient') >= 0) { errorMessage = `The public key you entered is invalid. Check that you copied it in correctly.`; } } diff --git a/src/app/bid-placed-modal/bid-placed-modal.component.html b/src/app/bid-placed-modal/bid-placed-modal.component.html index 309b8d417..b06d1d352 100644 --- a/src/app/bid-placed-modal/bid-placed-modal.component.html +++ b/src/app/bid-placed-modal/bid-placed-modal.component.html @@ -1,10 +1,18 @@
- +
Your bid was successful. We will notify you when the auction closes.
-
Explore the Showcase
+
+ Explore the Showcase +
diff --git a/src/app/bid-placed-modal/bid-placed-modal.component.ts b/src/app/bid-placed-modal/bid-placed-modal.component.ts index 7a64e0c14..4c90f67a2 100644 --- a/src/app/bid-placed-modal/bid-placed-modal.component.ts +++ b/src/app/bid-placed-modal/bid-placed-modal.component.ts @@ -1,10 +1,10 @@ -import { Component } from "@angular/core"; -import { BsModalRef, BsModalService } from "ngx-bootstrap/modal"; -import { GlobalVarsService } from "../global-vars.service"; +import { Component } from '@angular/core'; +import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; +import { GlobalVarsService } from '../global-vars.service'; @Component({ - selector: "bid-placed-modal", - templateUrl: "./bid-placed-modal.component.html", + selector: 'bid-placed-modal', + templateUrl: './bid-placed-modal.component.html', }) export class BidPlacedModalComponent { constructor( diff --git a/src/app/bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component.spec.ts b/src/app/bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component.spec.ts index 3d109b95a..d42f02390 100644 --- a/src/app/bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component.spec.ts +++ b/src/app/bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { BottomBarMobileTabComponent } from "./bottom-bar-mobile-tab.component"; +import { BottomBarMobileTabComponent } from './bottom-bar-mobile-tab.component'; -describe("BottomBarMobileTabComponent", () => { +describe('BottomBarMobileTabComponent', () => { let component: BottomBarMobileTabComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BottomBarMobileTabComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component.ts b/src/app/bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component.ts index 521873282..347e0cf75 100644 --- a/src/app/bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component.ts +++ b/src/app/bottom-bar-mobile/bottom-bar-mobile-tab/bottom-bar-mobile-tab.component.ts @@ -1,10 +1,10 @@ -import { Component, Input, OnInit } from "@angular/core"; -import { NavigationService } from "../../../lib/services/navigation-service"; +import { Component, Input, OnInit } from '@angular/core'; +import { NavigationService } from '../../../lib/services/navigation-service'; @Component({ - selector: "bottom-bar-mobile-tab", - templateUrl: "./bottom-bar-mobile-tab.component.html", - styleUrls: ["./bottom-bar-mobile-tab.component.scss"], + selector: 'bottom-bar-mobile-tab', + templateUrl: './bottom-bar-mobile-tab.component.html', + styleUrls: ['./bottom-bar-mobile-tab.component.scss'], }) export class BottomBarMobileTabComponent { @Input() link: string; diff --git a/src/app/bottom-bar-mobile/bottom-bar-mobile.component.html b/src/app/bottom-bar-mobile/bottom-bar-mobile.component.html index e90c11c9f..95274729d 100644 --- a/src/app/bottom-bar-mobile/bottom-bar-mobile.component.html +++ b/src/app/bottom-bar-mobile/bottom-bar-mobile.component.html @@ -1,6 +1,11 @@
-
- +
+ @@ -12,7 +17,10 @@ - + @@ -31,12 +39,15 @@ >
{{ globalVars.messageResponse.NumberOfUnreadThreads > 999 - ? "999+" + ? '999+' : globalVars.messageResponse.NumberOfUnreadThreads }}
diff --git a/src/app/bottom-bar-mobile/bottom-bar-mobile.component.spec.ts b/src/app/bottom-bar-mobile/bottom-bar-mobile.component.spec.ts index 889b8296e..87834ff62 100644 --- a/src/app/bottom-bar-mobile/bottom-bar-mobile.component.spec.ts +++ b/src/app/bottom-bar-mobile/bottom-bar-mobile.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { BottomBarMobileComponent } from "./bottom-bar-mobile.component"; +import { BottomBarMobileComponent } from './bottom-bar-mobile.component'; -describe("BottomBarMobileComponent", () => { +describe('BottomBarMobileComponent', () => { let component: BottomBarMobileComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BottomBarMobileComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/bottom-bar-mobile/bottom-bar-mobile.component.ts b/src/app/bottom-bar-mobile/bottom-bar-mobile.component.ts index eb35187b6..49ccce2ee 100644 --- a/src/app/bottom-bar-mobile/bottom-bar-mobile.component.ts +++ b/src/app/bottom-bar-mobile/bottom-bar-mobile.component.ts @@ -1,10 +1,10 @@ -import { Component, Input, OnInit } from "@angular/core"; -import { GlobalVarsService } from "../global-vars.service"; +import { Component, Input, OnInit } from '@angular/core'; +import { GlobalVarsService } from '../global-vars.service'; @Component({ - selector: "bottom-bar-mobile", - templateUrl: "./bottom-bar-mobile.component.html", - styleUrls: ["./bottom-bar-mobile.component.scss"], + selector: 'bottom-bar-mobile', + templateUrl: './bottom-bar-mobile.component.html', + styleUrls: ['./bottom-bar-mobile.component.scss'], }) export class BottomBarMobileComponent { @Input() showPostButton = false; diff --git a/src/app/browse-page/browse-page.component.html b/src/app/browse-page/browse-page.component.html index 59af8a7bc..5c9be01ba 100644 --- a/src/app/browse-page/browse-page.component.html +++ b/src/app/browse-page/browse-page.component.html @@ -27,7 +27,9 @@ class="global__top-bar__height d-flex align-items-center w-100 px-15px mr-15px fs-18px font-weight-bold fc-default justify-content-between border-bottom border-color-grey" >
- + Home
@@ -51,5 +53,9 @@
- +
diff --git a/src/app/browse-page/browse-page.component.spec.ts b/src/app/browse-page/browse-page.component.spec.ts index 161c70198..3a78bf44c 100644 --- a/src/app/browse-page/browse-page.component.spec.ts +++ b/src/app/browse-page/browse-page.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { BrowsePageComponent } from "./browse-page.component"; +import { BrowsePageComponent } from './browse-page.component'; -describe("BrowseComponent", () => { +describe('BrowseComponent', () => { let component: BrowsePageComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BrowseComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/browse-page/browse-page.component.ts b/src/app/browse-page/browse-page.component.ts index 3a86f779e..02837408d 100644 --- a/src/app/browse-page/browse-page.component.ts +++ b/src/app/browse-page/browse-page.component.ts @@ -1,12 +1,12 @@ -import { Component, HostListener, OnInit } from "@angular/core"; -import { GlobalVarsService } from "../global-vars.service"; -import { FeedComponent } from "../feed/feed.component"; -import { Router } from "@angular/router"; +import { Component, HostListener, OnInit } from '@angular/core'; +import { GlobalVarsService } from '../global-vars.service'; +import { FeedComponent } from '../feed/feed.component'; +import { Router } from '@angular/router'; @Component({ - selector: "browse-page", - templateUrl: "./browse-page.component.html", - styleUrls: ["./browse-page.component.sass"], + selector: 'browse-page', + templateUrl: './browse-page.component.html', + styleUrls: ['./browse-page.component.sass'], }) export class BrowsePageComponent implements OnInit { FeedComponent = FeedComponent; @@ -21,7 +21,7 @@ export class BrowsePageComponent implements OnInit { this.mobile = this.globalVars.isMobile(); } - @HostListener("window:resize") + @HostListener('window:resize') onResize() { this.setMobileBasedOnViewport(); } diff --git a/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.html b/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.html index 7886ed482..731bce551 100644 --- a/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.html +++ b/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.html @@ -2,7 +2,9 @@
- +  Buy Complete @@ -23,19 +25,27 @@
- Use $DESO to buy creator coins. Collect your favorite creators and get on their team! + Use $DESO to buy creator coins. Collect your favorite creators and get on + their team!
-
+
Next
diff --git a/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.spec.ts b/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.spec.ts index fa286cb43..1c126612d 100644 --- a/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.spec.ts +++ b/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { BuyDeSoCompleteComponent } from "./buy-deso-complete.component"; +import { BuyDeSoCompleteComponent } from './buy-deso-complete.component'; -describe("BuyDeSoCompleteComponent", () => { +describe('BuyDeSoCompleteComponent', () => { let component: BuyDeSoCompleteComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BuyDeSoCompleteComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.ts b/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.ts index aea48ef66..5984f601d 100644 --- a/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.ts +++ b/src/app/buy-deso-page/buy-deso-complete/buy-deso-complete.component.ts @@ -1,10 +1,10 @@ -import { Component, EventEmitter, OnInit, Output } from "@angular/core"; -import { GlobalVarsService } from "../../global-vars.service"; +import { Component, EventEmitter, OnInit, Output } from '@angular/core'; +import { GlobalVarsService } from '../../global-vars.service'; @Component({ - selector: "buy-deso-complete", - templateUrl: "./buy-deso-complete.component.html", - styleUrls: ["./buy-deso-complete.component.scss"], + selector: 'buy-deso-complete', + templateUrl: './buy-deso-complete.component.html', + styleUrls: ['./buy-deso-complete.component.scss'], }) export class BuyDeSoCompleteComponent implements OnInit { @Output() buyMoreDeSoClicked = new EventEmitter(); diff --git a/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.html b/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.html index 67ce0a98f..bbad9a06f 100644 --- a/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.html +++ b/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.html @@ -33,9 +33,7 @@
Minimum deposit is currently - - {{ (ethFeeEstimate * 2).toFixed(4) }} ETH - + {{ (ethFeeEstimate * 2).toFixed(4) }} ETH
-
+
Includes {{ globalVars.BuyDeSoFeeBasisPoints / 100 }}% slippage
@@ -201,7 +202,10 @@ {{ ethFeeEstimate.toFixed(8) }} ETH ≈ {{ - globalVars.formatUSD(ethFeeEstimate * globalVars.usdPerETHExchangeRate, 2) + globalVars.formatUSD( + ethFeeEstimate * globalVars.usdPerETHExchangeRate, + 2 + ) }} USD
@@ -216,12 +220,13 @@ Total ETH to swap
- {{ - ethToExchange.toFixed(8) - }} + {{ ethToExchange.toFixed(8) }} ETH ≈ {{ - globalVars.formatUSD(ethToExchange * globalVars.usdPerETHExchangeRate, 2) + globalVars.formatUSD( + ethToExchange * globalVars.usdPerETHExchangeRate, + 2 + ) }} USD
@@ -231,10 +236,7 @@
-
+
{{ error }}
diff --git a/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.spec.ts b/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.spec.ts index 47b58b722..2891a24b5 100644 --- a/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.spec.ts +++ b/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { BuyDeSoEthComponent } from "./buy-deso-eth.component"; +import { BuyDeSoEthComponent } from './buy-deso-eth.component'; -describe("BuyDeSoEthComponent", () => { +describe('BuyDeSoEthComponent', () => { let component: BuyDeSoEthComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BuyDeSoEthComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.ts b/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.ts index 6cb220142..6ca06dd81 100644 --- a/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.ts +++ b/src/app/buy-deso-page/buy-deso-eth/buy-deso-eth.component.ts @@ -1,17 +1,22 @@ -import { Component, Input, OnInit } from "@angular/core"; -import { GlobalVarsService } from "../../global-vars.service"; -import { BackendApiService } from "../../backend-api.service"; -import { sprintf } from "sprintf-js"; -import { SwalHelper } from "../../../lib/helpers/swal-helper"; -import { IdentityService } from "../../identity.service"; -import { BuyDeSoComponent } from "../buy-deso/buy-deso.component"; -import { fromWei, hexToNumber, toHex, toBN, toWei } from "web3-utils"; -import { Hex } from "web3-utils/types"; -import Common, { Chain, Hardfork } from "@ethereumjs/common"; -import { FeeMarketEIP1559Transaction, Transaction as LegacyTransaction, TxData, TxOptions } from "@ethereumjs/tx"; -import { FeeMarketEIP1559TxData } from "@ethereumjs/tx/src/types"; -import { Transaction, TransactionOptions } from "ethereumjs-tx"; -import { BN } from "ethereumjs-util"; +import { Component, Input, OnInit } from '@angular/core'; +import { GlobalVarsService } from '../../global-vars.service'; +import { BackendApiService } from '../../backend-api.service'; +import { sprintf } from 'sprintf-js'; +import { SwalHelper } from '../../../lib/helpers/swal-helper'; +import { IdentityService } from '../../identity.service'; +import { BuyDeSoComponent } from '../buy-deso/buy-deso.component'; +import { fromWei, hexToNumber, toHex, toBN, toWei } from 'web3-utils'; +import { Hex } from 'web3-utils/types'; +import Common, { Chain, Hardfork } from '@ethereumjs/common'; +import { + FeeMarketEIP1559Transaction, + Transaction as LegacyTransaction, + TxData, + TxOptions, +} from '@ethereumjs/tx'; +import { FeeMarketEIP1559TxData } from '@ethereumjs/tx/src/types'; +import { Transaction, TransactionOptions } from 'ethereumjs-tx'; +import { BN } from 'ethereumjs-util'; class Messages { static INCORRECT_PASSWORD = `The password you entered was incorrect.`; @@ -32,9 +37,15 @@ type SignedTransaction = { toSign: string[]; }; -type TransactionType = Transaction | LegacyTransaction | FeeMarketEIP1559Transaction; +type TransactionType = + | Transaction + | LegacyTransaction + | FeeMarketEIP1559Transaction; -type TypeOfTransactionType = typeof Transaction | typeof LegacyTransaction | typeof FeeMarketEIP1559Transaction; +type TypeOfTransactionType = + | typeof Transaction + | typeof LegacyTransaction + | typeof FeeMarketEIP1559Transaction; type FeeDetails = { baseFeePerGas: BN; @@ -52,9 +63,9 @@ type FeeDetails = { }; @Component({ - selector: "buy-deso-eth", - templateUrl: "./buy-deso-eth.component.html", - styleUrls: ["./buy-deso-eth.component.scss"], + selector: 'buy-deso-eth', + templateUrl: './buy-deso-eth.component.html', + styleUrls: ['./buy-deso-eth.component.scss'], }) export class BuyDeSoEthComponent implements OnInit { @Input() parentComponent: BuyDeSoComponent; @@ -80,7 +91,7 @@ export class BuyDeSoEthComponent implements OnInit { desoToBuy = 0; // User errors - error = ""; + error = ''; common: Common; @@ -107,54 +118,54 @@ export class BuyDeSoEthComponent implements OnInit { if (ethAddress != null && user.version >= 1) { return ethAddress; } else { - return "Please re-login to generate an ETH address"; + return 'Please re-login to generate an ETH address'; } } stepOneTooltip() { return ( - "DESO can be purchased in just a few minutes using ETH.\n\n" + - "To get started, simply send ETH to your deposit address below. Note that deposits should show up " + - "within thirty seconds or so but sometimes, for various technical reasons, it can take up to an hour " + - "(though this should be extremely rare).\n\n" + + 'DESO can be purchased in just a few minutes using ETH.\n\n' + + 'To get started, simply send ETH to your deposit address below. Note that deposits should show up ' + + 'within thirty seconds or so but sometimes, for various technical reasons, it can take up to an hour ' + + '(though this should be extremely rare).\n\n' + "Once you've deposited ETH, you can swap it for DESO in step two below. If it's your first " + - "time doing this, we recommend starting with a small test amount of ETH to get comfortable with the flow." + 'time doing this, we recommend starting with a small test amount of ETH to get comfortable with the flow.' ); } depositEthTooltip() { - return "Send ETH to this address so that you can swap it for DESO in step two below."; + return 'Send ETH to this address so that you can swap it for DESO in step two below.'; } minDepositTooltip() { return ( - "This is the minimum amount required to cover the Ethereum " + - "network fees associated with your purchase. We would love to make this " + - "lower, but if we did then the Ethereum network would reject your transaction." + 'This is the minimum amount required to cover the Ethereum ' + + 'network fees associated with your purchase. We would love to make this ' + + 'lower, but if we did then the Ethereum network would reject your transaction.' ); } withdrawEthTooltip() { return ( - "If you send too much ETH to your deposit address and need to get it back, you " + - "can access the ETH in this address by importing your Seed Hex into most standard Ethereum wallets. " + + 'If you send too much ETH to your deposit address and need to get it back, you ' + + 'can access the ETH in this address by importing your Seed Hex into most standard Ethereum wallets. ' + "We don't display this easily for security purposes. To see your Seed Hex open your browser's developer " + - "tools, then select Storage -> DeSo Identity -> Users -> Public Key -> Seed Hex." + 'tools, then select Storage -> DeSo Identity -> Users -> Public Key -> Seed Hex.' ); } balanceUpdateTooltip() { return ( - "Normally, when you send ETH to the deposit address, it will show up instantly. " + - "However, it can take up to an hour in rare cases depending on where you send it from." + 'Normally, when you send ETH to the deposit address, it will show up instantly. ' + + 'However, it can take up to an hour in rare cases depending on where you send it from.' ); } ethereumNetworkFeeTooltip() { return ( - "The process of exchanging ETH for DESO requires posting a transaction to " + - "the Ethereum blockchain. For this reason, we must add a network fee to " + - "incentivize miners to process the transaction." + 'The process of exchanging ETH for DESO requires posting a transaction to ' + + 'the Ethereum blockchain. For this reason, we must add a network fee to ' + + 'incentivize miners to process the transaction.' ); } @@ -183,21 +194,25 @@ export class BuyDeSoEthComponent implements OnInit { return; } - if (this.error != null && this.error !== "") { + if (this.error != null && this.error !== '') { this.globalVars._alertError(this.error); return; } - let confirmBuyDESOString = sprintf(Messages.CONFIRM_BUY_DESO, fromWei(this.weiToExchange), this.desoToBuy); + let confirmBuyDESOString = sprintf( + Messages.CONFIRM_BUY_DESO, + fromWei(this.weiToExchange), + this.desoToBuy + ); SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - title: "Are you ready?", + title: 'Are you ready?', html: confirmBuyDESOString, showCancelButton: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, reverseButtons: true, }).then((res: any) => { @@ -213,10 +228,10 @@ export class BuyDeSoEthComponent implements OnInit { : this.constructFeeMarketTransaction() ).then((res) => { if (!res?.signedTx) { - console.error("No signedTx found - aborting"); + console.error('No signedTx found - aborting'); return; } - const signedHash = res.signedTx.serialize().toString("hex"); + const signedHash = res.signedTx.serialize().toString('hex'); // Submit the transaction. this.parentComponent.waitingOnTxnConfirmation = true; this.backendApi @@ -229,9 +244,9 @@ export class BuyDeSoEthComponent implements OnInit { ) .subscribe( (res) => { - this.globalVars.logEvent("deso : buy : eth"); + this.globalVars.logEvent('deso : buy : eth'); // Reset all the form fields - this.error = ""; + this.error = ''; this.desoToBuy = 0; this.ethToExchange = 0; this.weiToExchange = new BN(0); @@ -244,16 +259,23 @@ export class BuyDeSoEthComponent implements OnInit { ); }, (err) => { - this.globalVars.logEvent("deso : buy : eth : error"); - if (err.error?.error && err.error?.error.includes("RPC Error") && retry) { + this.globalVars.logEvent('deso : buy : eth : error'); + if ( + err.error?.error && + err.error?.error.includes('RPC Error') && + retry + ) { console.error(err); - this.globalVars.logEvent("deso : buy : eth : retry"); + this.globalVars.logEvent('deso : buy : eth : retry'); // Sometimes fees will change between the time they were fetched and the transaction was broadcasted. // To combat this, we will retry by fetching fees again and constructing/signing/broadcasting the // transaction again. return this.signAndSubmitETH(false); } else { - this.parentComponent._clickBuyDeSoFailure(this.parentComponent, this.extractError(err)); + this.parentComponent._clickBuyDeSoFailure( + this.parentComponent, + this.extractError(err) + ); } } ); @@ -265,7 +287,9 @@ export class BuyDeSoEthComponent implements OnInit { // mining at all due to gas calculations so this function is not currently used. Upgrading to using this function in // the future is preferred as we'll lower the amount of gas paid per transaction. constructFeeMarketTransaction(): Promise> { - return this.generateSignedTransaction(FeeMarketEIP1559Transaction); + return this.generateSignedTransaction( + FeeMarketEIP1559Transaction + ); } // constructLegacyTransaction creates a Signed Legacy transaction with gasPrice using the maintained ethereumjs/tx @@ -314,19 +338,23 @@ export class BuyDeSoEthComponent implements OnInit { tx.v = new Buffer([]); tx.r = new Buffer([]); tx.s = new Buffer([]); - toSign = [tx.hash(false).toString("hex")]; + toSign = [tx.hash(false).toString('hex')]; break; } case LegacyTransaction: { // Generate an Unsigned Legacy Transaction from the data and generated a hash message to sign. - const tx = LegacyTransaction.fromTxData(txData, { common: this.common }); - toSign = [tx.getMessageToSign(true).toString("hex")]; + const tx = LegacyTransaction.fromTxData(txData, { + common: this.common, + }); + toSign = [tx.getMessageToSign(true).toString('hex')]; break; } case FeeMarketEIP1559Transaction: { // Generate an Unsigned EIP 1559 Fee Market Transaction from the data and generated a hash message to sign. - let tx = FeeMarketEIP1559Transaction.fromTxData(feeMarketTxData, { common: this.common }); - toSign = [tx.getMessageToSign(true).toString("hex")]; + let tx = FeeMarketEIP1559Transaction.fromTxData(feeMarketTxData, { + common: this.common, + }); + toSign = [tx.getMessageToSign(true).toString('hex')]; break; } } @@ -339,22 +367,29 @@ export class BuyDeSoEthComponent implements OnInit { } getTotalFee(fees: FeeDetails): BN { - return BuyDeSoEthComponent.useLegacyTransaction ? fees.maxTotalFeesLegacy : fees.totalFeesEIP1559; + return BuyDeSoEthComponent.useLegacyTransaction + ? fees.maxTotalFeesLegacy + : fees.totalFeesEIP1559; } // getNonceValueAndFees is a helper to get the nonce, transaction value, and current fees when constructing a tx. - getNonceValueAndFees(): Promise<{ nonce: Hex; value: Hex; fees: FeeDetails }> { - return Promise.all([this.getTransactionCount(this.ethDepositAddress(), "pending"), this.getFees()]).then( - ([transactionCount, fees]) => { - const nonce = toHex(transactionCount); - let value = this.getValue(fees); - return { - nonce, - value, - fees, - }; - } - ); + getNonceValueAndFees(): Promise<{ + nonce: Hex; + value: Hex; + fees: FeeDetails; + }> { + return Promise.all([ + this.getTransactionCount(this.ethDepositAddress(), 'pending'), + this.getFees(), + ]).then(([transactionCount, fees]) => { + const nonce = toHex(transactionCount); + let value = this.getValue(fees); + return { + nonce, + value, + fees, + }; + }); } // getSignedTransactionFromUnsignedHex takes an unsigned transaction, signs it, and returns the requested type of @@ -366,24 +401,36 @@ export class BuyDeSoEthComponent implements OnInit { ): Promise> { return this.identityService .signETH({ - ...this.identityService.identityServiceParamsForKey(this.globalVars.loggedInUser.PublicKeyBase58Check), + ...this.identityService.identityServiceParamsForKey( + this.globalVars.loggedInUser.PublicKeyBase58Check + ), unsignedHashes: toSign, }) .toPromise() .then( (res) => { // Get the signature and merge it into the TxData defined above. - const signature: { s: any; r: any; v: number | null } = res.signatures[0]; + const signature: { s: any; r: any; v: number | null } = + res.signatures[0]; // For Legacy transaction using the old library, we need to modify V to satisfy EIP 155 constraints. - if (signedTxType === Transaction && this.common.gteHardfork("spuriousDragon")) { - signature.v = signature.v === 0 ? this.getChain() * 2 + 35 : this.getChain() * 2 + 36; + if ( + signedTxType === Transaction && + this.common.gteHardfork('spuriousDragon') + ) { + signature.v = + signature.v === 0 + ? this.getChain() * 2 + 35 + : this.getChain() * 2 + 36; } // Merge the signature into the transaction data. const signedTxData = { ...txData, ...signature, }; - let signedTx: Transaction | LegacyTransaction | FeeMarketEIP1559Transaction; + let signedTx: + | Transaction + | LegacyTransaction + | FeeMarketEIP1559Transaction; switch (signedTxType) { case Transaction: { @@ -394,13 +441,19 @@ export class BuyDeSoEthComponent implements OnInit { case LegacyTransaction: { // Create a signed Legacy transaction using the maintained ethereumjs/tx library. const legacyTxData = txData as TxData; - signedTx = LegacyTransaction.fromTxData(legacyTxData, this.getOptions()); + signedTx = LegacyTransaction.fromTxData( + legacyTxData, + this.getOptions() + ); break; } case FeeMarketEIP1559Transaction: { // Create a Fee Market EIP-1559 transaction using the maintained ethereumjs/tx library. const feeMarketTxdata = txData as FeeMarketEIP1559TxData; - signedTx = FeeMarketEIP1559Transaction.fromTxData(feeMarketTxdata, this.getOptions()); + signedTx = FeeMarketEIP1559Transaction.fromTxData( + feeMarketTxdata, + this.getOptions() + ); break; } } @@ -429,9 +482,9 @@ export class BuyDeSoEthComponent implements OnInit { extractError(err: any): string { if (err.error != null && err.error.error != null) { let rawError = err.error.error; - if (rawError.includes("Not enough funds")) { + if (rawError.includes('Not enough funds')) { return Messages.INSUFFICIENT_BALANCE; - } else if (rawError.includes("Failed to create fee transaction")) { + } else if (rawError.includes('Failed to create fee transaction')) { return Messages.NOT_MINED; } else { return rawError; @@ -459,7 +512,9 @@ export class BuyDeSoEthComponent implements OnInit { } computeWeiToBurnGivenDESONanos(amountNanos: number): BN { - const weiMinusFees = new BN(amountNanos).mul(this.getWeiPerNanoExchangeRate()); + const weiMinusFees = new BN(amountNanos).mul( + this.getWeiPerNanoExchangeRate() + ); return weiMinusFees.add(this.weiFeeEstimate); } @@ -480,7 +535,7 @@ export class BuyDeSoEthComponent implements OnInit { } updateDESOToBuy(newVal) { - if (newVal == null || newVal === "") { + if (newVal == null || newVal === '') { this.desoToBuy = 0; this.ethToExchange = 0; this.weiToExchange = new BN(0); @@ -489,13 +544,17 @@ export class BuyDeSoEthComponent implements OnInit { this.desoToBuy = Number(newVal); // Update the other value - this.ethToExchange = this.computeETHToBurnGivenDESONanos(newVal * GlobalVarsService.NANOS_PER_UNIT); - this.weiToExchange = this.computeWeiToBurnGivenDESONanos(newVal * GlobalVarsService.NANOS_PER_UNIT); + this.ethToExchange = this.computeETHToBurnGivenDESONanos( + newVal * GlobalVarsService.NANOS_PER_UNIT + ); + this.weiToExchange = this.computeWeiToBurnGivenDESONanos( + newVal * GlobalVarsService.NANOS_PER_UNIT + ); } } updateETHToExchange(newVal) { - if (newVal == null || newVal === "") { + if (newVal == null || newVal === '') { this.desoToBuy = 0; this.ethToExchange = 0; this.weiToExchange = new BN(0); @@ -504,7 +563,9 @@ export class BuyDeSoEthComponent implements OnInit { this.weiToExchange = this.toWeiBN(newVal); this.ethToExchange = Number(newVal); // Update the other value - this.desoToBuy = this.computeNanosToCreateGivenWeiToBurn(this.weiToExchange) / GlobalVarsService.NANOS_PER_UNIT; + this.desoToBuy = + this.computeNanosToCreateGivenWeiToBurn(this.weiToExchange) / + GlobalVarsService.NANOS_PER_UNIT; } } @@ -515,7 +576,7 @@ export class BuyDeSoEthComponent implements OnInit { refreshBalance() { if (!this.loadingBalance) { this.loadingBalance = true; - this.getBalance(this.ethDepositAddress(), "latest") + this.getBalance(this.ethDepositAddress(), 'latest') .then((res) => { this.weiBalance = toBN(res); this.ethBalance = Number(fromWei(this.weiBalance)); @@ -551,68 +612,95 @@ export class BuyDeSoEthComponent implements OnInit { // Get current gas price. getGasPrice(): Promise { - return this.queryETHRPC("eth_gasPrice", []); + return this.queryETHRPC('eth_gasPrice', []); } // Gets the data about the pending block. getBlock(block: string): Promise { - return this.queryETHRPC("eth_getBlockByNumber", [block, false]); + return this.queryETHRPC('eth_getBlockByNumber', [block, false]); } - getTransactionCount(address: string, block: string = "pending"): Promise { - return this.queryETHRPC("eth_getTransactionCount", [address, block]).then((result) => hexToNumber(result)); + getTransactionCount( + address: string, + block: string = 'pending' + ): Promise { + return this.queryETHRPC('eth_getTransactionCount', [ + address, + block, + ]).then((result) => hexToNumber(result)); } // Gets balance for address. - getBalance(address: string, block: string = "latest"): Promise { - return this.queryETHRPC("eth_getBalance", [address, block]); + getBalance(address: string, block: string = 'latest'): Promise { + return this.queryETHRPC('eth_getBalance', [address, block]); } getMaxPriorityFeePerGas(): Promise { - return this.queryETHRPC("eth_maxPriorityFeePerGas", []); + return this.queryETHRPC('eth_maxPriorityFeePerGas', []); } // getFees returns all the numbers and hex-strings necessary for computing eth gas. getFees(): Promise { - return Promise.all([this.getBlock("pending"), this.getMaxPriorityFeePerGas(), this.getGasPrice()]).then( - ([block, maxPriorityFeePerGasHex, gasPriceHex]) => { - const baseFeePerGas = toBN(block.baseFeePerGas); - - // Add a gwei to make this transaction more attractive to miners. - const maxPriorityFeePerGas = toBN(maxPriorityFeePerGasHex).add(new BN(toWei("1", "gwei"))); - // Ensure transaction is marketable for the next 6 blocks. The base fee increase by 12.5% when the previos block - // was 100% full. 1.125^6 = 2.0273 - // Source: https://www.blocknative.com/blog/eip-1559-fees - const maxFeePerGas = baseFeePerGas.muln(2).add(maxPriorityFeePerGas); - const totalFeesEIP1559 = maxFeePerGas.mul(BuyDeSoEthComponent.instructionsPerBasicTransfer); - // In order to increase the priority of this transaction, we're willing to pay twice as much in gas. - const gasPrice = toBN(gasPriceHex).muln(2); - const totalFeesLegacy = gasPrice.mul(BuyDeSoEthComponent.instructionsPerBasicTransfer); - if (BuyDeSoEthComponent.logFees) { - console.log("gasPrice: ", fromWei(gasPrice, "gwei")); - console.log("legacy total gas fees: ", fromWei(totalFeesLegacy, "gwei")); - console.log("maxFeePerGas: ", fromWei(maxFeePerGas, "gwei")); - console.log("baseFeePerGas: ", fromWei(baseFeePerGas, "gwei")); - console.log("maxPriorityFeePerGas: ", fromWei(maxPriorityFeePerGas, "gwei")); - console.log("EIP 1559 total gas fees: ", fromWei(totalFeesEIP1559, "gwei")); - } - - return { - baseFeePerGas, - maxPriorityFeePerGas, - maxPriorityFeePerGasHex, - maxFeePerGas, - maxFeePerGasHex: toHex(maxFeePerGas), - totalFeesEIP1559, - gasPrice, - gasPriceHex: toHex(gasPrice), - totalFeesLegacy, - maxLegacyGasPrice: maxFeePerGas.gt(gasPrice) ? maxFeePerGas : gasPrice, - maxLegacyGasPriceHex: toHex(maxFeePerGas.gt(gasPrice) ? maxFeePerGas : gasPrice), - maxTotalFeesLegacy: totalFeesEIP1559.gt(totalFeesLegacy) ? totalFeesEIP1559 : totalFeesLegacy, - }; + return Promise.all([ + this.getBlock('pending'), + this.getMaxPriorityFeePerGas(), + this.getGasPrice(), + ]).then(([block, maxPriorityFeePerGasHex, gasPriceHex]) => { + const baseFeePerGas = toBN(block.baseFeePerGas); + + // Add a gwei to make this transaction more attractive to miners. + const maxPriorityFeePerGas = toBN(maxPriorityFeePerGasHex).add( + new BN(toWei('1', 'gwei')) + ); + // Ensure transaction is marketable for the next 6 blocks. The base fee increase by 12.5% when the previos block + // was 100% full. 1.125^6 = 2.0273 + // Source: https://www.blocknative.com/blog/eip-1559-fees + const maxFeePerGas = baseFeePerGas.muln(2).add(maxPriorityFeePerGas); + const totalFeesEIP1559 = maxFeePerGas.mul( + BuyDeSoEthComponent.instructionsPerBasicTransfer + ); + // In order to increase the priority of this transaction, we're willing to pay twice as much in gas. + const gasPrice = toBN(gasPriceHex).muln(2); + const totalFeesLegacy = gasPrice.mul( + BuyDeSoEthComponent.instructionsPerBasicTransfer + ); + if (BuyDeSoEthComponent.logFees) { + console.log('gasPrice: ', fromWei(gasPrice, 'gwei')); + console.log( + 'legacy total gas fees: ', + fromWei(totalFeesLegacy, 'gwei') + ); + console.log('maxFeePerGas: ', fromWei(maxFeePerGas, 'gwei')); + console.log('baseFeePerGas: ', fromWei(baseFeePerGas, 'gwei')); + console.log( + 'maxPriorityFeePerGas: ', + fromWei(maxPriorityFeePerGas, 'gwei') + ); + console.log( + 'EIP 1559 total gas fees: ', + fromWei(totalFeesEIP1559, 'gwei') + ); } - ); + + return { + baseFeePerGas, + maxPriorityFeePerGas, + maxPriorityFeePerGasHex, + maxFeePerGas, + maxFeePerGasHex: toHex(maxFeePerGas), + totalFeesEIP1559, + gasPrice, + gasPriceHex: toHex(gasPrice), + totalFeesLegacy, + maxLegacyGasPrice: maxFeePerGas.gt(gasPrice) ? maxFeePerGas : gasPrice, + maxLegacyGasPriceHex: toHex( + maxFeePerGas.gt(gasPrice) ? maxFeePerGas : gasPrice + ), + maxTotalFeesLegacy: totalFeesEIP1559.gt(totalFeesLegacy) + ? totalFeesEIP1559 + : totalFeesLegacy, + }; + }); } getChain(): Chain { @@ -620,15 +708,17 @@ export class BuyDeSoEthComponent implements OnInit { } getChainString(): string { - return this.globalVars.isTestnet ? "ropsten" : "mainnet"; + return this.globalVars.isTestnet ? 'ropsten' : 'mainnet'; } getHardfork(): Hardfork { - return BuyDeSoEthComponent.useLegacyTransaction ? Hardfork.Petersburg : Hardfork.London; + return BuyDeSoEthComponent.useLegacyTransaction + ? Hardfork.Petersburg + : Hardfork.London; } getHardforkString(): string { - return BuyDeSoEthComponent.useLegacyTransaction ? "petersburg" : "london"; + return BuyDeSoEthComponent.useLegacyTransaction ? 'petersburg' : 'london'; } getOptions(): TxOptions { @@ -642,7 +732,10 @@ export class BuyDeSoEthComponent implements OnInit { ngOnInit() { window.scroll(0, 0); - this.common = new Common({ chain: this.getChain(), hardfork: this.getHardfork() }); + this.common = new Common({ + chain: this.getChain(), + hardfork: this.getHardfork(), + }); this.refreshBalance(); diff --git a/src/app/buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component.html b/src/app/buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component.html index eac2594a4..463c5a484 100644 --- a/src/app/buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component.html +++ b/src/app/buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component.html @@ -4,7 +4,9 @@ class="w-100 fixed-top-bar global__top-bar__height d-flex align-items-center justify-content-between fs-18px font-weight-bold px-15px border-bottom border-color-grey" >
- + Buy $DESO
@@ -15,7 +17,8 @@
- $DESO is a cryptocurrency like Bitcoin, only it powers the first decentralized social network. + $DESO is a cryptocurrency like Bitcoin, only it powers the first + decentralized social network.
@@ -32,7 +35,9 @@
- Create an anonymous account + Create an anonymous account to buy $DESO in under a minute.
@@ -50,7 +55,9 @@ What is $DESO useful for?
-
+
You can use it to buy and sell
-
+
You can use it to send messages to people
-
+
You can buy it anonymously with Bitcoin in under a minute
{ +describe('BuyDeSoLoggedOutComponent', () => { let component: BuyDeSoLoggedOutComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BuyDeSoLoggedOutComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component.ts b/src/app/buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component.ts index 9cb75d961..644d7a25a 100644 --- a/src/app/buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component.ts +++ b/src/app/buy-deso-page/buy-deso-logged-out/buy-deso-logged-out.component.ts @@ -1,10 +1,10 @@ -import { Component } from "@angular/core"; -import { GlobalVarsService } from "../../global-vars.service"; +import { Component } from '@angular/core'; +import { GlobalVarsService } from '../../global-vars.service'; @Component({ - selector: "buy-deso-logged-out", - templateUrl: "./buy-deso-logged-out.component.html", - styleUrls: ["./buy-deso-logged-out.component.scss"], + selector: 'buy-deso-logged-out', + templateUrl: './buy-deso-logged-out.component.html', + styleUrls: ['./buy-deso-logged-out.component.scss'], }) export class BuyDeSoLoggedOutComponent { constructor(public globalVars: GlobalVarsService) {} diff --git a/src/app/buy-deso-page/buy-deso-page.component.spec.ts b/src/app/buy-deso-page/buy-deso-page.component.spec.ts index 27f5e11a9..f77e5c6a6 100644 --- a/src/app/buy-deso-page/buy-deso-page.component.spec.ts +++ b/src/app/buy-deso-page/buy-deso-page.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { BuyDeSoPageComponent } from "./buy-deso-page.component"; +import { BuyDeSoPageComponent } from './buy-deso-page.component'; -describe("BuyDeSoPageComponent", () => { +describe('BuyDeSoPageComponent', () => { let component: BuyDeSoPageComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BuyDeSoPageComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/buy-deso-page/buy-deso-page.component.ts b/src/app/buy-deso-page/buy-deso-page.component.ts index 723a43aad..9a5d31d26 100644 --- a/src/app/buy-deso-page/buy-deso-page.component.ts +++ b/src/app/buy-deso-page/buy-deso-page.component.ts @@ -1,12 +1,12 @@ -import { Component, OnInit } from "@angular/core"; -import { GlobalVarsService } from "../global-vars.service"; -import { Title } from "@angular/platform-browser"; -import { environment } from "src/environments/environment"; +import { Component, OnInit } from '@angular/core'; +import { GlobalVarsService } from '../global-vars.service'; +import { Title } from '@angular/platform-browser'; +import { environment } from 'src/environments/environment'; @Component({ - selector: "buy-deso-page", - templateUrl: "./buy-deso-page.component.html", - styleUrls: ["./buy-deso-page.component.scss"], + selector: 'buy-deso-page', + templateUrl: './buy-deso-page.component.html', + styleUrls: ['./buy-deso-page.component.scss'], }) export class BuyDeSoPageComponent implements OnInit { isLeftBarMobileOpen: boolean = false; @@ -15,5 +15,8 @@ export class BuyDeSoPageComponent implements OnInit { this.titleService.setTitle(`Buy $DESO - ${environment.node.name}`); } - constructor(public globalVars: GlobalVarsService, private titleService: Title) {} + constructor( + public globalVars: GlobalVarsService, + private titleService: Title + ) {} } diff --git a/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.html b/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.html index d8cc571af..0b1459f79 100644 --- a/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.html +++ b/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.html @@ -1,19 +1,33 @@
-
Enter an amount in USD to convert to $DESO
-

You can purchase up to ${{ maxUsdAmount }} of $DESO per week using USD.

+
+ Enter an amount in USD to convert to $DESO +
+

+ You can purchase up to ${{ maxUsdAmount }} of $DESO per week using USD. +

For larger purchases, - buy with Bitcoin. + buy with Bitcoin.

- {{ selectedFiatCurrencySymbol }} + {{ + selectedFiatCurrencySymbol + }}
- +
@@ -43,12 +57,18 @@ class="form-control" style="background-color: white" > -
-
+
Country @@ -59,7 +79,12 @@ class="form-control" style="background-color: white" > - +
diff --git a/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.spec.ts b/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.spec.ts index fad04ae5f..ef53b71c0 100644 --- a/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.spec.ts +++ b/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { BuyDeSoUSDComponent } from "./buy-deso-usd.component"; +import { BuyDeSoUSDComponent } from './buy-deso-usd.component'; -describe("BuyDeSoUSDComponent", () => { +describe('BuyDeSoUSDComponent', () => { let component: BuyDeSoUSDComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BuyDeSoUSDComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.ts b/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.ts index 10e85f2e6..fc8521405 100644 --- a/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.ts +++ b/src/app/buy-deso-page/buy-deso-usd/buy-deso-usd.component.ts @@ -1,20 +1,20 @@ -import { Component, OnInit } from "@angular/core"; -import { GlobalVarsService } from "../../global-vars.service"; -import { HttpClient } from "@angular/common/http"; -import { WyreService } from "../../../lib/services/wyre/wyre"; -import { IdentityService } from "../../identity.service"; -import { BackendApiService } from "../../backend-api.service"; -import * as _ from "lodash"; -import Swal from "sweetalert2"; -import { ActivatedRoute, Router } from "@angular/router"; -import { SwalHelper } from "../../../lib/helpers/swal-helper"; -import { FeedComponent } from "../../feed/feed.component"; -import currencyToSymbolMap from "currency-symbol-map/map"; +import { Component, OnInit } from '@angular/core'; +import { GlobalVarsService } from '../../global-vars.service'; +import { HttpClient } from '@angular/common/http'; +import { WyreService } from '../../../lib/services/wyre/wyre'; +import { IdentityService } from '../../identity.service'; +import { BackendApiService } from '../../backend-api.service'; +import * as _ from 'lodash'; +import Swal from 'sweetalert2'; +import { ActivatedRoute, Router } from '@angular/router'; +import { SwalHelper } from '../../../lib/helpers/swal-helper'; +import { FeedComponent } from '../../feed/feed.component'; +import currencyToSymbolMap from 'currency-symbol-map/map'; @Component({ - selector: "buy-deso-usd", - templateUrl: "./buy-deso-usd.component.html", - styleUrls: ["./buy-deso-usd.component.scss"], + selector: 'buy-deso-usd', + templateUrl: './buy-deso-usd.component.html', + styleUrls: ['./buy-deso-usd.component.scss'], }) export class BuyDeSoUSDComponent implements OnInit { wyreService: WyreService; @@ -32,12 +32,12 @@ export class BuyDeSoUSDComponent implements OnInit { supportedCountries: string[]; supportedFiatCurrencies: { [k: string]: string }; - selectedFiatCurrency = "USD"; - selectedFiatCurrencySymbol = "$"; - selectedCountry = "US"; + selectedFiatCurrency = 'USD'; + selectedFiatCurrencySymbol = '$'; + selectedCountry = 'US'; - quotationError: string = ""; - reservationError: string = ""; + quotationError: string = ''; + reservationError: string = ''; constructor( private globalVars: GlobalVarsService, @@ -47,37 +47,46 @@ export class BuyDeSoUSDComponent implements OnInit { private route: ActivatedRoute, private router: Router ) { - this.wyreService = new WyreService(this.httpClient, this.globalVars, this.backendApi); + this.wyreService = new WyreService( + this.httpClient, + this.globalVars, + this.backendApi + ); this.supportedFiatCurrencies = this.wyreService.getSupportedFiatCurrencies(); this.wyreService.getSupportedCountries().subscribe((res) => { this.supportedCountries = res; }); - this.debouncedGetQuotation = _.debounce(this._refreshQuotation.bind(this), 300); + this.debouncedGetQuotation = _.debounce( + this._refreshQuotation.bind(this), + 300 + ); this.route.queryParams.subscribe((queryParams) => { if (queryParams.destAmount) { - this.globalVars.logEvent("wyre : buy : success", queryParams); + this.globalVars.logEvent('wyre : buy : success', queryParams); const btcPurchased = queryParams.destAmount; this.globalVars.celebrate(); SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - icon: "success", + icon: 'success', title: `Purchase Completed`, - html: `Your purchase of approximately ${this.getDeSoReceived(btcPurchased).toFixed( + html: `Your purchase of approximately ${this.getDeSoReceived( + btcPurchased + ).toFixed( 4 )} DeSo was successful. It may take a few minutes to appear in your wallet.`, showConfirmButton: true, showCancelButton: true, reverseButtons: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, - confirmButtonText: "Continue to Feed ", - cancelButtonText: "Buy More", + confirmButtonText: 'Continue to Feed ', + cancelButtonText: 'Buy More', }).then((res) => { queryParams = {}; if (res.isConfirmed) { - this.router.navigate(["/" + globalVars.RouteNames.BROWSE], { + this.router.navigate(['/' + globalVars.RouteNames.BROWSE], { queryParams: { feedTab: FeedComponent.GLOBAL_TAB }, }); } else { @@ -96,37 +105,43 @@ export class BuyDeSoUSDComponent implements OnInit { if (this.quotationError) { return; } - this.wyreService.makeWalletOrderReservation(this.amount, this.selectedCountry, this.selectedFiatCurrency).subscribe( - (res) => { - const wyreUrl = res.url; - if (res.url) { - Swal.fire({ - target: this.globalVars.getTargetComponentSelector(), - title: "Purchase $DESO", - html: `You will complete your purchase through Wyre. Your ${this.selectedFiatCurrency} will be converted to Bitcoin and then into $DESO automatically.`, - showCancelButton: true, - showConfirmButton: true, - confirmButtonText: "Buy", - customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", - }, - reverseButtons: true, - }).then((res: any) => { - if (res.isConfirmed) { - this.globalVars.logEvent("wyre : buy", { amount: this.amount }); - window.open(wyreUrl); - } - }); - } else { - this.reservationError = res.message; - this.globalVars._alertError(res.message); + this.wyreService + .makeWalletOrderReservation( + this.amount, + this.selectedCountry, + this.selectedFiatCurrency + ) + .subscribe( + (res) => { + const wyreUrl = res.url; + if (res.url) { + Swal.fire({ + target: this.globalVars.getTargetComponentSelector(), + title: 'Purchase $DESO', + html: `You will complete your purchase through Wyre. Your ${this.selectedFiatCurrency} will be converted to Bitcoin and then into $DESO automatically.`, + showCancelButton: true, + showConfirmButton: true, + confirmButtonText: 'Buy', + customClass: { + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', + }, + reverseButtons: true, + }).then((res: any) => { + if (res.isConfirmed) { + this.globalVars.logEvent('wyre : buy', { amount: this.amount }); + window.open(wyreUrl); + } + }); + } else { + this.reservationError = res.message; + this.globalVars._alertError(res.message); + } + }, + (err) => { + this.globalVars._alertError(err.error.message); } - }, - (err) => { - this.globalVars._alertError(err.error.message); - } - ); + ); } updateQuotation(): void { @@ -138,15 +153,21 @@ export class BuyDeSoUSDComponent implements OnInit { this.fees = null; this.quotation = null; this.usdEquivalent = null; - this.quotationError = ""; - this.wyreService.makeWalletOrderQuotation(this.amount, this.selectedCountry, this.selectedFiatCurrency).subscribe( - (res) => { - this.parseQuotation(res); - }, - (err) => { - this.quotationError = err.error.message; - } - ); + this.quotationError = ''; + this.wyreService + .makeWalletOrderQuotation( + this.amount, + this.selectedCountry, + this.selectedFiatCurrency + ) + .subscribe( + (res) => { + this.parseQuotation(res); + }, + (err) => { + this.quotationError = err.error.message; + } + ); } parseQuotation(quotation: any): void { @@ -168,7 +189,8 @@ export class BuyDeSoUSDComponent implements OnInit { getDeSoReceived(btcReceived: number): number { return ( (btcReceived * 1e8) / - (this.globalVars.satoshisPerDeSoExchangeRate * (1 + this.globalVars.BuyDeSoFeeBasisPoints / (100 * 100))) + (this.globalVars.satoshisPerDeSoExchangeRate * + (1 + this.globalVars.BuyDeSoFeeBasisPoints / (100 * 100))) ); } diff --git a/src/app/buy-deso-page/buy-deso/buy-deso.component.html b/src/app/buy-deso-page/buy-deso/buy-deso.component.html index 85e7b9414..11c1dfebc 100644 --- a/src/app/buy-deso-page/buy-deso/buy-deso.component.html +++ b/src/app/buy-deso-page/buy-deso/buy-deso.component.html @@ -4,7 +4,9 @@ class="global__top-bar global__top-bar-height background-color-white d-flex align-items-center fs-18px font-weight-bold pl-15px border-bottom border-color-grey" style="z-index: 1" > - + Buy $DESO
@@ -12,9 +14,16 @@
-
+
- +
@@ -57,7 +66,14 @@ Minimum deposit is currently - {{ ((buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB * 0.3) / 1e8).toFixed(4) }} Bitcoin + {{ + ( + (buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB * + 0.3) / + 1e8 + ).toFixed(4) + }} + Bitcoin
-
+
Amount deposited
- {{ (appData.latestBitcoinAPIResponse.final_balance / 1e8).toFixed(8) }} BTC + {{ + ( + appData.latestBitcoinAPIResponse.final_balance / 1e8 + ).toFixed(8) + }} + BTC ≈ {{ appData.formatUSD( - (appData.latestBitcoinAPIResponse.final_balance * appData.usdPerBitcoinExchangeRate) / 1e8, + (appData.latestBitcoinAPIResponse.final_balance * + appData.usdPerBitcoinExchangeRate) / + 1e8, 2 ) }} USD
-
(Loading...)
+
+ (Loading...) +
@@ -138,7 +166,10 @@
-
+
Click "refresh" to check your bitcoin balance. Buy $DESO with Bitcoin
$DESO to buy
-
+
-
- Includes {{ globalVars.BuyDeSoFeeBasisPoints / 100 }}% slippage +
+ Includes {{ globalVars.BuyDeSoFeeBasisPoints / 100 }}% + slippage
-
Bitcoin to swap
-
+
+ Bitcoin to swap +
+
-
- {{ (buyDeSoFields.bitcoinTotalTransactionFeeSatoshis / 1e8).toFixed(8) }} Bitcoin ≈ +
+ {{ + ( + buyDeSoFields.bitcoinTotalTransactionFeeSatoshis / 1e8 + ).toFixed(8) + }} + Bitcoin ≈ {{ appData.formatUSD( - (buyDeSoFields.bitcoinTotalTransactionFeeSatoshis * appData.usdPerBitcoinExchangeRate) / + (buyDeSoFields.bitcoinTotalTransactionFeeSatoshis * + appData.usdPerBitcoinExchangeRate) / 1e8, 2 ) }} USD
-
+
0.00000000 Bitcoin ≈ {{ appData.formatUSD(0, 2) }} USD
@@ -266,7 +324,9 @@
@@ -302,5 +362,7 @@
- + diff --git a/src/app/buy-deso-page/buy-deso/buy-deso.component.spec.ts b/src/app/buy-deso-page/buy-deso/buy-deso.component.spec.ts index f926579c4..a6a58fdf9 100644 --- a/src/app/buy-deso-page/buy-deso/buy-deso.component.spec.ts +++ b/src/app/buy-deso-page/buy-deso/buy-deso.component.spec.ts @@ -1,8 +1,8 @@ -import { async, ComponentFixture, TestBed } from "@angular/core/testing"; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { BuyDeSoComponent } from "./buy-deso.component"; +import { BuyDeSoComponent } from './buy-deso.component'; -describe("BuyDeSoComponent", () => { +describe('BuyDeSoComponent', () => { let component: BuyDeSoComponent; let fixture: ComponentFixture; @@ -18,7 +18,7 @@ describe("BuyDeSoComponent", () => { fixture.detectChanges(); }); - it("should create", () => { + it('should create', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/app/buy-deso-page/buy-deso/buy-deso.component.ts b/src/app/buy-deso-page/buy-deso/buy-deso.component.ts index 2a03aeca2..b2b24939e 100644 --- a/src/app/buy-deso-page/buy-deso/buy-deso.component.ts +++ b/src/app/buy-deso-page/buy-deso/buy-deso.component.ts @@ -1,13 +1,21 @@ -import { ApplicationRef, ChangeDetectorRef, Component, OnInit, Input, Output, EventEmitter } from "@angular/core"; -import { GlobalVarsService } from "../../global-vars.service"; -import { BackendApiService, BackendRoutes } from "../../backend-api.service"; -import { sprintf } from "sprintf-js"; -import { Router, ActivatedRoute, Params } from "@angular/router"; -import { HttpClient, HttpErrorResponse } from "@angular/common/http"; -import { SwalHelper } from "../../../lib/helpers/swal-helper"; -import Swal from "sweetalert2"; -import { IdentityService } from "../../identity.service"; -import { WyreService } from "../../../lib/services/wyre/wyre"; +import { + ApplicationRef, + ChangeDetectorRef, + Component, + OnInit, + Input, + Output, + EventEmitter, +} from '@angular/core'; +import { GlobalVarsService } from '../../global-vars.service'; +import { BackendApiService, BackendRoutes } from '../../backend-api.service'; +import { sprintf } from 'sprintf-js'; +import { Router, ActivatedRoute, Params } from '@angular/router'; +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; +import { SwalHelper } from '../../../lib/helpers/swal-helper'; +import Swal from 'sweetalert2'; +import { IdentityService } from '../../identity.service'; +import { WyreService } from '../../../lib/services/wyre/wyre'; class Messages { static INCORRECT_PASSWORD = `The password you entered was incorrect.`; @@ -21,9 +29,9 @@ class Messages { } @Component({ - selector: "buy-deso", - templateUrl: "./buy-deso.component.html", - styleUrls: ["./buy-deso.component.scss"], + selector: 'buy-deso', + templateUrl: './buy-deso.component.html', + styleUrls: ['./buy-deso.component.scss'], }) export class BuyDeSoComponent implements OnInit { appData: GlobalVarsService; @@ -35,9 +43,9 @@ export class BuyDeSoComponent implements OnInit { BuyDeSoComponent = BuyDeSoComponent; - static BUY_WITH_USD = "Buy with USD"; - static BUY_WITH_BTC = "Buy with Bitcoin"; - static BUY_WITH_ETH = "Buy with ETH"; + static BUY_WITH_USD = 'Buy with USD'; + static BUY_WITH_BTC = 'Buy with Bitcoin'; + static BUY_WITH_ETH = 'Buy with ETH'; buyTabs = [BuyDeSoComponent.BUY_WITH_BTC]; activeTab = BuyDeSoComponent.BUY_WITH_BTC; @@ -72,31 +80,31 @@ export class BuyDeSoComponent implements OnInit { stepOneTooltip() { return ( - "DESO can be purchased in just a few minutes using Bitcoin.\n\n" + - "To get started, simply send Bitcoin to your deposit address below. Note that deposits should show up " + - "within thirty seconds or so but sometimes, for various technical reasons, it can take up to an hour " + - "(though this should be extremely rare).\n\n" + + 'DESO can be purchased in just a few minutes using Bitcoin.\n\n' + + 'To get started, simply send Bitcoin to your deposit address below. Note that deposits should show up ' + + 'within thirty seconds or so but sometimes, for various technical reasons, it can take up to an hour ' + + '(though this should be extremely rare).\n\n' + "Once you've deposited Bitcoin, you can swap it for DESO in step two below. If it's your first " + - "time doing this, we recommend starting with a small test amount of Bitcoin to get comfortable with the flow." + 'time doing this, we recommend starting with a small test amount of Bitcoin to get comfortable with the flow.' ); } depositBitcoinTooltip() { - return "Send Bitcoin to this address so that you can swap it for DESO in step two below."; + return 'Send Bitcoin to this address so that you can swap it for DESO in step two below.'; } minDepositTooltip() { return ( - "This is the minimum amount required to cover the Bitcoin " + - "network fees associated with your purchase. We would love to make this " + - "lower, but if we did then the Bitcoin network would reject your transaction." + 'This is the minimum amount required to cover the Bitcoin ' + + 'network fees associated with your purchase. We would love to make this ' + + 'lower, but if we did then the Bitcoin network would reject your transaction.' ); } withdrawBitcoinTooltip() { return ( - "If you send too much Bitcoin to your deposit address and need to get it back, you " + - "can access the Bitcoin in this address by importing your DeSo seed phrase into most standard Bitcoin wallets " + + 'If you send too much Bitcoin to your deposit address and need to get it back, you ' + + 'can access the Bitcoin in this address by importing your DeSo seed phrase into most standard Bitcoin wallets ' + "like Electrum and choosing m/44'/0'/0'/0/0 as your derivation path. This works because your DeSo seed phrase is " + "what's used to generate your Bitcoin deposit address." ); @@ -104,16 +112,16 @@ export class BuyDeSoComponent implements OnInit { balanceUpdateTooltip() { return ( - "Normally, when you send Bitcoin to the deposit address, it will show up instantly. " + - "However, it can take up to an hour in rare cases depending on where you send it from." + 'Normally, when you send Bitcoin to the deposit address, it will show up instantly. ' + + 'However, it can take up to an hour in rare cases depending on where you send it from.' ); } bitcoinNetworkFeeTooltip() { return ( - "The process of exchanging Bitcoin for DeSo requires posting a transaction to " + - "the Bitcoin blockchain. For this reason, we must add a network fee to " + - "incentivize miners to process the transaction." + 'The process of exchanging Bitcoin for DeSo requires posting a transaction to ' + + 'the Bitcoin blockchain. For this reason, we must add a network fee to ' + + 'incentivize miners to process the transaction.' ); } @@ -122,18 +130,18 @@ export class BuyDeSoComponent implements OnInit { // Is it obvious yet that I'm not a frontend gal? // TODO: Error handling between BE and FE needs a major redesign. let rawError = err.error.error; - if (rawError.includes("password")) { + if (rawError.includes('password')) { return Messages.INCORRECT_PASSWORD; - } else if (rawError.includes("not sufficient")) { + } else if (rawError.includes('not sufficient')) { return Messages.INSUFFICIENT_BALANCE; - } else if (rawError.includes("so high")) { + } else if (rawError.includes('so high')) { return `The amount of Bitcoin you've deposited is too low. Please deposit at least ${( (this.buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB * 0.3) / 1e8 ).toFixed(4)} Bitcoin.`; - } else if (rawError.includes("total=0")) { + } else if (rawError.includes('total=0')) { return `You must purchase a non-zero amount of DeSo.`; - } else if (rawError.includes("You must burn at least .0001 Bitcoins")) { + } else if (rawError.includes('You must burn at least .0001 Bitcoins')) { return `You must exchange at least ${( (this.buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB * 0.3) / 1e8 @@ -151,26 +159,30 @@ export class BuyDeSoComponent implements OnInit { } buyDeSoFields = { - desoToBuy: "", - bitcoinToExchange: "", + desoToBuy: '', + bitcoinToExchange: '', bitcoinTransactionFeeRateSatoshisPerKB: 1000 * 1000, - bitcoinTotalTransactionFeeSatoshis: "0", - error: "", + bitcoinTotalTransactionFeeSatoshis: '0', + error: '', }; _updateBitcoinFee(bitcoinToExchange: number): Promise { - if (this.appData == null || this.appData.loggedInUser == null || this.appData.latestBitcoinAPIResponse == null) { + if ( + this.appData == null || + this.appData.loggedInUser == null || + this.appData.latestBitcoinAPIResponse == null + ) { SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - icon: "error", + icon: 'error', title: `Oops...`, html: `Please wait for at least one balance update before hitting this button.`, showConfirmButton: true, showCancelButton: false, focusConfirm: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, }); @@ -192,17 +204,18 @@ export class BuyDeSoComponent implements OnInit { .then( (res) => { if (res == null || res.FeeSatoshis == null) { - this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = "0"; + this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = '0'; this.buyDeSoFields.error = Messages.UNKOWN_PROBLEM; return null; } - this.buyDeSoFields.error = ""; - this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = res.FeeSatoshis; + this.buyDeSoFields.error = ''; + this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = + res.FeeSatoshis; return res; }, (err) => { - console.error("Problem updating Bitcoin fee Satoshis Per KB", err); - this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = "0"; + console.error('Problem updating Bitcoin fee Satoshis Per KB', err); + this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = '0'; this.buyDeSoFields.error = this._extractBurnError(err); return null; } @@ -225,7 +238,10 @@ export class BuyDeSoComponent implements OnInit { return; } - if (this.buyDeSoFields.desoToBuy == "" || parseFloat(this.buyDeSoFields.desoToBuy) === 0) { + if ( + this.buyDeSoFields.desoToBuy == '' || + parseFloat(this.buyDeSoFields.desoToBuy) === 0 + ) { this.appData._alertError(Messages.ZERO_deso_ERROR); return; } @@ -234,7 +250,7 @@ export class BuyDeSoComponent implements OnInit { return; } - if (this.buyDeSoFields.error != null && this.buyDeSoFields.error !== "") { + if (this.buyDeSoFields.error != null && this.buyDeSoFields.error !== '') { this.appData._alertError(this.buyDeSoFields.error); return; } @@ -242,18 +258,20 @@ export class BuyDeSoComponent implements OnInit { let confirmBuyDeSoString = sprintf( Messages.CONFIRM_BUY_deso, this.buyDeSoFields.bitcoinToExchange, - (parseFloat(this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis) / 1e8).toFixed(8), + ( + parseFloat(this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis) / 1e8 + ).toFixed(8), this.buyDeSoFields.desoToBuy ); SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - title: "Are you ready?", + title: 'Are you ready?', html: confirmBuyDeSoString, showCancelButton: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, reverseButtons: true, }).then((res: any) => { @@ -267,25 +285,27 @@ export class BuyDeSoComponent implements OnInit { this.btcDepositAddress(), this.appData.loggedInUser.PublicKeyBase58Check, Math.floor(parseFloat(this.buyDeSoFields.bitcoinToExchange) * 1e8), - Math.floor(this.buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB), + Math.floor( + this.buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB + ), true ) .toPromise() .then( (res) => { if (res == null || res.FeeSatoshis == null) { - this.globalVars.logEvent("bitpop : buy : error"); - this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = "0"; + this.globalVars.logEvent('bitpop : buy : error'); + this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = '0'; this.buyDeSoFields.error = Messages.UNKOWN_PROBLEM; return null; } - this.globalVars.logEvent("bitpop : buy", this.buyDeSoFields); + this.globalVars.logEvent('bitpop : buy', this.buyDeSoFields); // Reset all the form fields and run a BitcoinAPI update - this.buyDeSoFields.error = ""; - this.buyDeSoFields.desoToBuy = ""; - this.buyDeSoFields.bitcoinToExchange = ""; - this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = "0"; + this.buyDeSoFields.error = ''; + this.buyDeSoFields.desoToBuy = ''; + this.buyDeSoFields.bitcoinToExchange = ''; + this.buyDeSoFields.bitcoinTotalTransactionFeeSatoshis = '0'; // Update the BitcoinAPIResponse this.appData.latestBitcoinAPIResponse = null; @@ -300,7 +320,7 @@ export class BuyDeSoComponent implements OnInit { return res; }, (err) => { - this.globalVars.logEvent("bitpop : buy : error"); + this.globalVars.logEvent('bitpop : buy : error'); this._clickBuyDeSoFailure(this, this._extractBurnError(err)); return null; } @@ -317,11 +337,11 @@ export class BuyDeSoComponent implements OnInit { } _clickBuyDeSoSuccessButTimeout(comp: BuyDeSoComponent) { - this.appData.logEvent("bitpop : buy : read-timeout"); + this.appData.logEvent('bitpop : buy : read-timeout'); comp.waitingOnTxnConfirmation = false; let errString = - "Your DeSo purchase was successfully broadcast. Due to high load" + - " your balance may take up to half an hour to show up in your wallet. Please " + + 'Your DeSo purchase was successfully broadcast. Due to high load' + + ' your balance may take up to half an hour to show up in your wallet. Please ' + " check back and hit the 'help' button if you have any problems."; comp.appData._alertSuccess(errString); } @@ -330,20 +350,20 @@ export class BuyDeSoComponent implements OnInit { comp.waitingOnTxnConfirmation = false; // The error about "replace by fee" has a link in it, and we want that link // to render. There is no risk of injection here. - if (errString && errString.indexOf("replace by fee") >= 0) { + if (errString && errString.indexOf('replace by fee') >= 0) { // TODO: We should add some kind of htmlSafe attribute or something to // do this rather than creating a potentially-insecure if statement as // we do here. Swal.fire({ target: this.globalVars.getTargetComponentSelector(), - icon: "info", + icon: 'info', title: `Almost there!`, html: errString, showConfirmButton: true, focusConfirm: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, }); return; @@ -360,7 +380,9 @@ export class BuyDeSoComponent implements OnInit { // The fee should have been updated by the time we get here so // just update the Bitcoin and DeSo amounts. - this.buyDeSoFields.bitcoinToExchange = (res.BurnAmountSatoshis / 1e8).toFixed(8); + this.buyDeSoFields.bitcoinToExchange = ( + res.BurnAmountSatoshis / 1e8 + ).toFixed(8); this._updateBitcoinToExchange(this.buyDeSoFields.bitcoinToExchange); }, (err) => { @@ -373,15 +395,15 @@ export class BuyDeSoComponent implements OnInit { if (!this.appData.satoshisPerDeSoExchangeRate) { SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - icon: "error", + icon: 'error', title: `Oops...`, html: `We're still fetching some exchange rate data. Try again in about ten seconds.`, showConfirmButton: true, showCancelButton: false, focusConfirm: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, }); @@ -392,7 +414,8 @@ export class BuyDeSoComponent implements OnInit { return ( amountDESO * - (this.globalVars.satoshisPerDeSoExchangeRate * (1 + this.globalVars.BuyDeSoFeeBasisPoints / (100 * 100))) + (this.globalVars.satoshisPerDeSoExchangeRate * + (1 + this.globalVars.BuyDeSoFeeBasisPoints / (100 * 100))) ); } @@ -402,15 +425,15 @@ export class BuyDeSoComponent implements OnInit { if (!this.appData.satoshisPerDeSoExchangeRate) { SwalHelper.fire({ target: this.globalVars.getTargetComponentSelector(), - icon: "error", + icon: 'error', title: `Oops...`, html: `We're still fetching some exchange rate data. Try again in about ten seconds.`, showConfirmButton: true, showCancelButton: false, focusConfirm: true, customClass: { - confirmButton: "btn btn-light", - cancelButton: "btn btn-light no", + confirmButton: 'btn btn-light', + cancelButton: 'btn btn-light no', }, }); @@ -418,19 +441,22 @@ export class BuyDeSoComponent implements OnInit { } return ( (satoshisToBurn / - (this.globalVars.satoshisPerDeSoExchangeRate * (1 + this.globalVars.BuyDeSoFeeBasisPoints / (100 * 100)))) * + (this.globalVars.satoshisPerDeSoExchangeRate * + (1 + this.globalVars.BuyDeSoFeeBasisPoints / (100 * 100)))) * 1e9 ); } _updateDeSoToBuy(newVal) { - if (newVal == null || newVal === "") { - this.buyDeSoFields.desoToBuy = ""; - this.buyDeSoFields.bitcoinToExchange = ""; + if (newVal == null || newVal === '') { + this.buyDeSoFields.desoToBuy = ''; + this.buyDeSoFields.bitcoinToExchange = ''; } else { // The .999 factor comes in due to having to consider BitcoinExchangeFeeBasisPoints // that goes to pay the miner. - this.buyDeSoFields.bitcoinToExchange = (this._computeSatoshisToBurnGivenDeSoNanos(newVal * 1e9) / 1e8).toFixed(8); + this.buyDeSoFields.bitcoinToExchange = ( + this._computeSatoshisToBurnGivenDeSoNanos(newVal * 1e9) / 1e8 + ).toFixed(8); } // Update the Bitcoin fee. @@ -438,9 +464,9 @@ export class BuyDeSoComponent implements OnInit { } _updateBitcoinToExchange(newVal) { - if (newVal == null || newVal === "") { - this.buyDeSoFields.bitcoinToExchange = ""; - this.buyDeSoFields.desoToBuy = ""; + if (newVal == null || newVal === '') { + this.buyDeSoFields.bitcoinToExchange = ''; + this.buyDeSoFields.desoToBuy = ''; } else { // Compute the amount of DeSo the user can buy for this amount of Bitcoin and // set it. @@ -448,7 +474,9 @@ export class BuyDeSoComponent implements OnInit { // The .999 factor comes in due to having to consider BitcoinExchangeFeeBasisPoints // that goes to pay the miner. this.buyDeSoFields.desoToBuy = ( - this._computeNanosToCreateGivenSatoshisToBurn(parseFloat(this.buyDeSoFields.bitcoinToExchange) * 1e8) / 1e9 + this._computeNanosToCreateGivenSatoshisToBurn( + parseFloat(this.buyDeSoFields.bitcoinToExchange) * 1e8 + ) / 1e9 ).toFixed(9); } @@ -465,23 +493,25 @@ export class BuyDeSoComponent implements OnInit { this.appData.latestBitcoinAPIResponse = null; this.queryingBitcoinAPI = true; - this.backendApi.GetBitcoinAPIInfo(this.btcDepositAddress(), this.appData.isTestnet).subscribe( - (resProm: any) => { - resProm - .then((res) => { - this.appData.latestBitcoinAPIResponse = res; - - this.queryingBitcoinAPI = false; - }) - .catch(() => { - this.queryingBitcoinAPI = false; - }); - }, - (error) => { - this.queryingBitcoinAPI = false; - console.error("Error getting BitcoinAPI data: ", error); - } - ); + this.backendApi + .GetBitcoinAPIInfo(this.btcDepositAddress(), this.appData.isTestnet) + .subscribe( + (resProm: any) => { + resProm + .then((res) => { + this.appData.latestBitcoinAPIResponse = res; + + this.queryingBitcoinAPI = false; + }) + .catch(() => { + this.queryingBitcoinAPI = false; + }); + }, + (error) => { + this.queryingBitcoinAPI = false; + console.error('Error getting BitcoinAPI data: ', error); + } + ); } ngOnInit() { @@ -501,14 +531,18 @@ export class BuyDeSoComponent implements OnInit { this.backendApi.GetBitcoinFeeRateSatoshisPerKB().subscribe( (res: any) => { if (res.priority != null) { - this.buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB = 2.0 * res.priority * 1000; + this.buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB = + 2.0 * res.priority * 1000; // console.log('Using Bitcoin sats/KB fee: ', this.buyDeSoFields.bitcoinTransactionFeeRateSatoshisPerKB) } else { - console.error("res.priority was null so didn't set default fee: ", res); + console.error( + "res.priority was null so didn't set default fee: ", + res + ); } }, (error) => { - console.error("Problem getting Bitcoin fee: ", error); + console.error('Problem getting Bitcoin fee: ', error); } ); diff --git a/src/app/change-account-selector/change-account-selector.component.html b/src/app/change-account-selector/change-account-selector.component.html index 6f3236ae4..d9036f37b 100755 --- a/src/app/change-account-selector/change-account-selector.component.html +++ b/src/app/change-account-selector/change-account-selector.component.html @@ -1,33 +1,70 @@ -
Log In
-
+
+ Log In +
+