diff --git a/.dockerignore b/.dockerignore
index 6629ae8a684..02ef9c61713 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -7,3 +7,4 @@
**/node_modules
**/docker-compose.yml
**/docker-compose.production.yml
+stats.json
\ No newline at end of file
diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml
new file mode 100644
index 00000000000..48fa5a33347
--- /dev/null
+++ b/.github/workflows/desktop.yml
@@ -0,0 +1,113 @@
+name: Desktop-release
+
+on:
+ push:
+ branches:
+ - desktop
+
+jobs:
+ release-mac:
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os: [macos-11]
+
+ steps:
+ - name: Check out Git repository
+ uses: actions/checkout@v3
+
+ - name: Install Node.js, NPM and Yarn
+ uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - name: npm install, lint and/or test
+ run: |
+ yarn
+ cd src/desktop
+ yarn
+
+ - name: Build/release Electron app
+ uses: samuelmeuli/action-electron-builder@v1
+ with:
+ # GitHub token, automatically provided to the action
+ # (No need to define this secret in the repo settings)
+ github_token: ${{ secrets.github_token }}
+ package_root: "./src/desktop/"
+ mac_certs: ${{ secrets.mac_certs }}
+ mac_certs_password: ${{ secrets.mac_certs_password }}
+ args: "--publish always"
+ max_attempts: "5"
+ env:
+ NODE_OPTIONS: '--max_old_space_size=4096'
+
+ release-win:
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os: [windows-latest]
+
+ steps:
+ - name: Check out Git repository
+ uses: actions/checkout@v3
+
+ - name: Install Node.js, NPM and Yarn
+ uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - name: npm install, lint and/or test
+ run: |
+ yarn
+ cd src/desktop
+ yarn
+
+ - name: Build/release Electron app
+ uses: samuelmeuli/action-electron-builder@v1
+ with:
+ # GitHub token, automatically provided to the action
+ # (No need to define this secret in the repo settings)
+ github_token: ${{ secrets.github_token }}
+ package_root: "./src/desktop/"
+ windows_certs: ${{ secrets.windows_certs }}
+ windows_certs_password: ${{ secrets.windows_certs_password }}
+ args: "--publish always"
+ max_attempts: "5"
+ env:
+ NODE_OPTIONS: '--max_old_space_size=4096'
+
+ release-unix:
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os: [ubuntu-latest]
+
+ steps:
+ - name: Check out Git repository
+ uses: actions/checkout@v3
+
+ - name: Install Node.js, NPM and Yarn
+ uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - name: npm install, lint and/or test
+ run: |
+ yarn
+ cd src/desktop
+ yarn
+
+ - name: Build/release Electron app
+ uses: samuelmeuli/action-electron-builder@v1
+ with:
+ # GitHub token, automatically provided to the action
+ # (No need to define this secret in the repo settings)
+ github_token: ${{ secrets.github_token }}
+ package_root: "./src/desktop/"
+ args: "--publish always"
+ max_attempts: "5"
+ env:
+ NODE_OPTIONS: '--max_old_space_size=4096'
diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml
index 77bbb2c7d9a..bac3987ea0d 100644
--- a/.github/workflows/master.yml
+++ b/.github/workflows/master.yml
@@ -8,11 +8,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [12.x]
+ node-version: [16.x]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v1
+ uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: npm install, lint and/or test
@@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check Out Repo
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v1
@@ -57,18 +57,20 @@ jobs:
uses: appleboy/ssh-action@master
env:
USE_PRIVATE: ${{secrets.USE_PRIVATE}}
+ REDIS_HOST_PASSWORD: ${{secrets.REDIS_HOST_PASSWORD}}
with:
host: ${{ secrets.SSH_HOST_EU }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
- envs: USE_PRIVATE
+ envs: USE_PRIVATE, REDIS_HOST_PASSWORD
script: |
export USE_PRIVATE=$USE_PRIVATE
+ export REDIS_HOST_PASSWORD=$REDIS_HOST_PASSWORD
cd ~/vision-production
git pull origin master
docker pull ecency/vision:latest
- docker stack deploy -c docker-compose.yml -c docker-compose.production.yml vis
+ docker-compose -f docker-compose.production.yml up -d
deploy-US:
needs: build
@@ -78,18 +80,20 @@ jobs:
uses: appleboy/ssh-action@master
env:
USE_PRIVATE: ${{secrets.USE_PRIVATE}}
+ REDIS_HOST_PASSWORD: ${{secrets.REDIS_HOST_PASSWORD}}
with:
host: ${{ secrets.SSH_HOST_US }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
- envs: USE_PRIVATE
+ envs: USE_PRIVATE, REDIS_HOST_PASSWORD
script: |
export USE_PRIVATE=$USE_PRIVATE
+ export REDIS_HOST_PASSWORD=$REDIS_HOST_PASSWORD
cd ~/vision-production
git pull origin master
docker pull ecency/vision:latest
- docker stack deploy -c docker-compose.yml -c docker-compose.production.yml vision
+ docker-compose -f docker-compose.production.yml up -d
deploy-SG:
needs: build
@@ -99,15 +103,17 @@ jobs:
uses: appleboy/ssh-action@master
env:
USE_PRIVATE: ${{secrets.USE_PRIVATE}}
+ REDIS_HOST_PASSWORD: ${{secrets.REDIS_HOST_PASSWORD}}
with:
host: ${{ secrets.SSH_HOST_SG }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
- envs: USE_PRIVATE
+ envs: USE_PRIVATE, REDIS_HOST_PASSWORD
script: |
export USE_PRIVATE=$USE_PRIVATE
+ export REDIS_HOST_PASSWORD=$REDIS_HOST_PASSWORD
cd ~/vision-production
git pull origin master
docker pull ecency/vision:latest
- docker stack deploy -c docker-compose.yml -c docker-compose.production.yml vision
+ docker-compose -f docker-compose.production.yml up -d
diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml
index 6b8f39ffece..fb398adfbc5 100644
--- a/.github/workflows/staging.yml
+++ b/.github/workflows/staging.yml
@@ -8,11 +8,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [12.x]
+ node-version: [16.x]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v1
+ uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: npm install, lint and/or test
@@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check Out Repo
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v1
@@ -57,15 +57,17 @@ jobs:
uses: appleboy/ssh-action@master
env:
USE_PRIVATE: ${{secrets.USE_PRIVATE}}
+ REDIS_HOST_PASSWORD: ${{secrets.REDIS_HOST_PASSWORD}}
with:
host: ${{ secrets.SSH_STAGING_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
- envs: USE_PRIVATE
+ envs: USE_PRIVATE, REDIS_HOST_PASSWORD
script: |
export USE_PRIVATE=$USE_PRIVATE
+ export REDIS_HOST_PASSWORD=$REDIS_HOST_PASSWORD
cd ~/vision-staging
git pull origin development
docker pull ecency/vision:development
- docker stack deploy -c docker-compose.yml vision
+ docker-compose up -d
diff --git a/.gitignore b/.gitignore
index e1e8fc6b9ec..13c3e8cedb9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ src/config.ts
.vscode
dev.sh
+stats.json
\ No newline at end of file
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 00000000000..be539834c53
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+yarn precommit
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 00000000000..06b2bf71485
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,7 @@
+{
+ "semi": true,
+ "printWidth": 100,
+ "singleQuote": false,
+ "trailingComma": "none",
+ "tabWidth": 2
+}
diff --git a/Dockerfile b/Dockerfile
index f066bbae6be..4bb3a34f2cb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:12.16.2 as base
+FROM node:16.13.2 as base
WORKDIR /var/app
@@ -18,7 +18,7 @@ FROM base as dependencies
RUN yarn install --non-interactive --frozen-lockfile --ignore-optional --production
### BUILD MINIFIED PRODUCTION ##
-FROM node:12.16.2-alpine as production
+FROM node:16.13.2 as production
# Add Tini
ENV TINI_VERSION v0.18.0
diff --git a/README.md b/README.md
index ba26c72a3f9..4adf6cc61ab 100644
--- a/README.md
+++ b/README.md
@@ -32,25 +32,49 @@ Feel free to test it out and submit improvements and pull requests.
- node ^12.0.0
- yarn
-##### Clone
+##### Clone
+
`$ git clone https://github.com/ecency/ecency-vision`
`$ cd ecency-vision`
##### Install dependencies
+
`$ yarn`
##### Edit config file or define environment variables
+
`$ nano src/config.ts`
##### Environment variables
-* `USE_PRIVATE` - if instance has private api address and auth (0 or 1 value)
+- `USE_PRIVATE` - if instance has private api address and auth (0 or 1 value)
+- `HIVESIGNER_ID` - This is a special application Hive account. If unset, "ecency.app" is the account used.
+- `HIVESIGNER_SECRET` - This is a secret your site shares with HIVE_SIGNER in order to communicate securely.
+
+* `REDIS_URL` - support for caching amp pages
+
+###### Hivesigner Variables
+
+When setting up another service like Ecency with Ecency-vision software:
+
+1. You may leave `HIVESIGNER_ID` and `HIVESIGNER_SECRET` environment variables unset and optionally set USE_PRIVATE=1 and leave "base" in the constants/defaults.json set to "https://ecency.com". Your new site will contain more features as it will use Ecency's private API. This is by far the easiest option.
+2. You may change `base` to the URL of your own site, but you will have to set environment variables `HIVESIGNER_ID` and `HIVESIGNER_SECRET`; set USE_PRIVATE=0 as well as configure your the `HIVESIGNER_ID` account at the [Hivesigner website.](https://hivesigner.com/profile). Hivesigner will need a `secret`, in the form of a long lowercase hexadecimal number. The HIVESIGNER_SECRET should be set to this value.
+
+###### Hivesigner Login Process
+
+In order to validate a login, and do posting level operations, this software relies on Hivesigner. A user @alice will use login credentials to login to the site via one of several methods, but the site will communicate with Hivesigner and ask it to do all posting operations on behalf of @alice. Hivesigner can and will do this because both @alice will have given posting authority to the `HIVESIGNER_ID` user and the `HIVESIGNER_ID` user will have given its posting authority to Hivesigner.
+
+##### Edit "default" values
+
+If you are setting up your own website other than Ecency.com, you can still leave the value `base` as "https://ecency.com". However, you should change `name`, `title` and `twitterHandle`. There are also a lot of static pages that are Ecency specific.
##### Start website in dev
+
`$ yarn start`
##### Start desktop in dev
+
`$ cd src/desktop`
`$ yarn`
`$ yarn dev`
@@ -71,7 +95,9 @@ docker run -it --rm -p 3000:3000 ecency/vision:latest
```
Configure the instance using following environment variables:
- * `USE_PRIVATE`
+
+- `USE_PRIVATE`
+- `REDIS_URL`
```bash
docker run -it --rm -p 3000:3000 -e USE_PRIVATE=1 ecency/vision:latest
@@ -89,6 +115,13 @@ docker stack deploy -c docker-compose.yml -c docker-compose.production.yml visio
[](https://github.com/ecency/ecency-vision/graphs/contributors)
+## Note to DEVS
+
+- Make PRs more clear with description, screenshots or videos, linking to issues, if no issue exist create one that describes PR and mention in PR. Reviewers may or may not run code, but PR should be reviewable even without running, visials helps there.
+- PR should have title WIP, if it is not ready yet. Once ready, run yarn test and update all tests, make sure linting also done before requesting for review.
+- Creating component?! Make sure to create simple tests, you can check other components for examples.
+- Always make sure component and pages stay fast without unnecessary re-renders because those will slow down app/performance.
+-
## Issues
@@ -98,7 +131,7 @@ If you find a security issue please report details to: security@ecency.com
We will evaluate the risk and make a patch available before filing the issue.
-[//]: # 'LINKS'
+[//]: # "LINKS"
[ecency_vision]: https://ecency.com
[ecency_desktop]: https://desktop.ecency.com
[ecency_alpha]: https://alpha.ecency.com
diff --git a/docker-compose.production.yml b/docker-compose.production.yml
index b577a3b2b7f..c6e5ccdd110 100644
--- a/docker-compose.production.yml
+++ b/docker-compose.production.yml
@@ -1,5 +1,77 @@
-version: '3.7'
+version: "3.7"
services:
- app:
+ redis:
+ image: redis:alpine
+ environment:
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "6379:6379"
+ hostname: redis
+ command:
+ - /bin/sh
+ - -c
+ - redis-server --save 20 1 --loglevel warning --requirepass "$${REDIS_HOST_PASSWORD:?REDIS_HOST_PASSWORD variable is not set}"
+ volumes:
+ - redis:/data
+
+ web1:
+ image: ecency/vision:latest
+ environment:
+ - USE_PRIVATE
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "3001:3000"
+ hostname: web1
+ depends_on:
+ - redis
+
+ web2:
+ image: ecency/vision:latest
+ environment:
+ - USE_PRIVATE
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "3002:3000"
+ hostname: web2
+ depends_on:
+ - redis
+
+ web3:
image: ecency/vision:latest
+ environment:
+ - USE_PRIVATE
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "3003:3000"
+ hostname: web3
+ depends_on:
+ - redis
+
+ web4:
+ image: ecency/vision:latest
+ environment:
+ - USE_PRIVATE
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "3004:3000"
+ hostname: web4
+ depends_on:
+ - redis
+
+ nginx:
+ build: ./nginx
+ ports:
+ - '3000:80'
+ depends_on:
+ - web1
+ - web2
+
+volumes:
+ redis:
+ driver: local
diff --git a/docker-compose.yml b/docker-compose.yml
index 2a491e6bebf..648b67570ab 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,28 +1,77 @@
-version: '3.7'
+version: "3.7"
services:
- app:
+ redis:
+ image: redis:alpine
+ environment:
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "6379:6379"
+ hostname: redis
+ command:
+ - /bin/sh
+ - -c
+ - redis-server --save 20 1 --loglevel warning --requirepass "$${REDIS_HOST_PASSWORD:?REDIS_HOST_PASSWORD variable is not set}"
+ volumes:
+ - redis:/data
+
+ web1:
image: ecency/vision:development
environment:
- USE_PRIVATE
+ - REDIS_HOST_PASSWORD
+ restart: always
ports:
- - "3000:3000"
- deploy:
- replicas: 4
- resources:
- limits:
- cpus: "0.9"
- memory: 2048M
- update_config:
- parallelism: 4
- order: start-first
- failure_action: rollback
- delay: 10s
- rollback_config:
- parallelism: 0
- order: stop-first
- restart_policy:
- condition: any
- delay: 5s
- max_attempts: 5
- window: 30s
+ - "3001:3000"
+ hostname: web1
+ depends_on:
+ - redis
+
+ web2:
+ image: ecency/vision:development
+ environment:
+ - USE_PRIVATE
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "3002:3000"
+ hostname: web2
+ depends_on:
+ - redis
+
+ web3:
+ image: ecency/vision:development
+ environment:
+ - USE_PRIVATE
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "3003:3000"
+ hostname: web3
+ depends_on:
+ - redis
+
+ web4:
+ image: ecency/vision:development
+ environment:
+ - USE_PRIVATE
+ - REDIS_HOST_PASSWORD
+ restart: always
+ ports:
+ - "3004:3000"
+ hostname: web4
+ depends_on:
+ - redis
+
+ nginx:
+ build: ./nginx
+ ports:
+ - '3000:80'
+ depends_on:
+ - web1
+ - web2
+
+volumes:
+ redis:
+ driver: local
diff --git a/nginx/Dockerfile b/nginx/Dockerfile
new file mode 100644
index 00000000000..cf813e2a586
--- /dev/null
+++ b/nginx/Dockerfile
@@ -0,0 +1,3 @@
+FROM nginx:1.21.6
+RUN rm /etc/nginx/conf.d/default.conf
+COPY nginx.conf /etc/nginx/conf.d/default.conf
\ No newline at end of file
diff --git a/nginx/nginx.conf b/nginx/nginx.conf
new file mode 100644
index 00000000000..109d9085e69
--- /dev/null
+++ b/nginx/nginx.conf
@@ -0,0 +1,14 @@
+upstream loadbalancer {
+ server web1:3000;
+ server web2:3000;
+ server web3:3000;
+ server web4:3000;
+}
+
+server {
+ listen 80;
+ server_name localhost;
+ location / {
+ proxy_pass http://loadbalancer;
+ }
+}
diff --git a/package.json b/package.json
index fca69c46cd3..074981a42a5 100644
--- a/package.json
+++ b/package.json
@@ -1,111 +1,167 @@
{
"name": "ecency-vision",
- "version": "3.0.22",
+ "version": "3.0.35",
"private": true,
"license": "MIT",
"scripts": {
"start": "razzle start",
"build": "razzle build --noninteractive",
"test": "TZ=UTC razzle test --env=jsdom",
+ "prepare": "husky install",
+ "format": "prettier --ignore-unknown --write './src/**/**/*.{js,jsx,ts,tsx,css,md,json}' --config ./.prettierrc",
+ "precommit": "lint-staged",
"start:prod": "NODE_ENV=production node build/server.js"
},
"dependencies": {
- "@ecency/render-helper": "^2.2.16",
- "@hiveio/dhive": "^1.1.0",
+ "@ecency/render-helper": "^2.2.24",
+ "@ecency/render-helper-amp": "^1.1.0",
+ "@firebase/analytics": "^0.8.0",
+ "@firebase/app": "^0.7.28",
+ "@firebase/messaging": "^0.9.16",
+ "@hiveio/dhive": "^1.2.5",
"@hiveio/hivescript": "^1.2.7",
- "@types/bs58": "^4.0.1",
- "@types/diff-match-patch": "^1.0.32",
- "@types/lodash": "^4.14.175",
- "@types/numeral": "^0.0.28",
- "@types/rss": "^0.0.28",
- "@types/sortablejs": "^1.10.6",
- "@types/speakingurl": "^13.0.2",
- "@types/webscopeio__react-textarea-autocomplete": "^4.7.2",
+ "@loadable/component": "^5.15.2",
+ "@loadable/server": "^5.15.2",
+ "@tanstack/react-query": "^4.29.7",
+ "@tanstack/react-query-devtools": "^4.29.7",
+ "@types/tus-js-client": "^2.1.0",
"@webscopeio/react-textarea-autocomplete": "^4.8.1",
"axios": "^0.21.2",
+ "axios-cookiejar-support": "^4.0.6",
"bs58": "^4.0.1",
"connected-react-router": "^6.8.0",
"cookie-parser": "^1.4.5",
"currency-symbol-map": "^4.0.4",
"debounce": "^1.2.1",
"diff-match-patch": "^1.0.5",
- "express": "^4.17.1",
+ "express": "^4.17.3",
"history": "^4.7.2",
"hive-uri": "^0.2.3",
- "hivesigner": "^3.2.5",
+ "hivesigner": "^3.3.4",
"html-react-parser": "^1.2.1",
"i18next": "^19.4.4",
"i18next-browser-languagedetector": "^4.2.0",
"immutability-helper": "^3.0.2",
+ "js-base64": "^3.7.5",
"js-cookie": "^2.2.1",
+ "js-md5": "^0.7.3",
+ "lightweight-charts": "^3.8.0",
+ "loadable-ts-transformer": "^1.0.0-alpha.3",
"medium-zoom": "^1.0.6",
- "moment": "^2.26.0",
+ "moment": "^2.29.4",
"node-cache": "^5.1.0",
- "node-sass": "^6.0.1",
+ "node-html-parser": "^5.3.3",
"numeral": "^2.0.6",
"path-to-regexp": "^6.1.0",
- "qs": "^6.9.4",
+ "qrcode": "^1.5.1",
+ "qs": "^6.10.3",
"query-string": "^6.13.1",
"react": "^16.8.6",
+ "react-beautiful-dnd": "^13.1.0",
"react-bootstrap": "^1.0.1",
"react-datetime": "^3.0.4",
"react-dom": "^16.8.6",
"react-fast-compare": "^3.2.0",
+ "react-google-recaptcha": "^2.1.0",
+ "react-grid-layout": "^1.3.4",
"react-helmet": "^6.0.0",
"react-highcharts": "^16.1.0",
"react-img-webp": "^2.0.2",
+ "react-in-viewport": "^1.0.0-alpha.30",
"react-popper": "^2.2.5",
"react-redux": "^7.2.0",
+ "react-resize-detector": "^7.1.2",
"react-router-dom": "^5.0.1",
"react-sortablejs": "^2.0.11",
+ "react-textarea-autosize": "^8.4.1",
+ "react-twitter-embed": "^4.0.4",
+ "react-use": "^17.4.0",
+ "react-virtualized": "^9.22.3",
+ "redis": "4.6.7",
"redux": "4.0.5",
"redux-thunk": "^2.3.0",
"rss": "^1.2.2",
+ "sass": "^1.56.2",
"serialize-javascript": "^3.1.0",
"sortablejs": "^1.13.0",
"speakingurl": "^14.0.1",
+ "tough-cookie": "^4.1.2",
+ "tus-js-client": "^3.1.0",
+ "use-async-effect": "^2.2.6",
+ "use-indexeddb": "^2.0.2",
+ "uuid": "^9.0.0",
"xss": "^1.0.8"
},
"devDependencies": {
+ "@loadable/webpack-plugin": "^5.15.2",
+ "@types/bs58": "^4.0.1",
"@types/bytebuffer": "^5.0.41",
"@types/cookie-parser": "^1.4.2",
+ "@types/diff-match-patch": "^1.0.32",
"@types/express": "^4.17.0",
"@types/jest": "^26.0.24",
"@types/js-cookie": "^2.2.6",
+ "@types/js-md5": "^0.7.0",
+ "@types/loadable__component": "^5.13.4",
+ "@types/loadable__server": "^5.12.6",
+ "@types/lodash": "^4.14.191",
"@types/node": "^12.6.6",
+ "@types/numeral": "^2.0.2",
"@types/path-to-regexp": "^1.7.0",
+ "@types/qrcode": "^1.4.2",
"@types/react": "^16.8.23",
+ "@types/react-beautiful-dnd": "^13.1.2",
"@types/react-dom": "^16.8.4",
+ "@types/react-google-recaptcha": "^2.1.5",
+ "@types/react-grid-layout": "^1.3.2",
"@types/react-helmet": "^6.0.0",
"@types/react-highcharts": "^16.0.3",
"@types/react-redux": "^7.1.9",
"@types/react-router-dom": "^4.3.4",
"@types/react-test-renderer": "^16.9.2",
+ "@types/react-virtualized": "^9.21.21",
+ "@types/redis": "^4.0.11",
+ "@types/resize-observer-browser": "^0.1.7",
+ "@types/rss": "^0.0.29",
"@types/serialize-javascript": "^1.5.0",
+ "@types/sortablejs": "^1.15.0",
+ "@types/speakingurl": "^13.0.3",
+ "@types/uuid": "^9.0.0",
"@types/webpack-env": "^1.14.0",
+ "@types/webscopeio__react-textarea-autocomplete": "^4.7.2",
"babel-preset-razzle": "^4.0.5",
"html-webpack-plugin": "4.5.2",
+ "husky": "^8.0.1",
"jest": "^26.0.0",
+ "lint-staged": "^13.0.3",
"mini-css-extract-plugin": "0.9.0",
"mockdate": "^3.0.2",
- "postcss": "8.2.10",
+ "postcss": "8.2.13",
+ "prettier": "^2.7.1",
"razzle": "^4.0.5",
"razzle-dev-utils": "^4.0.5",
"razzle-plugin-scss": "^4.0.5",
"razzle-plugin-typescript": "^3.0.0",
"react-test-renderer": "^16.13.1",
+ "timers": "^0.1.1",
"ts-jest": "^26.4.2",
"tslint": "^5.18.0",
"tslint-react": "^4.0.0",
- "typescript": "^3.5.3",
+ "typescript": "4.1.6",
"url-loader": "^4.1.1",
"webpack": "4.46.0",
+ "webpack-bundle-analyzer": "^4.8.0",
"webpack-dev-server": "3.11.0"
},
"resolutions": {
"jest": "^26.0.0",
"@types/react": "^16.8.23"
},
+ "lint-staged": {
+ "*.{js,jsx,ts,tsx,css,md,json}": [
+ "yarn format"
+ ]
+ },
"jest": {
"transform": {
"\\.(ts|tsx)$": "ts-jest",
diff --git a/public/assets/arrow1-about.png b/public/assets/arrow1-about.png
new file mode 100644
index 00000000000..2fcc8b7a0d0
Binary files /dev/null and b/public/assets/arrow1-about.png differ
diff --git a/public/assets/arrow2-about.png b/public/assets/arrow2-about.png
new file mode 100644
index 00000000000..a61b36c1062
Binary files /dev/null and b/public/assets/arrow2-about.png differ
diff --git a/public/assets/arrow3-about.png b/public/assets/arrow3-about.png
new file mode 100644
index 00000000000..a6ed1e9946e
Binary files /dev/null and b/public/assets/arrow3-about.png differ
diff --git a/public/firebase-messaging-sw.js b/public/firebase-messaging-sw.js
new file mode 100644
index 00000000000..6e1024ce492
--- /dev/null
+++ b/public/firebase-messaging-sw.js
@@ -0,0 +1,48 @@
+// Scripts for firebase and firebase messaging
+importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js');
+importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js');
+
+// Initialize the Firebase app in the service worker by passing the generated config
+var firebaseConfig = {
+ apiKey: 'AIzaSyDKF-JWDMmUs5ozjK7ZdgG4beHRsAMd2Yw',
+ authDomain: 'esteem-ded08.firebaseapp.com',
+ databaseURL: 'https://esteem-ded08.firebaseio.com',
+ projectId: 'esteem-ded08',
+ storageBucket: 'esteem-ded08.appspot.com',
+ messagingSenderId: '211285790917',
+ appId: '1:211285790917:web:c259d25ed1834c683760ac',
+ measurementId: 'G-TYQD1N3NR3'
+};
+
+firebase.initializeApp(firebaseConfig);
+
+// Retrieve firebase messaging
+const messaging = firebase.messaging();
+
+messaging.onBackgroundMessage(function (payload) {
+ //console.log('Received bg notification', payload);
+ const notificationTitle = payload.notification?.title || 'Ecency';
+
+ self.registration.showNotification(notificationTitle, {
+ body: payload.notification?.body,
+ icon: payload.notification?.image || 'https://ecency.com/static/media/logo-circle.2df6f251.svg',
+ data: payload.data,
+ });
+});
+
+self.addEventListener('notificationclick', function (event) {
+ const data = event.notification.data;
+ let url = 'https://ecency.com';
+ const fullPermlink = data.permlink1 + data.permlink2 + data.permlink3;
+ if (['vote', 'unvote', 'spin', 'inactive'].includes(data.type)) {
+ url += '/@' + data.target;
+ } else {
+ // delegation, mention, transfer, follow, unfollow, ignore, blacklist, reblog
+ url += '/@' + data.source;
+ }
+ if (fullPermlink) {
+ url += '/' + fullPermlink;
+ }
+
+ clients.openWindow(url, '_blank');
+});
\ No newline at end of file
diff --git a/razzle.config.js b/razzle.config.js
index d0a140e0092..fcc4629bbc4 100644
--- a/razzle.config.js
+++ b/razzle.config.js
@@ -1,26 +1,58 @@
-'use strict';
+"use strict";
+const LoadableWebpackPlugin = require("@loadable/webpack-plugin");
+const { loadableTransformer } = require("loadable-ts-transformer");
+const path = require("path");
+
+const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
module.exports = {
- plugins: ['typescript', 'scss'],
+ plugins: ["typescript", "scss"],
+ resolve: {
+ alias: {
+ styles: path.join(__dirname, "src/style/")
+ }
+ },
options: {
- buildType: 'iso'
+ buildType: "iso"
},
modifyWebpackConfig({
env: {
target, // the target 'node' or 'web'
- dev, // is this a development build? true or false
+ dev // is this a development build? true or false
},
webpackConfig, // the created webpack config
webpackObject, // the imported webpack node module
options: {
pluginOptions, // the options passed to the plugin ({ name:'pluginname', options: { key: 'value'}})
razzleOptions, // the modified options passed to Razzle in the `options` key in `razzle.config.js` (options: { key: 'value'})
- webpackOptions, // the modified options that was used to configure webpack/ webpack loaders and plugins
+ webpackOptions // the modified options that was used to configure webpack/ webpack loaders and plugins
},
- paths, // the modified paths that will be used by Razzle.
+ paths // the modified paths that will be used by Razzle.
}) {
// Do some stuff to webpackConfig
- webpackConfig.devtool = dev ? 'source-map' : false;
+ if (target === "web") {
+ const filename = path.resolve(__dirname, "build");
+ // saving stats file to build folder
+ // without this, stats files will go into
+ // build/public folder
+ webpackConfig.plugins.push(
+ new LoadableWebpackPlugin({
+ outputAsset: true,
+ writeToDisk: { filename }
+ })
+ );
+ }
+
+ // Enable SSR lazy-loading
+ const tsLoader = webpackConfig.module.rules.find(
+ (rule) => !(rule.test instanceof Array) && rule.test && rule.test.test(".tsx")
+ );
+ tsLoader.use[0].options.getCustomTransformers = () => ({ before: [loadableTransformer] });
+
+ if (target === "web" && dev) {
+ webpackConfig.plugins.push(new BundleAnalyzerPlugin());
+ }
+ webpackConfig.devtool = dev ? "source-map" : false;
return webpackConfig;
}
};
diff --git a/src/client/base-handlers.ts b/src/client/base-handlers.ts
index f70264b9161..3cab5199c31 100644
--- a/src/client/base-handlers.ts
+++ b/src/client/base-handlers.ts
@@ -1,73 +1,72 @@
// Base event handlers for browser window
-import {history} from "../common/store";
+import { history } from "../common/store";
import routes from "../common/routes";
-import {pathToRegexp} from "path-to-regexp";
+import { pathToRegexp } from "path-to-regexp";
// Global drag&drop
const handleDragOver = (e: DragEvent) => {
- if (!(e.target && e.dataTransfer)) {
- return;
- }
+ if (!(e.target && e.dataTransfer)) {
+ return;
+ }
- e.preventDefault();
- e.dataTransfer.effectAllowed = 'none';
- e.dataTransfer.dropEffect = 'none';
-}
+ e.preventDefault();
+ e.dataTransfer.effectAllowed = "none";
+ e.dataTransfer.dropEffect = "none";
+};
// Global click handler
const handleClick = (e: Event) => {
- const el = e.target as HTMLElement;
-
- // Anchor link handler
- if (el.tagName === "A" || (el.parentElement && el.parentElement.tagName === "A")) {
+ const el = e.target as HTMLElement;
- const href = el.getAttribute("href") || (el.parentElement ? el.parentElement.getAttribute("href") : null);
+ // Anchor link handler
+ if (el.tagName === "A" || (el.parentElement && el.parentElement.tagName === "A")) {
+ const href =
+ el.getAttribute("href") || (el.parentElement ? el.parentElement.getAttribute("href") : null);
- if (href && href.startsWith("/") && href.indexOf("#") !== -1) {
- const [route, anchor] = href.split("#");
+ if (href && href.startsWith("/") && href.indexOf("#") !== -1) {
+ const [route, anchor] = href.split("#");
- // make sure link matches with one of app routes
- if (Object.values(routes).find(p => pathToRegexp(p).test(route))) {
- e.preventDefault();
+ // make sure link matches with one of app routes
+ if (Object.values(routes).find((p) => pathToRegexp(p).test(route))) {
+ e.preventDefault();
- let delay = 75;
+ let delay = 75;
- if (history!.location.pathname !== route) {
- history!.push(href);
- }
+ if (history!.location.pathname !== route) {
+ history!.push(href);
+ }
- // scroll to anchor element
- const el = document.getElementById(anchor);
- if (el) {
- setTimeout(() => {
- el.scrollIntoView();
- }, delay);
- }
- }
+ // scroll to anchor element
+ const el = document.getElementById(anchor);
+ if (el) {
+ setTimeout(() => {
+ el.scrollIntoView();
+ }, delay);
}
+ }
}
-
- // Handle links in static pages. (faq etc...)
- if (el.tagName === "A") {
- if (el.classList.contains("push-link")) {
- e.preventDefault();
- const href = el.getAttribute("href");
- if (href && href.startsWith("/")) {
-
- // make sure link matches with one of app routes
- if (Object.values(routes).find(p => pathToRegexp(p).test(href))) {
- e.preventDefault();
- history!.push(href);
- }
- }
+ }
+
+ // Handle links in static pages. (faq etc...)
+ if (el.tagName === "A") {
+ if (el.classList.contains("push-link")) {
+ e.preventDefault();
+ const href = el.getAttribute("href");
+ if (href && href.startsWith("/")) {
+ // make sure link matches with one of app routes
+ if (Object.values(routes).find((p) => pathToRegexp(p).test(href))) {
+ e.preventDefault();
+ history!.push(href);
}
+ }
}
-}
+ }
+};
document.addEventListener("DOMContentLoaded", function () {
- document.body.addEventListener('dragover', handleDragOver);
- document.body.addEventListener('click', handleClick);
+ document.body.addEventListener("dragover", handleDragOver);
+ document.body.addEventListener("click", handleClick);
});
diff --git a/src/client/index.tsx b/src/client/index.tsx
index 9ec79ed008f..d818976bbbf 100644
--- a/src/client/index.tsx
+++ b/src/client/index.tsx
@@ -1,30 +1,25 @@
import React from "react";
-import {hydrate} from "react-dom";
-import {Provider} from "react-redux";
-import {ConnectedRouter} from "connected-react-router";
-
+import { hydrate } from "react-dom";
+import { Provider } from "react-redux";
+import { ConnectedRouter } from "connected-react-router";
import configureStore from "../common/store/configure";
-
-import {hasKeyChainAct} from "../common/store/global";
-import {clientStoreTasks} from "../common/store/helper";
-
-import {history} from "../common/store";
-
+import { hasKeyChainAct } from "../common/store/global";
+import { clientStoreTasks } from "../common/store/helper";
+import { history } from "../common/store";
import App from "../common/app";
-
-import {AppWindow} from "./window";
-
-import "../style/theme-day.scss";
-import "../style/theme-night.scss";
-
-import './base-handlers';
+import { AppWindow } from "./window";
+import "../style/style.scss";
+import "./base-handlers";
+import { loadableReady } from "@loadable/component";
+import { queryClient } from "../common/core";
+import { Hydrate, QueryClientProvider } from "@tanstack/react-query";
declare var window: AppWindow;
const store = configureStore(window["__PRELOADED_STATE__"]);
-if (process.env.NODE_ENV === 'production') {
- console.log(`@@@@@@@(((((@@@@@@@@@@@@@
+if (process.env.NODE_ENV === "production") {
+ console.log(`@@@@@@@(((((@@@@@@@@@@@@@
@@@(((((((((((((@@@@@@@@@
@((((@@@@@@@@@((((@@@@@@@
@(((@@@(((((@@@((((%@@@@@
@@ -33,48 +28,58 @@ if (process.env.NODE_ENV === 'production') {
((((@@@@@@&&&@@@@@@@@@(((
((((@@@@@@@@@@@@@@@@@((((
(((((%@@@@@@@@@%%(((((((@
-@@(((((((((((((((((((@@@@`
-);
- console.log('%c%s', 'font-size: 16px;', 'We are hiring!');
- console.log(
- '%c%s',
- 'font-size: 12px;',
- 'Are you developer, looking ways to contribute? \nhttps://github.com/ecency/ecency-vision \n\n'
- );
+@@(((((((((((((((((((@@@@`);
+ console.log("%c%s", "font-size: 16px;", "We are hiring!");
+ console.log(
+ "%c%s",
+ "font-size: 12px;",
+ "Are you developer, looking ways to contribute? \nhttps://github.com/ecency/ecency-vision \n\n"
+ );
}
-hydrate(
-
-
-
-
- ,
+loadableReady().then(() => {
+ hydrate(
+
+ {/*@ts-ignore*/}
+
+
+
+
+
+
+
+ ,
document.getElementById("root")
-);
+ );
-clientStoreTasks(store);
+ clientStoreTasks(store);
-// Check & activate keychain support
-window.addEventListener("load", () => {
+ // Check & activate keychain support
+ window.addEventListener("load", () => {
setTimeout(() => {
- if (window.hive_keychain) {
- window.hive_keychain.requestHandshake(() => {
- store.dispatch(hasKeyChainAct());
- });
- }
+ if (window.hive_keychain) {
+ window.hive_keychain.requestHandshake(() => {
+ store.dispatch(hasKeyChainAct());
+ });
+ }
}, 50);
+ });
});
if (module.hot) {
- module.hot.accept("../common/app", () => {
- hydrate(
-
-
-
-
- ,
- document.getElementById("root")
- );
- });
+ module.hot.accept("../common/app", () => {
+ hydrate(
+
+ {/*@ts-ignore*/}
+
+
+
+
+
+
+
+ ,
+ document.getElementById("root")
+ );
+ });
}
-
diff --git a/src/client/window.ts b/src/client/window.ts
index 86e6305162a..dfb19312bf8 100644
--- a/src/client/window.ts
+++ b/src/client/window.ts
@@ -1,13 +1,13 @@
-import {KeyChainImpl} from "../common/helper/keychain";
+import { KeyChainImpl } from "../common/helper/keychain";
export interface AppWindow extends Window {
- usePrivate: boolean;
- nws?: WebSocket;
- comTag?: {};
- hive_keychain?: KeyChainImpl;
- twttr?: {
- widgets?: {
- load: () => void
- }
- }
+ usePrivate: boolean;
+ nws?: WebSocket;
+ comTag?: {};
+ hive_keychain?: KeyChainImpl;
+ twttr: {
+ widgets?: {
+ load: () => void;
+ };
+ };
}
diff --git a/src/common/api/auth-api.ts b/src/common/api/auth-api.ts
index 63c0dc2a64c..4ffbdd23c9b 100644
--- a/src/common/api/auth-api.ts
+++ b/src/common/api/auth-api.ts
@@ -1,16 +1,17 @@
import axios from "axios";
-import {apiBase} from "./helper";
+import { apiBase } from "./helper";
-export const hsTokenRenew = (code: string): Promise<{
- username: string;
- access_token: string;
- refresh_token: string;
- expires_in: number;
+export const hsTokenRenew = (
+ code: string
+): Promise<{
+ username: string;
+ access_token: string;
+ refresh_token: string;
+ expires_in: number;
}> =>
- axios
- .post(apiBase(`/auth-api/hs-token-refresh`), {
- code,
- })
- .then((resp) => resp.data);
-
+ axios
+ .post(apiBase(`/auth-api/hs-token-refresh`), {
+ code
+ })
+ .then((resp) => resp.data);
diff --git a/src/common/api/bridge.ts b/src/common/api/bridge.ts
index 46ab40fc2d7..9699b8ebbcf 100644
--- a/src/common/api/bridge.ts
+++ b/src/common/api/bridge.ts
@@ -1,179 +1,219 @@
-import {Entry} from "../store/entries/types";
-import {Community} from "../store/communities/types";
-import {Subscription} from "../store/subscriptions/types";
-
-import {client as hiveClient} from "./hive";
-
-export const dataLimit = typeof window !== "undefined" && window.screen.width < 540 ? 5 : 20 || 20
-
-const bridgeApiCall = (endpoint: string, params: {}): Promise => hiveClient.call("bridge", endpoint, params);
-
-const resolvePost = (post: Entry, observer: string): Promise => {
- const {json_metadata: json} = post;
-
- if (json.original_author && json.original_permlink && json.tags && json.tags[0] === "cross-post") {
- return getPost(json.original_author, json.original_permlink, observer).then(resp => {
- if (resp) {
- return {
- ...post,
- original_entry: resp
- }
- }
+import { Entry } from "../store/entries/types";
+import { Community } from "../store/communities/types";
+import { Subscription } from "../store/subscriptions/types";
+
+import { Client } from "@hiveio/dhive";
+import SERVERS from "../constants/servers.json";
+
+export const bridgeServer = new Client(SERVERS, {
+ timeout: 3000,
+ failoverThreshold: 3,
+ consoleOnFailover: true
+});
+export const dataLimit = typeof window !== "undefined" && window.screen.width < 540 ? 5 : 20 || 20;
+
+const bridgeApiCall = (endpoint: string, params: {}): Promise =>
+ bridgeServer.call("bridge", endpoint, params);
+
+export const resolvePost = (post: Entry, observer: string, num?: number): Promise => {
+ const { json_metadata: json } = post;
+
+ if (
+ json.original_author &&
+ json.original_permlink &&
+ json.tags &&
+ json.tags[0] === "cross-post"
+ ) {
+ return getPost(json.original_author, json.original_permlink, observer, num)
+ .then((resp) => {
+ if (resp) {
+ return {
+ ...post,
+ original_entry: resp,
+ num
+ };
+ }
- return post;
- }).catch(() => {
- return post;
- })
- }
+ return post;
+ })
+ .catch(() => {
+ return post;
+ });
+ }
- return new Promise((resolve) => {
- resolve(post);
- });
-}
+ return new Promise((resolve) => {
+ resolve({ ...post, num });
+ });
+};
const resolvePosts = (posts: Entry[], observer: string): Promise => {
- const promises = posts.map(p => resolvePost(p, observer));
+ const promises = posts.map((p) => resolvePost(p, observer));
- return Promise.all(promises);
-}
+ return Promise.all(promises);
+};
export const getPostsRanked = (
- sort: string,
- start_author: string = "",
- start_permlink: string = "",
- limit: number = dataLimit,
- tag: string = "",
- observer: string = ""
+ sort: string,
+ start_author: string = "",
+ start_permlink: string = "",
+ limit: number = dataLimit,
+ tag: string = "",
+ observer: string = ""
): Promise => {
- return bridgeApiCall("get_ranked_posts", {
- sort,
- start_author,
- start_permlink,
- limit,
- tag,
- observer,
- }).then(resp => {
- if (resp) {
- return resolvePosts(resp, observer);
- }
+ return bridgeApiCall("get_ranked_posts", {
+ sort,
+ start_author,
+ start_permlink,
+ limit,
+ tag,
+ observer
+ }).then((resp) => {
+ if (resp) {
+ return resolvePosts(resp, observer);
+ }
- return resp;
- })
-}
+ return resp;
+ });
+};
export const getAccountPosts = (
- sort: string,
- account: string,
- start_author: string = "",
- start_permlink: string = "",
- limit: number = dataLimit,
- observer: string = ""
+ sort: string,
+ account: string,
+ start_author: string = "",
+ start_permlink: string = "",
+ limit: number = dataLimit,
+ observer: string = ""
): Promise => {
-
- return bridgeApiCall("get_account_posts", {
- sort,
- account,
- start_author,
- start_permlink,
- limit,
- observer,
- }).then(resp => {
- if (resp) {
- return resolvePosts(resp, observer);
- }
-
- return resp;
- })
-}
-
-export const getPost = (author: string = "", permlink: string = "", observer: string = ""): Promise => {
- return bridgeApiCall("get_post", {
- author,
- permlink,
- observer,
- }).then(resp => {
- if (resp) {
- return resolvePost(resp, observer);
- }
-
- return resp;
- })
-}
-
-export interface AccountNotification {
- date: string;
- id: number;
- msg: string;
- score: number;
- type: string;
- url: string;
-}
-
-export const getAccountNotifications = (account: string, lastId: number | null = null, limit = 50): Promise => {
- const params: { account: string, last_id?: number, limit: number } = {
- account, limit
+ return bridgeApiCall("get_account_posts", {
+ sort,
+ account,
+ start_author,
+ start_permlink,
+ limit,
+ observer
+ }).then((resp) => {
+ if (resp) {
+ return resolvePosts(resp, observer);
}
- if (lastId) {
- params.last_id = lastId;
+ return resp;
+ });
+};
+
+export const getPost = (
+ author: string = "",
+ permlink: string = "",
+ observer: string = "",
+ num?: number
+): Promise => {
+ return bridgeApiCall("get_post", {
+ author,
+ permlink,
+ observer
+ }).then((resp) => {
+ if (resp) {
+ return resolvePost(resp, observer, num);
}
- return bridgeApiCall("account_notifications", params);
-}
+ return resp;
+ });
+};
+
+export const getPostHeader = (
+ author: string = "",
+ permlink: string = ""
+): Promise => {
+ return bridgeApiCall("get_post_header", {
+ author,
+ permlink
+ }).then((resp) => {
+ return resp;
+ });
+};
-export const getDiscussion = (author: string, permlink: string): Promise | null> =>
- bridgeApiCall | null>("get_discussion", {
- author,
- permlink,
- });
+export interface AccountNotification {
+ date: string;
+ id: number;
+ msg: string;
+ score: number;
+ type: string;
+ url: string;
+}
-export const getCommunity = (name: string, observer: string | undefined = ""): Promise =>
- bridgeApiCall("get_community", {name, observer});
+export const getAccountNotifications = (
+ account: string,
+ lastId: number | null = null,
+ limit = 50
+): Promise => {
+ const params: { account: string; last_id?: number; limit: number } = {
+ account,
+ limit
+ };
+
+ if (lastId) {
+ params.last_id = lastId;
+ }
+
+ return bridgeApiCall("account_notifications", params);
+};
+
+export const getDiscussion = (
+ author: string,
+ permlink: string
+): Promise | null> =>
+ bridgeApiCall | null>("get_discussion", {
+ author,
+ permlink
+ });
+
+export const getCommunity = (
+ name: string,
+ observer: string | undefined = ""
+): Promise =>
+ bridgeApiCall("get_community", { name, observer });
export const getCommunities = (
- last: string = "",
- limit: number = 100,
- query?: string | null,
- sort: string = "rank",
- observer: string = ""
+ last: string = "",
+ limit: number = 100,
+ query?: string | null,
+ sort: string = "rank",
+ observer: string = ""
): Promise =>
- bridgeApiCall("list_communities", {
- last,
- limit,
- query,
- sort,
- observer,
- });
+ bridgeApiCall("list_communities", {
+ last,
+ limit,
+ query,
+ sort,
+ observer
+ });
export const normalizePost = (post: any): Promise =>
- bridgeApiCall("normalize_post", {
- post,
- });
+ bridgeApiCall("normalize_post", {
+ post
+ });
-export const getSubscriptions = (
- account: string
-): Promise =>
- bridgeApiCall("list_all_subscriptions", {
- account
- });
+export const getSubscriptions = (account: string): Promise =>
+ bridgeApiCall("list_all_subscriptions", {
+ account
+ });
-
-export const getSubscribers = (
- community: string
-): Promise =>
- bridgeApiCall("list_subscribers", {
- community
- });
+export const getSubscribers = (community: string): Promise =>
+ bridgeApiCall("list_subscribers", {
+ community
+ });
export interface AccountRelationship {
- follows: boolean,
- ignores: boolean,
- is_blacklisted: boolean,
- follows_blacklists: boolean
+ follows: boolean;
+ ignores: boolean;
+ is_blacklisted: boolean;
+ follows_blacklists: boolean;
}
-export const getRelationshipBetweenAccounts = (follower: string, following: string): Promise =>
- bridgeApiCall("get_relationship_between_accounts", [follower, following]);
-
-
-
+export const getRelationshipBetweenAccounts = (
+ follower: string,
+ following: string
+): Promise =>
+ bridgeApiCall("get_relationship_between_accounts", [
+ follower,
+ following
+ ]);
diff --git a/src/common/api/firebase.ts b/src/common/api/firebase.ts
new file mode 100644
index 00000000000..abfc8149bbe
--- /dev/null
+++ b/src/common/api/firebase.ts
@@ -0,0 +1,71 @@
+import { getMessaging, getToken, MessagePayload, Messaging, onMessage } from "@firebase/messaging";
+import { FirebaseApp, initializeApp } from "@firebase/app";
+import { Analytics, getAnalytics, logEvent } from "@firebase/analytics";
+
+let app: FirebaseApp;
+export let FCM: Messaging;
+export let FA: Analytics;
+
+export function initFirebase(initMessaging = true) {
+ if (typeof window === "undefined") {
+ return;
+ }
+
+ app = initializeApp({
+ apiKey: "AIzaSyDKF-JWDMmUs5ozjK7ZdgG4beHRsAMd2Yw",
+ authDomain: "esteem-ded08.firebaseapp.com",
+ databaseURL: "https://esteem-ded08.firebaseio.com",
+ projectId: "esteem-ded08",
+ storageBucket: "esteem-ded08.appspot.com",
+ messagingSenderId: "211285790917",
+ appId: "1:211285790917:web:c259d25ed1834c683760ac",
+ measurementId: "G-TYQD1N3NR3"
+ });
+ if (initMessaging) {
+ FCM = getMessaging(app);
+ }
+ FA = getAnalytics(app);
+
+ logEvent(FA, "test-event");
+}
+
+export const handleMessage = (payload: MessagePayload) => {
+ const notificationTitle = payload.notification?.title || "Ecency";
+
+ const notification = new Notification(notificationTitle, {
+ body: payload.notification?.body,
+ icon: payload.notification?.image
+ });
+
+ notification.onclick = () => {
+ let url = "https://ecency.com";
+ const data = (payload.data || {}) as any;
+ const fullPermlink = data.permlink1 + data.permlink2 + data.permlink3;
+
+ if (["vote", "unvote", "spin", "inactive"].includes(data.type)) {
+ url += "/@" + data.target;
+ } else {
+ // delegation, mention, transfer, follow, unfollow, ignore, blacklist, reblog
+ url += "/@" + data.source;
+ }
+ if (fullPermlink) {
+ url += "/" + fullPermlink;
+ }
+
+ window.open(url, "_blank");
+ };
+};
+
+export const getFcmToken = () =>
+ getToken(FCM, {
+ vapidKey:
+ "BA3SrGKAKMU_6PXOFwD9EQ1wIPzyYt90Q9ByWb3CkazBe8Isg7xr9Cgy0ka6SctHDW0VZLShTV_UDYNxewzWDjk"
+ });
+
+export const listenFCM = (callback: Function) => {
+ onMessage(FCM, (p) => {
+ //console.log('Received fg message', p);
+ handleMessage(p);
+ callback();
+ });
+};
diff --git a/src/common/api/hive-engine.ts b/src/common/api/hive-engine.ts
index deb5a901bf4..3d367a337b0 100644
--- a/src/common/api/hive-engine.ts
+++ b/src/common/api/hive-engine.ts
@@ -2,6 +2,7 @@ import axios from "axios";
import HiveEngineToken from "../helper/hive-engine-wallet";
import { TransactionConfirmation } from "@hiveio/dhive";
import { broadcastPostingJSON } from "./operations";
+import engine from "../constants/engine.json";
interface TokenBalance {
symbol: string;
@@ -42,9 +43,9 @@ export interface TokenStatus {
precision: number;
}
-const HIVE_ENGINE_RPC_URL = "https://api.hive-engine.com/rpc/contracts";
+const HIVE_ENGINE_RPC_URL = engine.engineRpcUrl;
-const getTokenBalances = (account: string): Promise => {
+export const getTokenBalances = (account: string): Promise => {
const data = {
jsonrpc: "2.0",
method: "find",
@@ -52,15 +53,15 @@ const getTokenBalances = (account: string): Promise => {
contract: "tokens",
table: "balances",
query: {
- account: account,
- },
+ account: account
+ }
},
- id: 1,
+ id: 1
};
return axios
.post(HIVE_ENGINE_RPC_URL, data, {
- headers: { "Content-type": "application/json" },
+ headers: { "Content-type": "application/json" }
})
.then((r) => r.data.result)
.catch((e) => {
@@ -76,15 +77,15 @@ const getTokens = (tokens: string[]): Promise => {
contract: "tokens",
table: "tokens",
query: {
- symbol: { $in: tokens },
- },
+ symbol: { $in: tokens }
+ }
},
- id: 2,
+ id: 2
};
return axios
.post(HIVE_ENGINE_RPC_URL, data, {
- headers: { "Content-type": "application/json" },
+ headers: { "Content-type": "application/json" }
})
.then((r) => r.data.result)
.catch((e) => {
@@ -92,42 +93,42 @@ const getTokens = (tokens: string[]): Promise => {
});
};
-export const getHiveEngineTokenBalances = async (
- account: string
-): Promise => {
-// commented just to try removing the non-existing unknowing HiveEngineTokenBalance type
-// ): Promise => {
+export const getHiveEngineTokenBalances = async (account: string): Promise => {
+ // commented just to try removing the non-existing unknowing HiveEngineTokenBalance type
+ // ): Promise => {
const balances = await getTokenBalances(account);
const tokens = await getTokens(balances.map((t) => t.symbol));
return balances.map((balance) => {
const token = tokens.find((t) => t.symbol == balance.symbol);
- const tokenMetadata = token && JSON.parse(token!.metadata) as TokenMetadata;
+ const tokenMetadata = token && (JSON.parse(token!.metadata) as TokenMetadata);
return new HiveEngineToken({ ...balance, ...token, ...tokenMetadata } as any);
});
};
-export const getUnclaimedRewards = async(
- account: string
-): Promise => {
- return (axios
- .get(`https://scot-api.hive-engine.com/@${account}?hive=1`)
- .then((r) => r.data)
- .then((r) => Object.values(r))
- .then((r) => r.filter((t) => (t as TokenStatus).pending_token > 0)) as any)
- .catch(() => {
- return [];
- });
+export const getUnclaimedRewards = async (account: string): Promise => {
+ const rewardsUrl = engine.engineRewardsUrl;
+ return (
+ axios
+ .get(`${rewardsUrl}/@${account}?hive=1`)
+ .then((r) => r.data)
+ .then((r) => Object.values(r))
+ .then((r) => r.filter((t) => (t as TokenStatus).pending_token > 0)) as any
+ ).catch(() => {
+ return [];
+ });
};
export const claimRewards = async (
account: string,
tokens: string[]
): Promise => {
- const json = JSON.stringify(tokens.map((r) => {
- return { symbol: r };
- }));
+ const json = JSON.stringify(
+ tokens.map((r) => {
+ return { symbol: r };
+ })
+ );
return broadcastPostingJSON(account, "scot_claim_token", json);
};
@@ -135,7 +136,7 @@ export const claimRewards = async (
export const stakeTokens = async (
account: string,
token: string,
- amount: string,
+ amount: string
): Promise => {
const json = JSON.stringify({
contractName: "tokens",
@@ -143,9 +144,47 @@ export const stakeTokens = async (
contractPayload: {
symbol: token,
to: account,
- quantity: amount,
- },
+ quantity: amount
+ }
});
return broadcastPostingJSON(account, "ssc-mainnet-hive", json);
};
+
+export const getMetrics: any = async (symbol?: any, account?: any) => {
+ const data = {
+ jsonrpc: "2.0",
+ method: "find",
+ params: {
+ contract: "market",
+ table: "metrics",
+ query: {
+ symbol: symbol,
+ account: account
+ }
+ },
+ id: 1
+ };
+
+ // const result = await axios
+ // .post(HIVE_ENGINE_RPC_URL, data, {
+ // headers: { "Content-type": "application/json" }
+ // })
+ // return result;
+ return axios
+ .post(HIVE_ENGINE_RPC_URL, data, {
+ headers: { "Content-type": "application/json" }
+ })
+ .then((r) => r.data.result)
+ .catch((e) => {
+ return [];
+ });
+};
+
+export const getMarketData = async (symbol: any) => {
+ const url: any = engine.chartApi;
+ const { data: history } = await axios.get(`${url}`, {
+ params: { symbol, interval: "daily" }
+ });
+ return history;
+};
diff --git a/src/common/api/hive.ts b/src/common/api/hive.ts
index 5a06261c433..5da3780c022 100644
--- a/src/common/api/hive.ts
+++ b/src/common/api/hive.ts
@@ -1,486 +1,658 @@
-import {Client, RCAPI, utils} from "@hiveio/dhive";
+import { Client, RCAPI, utils } from "@hiveio/dhive";
-import {RCAccount} from "@hiveio/dhive/lib/chain/rc";
+import { RCAccount } from "@hiveio/dhive/lib/chain/rc";
-import {TrendingTag} from "../store/trending-tags/types";
-import {DynamicProps} from "../store/dynamic-props/types";
-import {FullAccount, AccountProfile, AccountFollowStats} from "../store/accounts/types";
+import { TrendingTag } from "../store/trending-tags/types";
+import { DynamicProps } from "../store/dynamic-props/types";
+import { FullAccount, AccountProfile, AccountFollowStats } from "../store/accounts/types";
+import { Entry } from "../store/entries/types";
import parseAsset from "../helper/parse-asset";
-import {vestsToRshares} from "../helper/vesting";
+import { vestsToRshares } from "../helper/vesting";
import isCommunity from "../helper/is-community";
import SERVERS from "../constants/servers.json";
-import { dataLimit } from './bridge';
-import moment from "moment";
+import { dataLimit } from "./bridge";
+import moment, { Moment } from "moment";
export const client = new Client(SERVERS, {
- timeout: 4000,
- failoverThreshold: 2,
- consoleOnFailover: true,
+ timeout: 3000,
+ failoverThreshold: 3,
+ consoleOnFailover: true
});
export interface Vote {
- percent: number;
- reputation: number;
- rshares: string;
- time: string;
- timestamp?: number;
- voter: string;
- weight: number;
- reward?: number;
+ percent: number;
+ reputation: number;
+ rshares: string;
+ time: string;
+ timestamp?: number;
+ voter: string;
+ weight: number;
+ reward?: number;
}
export interface DynamicGlobalProperties {
- hbd_print_rate: number;
- total_vesting_fund_hive: string;
- total_vesting_shares: string;
- hbd_interest_rate: number;
- head_block_number: number;
- vesting_reward_percent: number;
- virtual_supply: string;
+ hbd_print_rate: number;
+ total_vesting_fund_hive: string;
+ total_vesting_shares: string;
+ hbd_interest_rate: number;
+ head_block_number: number;
+ vesting_reward_percent: number;
+ virtual_supply: string;
}
export interface FeedHistory {
- current_median_history: {
- base: string;
- quote: string;
- };
+ current_median_history: {
+ base: string;
+ quote: string;
+ };
+}
+
+export interface ChainProps {
+ account_creation_fee: string;
+ maximum_block_size: number;
+ hbd_interest_rate: number;
+ account_subsidy_budget: number;
+ account_subsidy_decay: number;
}
export interface RewardFund {
- recent_claims: string;
- reward_balance: string;
+ recent_claims: string;
+ reward_balance: string;
}
export interface DelegatedVestingShare {
- id: number;
- delegatee: string;
- delegator: string;
- min_delegation_time: string;
- vesting_shares: string;
+ id: number;
+ delegatee: string;
+ delegator: string;
+ min_delegation_time: string;
+ vesting_shares: string;
}
export interface Follow {
- follower: string;
- following: string;
- what: string[];
+ follower: string;
+ following: string;
+ what: string[];
}
export interface MarketStatistics {
- hbd_volume: string;
- highest_bid: string;
- hive_volume: string;
- latest: string;
- lowest_ask: string;
- percent_change: string;
+ hbd_volume: string;
+ highest_bid: string;
+ hive_volume: string;
+ latest: string;
+ lowest_ask: string;
+ percent_change: string;
}
export interface OpenOrdersData {
- id: number,
- created: string,
- expiration: string,
- seller: string,
- orderid: number,
- for_sale: number,
- sell_price: {
- base: string,
- quote: string
- },
- real_price: string,
- rewarded: boolean
+ id: number;
+ created: string;
+ expiration: string;
+ seller: string;
+ orderid: number;
+ for_sale: number;
+ sell_price: {
+ base: string;
+ quote: string;
+ };
+ real_price: string;
+ rewarded: boolean;
}
export interface OrdersDataItem {
- created: string;
- hbd: number;
- hive: number;
- order_price: {
- base: string;
- quote: string;
- }
- real_price: string;
+ created: string;
+ hbd: number;
+ hive: number;
+ order_price: {
+ base: string;
+ quote: string;
+ };
+ real_price: string;
+}
+
+export interface MarketCandlestickDataItem {
+ hive: {
+ high: number;
+ low: number;
+ open: number;
+ close: number;
+ volume: number;
+ };
+ id: number;
+ non_hive: {
+ high: number;
+ low: number;
+ open: number;
+ close: number;
+ volume: number;
+ };
+ open: string;
+ seconds: number;
}
export interface TradeDataItem {
- current_pays: string;
- date: number;
- open_pays: string;
+ current_pays: string;
+ date: number;
+ open_pays: string;
}
export interface OrdersData {
- bids: OrdersDataItem[];
- asks: OrdersDataItem[];
- trading: OrdersDataItem[];
+ bids: OrdersDataItem[];
+ asks: OrdersDataItem[];
+ trading: OrdersDataItem[];
+}
+
+interface ApiError {
+ error: string;
+ data: any;
}
+const handleError = (error: any) => {
+ debugger;
+ return { error: "api error", data: error };
+};
+
export const getPost = (username: string, permlink: string): Promise =>
- client.call("condenser_api", "get_content", [username, permlink]);
+ client.call("condenser_api", "get_content", [username, permlink]);
export const getMarketStatistics = (): Promise =>
- client.call("condenser_api", "get_ticker", []);
+ client.call("condenser_api", "get_ticker", []);
export const getOrderBook = (limit: number = 500): Promise =>
- client.call("condenser_api", "get_order_book", [limit]);
+ client.call("condenser_api", "get_order_book", [limit]);
export const getOpenOrder = (user: string): Promise =>
- client.call("condenser_api", "get_open_orders", [user]);
+ client.call("condenser_api", "get_open_orders", [user]);
export const getTradeHistory = (limit: number = 1000): Promise => {
- let today = moment(Date.now()).subtract(10, 'h').format().split('+')[0];
- return client.call("condenser_api", "get_trade_history", [today, "1969-12-31T23:59:59",limit]);}
+ let todayEarlier = moment(Date.now()).subtract(10, "h").format().split("+")[0];
+ let todayNow = moment(Date.now()).format().split("+")[0];
+ return client.call("condenser_api", "get_trade_history", [todayEarlier, todayNow, limit]);
+};
+
+export const getMarketBucketSizes = (): Promise =>
+ client.call("condenser_api", "get_market_history_buckets", []);
+
+export const getMarketHistory = (
+ seconds: number,
+ startDate: Moment,
+ endDate: Moment
+): Promise => {
+ let todayEarlier = startDate.format().split("+")[0];
+ let todayNow = endDate.format().split("+")[0];
+ return client.call("condenser_api", "get_market_history", [seconds, todayEarlier, todayNow]);
+};
export const getActiveVotes = (author: string, permlink: string): Promise =>
- client.database.call("get_active_votes", [author, permlink]);
+ client.database.call("get_active_votes", [author, permlink]);
export const getTrendingTags = (afterTag: string = "", limit: number = 250): Promise =>
- client.database
- .call("get_trending_tags", [afterTag, limit])
- .then((tags: TrendingTag[]) => {
- return tags
- .filter((x) => x.name !== "")
- .filter((x) => !isCommunity(x.name))
- .map((x) => x.name)
- }
- );
+ client.database.call("get_trending_tags", [afterTag, limit]).then((tags: TrendingTag[]) => {
+ return tags
+ .filter((x) => x.name !== "")
+ .filter((x) => !isCommunity(x.name))
+ .map((x) => x.name);
+ });
+
+export const getAllTrendingTags = (
+ afterTag: string = "",
+ limit: number = 250
+): Promise =>
+ client.database.call("get_trending_tags", [afterTag, limit]).then((tags: TrendingTag[]) => {
+ return tags.filter((x) => x.name !== "").filter((x) => !isCommunity(x.name));
+ });
export const lookupAccounts = (q: string, limit = 50): Promise =>
- client.database.call("lookup_accounts", [q, limit]);
+ client.database.call("lookup_accounts", [q, limit]);
export const getAccounts = (usernames: string[]): Promise => {
- return client.database.getAccounts(usernames).then((resp: any[]): FullAccount[] =>
- resp.map((x) => {
- const account: FullAccount = {
- name: x.name,
- owner: x.owner,
- active: x.active,
- posting: x.posting,
- memo_key: x.memo_key,
- post_count: x.post_count,
- created: x.created,
- reputation: x.reputation,
- posting_json_metadata: x.posting_json_metadata,
- last_vote_time: x.last_vote_time,
- last_post: x.last_post,
- json_metadata: x.json_metadata,
- reward_hive_balance: x.reward_hive_balance,
- reward_hbd_balance: x.reward_hbd_balance,
- reward_vesting_hive: x.reward_vesting_hive,
- reward_vesting_balance: x.reward_vesting_balance,
- balance: x.balance,
- hbd_balance: x.hbd_balance,
- savings_balance: x.savings_balance,
- savings_hbd_balance: x.savings_hbd_balance,
- next_vesting_withdrawal: x.next_vesting_withdrawal,
- vesting_shares: x.vesting_shares,
- delegated_vesting_shares: x.delegated_vesting_shares,
- received_vesting_shares: x.received_vesting_shares,
- vesting_withdraw_rate: x.vesting_withdraw_rate,
- to_withdraw: x.to_withdraw,
- withdrawn: x.withdrawn,
- witness_votes: x.witness_votes,
- proxy: x.proxy,
- proxied_vsf_votes: x.proxied_vsf_votes,
- voting_manabar: x.voting_manabar,
- voting_power: x.voting_power,
- downvote_manabar: x.downvote_manabar,
- __loaded: true,
- };
-
- let profile: AccountProfile | undefined;
-
- try {
- profile = JSON.parse(x.posting_json_metadata!).profile;
- } catch (e) {
- }
-
- if (!profile) {
- try {
- profile = JSON.parse(x.json_metadata!).profile;
- } catch (e) {
- }
- }
-
- if (!profile) {
- profile = {
- about: '',
- cover_image: '',
- location: '',
- name: '',
- profile_image: '',
- website: '',
- }
- }
-
- return {...account, profile};
- })
- );
+ return client.database.getAccounts(usernames).then((resp: any[]): FullAccount[] =>
+ resp.map((x) => {
+ const account: FullAccount = {
+ name: x.name,
+ owner: x.owner,
+ active: x.active,
+ posting: x.posting,
+ memo_key: x.memo_key,
+ post_count: x.post_count,
+ created: x.created,
+ reputation: x.reputation,
+ posting_json_metadata: x.posting_json_metadata,
+ last_vote_time: x.last_vote_time,
+ last_post: x.last_post,
+ json_metadata: x.json_metadata,
+ reward_hive_balance: x.reward_hive_balance,
+ reward_hbd_balance: x.reward_hbd_balance,
+ reward_vesting_hive: x.reward_vesting_hive,
+ reward_vesting_balance: x.reward_vesting_balance,
+ balance: x.balance,
+ hbd_balance: x.hbd_balance,
+ savings_balance: x.savings_balance,
+ savings_hbd_balance: x.savings_hbd_balance,
+ savings_hbd_last_interest_payment: x.savings_hbd_last_interest_payment,
+ savings_hbd_seconds_last_update: x.savings_hbd_seconds_last_update,
+ savings_hbd_seconds: x.savings_hbd_seconds,
+ next_vesting_withdrawal: x.next_vesting_withdrawal,
+ pending_claimed_accounts: x.pending_claimed_accounts,
+ vesting_shares: x.vesting_shares,
+ delegated_vesting_shares: x.delegated_vesting_shares,
+ received_vesting_shares: x.received_vesting_shares,
+ vesting_withdraw_rate: x.vesting_withdraw_rate,
+ to_withdraw: x.to_withdraw,
+ withdrawn: x.withdrawn,
+ witness_votes: x.witness_votes,
+ proxy: x.proxy,
+ recovery_account: x.recovery_account,
+ proxied_vsf_votes: x.proxied_vsf_votes,
+ voting_manabar: x.voting_manabar,
+ voting_power: x.voting_power,
+ downvote_manabar: x.downvote_manabar,
+ __loaded: true
+ };
+
+ let profile: AccountProfile | undefined;
+
+ try {
+ profile = JSON.parse(x.posting_json_metadata!).profile;
+ } catch (e) {}
+
+ if (!profile) {
+ try {
+ profile = JSON.parse(x.json_metadata!).profile;
+ } catch (e) {}
+ }
+
+ if (!profile) {
+ profile = {
+ about: "",
+ cover_image: "",
+ location: "",
+ name: "",
+ profile_image: "",
+ website: ""
+ };
+ }
+
+ return { ...account, profile };
+ })
+ );
};
-export const getAccount = (username: string): Promise => getAccounts([username]).then((resp) => resp[0]);
+export const getAccount = (username: string): Promise =>
+ getAccounts([username]).then((resp) => resp[0]);
export const getAccountFull = (username: string): Promise =>
- getAccount(username).then(async (account) => {
- let follow_stats: AccountFollowStats | undefined;
- try {
- follow_stats = await getFollowCount(username);
- } catch (e) {
- }
+ getAccount(username).then(async (account) => {
+ let follow_stats: AccountFollowStats | undefined;
+ try {
+ follow_stats = await getFollowCount(username);
+ } catch (e) {}
- return {...account, follow_stats};
- });
+ return { ...account, follow_stats };
+ });
export const getFollowCount = (username: string): Promise =>
- client.database.call("get_follow_count", [username]);
+ client.database.call("get_follow_count", [username]);
export const getFollowing = (
- follower: string,
- startFollowing: string,
- followType = "blog",
- limit = 100
-): Promise => client.database.call("get_following", [follower, startFollowing, followType, limit]);
+ follower: string,
+ startFollowing: string,
+ followType = "blog",
+ limit = 100
+): Promise =>
+ client.database.call("get_following", [follower, startFollowing, followType, limit]);
export const getFollowers = (
- following: string,
- startFollowing: string,
- followType = "blog",
- limit = 100
-): Promise => client.database.call("get_followers", [following, startFollowing === "" ? null : startFollowing, followType, limit]);
+ following: string,
+ startFollowing: string,
+ followType = "blog",
+ limit = 100
+): Promise =>
+ client.database.call("get_followers", [
+ following,
+ startFollowing === "" ? null : startFollowing,
+ followType,
+ limit
+ ]);
export const findRcAccounts = (username: string): Promise =>
- new RCAPI(client).findRCAccounts([username])
+ new RCAPI(client).findRCAccounts([username]);
export const getDynamicGlobalProperties = (): Promise =>
- client.database.getDynamicGlobalProperties().then((r: any) => {
- return({
- total_vesting_fund_hive: r.total_vesting_fund_hive || r.total_vesting_fund_steem,
- total_vesting_shares: r.total_vesting_shares,
- hbd_print_rate: r.hbd_print_rate || r.sbd_print_rate,
- hbd_interest_rate: r.hbd_interest_rate,
- head_block_number: r.head_block_number,
- vesting_reward_percent: r.vesting_reward_percent,
- virtual_supply: r.virtual_supply
- })});
-
-export const getAccountHistory = (username: string, filters: any[], start: number = -1, limit: number = 20): Promise => {
-
- return client.call("condenser_api", "get_account_history", [username, start, limit, ...filters]);
-}
+ client.database.getDynamicGlobalProperties().then((r: any) => {
+ return {
+ total_vesting_fund_hive: r.total_vesting_fund_hive || r.total_vesting_fund_steem,
+ total_vesting_shares: r.total_vesting_shares,
+ hbd_print_rate: r.hbd_print_rate || r.sbd_print_rate,
+ hbd_interest_rate: r.hbd_interest_rate,
+ head_block_number: r.head_block_number,
+ vesting_reward_percent: r.vesting_reward_percent,
+ virtual_supply: r.virtual_supply
+ };
+ });
+
+export const getAccountHistory = (
+ username: string,
+ filters: any[] | any,
+ start: number = -1,
+ limit: number = 20
+): Promise => {
+ return filters
+ ? client.call("condenser_api", "get_account_history", [username, start, limit, ...filters])
+ : client.call("condenser_api", "get_account_history", [username, start, limit]);
+};
export const getFeedHistory = (): Promise => client.database.call("get_feed_history");
-export const getRewardFund = (): Promise => client.database.call("get_reward_fund", ["post"]);
+export const getRewardFund = (): Promise =>
+ client.database.call("get_reward_fund", ["post"]);
-export const getDynamicProps = async (): Promise => {
- const globalDynamic = await getDynamicGlobalProperties();
- const feedHistory = await getFeedHistory();
- const rewardFund = await getRewardFund();
-
- const hivePerMVests =
- (parseAsset(globalDynamic.total_vesting_fund_hive).amount / parseAsset(globalDynamic.total_vesting_shares).amount) *
- 1e6;
- const base = parseAsset(feedHistory.current_median_history.base).amount;
- const quote = parseAsset(feedHistory.current_median_history.quote).amount;
- const fundRecentClaims = parseFloat(rewardFund.recent_claims);
- const fundRewardBalance = parseAsset(rewardFund.reward_balance).amount;
- const hbdPrintRate = globalDynamic.hbd_print_rate;
- const hbdInterestRate = globalDynamic.hbd_interest_rate;
- const headBlock = globalDynamic.head_block_number;
- const totalVestingFund = parseAsset(globalDynamic.total_vesting_fund_hive).amount;
- const totalVestingShares = parseAsset(globalDynamic.total_vesting_shares).amount;
- const virtualSupply = parseAsset(globalDynamic.virtual_supply).amount;
- const vestingRewardPercent = globalDynamic.vesting_reward_percent;
+export const getChainProps = (): Promise =>
+ client.database.call("get_chain_properties");
- return {
- hivePerMVests,
- base,
- quote,
- fundRecentClaims,
- fundRewardBalance,
- hbdPrintRate,
- hbdInterestRate,
- headBlock,
- totalVestingFund,
- totalVestingShares,
- virtualSupply,
- vestingRewardPercent
- };
+export const getDynamicProps = async (): Promise => {
+ const globalDynamic = await getDynamicGlobalProperties();
+ const feedHistory = await getFeedHistory();
+ const chainProps = await getChainProps();
+ const rewardFund = await getRewardFund();
+
+ const hivePerMVests =
+ (parseAsset(globalDynamic.total_vesting_fund_hive).amount /
+ parseAsset(globalDynamic.total_vesting_shares).amount) *
+ 1e6;
+ const base = parseAsset(feedHistory.current_median_history.base).amount;
+ const quote = parseAsset(feedHistory.current_median_history.quote).amount;
+ const fundRecentClaims = parseFloat(rewardFund.recent_claims);
+ const fundRewardBalance = parseAsset(rewardFund.reward_balance).amount;
+ const hbdPrintRate = globalDynamic.hbd_print_rate;
+ const hbdInterestRate = globalDynamic.hbd_interest_rate;
+ const headBlock = globalDynamic.head_block_number;
+ const totalVestingFund = parseAsset(globalDynamic.total_vesting_fund_hive).amount;
+ const totalVestingShares = parseAsset(globalDynamic.total_vesting_shares).amount;
+ const virtualSupply = parseAsset(globalDynamic.virtual_supply).amount;
+ const vestingRewardPercent = globalDynamic.vesting_reward_percent;
+ const accountCreationFee = chainProps.account_creation_fee;
+
+ return {
+ hivePerMVests,
+ base,
+ quote,
+ fundRecentClaims,
+ fundRewardBalance,
+ hbdPrintRate,
+ hbdInterestRate,
+ headBlock,
+ totalVestingFund,
+ totalVestingShares,
+ virtualSupply,
+ vestingRewardPercent,
+ accountCreationFee
+ };
};
export const getVestingDelegations = (
- username: string,
- from: string = "",
- limit: number = 50
-): Promise => client.database.call("get_vesting_delegations", [username, from, limit]);
+ username: string,
+ from: string = "",
+ limit: number = 50
+): Promise =>
+ client.database.call("get_vesting_delegations", [username, from, limit]);
+
+export const getOutgoingRc = async (
+ from: string,
+ to: string = "",
+ limit: number = 50
+): Promise => {
+ const data = await client.call("rc_api", "list_rc_direct_delegations", {
+ start: [from, to],
+ limit: limit
+ });
+ return data;
+};
+
+export const getIncomingRc = async (user: string): Promise => {
+ const data = await fetch(`https://ecency.com/private-api/received-rc/${user}`)
+ .then((res: any) => res.json())
+ .then((r: any) => r);
+ return data;
+};
export interface Witness {
- total_missed: number;
- url: string;
- props: {
- account_creation_fee: string;
- account_subsidy_budget: number;
- maximum_block_size: number;
- },
- hbd_exchange_rate: {
- base: string;
- },
- available_witness_account_subsidies: number;
- running_version: string;
- owner: string;
- signing_key:string,
- last_hbd_exchange_update:string
+ total_missed: number;
+ url: string;
+ props: {
+ account_creation_fee: string;
+ account_subsidy_budget: number;
+ maximum_block_size: number;
+ };
+ hbd_exchange_rate: {
+ base: string;
+ };
+ available_witness_account_subsidies: number;
+ running_version: string;
+ owner: string;
+ signing_key: string;
+ last_hbd_exchange_update: string;
}
-export const getWitnessesByVote = (
- from: string = "",
- limit: number = 50
-): Promise => client.call("condenser_api", "get_witnesses_by_vote", [from, limit]);
-
+export const getWitnessesByVote = (from: string, limit: number): Promise =>
+ client.call("condenser_api", "get_witnesses_by_vote", [from, limit]);
export interface Proposal {
- creator: string;
- daily_pay: {
- amount: string
- nai: string
- precision: number
- };
- end_date: string;
- id: number;
- permlink: string;
- proposal_id: number;
- receiver: string;
- start_date: string;
- status: string;
- subject: string;
- total_votes: string;
+ creator: string;
+ daily_pay: {
+ amount: string;
+ nai: string;
+ precision: number;
+ };
+ end_date: string;
+ id: number;
+ permlink: string;
+ proposal_id: number;
+ receiver: string;
+ start_date: string;
+ status: string;
+ subject: string;
+ total_votes: string;
}
-export const getProposals = (): Promise => client.call("database_api", "list_proposals", {
- start: [-1],
- limit: 200,
- order: 'by_total_votes',
- order_direction: 'descending',
- status: 'all'
-}).then(r => r.proposals);
+export const getProposals = (): Promise =>
+ client
+ .call("database_api", "list_proposals", {
+ start: [-1],
+ limit: 200,
+ order: "by_total_votes",
+ order_direction: "descending",
+ status: "all"
+ })
+ .then((r) => r.proposals);
export interface ProposalVote {
- id: number;
- proposal: Proposal;
- voter: string;
+ id: number;
+ proposal: Proposal;
+ voter: string;
}
-export const getProposalVotes = (proposalId: number, voter: string = "", limit: number = 300): Promise =>
- client.call('condenser_api', 'list_proposal_votes', [
- [proposalId, voter],
- limit,
- 'by_proposal_voter'
- ])
- .then(r => r.filter((x: ProposalVote) => x.proposal.proposal_id === proposalId))
- .then(r => r.map((x: ProposalVote) => ({id: x.id, voter: x.voter})))
-
+export const getProposalVotes = (
+ proposalId: number,
+ voter: string,
+ limit: number
+): Promise =>
+ client
+ .call("condenser_api", "list_proposal_votes", [[proposalId, voter], limit, "by_proposal_voter"])
+ .then((r) => r.filter((x: ProposalVote) => x.proposal.proposal_id === proposalId))
+ .then((r) => r.map((x: ProposalVote) => ({ id: x.id, voter: x.voter })));
export interface WithdrawRoute {
- auto_vest: boolean;
- from_account: string;
- id: number;
- percent: number;
- to_account: string;
+ auto_vest: boolean;
+ from_account: string;
+ id: number;
+ percent: number;
+ to_account: string;
}
export const getWithdrawRoutes = (account: string): Promise =>
- client.database.call("get_withdraw_routes", [account, "outgoing"]);
+ client.database.call("get_withdraw_routes", [account, "outgoing"]);
export const votingPower = (account: FullAccount): number => {
- // @ts-ignore "Account" is compatible with dhive's "ExtendedAccount"
- const calc = account && client.rc.calculateVPMana(account);
- const {percentage} = calc;
+ // @ts-ignore "Account" is compatible with dhive's "ExtendedAccount"
+ const calc = account && client.rc.calculateVPMana(account);
+ const { percentage } = calc;
- return percentage / 100;
+ return percentage / 100;
};
export const powerRechargeTime = (power: number) => {
- const missingPower = 100 - power
- return missingPower * 100 * 432000 / 10000;
-}
+ const missingPower = 100 - power;
+ return (missingPower * 100 * 432000) / 10000;
+};
-export const votingValue = (account: FullAccount, dynamicProps: DynamicProps, votingPower: number, weight: number = 10000): number => {
- const {fundRecentClaims, fundRewardBalance, base, quote} = dynamicProps;
+export const votingValue = (
+ account: FullAccount,
+ dynamicProps: DynamicProps,
+ votingPower: number,
+ weight: number = 10000
+): number => {
+ const { fundRecentClaims, fundRewardBalance, base, quote } = dynamicProps;
- const total_vests =
- parseAsset(account.vesting_shares).amount +
- parseAsset(account.received_vesting_shares).amount -
- parseAsset(account.delegated_vesting_shares).amount;
+ const total_vests =
+ parseAsset(account.vesting_shares).amount +
+ parseAsset(account.received_vesting_shares).amount -
+ parseAsset(account.delegated_vesting_shares).amount;
- const rShares = vestsToRshares(total_vests, votingPower, weight);
+ const rShares = vestsToRshares(total_vests, votingPower, weight);
- return rShares / fundRecentClaims * fundRewardBalance * (base / quote);
-}
+ return (rShares / fundRecentClaims) * fundRewardBalance * (base / quote);
+};
-const HIVE_VOTING_MANA_REGENERATION_SECONDS = 5*60*60*24; //5 days
+const HIVE_VOTING_MANA_REGENERATION_SECONDS = 5 * 60 * 60 * 24; //5 days
export const downVotingPower = (account: FullAccount): number => {
- const totalShares = parseFloat(account.vesting_shares) + parseFloat(account.received_vesting_shares) - parseFloat(account.delegated_vesting_shares) - parseFloat(account.vesting_withdraw_rate);
- const elapsed = Math.floor(Date.now() / 1000) - account.downvote_manabar.last_update_time;
- const maxMana = totalShares * 1000000 / 4;
-
- let currentMana = parseFloat(account.downvote_manabar.current_mana.toString()) + elapsed * maxMana / HIVE_VOTING_MANA_REGENERATION_SECONDS;
-
- if (currentMana > maxMana) {
- currentMana = maxMana;
- }
- const currentManaPerc = currentMana * 100 / maxMana;
-
- if (isNaN(currentManaPerc)) {
- return 0;
- }
-
- if (currentManaPerc > 100) {
- return 100;
- }
- return currentManaPerc;
+ const totalShares =
+ parseFloat(account.vesting_shares) +
+ parseFloat(account.received_vesting_shares) -
+ parseFloat(account.delegated_vesting_shares) -
+ parseFloat(account.vesting_withdraw_rate);
+ const elapsed = Math.floor(Date.now() / 1000) - account.downvote_manabar.last_update_time;
+ const maxMana = (totalShares * 1000000) / 4;
+
+ let currentMana =
+ parseFloat(account.downvote_manabar.current_mana.toString()) +
+ (elapsed * maxMana) / HIVE_VOTING_MANA_REGENERATION_SECONDS;
+
+ if (currentMana > maxMana) {
+ currentMana = maxMana;
+ }
+ const currentManaPerc = (currentMana * 100) / maxMana;
+
+ if (isNaN(currentManaPerc)) {
+ return 0;
+ }
+
+ if (currentManaPerc > 100) {
+ return 100;
+ }
+ return currentManaPerc;
};
export const rcPower = (account: RCAccount): number => {
- const calc = client.rc.calculateRCMana(account);
- const {percentage} = calc;
- return percentage / 100;
+ const calc = client.rc.calculateRCMana(account);
+ const { percentage } = calc;
+ return percentage / 100;
};
export interface ConversionRequest {
- amount: string;
- conversion_date: string;
- id: number;
- owner: string;
- requestid: number;
+ amount: string;
+ conversion_date: string;
+ id: number;
+ owner: string;
+ requestid: number;
+}
+
+export interface CollateralizedConversionRequest {
+ collateral_amount: string;
+ conversion_date: string;
+ converted_amount: string;
+ id: number;
+ owner: string;
+ requestid: number;
}
export const getConversionRequests = (account: string): Promise =>
- client.database.call("get_conversion_requests", [account]);
+ client.database.call("get_conversion_requests", [account]);
+
+export const getCollateralizedConversionRequests = (
+ account: string
+): Promise =>
+ client.database.call("get_collateralized_conversion_requests", [account]);
export interface SavingsWithdrawRequest {
- id: number;
- from: string;
- to: string;
- memo: string;
- request_id: number;
- amount: string;
- complete: string;
-}
+ id: number;
+ from: string;
+ to: string;
+ memo: string;
+ request_id: number;
+ amount: string;
+ complete: string;
+}
export const getSavingsWithdrawFrom = (account: string): Promise =>
- client.database.call("get_savings_withdraw_from", [account]);
+ client.database.call("get_savings_withdraw_from", [account]);
export interface BlogEntry {
- blog: string,
- entry_id: number,
- author: string,
- permlink: string,
- reblogged_on: string
+ blog: string;
+ entry_id: number;
+ post_id?: number;
+ num?: number;
+ author: string;
+ permlink: string;
+ reblogged_on: string;
+ created?: string;
}
export const getBlogEntries = (username: string, limit: number = dataLimit): Promise =>
- client.call('condenser_api', 'get_blog_entries', [
- username,
- 0,
- limit
- ]);
+ client.call("condenser_api", "get_blog_entries", [username, 0, limit]);
+
+export const findAccountRecoveryRequest = (account: string): Promise =>
+ client.call("database_api", "find_change_recovery_account_requests", { accounts: [account] });
+
+// @source https://ecency.com/hive-139531/@andablackwidow/rc-stats-in-1-27
+export type RcOperation =
+ | "comment_operation"
+ | "vote_operation"
+ | "transfer_operation"
+ | "custom_json_operation";
+
+export interface RcOperationStats {
+ count: number; // number of such operations executed during last day
+ avg_cost_rc: number; // average RC cost of single operation
+ resource_cost: {
+ // average RC cost split between various resources
+ history_rc: number;
+ tokens_rc: number;
+ market_rc: number;
+ state_rc: number;
+ exec_rc: number;
+ };
+ resource_cost_share: {
+ // share of resource cost in average final cost (expressed in basis points)
+ history_bp: number;
+ tokens_bp: number;
+ market_bp: number;
+ state_bp: number;
+ exec_bp: number;
+ };
+ resource_usage: {
+ // average consumption of resources per operation
+ history_bytes: number; // - size of transaction in bytes
+ tokens: string; // - number of tokens (always 0 or 1 (with exception of multiop) - tokens are internally expressed with 4 digit precision
+ market_bytes: number; // - size of transaction in bytes when it belongs to market category or 0 otherwise
+ state_hbytes: number; // - hour-bytes of state
+ exec_ns: number; // - nanoseconds of execution time
+ };
+}
+
+export const getRcOperationStats = (): Promise => client.call("rc_api", "get_rc_stats", {});
+
+export const getContentReplies = (author: string, permlink: string): Promise =>
+ client.call("condenser_api", "get_content_replies", { author, permlink });
diff --git a/src/common/api/misc.ts b/src/common/api/misc.ts
index 7abb7b869ad..5b13768e72d 100644
--- a/src/common/api/misc.ts
+++ b/src/common/api/misc.ts
@@ -1,41 +1,73 @@
-import axios from 'axios';
+import axios from "axios";
import defaults from "../constants/defaults.json";
-import {apiBase} from "./helper";
+import { apiBase } from "./helper";
export const getEmojiData = () => fetch(apiBase("/emoji.json")).then((response) => response.json());
-export const uploadImage = async (file: File, token: string): Promise<{
- url: string
+export const uploadImage = async (
+ file: File,
+ token: string
+): Promise<{
+ url: string;
}> => {
- const fData = new FormData();
- fData.append('file', file);
+ const fData = new FormData();
+ fData.append("file", file);
- const postUrl = `${defaults.imageServer}/hs/${token}`;
+ const postUrl = `${defaults.imageServer}/hs/${token}`;
- return axios.post(postUrl, fData, {
- headers: {
- 'Content-Type': 'multipart/form-data'
- }
- }).then(r => r.data);
+ return axios
+ .post(postUrl, fData, {
+ headers: {
+ "Content-Type": "multipart/form-data"
+ }
+ })
+ .then((r) => r.data);
};
-export const getMarketData = (coin: string, vsCurrency: string, fromTs: string, toTs: string): Promise<{ prices?: [number, number] }> => {
- const u = `https://api.coingecko.com/api/v3/coins/${coin}/market_chart/range?vs_currency=${vsCurrency}&from=${fromTs}&to=${toTs}`
- return axios.get(u).then(r => r.data);
-}
+export const getMarketData = (
+ coin: string,
+ vsCurrency: string,
+ fromTs: string,
+ toTs: string
+): Promise<{ prices?: [number, number] }> => {
+ const u = `https://api.coingecko.com/api/v3/coins/${coin}/market_chart/range?vs_currency=${vsCurrency}&from=${fromTs}&to=${toTs}`;
+ return axios.get(u).then((r) => r.data);
+};
export const getCurrencyRate = (cur: string): Promise => {
- if (cur === "hbd") {
- return new Promise((resolve) => resolve(1));
- }
+ if (cur === "hbd") {
+ return new Promise((resolve) => resolve(1));
+ }
- const u = `https://api.coingecko.com/api/v3/simple/price?ids=hive_dollar&vs_currencies=${cur}`;
- return axios.get(u).then(r => r.data).then(r => r.hive_dollar[cur]);
-}
+ const u = `https://api.coingecko.com/api/v3/simple/price?ids=hive_dollar&vs_currencies=${cur}`;
+ return axios
+ .get(u)
+ .then((r) => r.data)
+ .then((r) => r.hive_dollar[cur]);
+};
export const geLatestDesktopTag = (): Promise =>
- axios.get("https://api.github.com/repos/ecency/ecency-vision/releases/latest")
- .then(r => r.data)
- .then(r => r.tag_name);
+ axios
+ .get("https://api.github.com/repos/ecency/ecency-vision/releases/latest")
+ .then((r) => r.data)
+ .then((r) => r.tag_name);
+
+export const GIPHY_API_KEY = "DQ7mV4VsZ749GcCBZEunztICJ5nA4Vef";
+export const GIPHY_API = `https://api.giphy.com/v1/gifs/trending?api_key=${GIPHY_API_KEY}&limit=10&offset=0`;
+export const GIPHY_SEARCH_API = `https://api.giphy.com/v1/gifs/search?api_key=${GIPHY_API_KEY}&limit=40&offset=0&q=`;
+
+export const fetchGif = async (query: string | null, limit: string, offset: string) => {
+ let gifs;
+ if (query) {
+ gifs = await axios(
+ `https://api.giphy.com/v1/gifs/search?api_key=${GIPHY_API_KEY}&limit=${limit}&offset=${offset}&q=${query}`
+ );
+ } else {
+ gifs = await axios(
+ `https://api.giphy.com/v1/gifs/trending?api_key=${GIPHY_API_KEY}&limit=${limit}&offset=${offset}`
+ );
+ }
+ return gifs;
+};
diff --git a/src/common/api/mutations.ts b/src/common/api/mutations.ts
new file mode 100644
index 00000000000..e5f0e06c8e8
--- /dev/null
+++ b/src/common/api/mutations.ts
@@ -0,0 +1,15 @@
+import { useMutation } from "@tanstack/react-query";
+import { usrActivity } from "./private-api";
+
+interface Params {
+ bl?: string | number;
+ tx?: string | number;
+}
+
+export function useUserActivity(username: string | undefined, ty: number) {
+ return useMutation(["user-activity", username, ty], async (params: Params | undefined) => {
+ if (username) {
+ await usrActivity(username, ty, params?.bl, params?.tx);
+ }
+ });
+}
diff --git a/src/common/api/notifications-ws-api.ts b/src/common/api/notifications-ws-api.ts
new file mode 100644
index 00000000000..81bf1771383
--- /dev/null
+++ b/src/common/api/notifications-ws-api.ts
@@ -0,0 +1,190 @@
+import { WsNotification } from "../store/notifications/types";
+import { _t } from "../i18n";
+import { requestNotificationPermission } from "../util/request-notification-permission";
+import { ActiveUser } from "../store/active-user/types";
+import defaults from "../constants/defaults.json";
+import { NotifyTypes } from "../enums";
+import { playNotificationSound } from "../util/play-notification-sound";
+
+declare var window: Window & {
+ nws?: WebSocket;
+};
+
+export class NotificationsWebSocket {
+ private activeUser: ActiveUser | null = null;
+ private isElectron = false;
+ private hasNotifications = false;
+ private hasUiNotifications = false;
+ private onSuccessCallbacks: Function[] = [];
+ private enabledNotifyTypes: NotifyTypes[] = [];
+ private toggleUiProp: Function = () => {};
+ private isConnected = false;
+
+ private static getBody(data: WsNotification) {
+ const { source } = data;
+ switch (data.type) {
+ case "vote":
+ return _t("notification.voted", { source });
+ case "mention":
+ return data.extra.is_post === 1
+ ? _t("notification.mention-post", { source })
+ : _t("notification.mention-comment", { source });
+ case "favorites":
+ return _t("notification.favorite", { source });
+ case "bookmarks":
+ return _t("notification.bookmark", { source });
+ case "follow":
+ return _t("notification.followed", { source });
+ case "reply":
+ return _t("notification.replied", { source });
+ case "reblog":
+ return _t("notification.reblogged", { source });
+ case "transfer":
+ return _t("notification.transfer", { source, amount: data.extra.amount });
+ case "delegations":
+ return _t("notification.delegations", { source, amount: data.extra.amount });
+ default:
+ return "";
+ }
+ }
+
+ private async playSound() {
+ if (!("Notification" in window)) {
+ return;
+ }
+ const permission = await requestNotificationPermission();
+ if (permission !== "granted") return;
+
+ playNotificationSound(this.isElectron);
+ }
+
+ private async onMessageReceive(evt: MessageEvent) {
+ const logo = this.isElectron ? "./img/logo-circle.svg" : require("../img/logo-circle.svg");
+
+ const data = JSON.parse(evt.data);
+ const msg = NotificationsWebSocket.getBody(data);
+
+ const messageNotifyType = this.getNotificationType(data.type);
+ const allowedToNotify =
+ messageNotifyType && this.enabledNotifyTypes.length > 0
+ ? this.enabledNotifyTypes.includes(messageNotifyType)
+ : true;
+
+ if (msg) {
+ this.onSuccessCallbacks.forEach((cb) => cb());
+ if (!this.hasNotifications || !allowedToNotify) {
+ return;
+ }
+
+ await this.playSound();
+
+ new Notification(_t("notification.popup-title"), { body: msg, icon: logo }).onclick = () => {
+ if (!this.hasUiNotifications) {
+ this.toggleUiProp("notifications");
+ }
+ };
+ }
+ }
+
+ public async connect() {
+ if (this.isConnected) {
+ return;
+ }
+
+ if (!this.activeUser) {
+ this.disconnect();
+ return;
+ }
+
+ if (window.nws !== undefined) {
+ return;
+ }
+
+ if ("Notification" in window) {
+ await requestNotificationPermission();
+ }
+
+ window.nws = new WebSocket(`${defaults.nwsServer}/ws?user=${this.activeUser.username}`);
+ window.nws.onopen = () => {
+ console.log("nws connected");
+ this.isConnected = true;
+ };
+ window.nws.onmessage = (e) => this.onMessageReceive(e);
+ window.nws.onclose = (evt: CloseEvent) => {
+ console.log("nws disconnected");
+
+ window.nws = undefined;
+
+ if (!evt.wasClean) {
+ // Disconnected due connection error
+ console.log("nws trying to reconnect");
+
+ setTimeout(() => {
+ this.connect();
+ }, 2000);
+ }
+ };
+ }
+
+ public disconnect() {
+ if (window.nws !== undefined && this.isConnected) {
+ window.nws.close();
+ window.nws = undefined;
+ this.isConnected = false;
+ }
+ }
+
+ public withActiveUser(activeUser: ActiveUser | null) {
+ this.activeUser = activeUser;
+ return this;
+ }
+
+ public withElectron(isElectron: boolean) {
+ this.isElectron = isElectron;
+ return this;
+ }
+
+ public withToggleUi(toggle: Function) {
+ this.toggleUiProp = toggle;
+ return this;
+ }
+
+ public setHasNotifications(has: boolean) {
+ this.hasNotifications = has;
+ return this;
+ }
+
+ public withCallbackOnMessage(cb: Function) {
+ this.onSuccessCallbacks.push(cb);
+ return this;
+ }
+
+ public setHasUiNotifications(has: boolean) {
+ this.hasUiNotifications = has;
+ return this;
+ }
+
+ public setEnabledNotificationsTypes(value: NotifyTypes[]) {
+ this.enabledNotifyTypes = value;
+ return this;
+ }
+
+ public getNotificationType(value: string): NotifyTypes | null {
+ switch (value) {
+ case "vote":
+ return NotifyTypes.VOTE;
+ case "mention":
+ return NotifyTypes.MENTION;
+ case "follow":
+ return NotifyTypes.FOLLOW;
+ case "reply":
+ return NotifyTypes.COMMENT;
+ case "reblog":
+ return NotifyTypes.RE_BLOG;
+ case "transfer":
+ return NotifyTypes.TRANSFERS;
+ default:
+ return null;
+ }
+ }
+}
diff --git a/src/common/api/operations.ts b/src/common/api/operations.ts
index b7688d0bc5a..922e861eca3 100644
--- a/src/common/api/operations.ts
+++ b/src/common/api/operations.ts
@@ -1,1091 +1,2281 @@
import hs from "hivesigner";
-import {PrivateKey, Operation, TransactionConfirmation, AccountUpdateOperation, CustomJsonOperation} from '@hiveio/dhive';
+import {
+ AccountUpdateOperation,
+ Authority,
+ CustomJsonOperation,
+ KeyRole,
+ Operation,
+ OperationName,
+ VirtualOperationName,
+ PrivateKey,
+ TransactionConfirmation
+} from "@hiveio/dhive";
-import {Parameters} from 'hive-uri';
+import { Parameters } from "hive-uri";
-import {client as hiveClient} from "./hive";
+import { client as hiveClient } from "./hive";
-import {Account} from "../store/accounts/types";
+import { Account } from "../store/accounts/types";
-import {usrActivity} from "./private-api";
+import { usrActivity } from "./private-api";
-import {getAccessToken, getPostingKey} from "../helper/user-token";
+import { getAccessToken, getPostingKey } from "../helper/user-token";
import * as keychain from "../helper/keychain";
import parseAsset from "../helper/parse-asset";
-import {hotSign} from "../helper/hive-signer";
+import { hotSign } from "../helper/hive-signer";
-import {_t} from "../i18n";
+import { _t } from "../i18n";
import { TransactionType } from "../components/buy-sell-hive";
+import { ErrorTypes } from "../enums";
+import { formatNumber } from "../helper/format-number";
export interface MetaData {
- links?: string[];
- image?: string[];
- thumbnails?: string[];
- users?: string[];
- tags?: string[];
- app?: string;
- format?: string;
- community?: string;
+ image?: string[];
+ image_ratios?: any;
+ thumbnails?: string[];
+ tags?: string[];
+ app?: string;
+ format?: string;
+ community?: string;
+ description?: string;
}
export interface BeneficiaryRoute {
- account: string;
- weight: number;
+ account: string;
+ weight: number;
}
export interface CommentOptions {
- allow_curation_rewards: boolean;
- allow_votes: boolean;
- author: string;
- permlink: string;
- max_accepted_payout: string;
- percent_hbd: number;
- extensions: Array<[0, { beneficiaries: BeneficiaryRoute[] }]>;
+ allow_curation_rewards: boolean;
+ allow_votes: boolean;
+ author: string;
+ permlink: string;
+ max_accepted_payout: string;
+ percent_hbd: number;
+ extensions: Array<[0, { beneficiaries: BeneficiaryRoute[] }]>;
+}
+
+export enum OrderIdPrefix {
+ EMPTY = "",
+ SWAP = "9"
}
export type RewardType = "default" | "sp" | "dp";
-const handleChainError = (strErr: string) => {
- if (/You may only post once every/.test(strErr)) {
- return _t("chain-error.min-root-comment");
- } else if (/Your current vote on this comment is identical/.test(strErr)) {
- return _t("chain-error.identical-vote");
- } else if (/Please wait to transact, or power up/.test(strErr)) {
- return _t("chain-error.insufficient-resource");
- } else if (/Cannot delete a comment with net positive/.test(strErr)) {
- return _t("chain-error.delete-comment-with-vote");
- } else if (/children == 0/.test(strErr)) {
- return _t("chain-error.comment-children");
- } else if (/comment_cashout/.test(strErr)) {
- return _t("chain-error.comment-cashout");
- } else if (/Votes evaluating for comment that is paid out is forbidden/.test(strErr)) {
- return _t("chain-error.paid-out-post-forbidden");
- }
-
- return null;
-}
+const handleChainError = (strErr: string): [string | null, ErrorTypes] => {
+ if (/You may only post once every/.test(strErr)) {
+ return [_t("chain-error.min-root-comment"), ErrorTypes.COMMON];
+ } else if (/Your current vote on this comment is identical/.test(strErr)) {
+ return [_t("chain-error.identical-vote"), ErrorTypes.INFO];
+ } else if (/Please wait to transact, or power up/.test(strErr)) {
+ return [_t("chain-error.insufficient-resource"), ErrorTypes.INSUFFICIENT_RESOURCE_CREDITS];
+ } else if (/Cannot delete a comment with net positive/.test(strErr)) {
+ return [_t("chain-error.delete-comment-with-vote"), ErrorTypes.INFO];
+ } else if (/children == 0/.test(strErr)) {
+ return [_t("chain-error.comment-children"), ErrorTypes.COMMON];
+ } else if (/comment_cashout/.test(strErr)) {
+ return [_t("chain-error.comment-cashout"), ErrorTypes.COMMON];
+ } else if (/Votes evaluating for comment that is paid out is forbidden/.test(strErr)) {
+ return [_t("chain-error.paid-out-post-forbidden"), ErrorTypes.COMMON];
+ } else if (/Missing Active Authority/.test(strErr)) {
+ return [_t("chain-error.missing-authority"), ErrorTypes.INFO];
+ } else if (/Missing Owner Authority/.test(strErr)) {
+ return [_t("chain-error.missing-owner-authority"), ErrorTypes.INFO];
+ }
+
+ return [null, ErrorTypes.COMMON];
+};
-export const formatError = (err: any): string => {
+export const formatError = (err: any): [string, ErrorTypes] => {
+ let [chainErr, type] = handleChainError(err.toString());
+ if (chainErr) {
+ return [chainErr, type];
+ }
- let chainErr = handleChainError(err.toString());
+ if (err.error_description && typeof err.error_description === "string") {
+ let [chainErr, type] = handleChainError(err.error_description);
if (chainErr) {
- return chainErr;
+ return [chainErr, type];
}
- if (err.error_description && typeof err.error_description === "string") {
- let chainErr = handleChainError(err.error_description);
- if (chainErr) {
- return chainErr;
- }
+ return [err.error_description.substring(0, 80), ErrorTypes.COMMON];
+ }
- return err.error_description.substring(0, 80);
+ if (err.message && typeof err.message === "string") {
+ let [chainErr, type] = handleChainError(err.message);
+ if (chainErr) {
+ return [chainErr, type];
}
- if (err.message && typeof err.message === "string") {
- let chainErr = handleChainError(err.message);
- if (chainErr) {
- return chainErr;
- }
-
- return err.message.substring(0, 80);
- }
+ return [err.message.substring(0, 80), ErrorTypes.COMMON];
+ }
- return '';
+ return ["", ErrorTypes.COMMON];
};
-export const broadcastPostingJSON = (username: string, id: string, json: {}): Promise => {
+export const broadcastPostingJSON = (
+ username: string,
+ id: string,
+ json: {}
+): Promise => {
+ // With posting private key
+ const postingKey = getPostingKey(username);
+ if (postingKey) {
+ const privateKey = PrivateKey.fromString(postingKey);
+
+ const operation: CustomJsonOperation[1] = {
+ id,
+ required_auths: [],
+ required_posting_auths: [username],
+ json: JSON.stringify(json)
+ };
+
+ return hiveClient.broadcast.json(operation, privateKey);
+ }
+
+ // With hivesigner access token
- // With posting private key
- const postingKey = getPostingKey(username);
- if (postingKey) {
- const privateKey = PrivateKey.fromString(postingKey);
+ let token = getAccessToken(username);
+ return token
+ ? new hs.Client({
+ accessToken: token
+ })
+ .customJson([], [username], id, JSON.stringify(json))
+ .then((r: any) => r.result)
+ : Promise.resolve(0);
+};
+
+const broadcastPostingOperations = (
+ username: string,
+ operations: Operation[]
+): Promise => {
+ // With posting private key
+ const postingKey = getPostingKey(username);
+ if (postingKey) {
+ const privateKey = PrivateKey.fromString(postingKey);
+
+ return hiveClient.broadcast.sendOperations(operations, privateKey);
+ }
+
+ // With hivesigner access token
+ let token = getAccessToken(username);
+ return token
+ ? new hs.Client({
+ accessToken: token
+ })
+ .broadcast(operations)
+ .then((r: any) => r.result)
+ : Promise.resolve(0);
+};
- const operation: CustomJsonOperation[1] = {
- id,
- required_auths: [],
- required_posting_auths: [username],
- json: JSON.stringify(json)
- }
+export const reblog = (
+ username: string,
+ author: string,
+ permlink: string,
+ _delete: boolean = false
+): Promise => {
+ const message = {
+ account: username,
+ author,
+ permlink
+ };
+
+ if (_delete) {
+ message["delete"] = "delete";
+ }
+
+ const json = ["reblog", message];
+
+ return broadcastPostingJSON(username, "follow", json).then((r: TransactionConfirmation) => {
+ usrActivity(username, 130, r.block_num, r.id).then();
+ return r;
+ });
+};
- return hiveClient.broadcast.json(operation, privateKey);
+export const comment = (
+ username: string,
+ parentAuthor: string,
+ parentPermlink: string,
+ permlink: string,
+ title: string,
+ body: string,
+ jsonMetadata: MetaData,
+ options: CommentOptions | null,
+ point: boolean = false
+): Promise => {
+ const params = {
+ parent_author: parentAuthor,
+ parent_permlink: parentPermlink,
+ author: username,
+ permlink,
+ title,
+ body,
+ json_metadata: JSON.stringify(jsonMetadata)
+ };
+
+ const opArray: Operation[] = [["comment", params]];
+
+ if (options) {
+ const e: Operation = ["comment_options", options];
+ opArray.push(e);
+ }
+
+ return broadcastPostingOperations(username, opArray).then((r) => {
+ if (point) {
+ const t = title ? 100 : 110;
+ usrActivity(username, t, r.block_num, r.id).then();
}
+ return r;
+ });
+};
- // With hivesigner access token
+export const deleteComment = (
+ username: string,
+ author: string,
+ permlink: string
+): Promise => {
+ const params = {
+ author,
+ permlink
+ };
- let token = getAccessToken(username);
- return token ? new hs.Client({
- accessToken: token,
- }).customJson([], [username], id, JSON.stringify(json))
- .then((r: any) => r.result) : Promise.resolve(0);
-}
+ const opArray: Operation[] = [["delete_comment", params]];
-const broadcastPostingOperations = (username: string, operations: Operation[]): Promise => {
+ return broadcastPostingOperations(username, opArray);
+};
- // With posting private key
- const postingKey = getPostingKey(username);
- if (postingKey) {
- const privateKey = PrivateKey.fromString(postingKey);
+export const vote = (
+ username: string,
+ author: string,
+ permlink: string,
+ weight: number
+): Promise => {
+ const params = {
+ voter: username,
+ author,
+ permlink,
+ weight
+ };
+
+ const opArray: Operation[] = [["vote", params]];
+
+ return broadcastPostingOperations(username, opArray).then((r: TransactionConfirmation) => {
+ usrActivity(username, 120, r.block_num, r.id).then();
+ return r;
+ });
+};
- return hiveClient.broadcast.sendOperations(operations, privateKey);
+export const changeRecoveryAccount = (
+ account_to_recover: string,
+ new_recovery_account: string,
+ extensions: [],
+ key: PrivateKey
+): Promise => {
+ const op: Operation = [
+ "change_recovery_account",
+ {
+ account_to_recover,
+ new_recovery_account,
+ extensions
}
+ ];
+ return hiveClient.broadcast.sendOperations([op], key);
+};
- // With hivesigner access token
- let token = getAccessToken(username);
- return token ? new hs.Client({
- accessToken: token,
- }).broadcast(operations)
- .then((r: any) => r.result) : Promise.resolve(0);
-}
+export const changeRecoveryAccountHot = (
+ account_to_recover: string,
+ new_recovery_account: string,
+ extensions: []
+) => {
+ const op: Operation = [
+ "change_recovery_account",
+ {
+ account_to_recover,
+ new_recovery_account,
+ extensions
+ }
+ ];
-export const reblog = (username: string, author: string, permlink: string, _delete: boolean = false): Promise => {
- const message = {
- account: username,
- author,
- permlink
- };
+ const params: Parameters = { callback: `https://ecency.com/@${account_to_recover}/permissions` };
+ return hs.sendOperation(op, params, () => {});
+};
- if (_delete) {
- message["delete"] = "delete";
+export const changeRecoveryAccountKc = (
+ account_to_recover: string,
+ new_recovery_account: string,
+ extensions: []
+) => {
+ const op: Operation = [
+ "change_recovery_account",
+ {
+ account_to_recover,
+ new_recovery_account,
+ extensions
}
+ ];
- const json = ["reblog", message];
+ return keychain.broadcast(account_to_recover, [op], "Owner");
+};
+
+export const follow = (follower: string, following: string): Promise => {
+ const json = [
+ "follow",
+ {
+ follower,
+ following,
+ what: ["blog"]
+ }
+ ];
- return broadcastPostingJSON(username, "follow", json)
- .then((r: TransactionConfirmation) => {
- usrActivity(username, 130, r.block_num, r.id).then();
- return r;
- });
+ return broadcastPostingJSON(follower, "follow", json);
};
-export const comment = (
- username: string,
- parentAuthor: string,
- parentPermlink: string,
- permlink: string,
- title: string,
- body: string,
- jsonMetadata: MetaData,
- options: CommentOptions | null,
- point: boolean = false
-): Promise => {
- const params = {
- parent_author: parentAuthor,
- parent_permlink: parentPermlink,
- author: username,
- permlink,
- title,
- body,
- json_metadata: JSON.stringify(jsonMetadata),
- };
+export const unFollow = (follower: string, following: string): Promise => {
+ const json = [
+ "follow",
+ {
+ follower,
+ following,
+ what: []
+ }
+ ];
- const opArray: Operation[] = [["comment", params]];
+ return broadcastPostingJSON(follower, "follow", json);
+};
- if (options) {
- const e: Operation = ["comment_options", options];
- opArray.push(e);
+export const ignore = (follower: string, following: string): Promise => {
+ const json = [
+ "follow",
+ {
+ follower,
+ following,
+ what: ["ignore"]
}
+ ];
- return broadcastPostingOperations(username, opArray)
- .then((r) => {
- if (point) {
- const t = title ? 100 : 110;
- usrActivity(username, t, r.block_num, r.id).then();
- }
- return r;
- })
+ return broadcastPostingJSON(follower, "follow", json);
};
-export const deleteComment = (username: string, author: string, permlink: string): Promise => {
- const params = {
- author,
- permlink,
- };
+export const claimRewardBalance = (
+ username: string,
+ rewardHive: string,
+ rewardHbd: string,
+ rewardVests: string
+): Promise => {
+ const params = {
+ account: username,
+ reward_hive: rewardHive,
+ reward_hbd: rewardHbd,
+ reward_vests: rewardVests
+ };
- const opArray: Operation[] = [["delete_comment", params]];
+ const opArray: Operation[] = [["claim_reward_balance", params]];
- return broadcastPostingOperations(username, opArray);
+ return broadcastPostingOperations(username, opArray);
};
-export const vote = (username: string, author: string, permlink: string, weight: number): Promise => {
- const params = {
- voter: username,
- author,
- permlink,
- weight
- }
+export const transfer = (
+ from: string,
+ key: PrivateKey,
+ to: string,
+ amount: string,
+ memo: string
+): Promise => {
+ const args = {
+ from,
+ to,
+ amount,
+ memo
+ };
+
+ return hiveClient.broadcast.transfer(args, key);
+};
- const opArray: Operation[] = [["vote", params]];
+export const transferHot = (from: string, to: string, amount: string, memo: string) => {
+ const op: Operation = [
+ "transfer",
+ {
+ from,
+ to,
+ amount,
+ memo
+ }
+ ];
- return broadcastPostingOperations(username, opArray)
- .then((r: TransactionConfirmation) => {
- usrActivity(username, 120, r.block_num, r.id).then();
- return r;
- });
+ const params: Parameters = { callback: `https://ecency.com/@${from}/wallet` };
+ return hs.sendOperation(op, params, () => {});
};
-export const follow = (follower: string, following: string): Promise => {
- const json = ["follow", {
- follower,
- following,
- what: ["blog"]
- }];
+export const transferKc = (from: string, to: string, amount: string, memo: string) => {
+ const asset = parseAsset(amount);
+ return keychain.transfer(from, to, asset.amount.toFixed(3).toString(), memo, asset.symbol, true);
+};
- return broadcastPostingJSON(follower, "follow", json);
-}
+export const transferPoint = (
+ from: string,
+ key: PrivateKey,
+ to: string,
+ amount: string,
+ memo: string
+): Promise => {
+ const json = JSON.stringify({
+ sender: from,
+ receiver: to,
+ amount,
+ memo
+ });
+
+ const op = {
+ id: "ecency_point_transfer",
+ json,
+ required_auths: [from],
+ required_posting_auths: []
+ };
+
+ return hiveClient.broadcast.json(op, key);
+};
-export const unFollow = (follower: string, following: string): Promise => {
- const json = ["follow", {
- follower,
- following,
- what: []
- }];
+export const transferPointHot = (from: string, to: string, amount: string, memo: string) => {
+ const params = {
+ authority: "active",
+ required_auths: `["${from}"]`,
+ required_posting_auths: "[]",
+ id: "ecency_point_transfer",
+ json: JSON.stringify({
+ sender: from,
+ receiver: to,
+ amount,
+ memo
+ })
+ };
+
+ hotSign("custom-json", params, `@${from}/points`);
+};
- return broadcastPostingJSON(follower, "follow", json);
-}
+export const transferPointKc = (from: string, to: string, amount: string, memo: string) => {
+ const json = JSON.stringify({
+ sender: from,
+ receiver: to,
+ amount,
+ memo
+ });
+
+ return keychain.customJson(from, "ecency_point_transfer", "Active", json, "Point Transfer");
+};
-export const ignore = (follower: string, following: string): Promise => {
- const json = ["follow", {
- follower,
- following,
- what: ["ignore"]
- }];
+export const transferToSavings = (
+ from: string,
+ key: PrivateKey,
+ to: string,
+ amount: string,
+ memo: string
+): Promise => {
+ const op: Operation = [
+ "transfer_to_savings",
+ {
+ from,
+ to,
+ amount,
+ memo
+ }
+ ];
- return broadcastPostingJSON(follower, "follow", json);
-}
+ return hiveClient.broadcast.sendOperations([op], key);
+};
-export const claimRewardBalance = (username: string, rewardHive: string, rewardHbd: string, rewardVests: string): Promise => {
- const params = {
- account: username,
- reward_hive: rewardHive,
- reward_hbd: rewardHbd,
- reward_vests: rewardVests
+export const transferToSavingsHot = (from: string, to: string, amount: string, memo: string) => {
+ const op: Operation = [
+ "transfer_to_savings",
+ {
+ from,
+ to,
+ amount,
+ memo
}
+ ];
- const opArray: Operation[] = [['claim_reward_balance', params]];
-
- return broadcastPostingOperations(username, opArray);
-}
+ const params: Parameters = { callback: `https://ecency.com/@${from}/wallet` };
+ return hs.sendOperation(op, params, () => {});
+};
-export const transfer = (from: string, key: PrivateKey, to: string, amount: string, memo: string): Promise => {
- const args = {
- from,
- to,
- amount,
- memo
- };
+export const transferToSavingsKc = (from: string, to: string, amount: string, memo: string) => {
+ const op: Operation = [
+ "transfer_to_savings",
+ {
+ from,
+ to,
+ amount,
+ memo
+ }
+ ];
- return hiveClient.broadcast.transfer(args, key);
-}
+ return keychain.broadcast(from, [op], "Active");
+};
-export const transferHot = (from: string, to: string, amount: string, memo: string) => {
+export const limitOrderCreate = (
+ owner: string,
+ key: PrivateKey,
+ amount_to_sell: any,
+ min_to_receive: any,
+ orderType: TransactionType,
+ idPrefix = OrderIdPrefix.EMPTY
+): Promise => {
+ let expiration: any = new Date(Date.now());
+ expiration.setDate(expiration.getDate() + 27);
+ expiration = expiration.toISOString().split(".")[0];
+
+ const op: Operation = [
+ "limit_order_create",
+ {
+ orderid: Number(
+ `${idPrefix}${Math.floor(Date.now() / 1000)
+ .toString()
+ .slice(2)}`
+ ),
+ owner: owner,
+ amount_to_sell: `${
+ orderType === TransactionType.Buy
+ ? formatNumber(amount_to_sell, 3)
+ : formatNumber(min_to_receive, 3)
+ } ${orderType === TransactionType.Buy ? "HBD" : "HIVE"}`,
+ min_to_receive: `${
+ orderType === TransactionType.Buy
+ ? formatNumber(min_to_receive, 3)
+ : formatNumber(amount_to_sell, 3)
+ } ${orderType === TransactionType.Buy ? "HIVE" : "HBD"}`,
+ fill_or_kill: false,
+ expiration: expiration
+ }
+ ];
- const op: Operation = ['transfer', {
- from,
- to,
- amount,
- memo
- }];
+ return hiveClient.broadcast.sendOperations([op], key);
+};
- const params: Parameters = {callback: `https://ecency.com/@${from}/wallet`};
- return hs.sendOperation(op, params, () => {
- });
-}
+export const limitOrderCancel = (
+ owner: string,
+ key: PrivateKey,
+ orderid: number
+): Promise => {
+ const op: Operation = [
+ "limit_order_cancel",
+ {
+ owner: owner,
+ orderid: orderid
+ }
+ ];
-export const transferKc = (from: string, to: string, amount: string, memo: string) => {
- const asset = parseAsset(amount);
- return keychain.transfer(from, to, asset.amount.toFixed(3).toString(), memo, asset.symbol, true);
-}
+ return hiveClient.broadcast.sendOperations([op], key);
+};
-export const transferPoint = (from: string, key: PrivateKey, to: string, amount: string, memo: string): Promise => {
- const json = JSON.stringify({
- sender: from,
- receiver: to,
- amount,
- memo
- });
+export const limitOrderCreateHot = (
+ owner: string,
+ amount_to_sell: any,
+ min_to_receive: any,
+ orderType: TransactionType,
+ idPrefix = OrderIdPrefix.EMPTY
+) => {
+ let expiration: any = new Date();
+ expiration.setDate(expiration.getDate() + 27);
+ expiration = expiration.toISOString().split(".")[0];
+ const op: Operation = [
+ "limit_order_create",
+ {
+ orderid: Number(
+ `${idPrefix}${Math.floor(Date.now() / 1000)
+ .toString()
+ .slice(2)}`
+ ),
+ owner: owner,
+ amount_to_sell: `${
+ orderType === TransactionType.Buy
+ ? formatNumber(amount_to_sell, 3)
+ : formatNumber(min_to_receive, 3)
+ } ${orderType === TransactionType.Buy ? "HBD" : "HIVE"}`,
+ min_to_receive: `${
+ orderType === TransactionType.Buy
+ ? formatNumber(min_to_receive, 3)
+ : formatNumber(amount_to_sell, 3)
+ } ${orderType === TransactionType.Buy ? "HIVE" : "HBD"}`,
+ fill_or_kill: false,
+ expiration: expiration
+ }
+ ];
- const op = {
- id: 'ecency_point_transfer',
- json,
- required_auths: [from],
- required_posting_auths: []
- };
+ const params: Parameters = {
+ callback: `https://ecency.com/market${idPrefix === OrderIdPrefix.SWAP ? "#swap" : ""}`
+ };
+ return hs.sendOperation(op, params, () => {});
+};
- return hiveClient.broadcast.json(op, key);
-}
+export const limitOrderCancelHot = (owner: string, orderid: number) => {
+ const op: Operation = [
+ "limit_order_cancel",
+ {
+ orderid: orderid,
+ owner: owner
+ }
+ ];
-export const transferPointHot = (from: string, to: string, amount: string, memo: string) => {
- const params = {
- authority: "active",
- required_auths: `["${from}"]`,
- required_posting_auths: "[]",
- id: "ecency_point_transfer",
- json: JSON.stringify({
- sender: from,
- receiver: to,
- amount,
- memo
- }),
- }
-
- hotSign("custom-json", params, `@${from}/points`);
-}
+ const params: Parameters = { callback: `https://ecency.com/market` };
+ return hs.sendOperation(op, params, () => {});
+};
-export const transferPointKc = (from: string, to: string, amount: string, memo: string) => {
- const json = JSON.stringify({
- sender: from,
- receiver: to,
- amount,
- memo
- });
+export const limitOrderCreateKc = (
+ owner: string,
+ amount_to_sell: any,
+ min_to_receive: any,
+ orderType: TransactionType,
+ idPrefix: OrderIdPrefix = OrderIdPrefix.EMPTY
+) => {
+ let expiration: any = new Date();
+ expiration.setDate(expiration.getDate() + 27);
+ expiration = expiration.toISOString().split(".")[0];
+ const op: Operation = [
+ "limit_order_create",
+ {
+ orderid: Number(
+ `${idPrefix}${Math.floor(Date.now() / 1000)
+ .toString()
+ .slice(2)}`
+ ),
+ owner: owner,
+ amount_to_sell: `${
+ orderType === TransactionType.Buy
+ ? formatNumber(amount_to_sell, 3)
+ : formatNumber(min_to_receive, 3)
+ } ${orderType === TransactionType.Buy ? "HBD" : "HIVE"}`,
+ min_to_receive: `${
+ orderType === TransactionType.Buy
+ ? formatNumber(min_to_receive, 3)
+ : formatNumber(amount_to_sell, 3)
+ } ${orderType === TransactionType.Buy ? "HIVE" : "HBD"}`,
+ fill_or_kill: false,
+ expiration: expiration
+ }
+ ];
- return keychain.customJson(from, "ecency_point_transfer", "Active", json, "Point Transfer")
-}
+ return keychain.broadcast(owner, [op], "Active");
+};
-export const transferToSavings = (from: string, key: PrivateKey, to: string, amount: string, memo: string): Promise => {
+export const limitOrderCancelKc = (owner: string, orderid: any) => {
+ const op: Operation = [
+ "limit_order_cancel",
+ {
+ orderid: orderid,
+ owner: owner
+ }
+ ];
- const op: Operation = [
- 'transfer_to_savings',
- {
- from,
- to,
- amount,
- memo
- }
- ]
+ return keychain.broadcast(owner, [op], "Active");
+};
- return hiveClient.broadcast.sendOperations([op], key);
-}
+export const convert = (
+ owner: string,
+ key: PrivateKey,
+ amount: string
+): Promise => {
+ const op: Operation = [
+ "convert",
+ {
+ owner,
+ amount,
+ requestid: new Date().getTime() >>> 0
+ }
+ ];
-export const transferToSavingsHot = (from: string, to: string, amount: string, memo: string) => {
+ return hiveClient.broadcast.sendOperations([op], key);
+};
- const op: Operation = ['transfer_to_savings', {
- from,
- to,
- amount,
- memo
- }];
+export const convertHot = (owner: string, amount: string) => {
+ const op: Operation = [
+ "convert",
+ {
+ owner,
+ amount,
+ requestid: new Date().getTime() >>> 0
+ }
+ ];
- const params: Parameters = {callback: `https://ecency.com/@${from}/wallet`};
- return hs.sendOperation(op, params, () => {
- });
-}
+ const params: Parameters = { callback: `https://ecency.com/@${owner}/wallet` };
+ return hs.sendOperation(op, params, () => {});
+};
-export const transferToSavingsKc = (from: string, to: string, amount: string, memo: string) => {
- const op: Operation = [
- 'transfer_to_savings',
- {
- from,
- to,
- amount,
- memo
- }
- ]
-
- return keychain.broadcast(from, [op], "Active");
-}
+export const convertKc = (owner: string, amount: string) => {
+ const op: Operation = [
+ "convert",
+ {
+ owner,
+ amount,
+ requestid: new Date().getTime() >>> 0
+ }
+ ];
-export const limitOrderCreate = (owner: string, key: PrivateKey, amount_to_sell: any, min_to_receive: any, orderType: TransactionType): Promise => {
- let expiration:any = new Date(Date.now());
- expiration.setDate(expiration.getDate() + 27);
- expiration = expiration.toISOString().split(".")[0];
-
- const op: Operation = [
- 'limit_order_create',
- {
- "orderid": Math.floor(Date.now() / 1000),
- "owner": owner,
- "amount_to_sell": `${orderType === TransactionType.Buy ? amount_to_sell.toFixed(3) : min_to_receive.toFixed(3)} ${orderType === TransactionType.Buy ? 'HBD' : "HIVE"}`,
- "min_to_receive": `${orderType === TransactionType.Buy ? min_to_receive.toFixed(3): amount_to_sell.toFixed(3)} ${orderType === TransactionType.Buy ? 'HIVE' : "HBD"}`,
- "fill_or_kill": false,
- "expiration": expiration
- }
- ]
-
- return hiveClient.broadcast.sendOperations([op], key);
-}
+ return keychain.broadcast(owner, [op], "Active");
+};
-export const limitOrderCancel = (owner: string, key: PrivateKey, orderid:number, ): Promise => {
+export const transferFromSavings = (
+ from: string,
+ key: PrivateKey,
+ to: string,
+ amount: string,
+ memo: string
+): Promise => {
+ const op: Operation = [
+ "transfer_from_savings",
+ {
+ from,
+ to,
+ amount,
+ memo,
+ request_id: new Date().getTime() >>> 0
+ }
+ ];
- const op: Operation = [
- 'limit_order_cancel',
- {
- "owner": owner,
- "orderid": orderid,
- }
- ]
+ return hiveClient.broadcast.sendOperations([op], key);
+};
- return hiveClient.broadcast.sendOperations([op], key);
-}
+export const transferFromSavingsHot = (from: string, to: string, amount: string, memo: string) => {
+ const op: Operation = [
+ "transfer_from_savings",
+ {
+ from,
+ to,
+ amount,
+ memo,
+ request_id: new Date().getTime() >>> 0
+ }
+ ];
-export const limitOrderCreateHot = (owner:string, amount_to_sell:any, min_to_receive:any, orderType: TransactionType) => {
- let expiration:any = new Date();
- expiration.setDate(expiration.getDate() + 27);
- expiration = expiration.toISOString().split(".")[0]
- const op: Operation = [
- 'limit_order_create',
- {
- "orderid": Math.floor(Date.now() / 1000),
- "owner": owner,
- "amount_to_sell": `${orderType === TransactionType.Buy ? amount_to_sell.toFixed(3) : min_to_receive.toFixed(3)} ${orderType === TransactionType.Buy ? 'HBD' : "HIVE"}`,
- "min_to_receive": `${orderType === TransactionType.Buy ? min_to_receive.toFixed(3): amount_to_sell.toFixed(3)} ${orderType === TransactionType.Buy ? 'HIVE' : "HBD"}`,
- "fill_or_kill": false,
- "expiration": expiration
- }
- ]
-
- const params: Parameters = {callback: `https://ecency.com/market`};
- return hs.sendOperation(op, params, () => {});
-}
+ const params: Parameters = { callback: `https://ecency.com/@${from}/wallet` };
+ return hs.sendOperation(op, params, () => {});
+};
-export const limitOrderCancelHot = (owner:string, orderid:number) => {
- const op: Operation = [
- 'limit_order_cancel',
- {
- "orderid": orderid,
- "owner": owner,
- }
- ]
-
- const params: Parameters = {callback: `https://ecency.com/market`};
- return hs.sendOperation(op, params, () => {});
-}
+export const transferFromSavingsKc = (from: string, to: string, amount: string, memo: string) => {
+ const op: Operation = [
+ "transfer_from_savings",
+ {
+ from,
+ to,
+ amount,
+ memo,
+ request_id: new Date().getTime() >>> 0
+ }
+ ];
-export const limitOrderCreateKc = (owner:string, amount_to_sell:any, min_to_receive:any, orderType: TransactionType) => {
- let expiration:any = new Date();
- expiration.setDate(expiration.getDate() + 27);
- expiration = expiration.toISOString().split(".")[0]
- const op: Operation = [
- 'limit_order_create',
- {
- "orderid": Math.floor(Date.now() / 1000),
- "owner": owner,
- "amount_to_sell": `${orderType === TransactionType.Buy ? amount_to_sell.toFixed(3) : min_to_receive.toFixed(3)} ${orderType === TransactionType.Buy ? 'HBD' : "HIVE"}`,
- "min_to_receive": `${orderType === TransactionType.Buy ? min_to_receive.toFixed(3): amount_to_sell.toFixed(3)} ${orderType === TransactionType.Buy ? 'HIVE' : "HBD"}`,
- "fill_or_kill": false,
- "expiration": expiration
- }
- ]
-
- return keychain.broadcast(owner, [op], "Active");
-}
+ return keychain.broadcast(from, [op], "Active");
+};
-export const limitOrderCancelKc = (owner:string, orderid:any) => {
- const op: Operation = [
- 'limit_order_cancel',
- {
- "orderid": orderid,
- "owner": owner,
- }
- ]
+export const claimInterest = (
+ from: string,
+ key: PrivateKey,
+ to: string,
+ amount: string,
+ memo: string
+): Promise => {
+ const rid = new Date().getTime() >>> 0;
+ const op: Operation = [
+ "transfer_from_savings",
+ {
+ from,
+ to,
+ amount,
+ memo,
+ request_id: rid
+ }
+ ];
+ const cop: Operation = [
+ "cancel_transfer_from_savings",
+ {
+ from,
+ request_id: rid
+ }
+ ];
- return keychain.broadcast(owner, [op], "Active");
-}
+ return hiveClient.broadcast.sendOperations([op, cop], key);
+};
-export const convert = (owner: string, key: PrivateKey, amount: string): Promise => {
- const op: Operation = [
- 'convert',
- {
- owner,
- amount,
- requestid: new Date().getTime() >>> 0
- }
- ]
-
- return hiveClient.broadcast.sendOperations([op], key);
-}
+export const claimInterestHot = (from: string, to: string, amount: string, memo: string) => {
+ const rid = new Date().getTime() >>> 0;
+ const op: Operation = [
+ "transfer_from_savings",
+ {
+ from,
+ to,
+ amount,
+ memo,
+ request_id: rid
+ }
+ ];
+ const cop: Operation = [
+ "cancel_transfer_from_savings",
+ {
+ from,
+ request_id: rid
+ }
+ ];
-export const convertHot = (owner: string, amount: string) => {
+ const params: Parameters = { callback: `https://ecency.com/@${from}/wallet` };
+ return hs.sendOperations([op, cop], params, () => {});
+};
- const op: Operation = ['convert', {
- owner,
- amount,
- requestid: new Date().getTime() >>> 0
- }];
+export const claimInterestKc = (from: string, to: string, amount: string, memo: string) => {
+ const rid = new Date().getTime() >>> 0;
+ const op: Operation = [
+ "transfer_from_savings",
+ {
+ from,
+ to,
+ amount,
+ memo,
+ request_id: rid
+ }
+ ];
+ const cop: Operation = [
+ "cancel_transfer_from_savings",
+ {
+ from,
+ request_id: rid
+ }
+ ];
- const params: Parameters = {callback: `https://ecency.com/@${owner}/wallet`};
- return hs.sendOperation(op, params, () => {
- });
-}
+ return keychain.broadcast(from, [op, cop], "Active");
+};
-export const convertKc = (owner: string, amount: string) => {
- const op: Operation = [
- 'convert',
- {
- owner,
- amount,
- requestid: new Date().getTime() >>> 0
- }
- ]
-
- return keychain.broadcast(owner, [op], "Active");
-}
+export const transferToVesting = (
+ from: string,
+ key: PrivateKey,
+ to: string,
+ amount: string
+): Promise => {
+ const op: Operation = [
+ "transfer_to_vesting",
+ {
+ from,
+ to,
+ amount
+ }
+ ];
-export const transferFromSavings = (from: string, key: PrivateKey, to: string, amount: string, memo: string): Promise => {
- const op: Operation = [
- 'transfer_from_savings',
- {
- from,
- to,
- amount,
- memo,
- request_id: new Date().getTime() >>> 0
- }
- ]
-
- return hiveClient.broadcast.sendOperations([op], key);
-}
+ return hiveClient.broadcast.sendOperations([op], key);
+};
-export const transferFromSavingsHot = (from: string, to: string, amount: string, memo: string) => {
+export const transferToVestingHot = (from: string, to: string, amount: string) => {
+ const op: Operation = [
+ "transfer_to_vesting",
+ {
+ from,
+ to,
+ amount
+ }
+ ];
- const op: Operation = ['transfer_from_savings', {
- from,
- to,
- amount,
- memo,
- request_id: new Date().getTime() >>> 0
- }];
-
- const params: Parameters = {callback: `https://ecency.com/@${from}/wallet`};
- return hs.sendOperation(op, params, () => {
- });
-}
+ const params: Parameters = { callback: `https://ecency.com/@${from}/wallet` };
+ return hs.sendOperation(op, params, () => {});
+};
-export const transferFromSavingsKc = (from: string, to: string, amount: string, memo: string) => {
- const op: Operation = [
- 'transfer_from_savings',
- {
- from,
- to,
- amount,
- memo,
- request_id: new Date().getTime() >>> 0
- }
- ]
-
- return keychain.broadcast(from, [op], "Active");
-}
+export const transferToVestingKc = (from: string, to: string, amount: string) => {
+ const op: Operation = [
+ "transfer_to_vesting",
+ {
+ from,
+ to,
+ amount
+ }
+ ];
-export const transferToVesting = (from: string, key: PrivateKey, to: string, amount: string): Promise => {
- const op: Operation = [
- 'transfer_to_vesting',
- {
- from,
- to,
- amount
- }
- ]
-
- return hiveClient.broadcast.sendOperations([op], key);
-}
+ return keychain.broadcast(from, [op], "Active");
+};
-export const transferToVestingHot = (from: string, to: string, amount: string) => {
+export const delegateVestingShares = (
+ delegator: string,
+ key: PrivateKey,
+ delegatee: string,
+ vestingShares: string
+): Promise => {
+ const op: Operation = [
+ "delegate_vesting_shares",
+ {
+ delegator,
+ delegatee,
+ vesting_shares: vestingShares
+ }
+ ];
- const op: Operation = ['transfer_to_vesting', {
- from,
- to,
- amount
- }];
+ return hiveClient.broadcast.sendOperations([op], key);
+};
- const params: Parameters = {callback: `https://ecency.com/@${from}/wallet`};
- return hs.sendOperation(op, params, () => {
- });
-}
+export const delegateVestingSharesHot = (
+ delegator: string,
+ delegatee: string,
+ vestingShares: string
+) => {
+ const op: Operation = [
+ "delegate_vesting_shares",
+ {
+ delegator,
+ delegatee,
+ vesting_shares: vestingShares
+ }
+ ];
-export const transferToVestingKc = (from: string, to: string, amount: string) => {
- const op: Operation = [
- 'transfer_to_vesting',
- {
- from,
- to,
- amount
- }
- ]
-
- return keychain.broadcast(from, [op], "Active");
-}
+ const params: Parameters = { callback: `https://ecency.com/@${delegator}/wallet` };
+ return hs.sendOperation(op, params, () => {});
+};
-export const delegateVestingShares = (delegator: string, key: PrivateKey, delegatee: string, vestingShares: string): Promise => {
- const op: Operation = [
- 'delegate_vesting_shares',
- {
- delegator,
- delegatee,
- vesting_shares: vestingShares
- }
- ]
-
- return hiveClient.broadcast.sendOperations([op], key);
-}
+export const delegateVestingSharesKc = (
+ delegator: string,
+ delegatee: string,
+ vestingShares: string
+) => {
+ const op: Operation = [
+ "delegate_vesting_shares",
+ {
+ delegator,
+ delegatee,
+ vesting_shares: vestingShares
+ }
+ ];
-export const delegateVestingSharesHot = (delegator: string, delegatee: string, vestingShares: string) => {
- const op: Operation = ['delegate_vesting_shares', {
- delegator,
- delegatee,
- vesting_shares: vestingShares
- }];
+ return keychain.broadcast(delegator, [op], "Active");
+};
- const params: Parameters = {callback: `https://ecency.com/@${delegator}/wallet`};
- return hs.sendOperation(op, params, () => {
- });
-}
+export const delegateRC = (
+ delegator: string,
+ delegatees: string,
+ max_rc: string | number
+): Promise => {
+ const json = [
+ "delegate_rc",
+ {
+ from: delegator,
+ delegatees: delegatees.includes(",") ? delegatees.split(",") : [delegatees],
+ max_rc: max_rc
+ }
+ ];
-export const delegateVestingSharesKc = (delegator: string, delegatee: string, vestingShares: string) => {
- const op: Operation = [
- 'delegate_vesting_shares',
- {
- delegator,
- delegatee,
- vesting_shares: vestingShares
- }
- ]
-
- return keychain.broadcast(delegator, [op], "Active");
-}
+ return broadcastPostingJSON(delegator, "rc", json);
+};
-export const withdrawVesting = (account: string, key: PrivateKey, vestingShares: string): Promise => {
- const op: Operation = [
- 'withdraw_vesting',
- {
- account,
- vesting_shares: vestingShares
- }
- ]
+export const withdrawVesting = (
+ account: string,
+ key: PrivateKey,
+ vestingShares: string
+): Promise => {
+ const op: Operation = [
+ "withdraw_vesting",
+ {
+ account,
+ vesting_shares: vestingShares
+ }
+ ];
- return hiveClient.broadcast.sendOperations([op], key);
-}
+ return hiveClient.broadcast.sendOperations([op], key);
+};
export const withdrawVestingHot = (account: string, vestingShares: string) => {
- const op: Operation = ['withdraw_vesting', {
- account,
- vesting_shares: vestingShares
- }];
-
- const params: Parameters = {callback: `https://ecency.com/@${account}/wallet`};
- return hs.sendOperation(op, params, () => {
- });
-}
+ const op: Operation = [
+ "withdraw_vesting",
+ {
+ account,
+ vesting_shares: vestingShares
+ }
+ ];
+
+ const params: Parameters = { callback: `https://ecency.com/@${account}/wallet` };
+ return hs.sendOperation(op, params, () => {});
+};
export const withdrawVestingKc = (account: string, vestingShares: string) => {
- const op: Operation = [
- 'withdraw_vesting',
- {
- account,
- vesting_shares: vestingShares
- }
- ]
-
- return keychain.broadcast(account, [op], "Active");
-}
+ const op: Operation = [
+ "withdraw_vesting",
+ {
+ account,
+ vesting_shares: vestingShares
+ }
+ ];
-export const setWithdrawVestingRoute = (from: string, key: PrivateKey, to: string, percent: number, autoVest: boolean): Promise => {
- const op: Operation = [
- 'set_withdraw_vesting_route',
- {
- from_account: from,
- to_account: to,
- percent,
- auto_vest: autoVest
- }
- ]
-
- return hiveClient.broadcast.sendOperations([op], key);
-}
+ return keychain.broadcast(account, [op], "Active");
+};
-export const setWithdrawVestingRouteHot = (from: string, to: string, percent: number, autoVest: boolean) => {
- const op: Operation = ['set_withdraw_vesting_route', {
- from_account: from,
- to_account: to,
- percent,
- auto_vest: autoVest
- }];
-
- const params: Parameters = {callback: `https://ecency.com/@${from}/wallet`};
- return hs.sendOperation(op, params, () => {
- });
-}
+export const setWithdrawVestingRoute = (
+ from: string,
+ key: PrivateKey,
+ to: string,
+ percent: number,
+ autoVest: boolean
+): Promise => {
+ const op: Operation = [
+ "set_withdraw_vesting_route",
+ {
+ from_account: from,
+ to_account: to,
+ percent,
+ auto_vest: autoVest
+ }
+ ];
-export const setWithdrawVestingRouteKc = (from: string, to: string, percent: number, autoVest: boolean) => {
- const op: Operation = [
- 'set_withdraw_vesting_route',
- {
- from_account: from,
- to_account: to,
- percent,
- auto_vest: autoVest
- }
- ]
-
- return keychain.broadcast(from, [op], "Active");
-}
+ return hiveClient.broadcast.sendOperations([op], key);
+};
-export const witnessVote = (account: string, key: PrivateKey, witness: string, approve: boolean): Promise => {
- const op: Operation = [
- 'account_witness_vote',
- {
- account,
- witness,
- approve
- }
- ]
-
- return hiveClient.broadcast.sendOperations([op], key);
-}
+export const setWithdrawVestingRouteHot = (
+ from: string,
+ to: string,
+ percent: number,
+ autoVest: boolean
+) => {
+ const op: Operation = [
+ "set_withdraw_vesting_route",
+ {
+ from_account: from,
+ to_account: to,
+ percent,
+ auto_vest: autoVest
+ }
+ ];
-export const witnessVoteHot = (account: string, witness: string, approve: boolean) => {
- const params = {
- account,
- witness,
- approve,
+ const params: Parameters = { callback: `https://ecency.com/@${from}/wallet` };
+ return hs.sendOperation(op, params, () => {});
+};
+
+export const setWithdrawVestingRouteKc = (
+ from: string,
+ to: string,
+ percent: number,
+ autoVest: boolean
+) => {
+ const op: Operation = [
+ "set_withdraw_vesting_route",
+ {
+ from_account: from,
+ to_account: to,
+ percent,
+ auto_vest: autoVest
}
+ ];
- hotSign("account-witness-vote", params, "witnesses");
-}
+ return keychain.broadcast(from, [op], "Active");
+};
+
+export const witnessVote = (
+ account: string,
+ key: PrivateKey,
+ witness: string,
+ approve: boolean
+): Promise => {
+ const op: Operation = [
+ "account_witness_vote",
+ {
+ account,
+ witness,
+ approve
+ }
+ ];
+
+ return hiveClient.broadcast.sendOperations([op], key);
+};
+
+export const witnessVoteHot = (account: string, witness: string, approve: boolean) => {
+ const params = {
+ account,
+ witness,
+ approve
+ };
+
+ hotSign("account-witness-vote", params, "witnesses");
+};
export const witnessVoteKc = (account: string, witness: string, approve: boolean) => {
- return keychain.witnessVote(account, witness, approve);
-}
+ return keychain.witnessVote(account, witness, approve);
+};
-export const witnessProxy = (account: string, key: PrivateKey, proxy: string): Promise => {
- const op: Operation = [
- 'account_witness_proxy',
- {
- account,
- proxy
- }
- ]
+export const witnessProxy = (
+ account: string,
+ key: PrivateKey,
+ proxy: string
+): Promise => {
+ const op: Operation = [
+ "account_witness_proxy",
+ {
+ account,
+ proxy
+ }
+ ];
- return hiveClient.broadcast.sendOperations([op], key);
-}
+ return hiveClient.broadcast.sendOperations([op], key);
+};
export const witnessProxyHot = (account: string, proxy: string) => {
- const params = {
- account,
- proxy
- }
+ const params = {
+ account,
+ proxy
+ };
- hotSign("account-witness-proxy", params, "witnesses");
-}
+ hotSign("account-witness-proxy", params, "witnesses");
+};
export const witnessProxyKc = (account: string, witness: string) => {
- return keychain.witnessProxy(account, witness);
-}
-
-export const proposalVote = (account: string, key: PrivateKey, proposal: number, approve: boolean): Promise => {
- const op: Operation = [
- 'update_proposal_votes',
- {
- voter: account,
- proposal_ids: [proposal],
- approve,
- extensions: []
- }
- ]
-
- return hiveClient.broadcast.sendOperations([op], key);
-}
+ return keychain.witnessProxy(account, witness);
+};
-export const proposalVoteHot = (account: string, proposal: number, approve: boolean) => {
- const params = {
- account,
- proposal_ids: JSON.stringify(
- [proposal]
- ),
- approve,
+export const proposalVote = (
+ account: string,
+ key: PrivateKey,
+ proposal: number,
+ approve: boolean
+): Promise => {
+ const op: Operation = [
+ "update_proposal_votes",
+ {
+ voter: account,
+ proposal_ids: [proposal],
+ approve,
+ extensions: []
}
+ ];
- hotSign("update-proposal-votes", params, "proposals");
-}
-
-export const proposalVoteKc = (account: string, proposal: number, approve: boolean) => {
- const op: Operation = [
- 'update_proposal_votes',
- {
- voter: account,
- proposal_ids: [proposal],
- approve,
- extensions: []
- }
- ]
-
- return keychain.broadcast(account, [op], "Active");
+ return hiveClient.broadcast.sendOperations([op], key);
+};
-}
+export const proposalVoteHot = (account: string, proposal: number, approve: boolean) => {
+ const params = {
+ account,
+ proposal_ids: JSON.stringify([proposal]),
+ approve
+ };
-export const subscribe = (username: string, community: string): Promise => {
- const json = [
- 'subscribe', {community}
- ];
+ hotSign("update-proposal-votes", params, "proposals");
+};
- return broadcastPostingJSON(username, "community", json);
-}
+export const proposalVoteKc = (account: string, proposal: number, approve: boolean) => {
+ const op: Operation = [
+ "update_proposal_votes",
+ {
+ voter: account,
+ proposal_ids: [proposal],
+ approve,
+ extensions: []
+ }
+ ];
-export const unSubscribe = (username: string, community: string): Promise => {
- const json = [
- 'unsubscribe', {community}
- ]
+ return keychain.broadcast(account, [op], "Active");
+};
- return broadcastPostingJSON(username, "community", json);
-}
+export const subscribe = (
+ username: string,
+ community: string
+): Promise => {
+ const json = ["subscribe", { community }];
-export const promote = (key: PrivateKey, user: string, author: string, permlink: string, duration: number): Promise => {
+ return broadcastPostingJSON(username, "community", json);
+};
- const json = JSON.stringify({
- user,
- author,
- permlink,
- duration
- });
+export const unSubscribe = (
+ username: string,
+ community: string
+): Promise => {
+ const json = ["unsubscribe", { community }];
- const op = {
- id: 'ecency_promote',
- json,
- required_auths: [user],
- required_posting_auths: []
- };
+ return broadcastPostingJSON(username, "community", json);
+};
- return hiveClient.broadcast.json(op, key);
-}
+export const promote = (
+ key: PrivateKey,
+ user: string,
+ author: string,
+ permlink: string,
+ duration: number
+): Promise => {
+ const json = JSON.stringify({
+ user,
+ author,
+ permlink,
+ duration
+ });
+
+ const op = {
+ id: "ecency_promote",
+ json,
+ required_auths: [user],
+ required_posting_auths: []
+ };
+
+ return hiveClient.broadcast.json(op, key);
+};
export const promoteHot = (user: string, author: string, permlink: string, duration: number) => {
- const params = {
- authority: "active",
- required_auths: `["${user}"]`,
- required_posting_auths: "[]",
- id: "ecency_promote",
- json: JSON.stringify({
- user,
- author,
- permlink,
- duration
- })
- }
-
- hotSign("custom-json", params, `@${user}/points`);
-}
+ const params = {
+ authority: "active",
+ required_auths: `["${user}"]`,
+ required_posting_auths: "[]",
+ id: "ecency_promote",
+ json: JSON.stringify({
+ user,
+ author,
+ permlink,
+ duration
+ })
+ };
+
+ hotSign("custom-json", params, `@${user}/points`);
+};
export const promoteKc = (user: string, author: string, permlink: string, duration: number) => {
- const json = JSON.stringify({
- user,
- author,
- permlink,
- duration
- });
-
- return keychain.customJson(user, "ecency_promote", "Active", json, "Promote");
-}
-
-export const boost = (key: PrivateKey, user: string, author: string, permlink: string, amount: string): Promise => {
- const json = JSON.stringify({
- user,
- author,
- permlink,
- amount
- });
-
- const op = {
- id: 'ecency_boost',
- json,
- required_auths: [user],
- required_posting_auths: []
- };
+ const json = JSON.stringify({
+ user,
+ author,
+ permlink,
+ duration
+ });
+
+ return keychain.customJson(user, "ecency_promote", "Active", json, "Promote");
+};
- return hiveClient.broadcast.json(op, key);
-}
+export const boost = (
+ key: PrivateKey,
+ user: string,
+ author: string,
+ permlink: string,
+ amount: string
+): Promise => {
+ const json = JSON.stringify({
+ user,
+ author,
+ permlink,
+ amount
+ });
+
+ const op = {
+ id: "ecency_boost",
+ json,
+ required_auths: [user],
+ required_posting_auths: []
+ };
+
+ return hiveClient.broadcast.json(op, key);
+};
export const boostHot = (user: string, author: string, permlink: string, amount: string) => {
- const params = {
- authority: "active",
- required_auths: `["${user}"]`,
- required_posting_auths: "[]",
- id: "ecency_boost",
- json: JSON.stringify({
- user,
- author,
- permlink,
- amount
- })
- }
-
- hotSign("custom-json", params, `@${user}/points`);
-}
+ const params = {
+ authority: "active",
+ required_auths: `["${user}"]`,
+ required_posting_auths: "[]",
+ id: "ecency_boost",
+ json: JSON.stringify({
+ user,
+ author,
+ permlink,
+ amount
+ })
+ };
+
+ hotSign("custom-json", params, `@${user}/points`);
+};
export const boostKc = (user: string, author: string, permlink: string, amount: string) => {
- const json = JSON.stringify({
- user,
- author,
- permlink,
- amount
- });
-
- return keychain.customJson(user, "ecency_boost", "Active", json, "Boost");
-}
+ const json = JSON.stringify({
+ user,
+ author,
+ permlink,
+ amount
+ });
+
+ return keychain.customJson(user, "ecency_boost", "Active", json, "Boost");
+};
-export const communityRewardsRegister = (key: PrivateKey, name: string): Promise => {
- const json = JSON.stringify({
- name,
- });
+export const communityRewardsRegister = (
+ key: PrivateKey,
+ name: string
+): Promise => {
+ const json = JSON.stringify({
+ name
+ });
+
+ const op = {
+ id: "ecency_registration",
+ json,
+ required_auths: [name],
+ required_posting_auths: []
+ };
+
+ return hiveClient.broadcast.json(op, key);
+};
- const op = {
- id: 'ecency_registration',
- json,
- required_auths: [name],
- required_posting_auths: []
- };
+export const communityRewardsRegisterHot = (name: string) => {
+ const params = {
+ authority: "active",
+ required_auths: `["${name}"]`,
+ required_posting_auths: "[]",
+ id: "ecency_registration",
+ json: JSON.stringify({
+ name
+ })
+ };
+
+ hotSign("custom-json", params, `created/${name}`);
+};
- return hiveClient.broadcast.json(op, key);
-}
+export const communityRewardsRegisterKc = (name: string) => {
+ const json = JSON.stringify({
+ name
+ });
-export const communityRewardsRegisterHot = (name: string) => {
- const params = {
- authority: "active",
- required_auths: `["${name}"]`,
- required_posting_auths: "[]",
- id: "ecency_registration",
- json: JSON.stringify({
- name
- })
+ return keychain.customJson(name, "ecency_registration", "Active", json, "Community Registration");
+};
+
+export const updateProfile = (
+ account: Account,
+ newProfile: any
+): Promise => {
+ const params = {
+ account: account.name,
+ json_metadata: "",
+ posting_json_metadata: JSON.stringify({ profile: { ...newProfile, version: 2 } }),
+ extensions: []
+ };
+
+ const opArray: Operation[] = [["account_update2", params]];
+
+ return broadcastPostingOperations(account.name, opArray);
+};
+
+export const grantPostingPermission = (key: PrivateKey, account: Account, pAccount: string) => {
+ if (!account.__loaded) {
+ throw "posting|memo_key|json_metadata required with account instance";
+ }
+
+ const newPosting = Object.assign(
+ {},
+ { ...account.posting },
+ {
+ account_auths: [
+ ...account.posting.account_auths,
+ [pAccount, account.posting.weight_threshold]
+ ]
}
+ );
+
+ // important!
+ newPosting.account_auths.sort((a, b) => (a[0] > b[0] ? 1 : -1));
+
+ return hiveClient.broadcast.updateAccount(
+ {
+ account: account.name,
+ posting: newPosting,
+ active: undefined,
+ memo_key: account.memo_key,
+ json_metadata: account.json_metadata
+ },
+ key
+ );
+};
- hotSign("custom-json", params, `created/${name}`);
-}
+export const revokePostingPermission = (key: PrivateKey, account: Account, pAccount: string) => {
+ if (!account.__loaded) {
+ throw "posting|memo_key|json_metadata required with account instance";
+ }
+
+ const newPosting = Object.assign(
+ {},
+ { ...account.posting },
+ {
+ account_auths: account.posting.account_auths.filter((x) => x[0] !== pAccount)
+ }
+ );
+
+ return hiveClient.broadcast.updateAccount(
+ {
+ account: account.name,
+ posting: newPosting,
+ memo_key: account.memo_key,
+ json_metadata: account.json_metadata
+ },
+ key
+ );
+};
-export const communityRewardsRegisterKc = (name: string) => {
- const json = JSON.stringify({
- name
- });
+export const setUserRole = (
+ username: string,
+ community: string,
+ account: string,
+ role: string
+): Promise => {
+ const json = ["setRole", { community, account, role }];
- return keychain.customJson(name, "ecency_registration", "Active", json, "Community Registration");
-}
+ return broadcastPostingJSON(username, "community", json);
+};
+
+export const updateCommunity = (
+ username: string,
+ community: string,
+ props: {
+ title: string;
+ about: string;
+ lang: string;
+ description: string;
+ flag_text: string;
+ is_nsfw: boolean;
+ }
+): Promise => {
+ const json = ["updateProps", { community, props }];
+
+ return broadcastPostingJSON(username, "community", json);
+};
+
+export const pinPost = (
+ username: string,
+ community: string,
+ account: string,
+ permlink: string,
+ pin: boolean
+): Promise => {
+ const json = [pin ? "pinPost" : "unpinPost", { community, account, permlink }];
+
+ return broadcastPostingJSON(username, "community", json);
+};
+
+export const mutePost = (
+ username: string,
+ community: string,
+ account: string,
+ permlink: string,
+ notes: string,
+ mute: boolean
+): Promise => {
+ const json = [mute ? "mutePost" : "unmutePost", { community, account, permlink, notes }];
+
+ return broadcastPostingJSON(username, "community", json);
+};
+
+export const hiveNotifySetLastRead = (username: string): Promise => {
+ const now = new Date().toISOString();
+ const date = now.split(".")[0];
+
+ const params = {
+ id: "notify",
+ required_auths: [],
+ required_posting_auths: [username],
+ json: JSON.stringify(["setLastRead", { date }])
+ };
+ const params1 = {
+ id: "ecency_notify",
+ required_auths: [],
+ required_posting_auths: [username],
+ json: JSON.stringify(["setLastRead", { date }])
+ };
+
+ const opArray: Operation[] = [
+ ["custom_json", params],
+ ["custom_json", params1]
+ ];
+
+ return broadcastPostingOperations(username, opArray);
+};
+
+export const updatePassword = (
+ update: AccountUpdateOperation[1],
+ ownerKey: PrivateKey
+): Promise => hiveClient.broadcast.updateAccount(update, ownerKey);
+
+// HE Operations
+export const transferHiveEngineKc = (
+ from: string,
+ to: string,
+ symbol: string,
+ amount: string,
+ memo: string
+) => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "transfer",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString(),
+ memo
+ }
+ });
+
+ return keychain.customJson(from, "ssc-mainnet-hive", "Active", json, "Transfer");
+};
+export const delegateHiveEngineKc = (from: string, to: string, symbol: string, amount: string) => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "delegate",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ });
+
+ return keychain.customJson(from, "ssc-mainnet-hive", "Active", json, "Transfer");
+};
+export const undelegateHiveEngineKc = (
+ from: string,
+ to: string,
+ symbol: string,
+ amount: string
+) => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "undelegate",
+ contractPayload: {
+ symbol,
+ from: to,
+ quantity: amount.toString()
+ }
+ });
+
+ return keychain.customJson(from, "ssc-mainnet-hive", "Active", json, "Transfer");
+};
+export const stakeHiveEngineKc = (from: string, to: string, symbol: string, amount: string) => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "stake",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ });
+
+ return keychain.customJson(from, "ssc-mainnet-hive", "Active", json, "Transfer");
+};
+export const unstakeHiveEngineKc = (from: string, to: string, symbol: string, amount: string) => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "unstake",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ });
+
+ return keychain.customJson(from, "ssc-mainnet-hive", "Active", json, "Transfer");
+};
+
+// HE Hive Signer Operations
+export const transferHiveEngineHs = (
+ from: string,
+ to: string,
+ symbol: string,
+ amount: string,
+ memo: string
+): any => {
+ const params = {
+ authority: "active",
+ required_auths: `["${from}"]`,
+ required_posting_auths: "[]",
+ id: "ssc-mainnet-hive",
+ json: JSON.stringify({
+ contractName: "tokens",
+ contractAction: "transfer",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString(),
+ memo
+ }
+ })
+ };
+
+ return hotSign("custom-json", params, `@${from}/engine`);
+};
+
+export const delegateHiveEngineHs = (
+ from: string,
+ to: string,
+ symbol: string,
+ amount: string
+): any => {
+ const params = {
+ authority: "active",
+ required_auths: `["${from}"]`,
+ required_posting_auths: "[]",
+ id: "ssc-mainnet-hive",
+ json: JSON.stringify({
+ contractName: "tokens",
+ contractAction: "delegate",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ })
+ };
+
+ return hotSign("custom-json", params, `@${from}/engine`);
+};
+
+export const undelegateHiveEngineHs = (
+ from: string,
+ to: string,
+ symbol: string,
+ amount: string
+): any => {
+ const params = {
+ authority: "active",
+ required_auths: `["${from}"]`,
+ required_posting_auths: "[]",
+ id: "ssc-mainnet-hive",
+ json: JSON.stringify({
+ contractName: "tokens",
+ contractAction: "undelegate",
+ contractPayload: {
+ symbol,
+ from: to,
+ quantity: amount.toString()
+ }
+ })
+ };
+
+ return hotSign("custom-json", params, `@${from}/engine`);
+};
-export const updateProfile = (account: Account, newProfile: {
- name: string,
- about: string,
- website: string,
- location: string,
- cover_image: string,
- profile_image: string,
-}): Promise => {
- const params = {
- account: account.name,
- json_metadata: '',
- posting_json_metadata: JSON.stringify({profile: {...newProfile, version: 2}}),
- extensions: []
+export const stakeHiveEngineHs = (
+ from: string,
+ to: string,
+ symbol: string,
+ amount: string
+): any => {
+ const params = {
+ authority: "active",
+ required_auths: `["${from}"]`,
+ required_posting_auths: "[]",
+ id: "ssc-mainnet-hive",
+ json: JSON.stringify({
+ contractName: "tokens",
+ contractAction: "stake",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ })
+ };
+
+ return hotSign("custom-json", params, `@${from}/engine`);
+};
+
+export const unstakeHiveEngineHs = (
+ from: string,
+ to: string,
+ symbol: string,
+ amount: string
+): any => {
+ const params = {
+ authority: "active",
+ required_auths: `["${from}"]`,
+ required_posting_auths: "[]",
+ id: "ssc-mainnet-hive",
+ json: JSON.stringify({
+ contractName: "tokens",
+ contractAction: "unstake",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ })
+ };
+
+ return hotSign("custom-json", params, `@${from}/engine`);
+};
+
+//HE Key Operations
+export const transferHiveEngineKey = async (
+ from: string,
+ key: PrivateKey,
+ symbol: string,
+ to: string,
+ amount: string,
+ memo: string
+): Promise => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "transfer",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString(),
+ memo
+ }
+ });
+
+ const op = {
+ id: "ssc-mainnet-hive",
+ json,
+ required_auths: [from],
+ required_posting_auths: []
+ };
+
+ const result = await hiveClient.broadcast.json(op, key);
+
+ return result;
+};
+
+export const delegateHiveEngineKey = async (
+ from: string,
+ key: PrivateKey,
+ symbol: string,
+ to: string,
+ amount: string
+): Promise => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "delegate",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ });
+
+ const op = {
+ id: "ssc-mainnet-hive",
+ json,
+ required_auths: [from],
+ required_posting_auths: []
+ };
+
+ const result = await hiveClient.broadcast.json(op, key);
+ return result;
+};
+
+export const undelegateHiveEngineKey = async (
+ from: string,
+ key: PrivateKey,
+ symbol: string,
+ to: string,
+ amount: string
+): Promise => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "undelegate",
+ contractPayload: {
+ symbol,
+ from: to,
+ quantity: amount.toString()
+ }
+ });
+
+ const op = {
+ id: "ssc-mainnet-hive",
+ json,
+ required_auths: [from],
+ required_posting_auths: []
+ };
+
+ const result = await hiveClient.broadcast.json(op, key);
+ return result;
+};
+
+export const stakeHiveEngineKey = async (
+ from: string,
+ key: PrivateKey,
+ symbol: string,
+ to: string,
+ amount: string
+): Promise => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "stake",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ });
+
+ const op = {
+ id: "ssc-mainnet-hive",
+ json,
+ required_auths: [from],
+ required_posting_auths: []
+ };
+
+ const result = await hiveClient.broadcast.json(op, key);
+ return result;
+};
+
+export const unstakeHiveEngineKey = async (
+ from: string,
+ key: PrivateKey,
+ symbol: string,
+ to: string,
+ amount: string
+): Promise => {
+ const json = JSON.stringify({
+ contractName: "tokens",
+ contractAction: "stake",
+ contractPayload: {
+ symbol,
+ to,
+ quantity: amount.toString()
+ }
+ });
+
+ const op = {
+ id: "ssc-mainnet-hive",
+ json,
+ required_auths: [from],
+ required_posting_auths: []
+ };
+
+ const result = await hiveClient.broadcast.json(op, key);
+ return result;
+};
+
+export const Revoke = (
+ account: string,
+ weight_threshold: number,
+ account_auths: [string, number][],
+ key_auths: any[],
+ memo_key: string,
+ key: PrivateKey
+): Promise => {
+ const newPosting = {
+ weight_threshold,
+ account_auths,
+ key_auths
+ };
+
+ const op: Operation = [
+ "account_update",
+ {
+ account,
+ posting: newPosting,
+ memo_key,
+ json_metadata: ""
+ }
+ ];
+ return hiveClient.broadcast.sendOperations([op], key);
+};
+
+export const RevokeHot = (
+ account: string,
+ weight_threshold: number,
+ account_auths: [string, number][],
+ key_auths: any[],
+ memo_key: string
+) => {
+ const newPosting = {
+ weight_threshold,
+ account_auths,
+ key_auths
+ };
+ const op: Operation = [
+ "account_update",
+ {
+ account,
+ posting: newPosting,
+ memo_key,
+ json_metadata: ""
+ }
+ ];
+
+ const params: Parameters = { callback: `https://ecency.com/@${account}/permissions` };
+ return hs.sendOperation(op, params, () => {});
+};
+
+export const RevokeKc = (
+ account: string,
+ weight_threshold: number,
+ account_auths: [string, number][],
+ key_auths: any[],
+ memo_key: string
+) => {
+ const newPosting = {
+ weight_threshold,
+ account_auths,
+ key_auths
+ };
+ const op: Operation = [
+ "account_update",
+ {
+ account,
+ posting: newPosting,
+ memo_key,
+ json_metadata: ""
+ }
+ ];
+ return keychain.broadcast(account, [op], "Active");
+};
+
+// Create account with hive keychain
+export const createAccountKc = async (data: any, creator_account: string) => {
+ try {
+ const { username, pub_keys, fee } = data;
+
+ const account = {
+ name: username,
+ ...pub_keys,
+ active: false
};
- const opArray: Operation[] = [["account_update2", params]];
+ const op_name: OperationName = "account_create";
- return broadcastPostingOperations(account.name, opArray);
-}
+ const owner = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.ownerPublicKey, 1]]
+ };
+ const active = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.activePublicKey, 1]]
+ };
+ const posting = {
+ weight_threshold: 1,
+ account_auths: [["ecency.app", 1]],
+ key_auths: [[account.postingPublicKey, 1]]
+ };
+ const ops: Array = [];
+ const params: any = {
+ creator: creator_account,
+ new_account_name: account.name,
+ owner,
+ active,
+ posting,
+ memo_key: account.memoPublicKey,
+ json_metadata: "",
+ extensions: [],
+ fee
+ };
-export const grantPostingPermission = (key: PrivateKey, account: Account, pAccount: string) => {
- if (!account.__loaded) {
- throw "posting|memo_key|json_metadata required with account instance";
+ const operation: Operation = [op_name, params];
+ ops.push(operation);
+ try {
+ // For Keychain
+ const newAccount = await keychain.broadcast(creator_account, [operation], "Active");
+ return newAccount;
+ } catch (err: any) {
+ console.log(err);
+ return err.jse_info.name;
}
+ } catch (err) {
+ return err;
+ }
+};
- const newPosting = Object.assign(
- {},
- {...account.posting},
- {
- account_auths: [
- ...account.posting.account_auths,
- [pAccount, account.posting.weight_threshold]
- ]
- }
- );
+// Create account with hive Hs
+export const createAccountHs = async (data: any, creator_account: string, hash: string) => {
+ try {
+ const { username, pub_keys, fee } = data;
+
+ const account = {
+ name: username,
+ ...pub_keys,
+ active: false
+ };
+
+ const op_name: OperationName = "account_create";
+
+ const owner = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.ownerPublicKey, 1]]
+ };
+ const active = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.activePublicKey, 1]]
+ };
+ const posting = {
+ weight_threshold: 1,
+ account_auths: [["ecency.app", 1]],
+ key_auths: [[account.postingPublicKey, 1]]
+ };
- // important!
- newPosting.account_auths.sort((a, b) => (a[0] > b[0] ? 1 : -1));
+ const params: any = {
+ creator: creator_account,
+ new_account_name: account.name,
+ owner,
+ active,
+ posting,
+ memo_key: account.memoPublicKey,
+ json_metadata: "",
+ extensions: [],
+ fee
+ };
- return hiveClient.broadcast.updateAccount({
- account: account.name,
- posting: newPosting,
- active: undefined,
- memo_key: account.memo_key,
- json_metadata: account.json_metadata
- }, key);
+ const operation: Operation = [op_name, params];
+
+ try {
+ // For Hive Signer
+ const params: Parameters = {
+ callback: `https://ecency.com/onboard-friend/confirming/${hash}?tid={{id}}`
+ };
+ const newAccount = hs.sendOperation(operation, params, () => {});
+ return newAccount;
+ } catch (err: any) {
+ console.log(err);
+ return err.jse_info.name;
+ }
+ } catch (err) {
+ return err;
+ }
};
-export const revokePostingPermission = (key: PrivateKey, account: Account, pAccount: string) => {
- if (!account.__loaded) {
- throw "posting|memo_key|json_metadata required with account instance";
- }
-
- const newPosting = Object.assign(
- {},
- {...account.posting},
- {
- account_auths: account.posting.account_auths.filter(x => x[0] !== pAccount)
- }
- );
-
- return hiveClient.broadcast.updateAccount(
- {
- account: account.name,
- posting: newPosting,
- memo_key: account.memo_key,
- json_metadata: account.json_metadata
- },
- key
- );
-};
-
-export const setUserRole = (username: string, community: string, account: string, role: string): Promise => {
- const json = [
- 'setRole', {community, account, role}
- ]
-
- return broadcastPostingJSON(username, "community", json);
-}
+// Create account with hive key
+export const createAccountKey = async (
+ data: any,
+ creator_account: string,
+ creator_key: PrivateKey
+) => {
+ try {
+ const { username, pub_keys, fee } = data;
+
+ const account = {
+ name: username,
+ ...pub_keys,
+ active: false
+ };
-export const updateCommunity = (username: string, community: string, props: { title: string, about: string, lang: string, description: string, flag_text: string, is_nsfw: boolean }): Promise => {
- const json = [
- 'updateProps', {community, props}
- ];
+ let tokens: any = await hiveClient.database.getAccounts([creator_account]);
+ tokens = tokens[0]?.pending_claimed_accounts;
- return broadcastPostingJSON(username, "community", json);
-}
+ let op_name: OperationName = "account_create";
-export const pinPost = (username: string, community: string, account: string, permlink: string, pin: boolean): Promise => {
- const json = [
- pin ? 'pinPost' : 'unpinPost', {community, account, permlink}
- ]
+ const owner = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.ownerPublicKey, 1]]
+ };
+ const active = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.activePublicKey, 1]]
+ };
+ const posting = {
+ weight_threshold: 1,
+ account_auths: [["ecency.app", 1]],
+ key_auths: [[account.postingPublicKey, 1]]
+ };
+ const ops: Array = [];
+ const params: any = {
+ creator: creator_account,
+ new_account_name: account?.name,
+ owner,
+ active,
+ posting,
+ memo_key: account.memoPublicKey,
+ json_metadata: "",
+ extensions: [],
+ fee
+ };
- return broadcastPostingJSON(username, "community", json);
-}
+ const operation: Operation = [op_name, params];
+ ops.push(operation);
+
+ try {
+ // With Private Key
+ const newAccount = await hiveClient.broadcast.sendOperations(ops, creator_key);
+ return newAccount;
+ } catch (err: any) {
+ console.log(err.message);
+ return err.jse_info.name;
+ }
+ } catch (err) {
+ console.log(err);
+ return err;
+ }
+};
-export const mutePost = (username: string, community: string, account: string, permlink: string, notes: string, mute: boolean): Promise => {
- const json = [
- mute ? 'mutePost' : 'unmutePost', {community, account, permlink, notes}
- ];
+// Create account with credit Kc
+export const createAccountWithCreditKc = async (data: any, creator_account: string) => {
+ try {
+ const { username, pub_keys } = data;
- return broadcastPostingJSON(username, "community", json);
-}
+ const account = {
+ name: username,
+ ...pub_keys,
+ active: false
+ };
-export const hiveNotifySetLastRead = (username: string): Promise => {
- const now = new Date().toISOString();
- const date = now.split(".")[0];
+ let tokens: any = await hiveClient.database.getAccounts([creator_account]);
+ tokens = tokens[0]?.pending_claimed_accounts;
+
+ let fee = null;
+ let op_name: OperationName = "create_claimed_account";
- const params = {
- id: "notify",
- required_auths: [],
- required_posting_auths: [username],
- json: JSON.stringify(['setLastRead', {date}])
+ const owner = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.ownerPublicKey, 1]]
+ };
+ const active = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.activePublicKey, 1]]
+ };
+ const posting = {
+ weight_threshold: 1,
+ account_auths: [["ecency.app", 1]],
+ key_auths: [[account.postingPublicKey, 1]]
+ };
+ const ops: Array = [];
+ const params: any = {
+ creator: creator_account,
+ new_account_name: account.name,
+ owner,
+ active,
+ posting,
+ memo_key: account.memoPublicKey,
+ json_metadata: "",
+ extensions: []
+ };
+
+ if (fee) params.fee = fee;
+ const operation: Operation = [op_name, params];
+ ops.push(operation);
+ try {
+ // For Keychain
+ const newAccount = await keychain.broadcast(creator_account, [operation], "Active");
+ return newAccount;
+ } catch (err: any) {
+ return err.jse_info.name;
}
- const params1 = {
- id: "ecency_notify",
- required_auths: [],
- required_posting_auths: [username],
- json: JSON.stringify(['setLastRead', {date}])
+ } catch (err) {
+ console.log(err);
+ return err;
+ }
+};
+
+// Create account with credit Hs
+export const createAccountWithCreditHs = async (
+ data: any,
+ creator_account: string,
+ hash: string
+) => {
+ try {
+ const { username, pub_keys } = data;
+
+ const account = {
+ name: username,
+ ...pub_keys,
+ active: false
+ };
+
+ let tokens: any = await hiveClient.database.getAccounts([creator_account]);
+ tokens = tokens[0]?.pending_claimed_accounts;
+
+ let fee = null;
+ let op_name: OperationName = "create_claimed_account";
+
+ const owner = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.ownerPublicKey, 1]]
+ };
+ const active = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.activePublicKey, 1]]
+ };
+ const posting = {
+ weight_threshold: 1,
+ account_auths: [["ecency.app", 1]],
+ key_auths: [[account.postingPublicKey, 1]]
+ };
+
+ const params: any = {
+ creator: creator_account,
+ new_account_name: account.name,
+ owner,
+ active,
+ posting,
+ memo_key: account.memoPublicKey,
+ json_metadata: "",
+ extensions: []
+ };
+
+ if (fee) params.fee = fee;
+ const operation: Operation = [op_name, params];
+
+ try {
+ // For Hive Signer
+ const params: Parameters = {
+ callback: `https://ecency.com/onboard-friend/confirming/${hash}?tid={{id}}`
+ };
+ console.log(params);
+ const newAccount = hs.sendOperation(operation, params, () => {});
+ return newAccount;
+ } catch (err: any) {
+ console.log(err);
+ return err.jse_info.name;
}
+ } catch (err) {
+ return err;
+ }
+};
- const opArray: Operation[] = [['custom_json', params], ['custom_json', params1]];
+// Create account with credit key
+export const createAccountWithCreditKey = async (
+ data: any,
+ creator_account: string,
+ creator_key: PrivateKey
+) => {
+ try {
+ const { username, pub_keys } = data;
+
+ const account = {
+ name: username,
+ ...pub_keys,
+ active: false
+ };
- return broadcastPostingOperations(username, opArray);
-}
+ let tokens: any = await hiveClient.database.getAccounts([creator_account]);
+ tokens = tokens[0]?.pending_claimed_accounts;
+
+ let fee = null;
+ let op_name: OperationName = "create_claimed_account";
-export const updatePassword = (update: AccountUpdateOperation[1], ownerKey: PrivateKey): Promise => hiveClient.broadcast.updateAccount(update, ownerKey)
+ const owner = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.ownerPublicKey, 1]]
+ };
+ const active = {
+ weight_threshold: 1,
+ account_auths: [],
+ key_auths: [[account.activePublicKey, 1]]
+ };
+ const posting = {
+ weight_threshold: 1,
+ account_auths: [["ecency.app", 1]],
+ key_auths: [[account.postingPublicKey, 1]]
+ };
+ const ops: Array = [];
+ const params: any = {
+ creator: creator_account,
+ new_account_name: account?.name,
+ owner,
+ active,
+ posting,
+ memo_key: account.memoPublicKey,
+ json_metadata: "",
+ extensions: []
+ };
+
+ if (fee) params.fee = fee;
+ const operation: Operation = [op_name, params];
+ ops.push(operation);
+
+ try {
+ // With Private Key
+ const newAccount = await hiveClient.broadcast.sendOperations(ops, creator_key);
+ return newAccount;
+ } catch (err: any) {
+ console.log(err.message);
+ return err.jse_info.name;
+ }
+ } catch (err) {
+ return err;
+ }
+};
diff --git a/src/common/api/private-api.ts b/src/common/api/private-api.ts
index 9218a5d6112..84cc539eb51 100644
--- a/src/common/api/private-api.ts
+++ b/src/common/api/private-api.ts
@@ -1,391 +1,640 @@
import axios from "axios";
-import {PointTransaction} from "../store/points/types";
-import {ApiNotification, NotificationFilter} from "../store/notifications/types";
-import {Entry} from "../store/entries/types";
-
-import {getAccessToken} from "../helper/user-token";
-
-import {apiBase} from "./helper";
-
-import {AppWindow} from "../../client/window";
+import { PointTransaction } from "../store/points/types";
+import {
+ ApiNotification,
+ ApiNotificationSetting,
+ NotificationFilter
+} from "../store/notifications/types";
+import { Entry } from "../store/entries/types";
+
+import { getAccessToken } from "../helper/user-token";
+
+import { apiBase } from "./helper";
+import { AppWindow } from "../../client/window";
+import isElectron from "../util/is-electron";
+import { NotifyTypes } from "../enums";
+import { BeneficiaryRoute, MetaData, RewardType } from "./operations";
declare var window: AppWindow;
export interface ReceivedVestingShare {
- delegatee: string;
- delegator: string;
- timestamp: string;
- vesting_shares: string;
+ delegatee: string;
+ delegator: string;
+ timestamp: string;
+ vesting_shares: string;
}
export const getReceivedVestingShares = (username: string): Promise =>
- axios.get(apiBase(`/private-api/received-vesting/${username}`)).then((resp) => resp.data.list);
-
+ axios.get(apiBase(`/private-api/received-vesting/${username}`)).then((resp) => resp.data.list);
export interface RewardedCommunity {
- start_date: string;
- total_rewards: string;
- name: string;
+ start_date: string;
+ total_rewards: string;
+ name: string;
}
export const getRewardedCommunities = (): Promise =>
- axios.get(apiBase(`/private-api/rewarded-communities`)).then((resp) => resp.data);
+ axios.get(apiBase(`/private-api/rewarded-communities`)).then((resp) => resp.data);
export interface LeaderBoardItem {
- _id: string;
- count: number;
- points: string
+ _id: string;
+ count: number;
+ points: string;
}
export type LeaderBoardDuration = "day" | "week" | "month";
export const getLeaderboard = (duration: LeaderBoardDuration): Promise => {
- return axios.get(apiBase(`/private-api/leaderboard/${duration}`)).then(resp => resp.data);
+ return axios.get(apiBase(`/private-api/leaderboard/${duration}`)).then((resp) => resp.data);
};
export interface CurationItem {
- efficiency: number;
- account: string;
- vests: number;
- votes: number;
- uniques: number;
+ efficiency: number;
+ account: string;
+ vests: number;
+ votes: number;
+ uniques: number;
}
export type CurationDuration = "day" | "week" | "month";
export const getCuration = (duration: CurationDuration): Promise => {
- return axios.get(apiBase(`/private-api/curation/${duration}`)).then(resp => resp.data);
+ return axios.get(apiBase(`/private-api/curation/${duration}`)).then((resp) => resp.data);
};
export const signUp = (username: string, email: string, referral: string): Promise =>
- axios
- .post(apiBase(`/private-api/account-create`), {
- username: username,
- email: email,
- referral: referral
- })
- .then(resp => {
- return resp;
- });
+ axios
+ .post(apiBase(`/private-api/account-create`), {
+ username: username,
+ email: email,
+ referral: referral
+ })
+ .then((resp) => {
+ return resp;
+ });
export const subscribeEmail = (email: string): Promise =>
- axios
- .post(apiBase(`/private-api/subscribe`), {
- email: email
- })
- .then(resp => {
- return resp;
- });
-
-export const usrActivity = (username: string, ty: number, bl: string | number = '', tx: string | number = '') => {
- if (!window.usePrivate) {
- return new Promise((resolve) => resolve(null));
- }
-
- const params: {
- code: string | undefined;
- ty: number;
- bl?: string | number;
- tx?: string | number;
- } = {code: getAccessToken(username), ty};
-
- if (bl) params.bl = bl;
- if (tx) params.tx = tx;
+ axios
+ .post(apiBase(`/private-api/subscribe`), {
+ email: email
+ })
+ .then((resp) => {
+ return resp;
+ });
- return axios.post(apiBase(`/private-api/usr-activity`), params);
+export const usrActivity = (
+ username: string,
+ ty: number,
+ bl: string | number = "",
+ tx: string | number = ""
+) => {
+ if (!window.usePrivate) {
+ return new Promise((resolve) => resolve(null));
+ }
+
+ const params: {
+ code: string | undefined;
+ ty: number;
+ bl?: string | number;
+ tx?: string | number;
+ } = { code: getAccessToken(username), ty };
+
+ if (bl) params.bl = bl;
+ if (tx) params.tx = tx;
+
+ return axios.post(apiBase(`/private-api/usr-activity`), params);
};
-export const getNotifications = (username: string, filter: NotificationFilter | null, since: string | null = null): Promise => {
-
- const data: { code: string | undefined; filter?: string, since?: string } = {code: getAccessToken(username)};
-
- if (filter) {
- data.filter = filter;
- }
+export const getNotifications = (
+ username: string,
+ filter: NotificationFilter | null,
+ since: string | null = null,
+ user: string | null = null
+): Promise => {
+ const data: { code: string | undefined; filter?: string; since?: string; user?: string } = {
+ code: getAccessToken(username)
+ };
+
+ if (filter) {
+ data.filter = filter;
+ }
+
+ if (since) {
+ data.since = since;
+ }
+
+ if (user) {
+ data.user = user;
+ }
+
+ return axios.post(apiBase(`/private-api/notifications`), data).then((resp) => resp.data);
+};
- if (since) {
- data.since = since;
- }
+export const saveNotificationSetting = (
+ username: string,
+ system: string,
+ allows_notify: number,
+ notify_types: number[],
+ token: string
+): Promise => {
+ const data = {
+ code: getAccessToken(username),
+ username,
+ token,
+ system,
+ allows_notify,
+ notify_types
+ };
+ return axios.post(apiBase(`/private-api/register-device`), data).then((resp) => resp.data);
+};
- return axios.post(apiBase(`/private-api/notifications`), data).then(resp => resp.data);
+export const getNotificationSetting = (
+ username: string,
+ token: string
+): Promise => {
+ const data = { code: getAccessToken(username), username, token };
+ return axios.post(apiBase(`/private-api/detail-device`), data).then((resp) => resp.data);
};
-export const getCurrencyTokenRate = (currency:string, token:string): Promise =>
- axios.get(apiBase(`/private-api/market-data/${currency==="hbd" ? "usd" : currency}/${token}`)).then((resp:any) => resp.data)
+export const getCurrencyTokenRate = (currency: string, token: string): Promise =>
+ axios
+ .get(apiBase(`/private-api/market-data/${currency === "hbd" ? "usd" : currency}/${token}`))
+ .then((resp: any) => resp.data);
+
+export const getCurrencyRates = (): Promise<{
+ [currency: string]: {
+ quotes: {
+ [currency: string]: {
+ last_updated: string;
+ percent_change: number;
+ price: number;
+ };
+ };
+ };
+}> => axios.get(apiBase("/private-api/market-data/latest")).then((resp: any) => resp.data);
export const getUnreadNotificationCount = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
+ const data = { code: getAccessToken(username) };
- return data.code ? axios
- .post(apiBase(`/private-api/notifications/unread`), data)
- .then(resp => resp.data.count) : Promise.resolve(0);
-}
+ return data.code
+ ? axios.post(apiBase(`/private-api/notifications/unread`), data).then((resp) => resp.data.count)
+ : Promise.resolve(0);
+};
export const markNotifications = (username: string, id: string | null = null) => {
- const data: { code: string | undefined; id?: string } = {code: getAccessToken(username)}
- if (id) {
- data.id = id;
- }
+ const data: { code: string | undefined; id?: string } = { code: getAccessToken(username) };
+ if (id) {
+ data.id = id;
+ }
- return axios.post(apiBase(`/private-api/notifications/mark`), data);
+ return axios.post(apiBase(`/private-api/notifications/mark`), data);
};
export interface UserImage {
- created: string
- timestamp: number
- url: string
- _id: string
+ created: string;
+ timestamp: number;
+ url: string;
+ _id: string;
}
export const getImages = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/images`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/images`), data).then((resp) => resp.data);
+};
export const deleteImage = (username: string, imageID: string): Promise => {
- const data = {code: getAccessToken(username), id: imageID};
- return axios.post(apiBase(`/private-api/images-delete`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username), id: imageID };
+ return axios.post(apiBase(`/private-api/images-delete`), data).then((resp) => resp.data);
+};
export const addImage = (username: string, url: string): Promise => {
- const data = {code: getAccessToken(username), url: url};
- return axios.post(apiBase(`/private-api/images-add`), data).then(resp => resp.data);
+ const data = { code: getAccessToken(username), url: url };
+ return axios.post(apiBase(`/private-api/images-add`), data).then((resp) => resp.data);
+};
+
+export interface DraftMetadata extends MetaData {
+ beneficiaries: BeneficiaryRoute[];
+ rewardType: RewardType;
}
export interface Draft {
- body: string
- created: string
- post_type: string
- tags: string
- timestamp: number
- title: string
- _id: string
+ body: string;
+ created: string;
+ post_type: string;
+ tags: string;
+ timestamp: number;
+ title: string;
+ _id: string;
+ meta?: DraftMetadata;
}
export const getDrafts = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/drafts`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/drafts`), data).then((resp) => resp.data);
+};
-export const addDraft = (username: string, title: string, body: string, tags: string): Promise<{ drafts: Draft[] }> => {
- const data = {code: getAccessToken(username), title, body, tags};
- return axios.post(apiBase(`/private-api/drafts-add`), data).then(resp => resp.data);
-}
+export const addDraft = (
+ username: string,
+ title: string,
+ body: string,
+ tags: string,
+ meta: DraftMetadata
+): Promise<{ drafts: Draft[] }> => {
+ const data = { code: getAccessToken(username), title, body, tags, meta };
+ return axios.post(apiBase(`/private-api/drafts-add`), data).then((resp) => resp.data);
+};
-export const updateDraft = (username: string, draftId: string, title: string, body: string, tags: string): Promise => {
- const data = {code: getAccessToken(username), id: draftId, title, body, tags};
- return axios.post(apiBase(`/private-api/drafts-update`), data).then(resp => resp.data);
-}
+export const updateDraft = (
+ username: string,
+ draftId: string,
+ title: string,
+ body: string,
+ tags: string,
+ meta: DraftMetadata
+): Promise => {
+ const data = { code: getAccessToken(username), id: draftId, title, body, tags, meta };
+ return axios.post(apiBase(`/private-api/drafts-update`), data).then((resp) => resp.data);
+};
export const deleteDraft = (username: string, draftId: string): Promise => {
- const data = {code: getAccessToken(username), id: draftId};
- return axios.post(apiBase(`/private-api/drafts-delete`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username), id: draftId };
+ return axios.post(apiBase(`/private-api/drafts-delete`), data).then((resp) => resp.data);
+};
export interface Schedule {
- _id: string;
- username: string;
- permlink: string;
- title: string;
- body: string;
- tags: string[];
- tags_arr: string;
- schedule: string;
- original_schedule: string;
- reblog: boolean;
- status: 1 | 2 | 3 | 4;
- message: string | null
+ _id: string;
+ username: string;
+ permlink: string;
+ title: string;
+ body: string;
+ tags: string[];
+ tags_arr: string;
+ schedule: string;
+ original_schedule: string;
+ reblog: boolean;
+ status: 1 | 2 | 3 | 4;
+ message: string | null;
}
export const getSchedules = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/schedules`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/schedules`), data).then((resp) => resp.data);
+};
-export const addSchedule = (username: string, permlink: string, title: string, body: string, meta: {}, options: {}, schedule: string, reblog: boolean): Promise => {
- const data = {code: getAccessToken(username), permlink, title, body, meta, options, schedule, reblog}
- return axios.post(apiBase(`/private-api/schedules-add`), data).then(resp => resp.data);
-}
+export const addSchedule = (
+ username: string,
+ permlink: string,
+ title: string,
+ body: string,
+ meta: {},
+ options: {},
+ schedule: string,
+ reblog: boolean
+): Promise => {
+ const data = {
+ code: getAccessToken(username),
+ permlink,
+ title,
+ body,
+ meta,
+ options,
+ schedule,
+ reblog
+ };
+ return axios.post(apiBase(`/private-api/schedules-add`), data).then((resp) => resp.data);
+};
export const deleteSchedule = (username: string, id: string): Promise => {
- const data = {code: getAccessToken(username), id};
- return axios.post(apiBase(`/private-api/schedules-delete`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username), id };
+ return axios.post(apiBase(`/private-api/schedules-delete`), data).then((resp) => resp.data);
+};
export const moveSchedule = (username: string, id: string): Promise => {
- const data = {code: getAccessToken(username), id};
- return axios.post(apiBase(`/private-api/schedules-move`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username), id };
+ return axios.post(apiBase(`/private-api/schedules-move`), data).then((resp) => resp.data);
+};
export interface Bookmark {
- _id: string,
- author: string,
- permlink: string,
- timestamp: number,
- created: string
+ _id: string;
+ author: string;
+ permlink: string;
+ timestamp: number;
+ created: string;
}
export const getBookmarks = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/bookmarks`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/bookmarks`), data).then((resp) => resp.data);
+};
-export const addBookmark = (username: string, author: string, permlink: string): Promise<{ bookmarks: Bookmark[] }> => {
- const data = {code: getAccessToken(username), author, permlink};
- return axios.post(apiBase(`/private-api/bookmarks-add`), data).then(resp => resp.data);
-}
+export const addBookmark = (
+ username: string,
+ author: string,
+ permlink: string
+): Promise<{ bookmarks: Bookmark[] }> => {
+ const data = { code: getAccessToken(username), author, permlink };
+ return axios.post(apiBase(`/private-api/bookmarks-add`), data).then((resp) => resp.data);
+};
export const deleteBookmark = (username: string, bookmarkId: string): Promise => {
- const data = {code: getAccessToken(username), id: bookmarkId};
- return axios.post(apiBase(`/private-api/bookmarks-delete`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username), id: bookmarkId };
+ return axios.post(apiBase(`/private-api/bookmarks-delete`), data).then((resp) => resp.data);
+};
export interface Favorite {
- _id: string,
- account: string,
- timestamp: number,
+ _id: string;
+ account: string;
+ timestamp: number;
}
export const getFavorites = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/favorites`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/favorites`), data).then((resp) => resp.data);
+};
export const checkFavorite = (username: string, account: string): Promise => {
- const data = {code: getAccessToken(username), account};
- return axios.post(apiBase(`/private-api/favorites-check`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username), account };
+ return axios.post(apiBase(`/private-api/favorites-check`), data).then((resp) => resp.data);
+};
-export const addFavorite = (username: string, account: string): Promise<{ favorites: Favorite[] }> => {
- const data = {code: getAccessToken(username), account};
- return axios.post(apiBase(`/private-api/favorites-add`), data).then(resp => resp.data);
-}
+export const addFavorite = (
+ username: string,
+ account: string
+): Promise<{ favorites: Favorite[] }> => {
+ const data = { code: getAccessToken(username), account };
+ return axios.post(apiBase(`/private-api/favorites-add`), data).then((resp) => resp.data);
+};
export const deleteFavorite = (username: string, account: string): Promise => {
- const data = {code: getAccessToken(username), account};
- return axios.post(apiBase(`/private-api/favorites-delete`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username), account };
+ return axios.post(apiBase(`/private-api/favorites-delete`), data).then((resp) => resp.data);
+};
export interface Fragment {
- id: string;
- title: string;
- body: string;
- created: string;
- modified: string;
+ id: string;
+ title: string;
+ body: string;
+ created: string;
+ modified: string;
}
export const getFragments = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/fragments`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/fragments`), data).then((resp) => resp.data);
+};
-export const addFragment = (username: string, title: string, body: string): Promise<{ fragments: Fragment[] }> => {
- const data = {code: getAccessToken(username), title, body};
- return axios.post(apiBase(`/private-api/fragments-add`), data).then(resp => resp.data);
-}
+export const addFragment = (
+ username: string,
+ title: string,
+ body: string
+): Promise<{ fragments: Fragment[] }> => {
+ const data = { code: getAccessToken(username), title, body };
+ return axios.post(apiBase(`/private-api/fragments-add`), data).then((resp) => resp.data);
+};
-export const updateFragment = (username: string, fragmentId: string, title: string, body: string): Promise => {
- const data = {code: getAccessToken(username), id: fragmentId, title, body};
- return axios.post(apiBase(`/private-api/fragments-update`), data).then(resp => resp.data);
-}
+export const updateFragment = (
+ username: string,
+ fragmentId: string,
+ title: string,
+ body: string
+): Promise => {
+ const data = { code: getAccessToken(username), id: fragmentId, title, body };
+ return axios.post(apiBase(`/private-api/fragments-update`), data).then((resp) => resp.data);
+};
export const deleteFragment = (username: string, fragmentId: string): Promise => {
- const data = {code: getAccessToken(username), id: fragmentId};
- return axios.post(apiBase(`/private-api/fragments-delete`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username), id: fragmentId };
+ return axios.post(apiBase(`/private-api/fragments-delete`), data).then((resp) => resp.data);
+};
-export const getPoints = (username: string): Promise<{
- points: string;
- unclaimed_points: string;
+export const getPoints = async (
+ username: string,
+ usePrivate?: boolean
+): Promise<{
+ points: string;
+ unclaimed_points: string;
}> => {
- if (window.usePrivate) {
- const data = {username};
- return axios.post(apiBase(`/private-api/points`), data).then(resp => resp.data);
- }
-
- return new Promise((resolve) => {
- resolve({
- points: "0.000",
- unclaimed_points: "0.000"
- })
- });
-}
-
-export const getPointTransactions = (username: string, type?: number): Promise => {
- if (window.usePrivate) {
- const data = {username, type};
- return axios.post(apiBase(`/private-api/point-list`), data).then(resp => resp.data);
- }
+ if (usePrivate ?? window.usePrivate) {
+ const data = { username };
+ return axios.post(apiBase(`/private-api/points`), data).then((resp) => resp.data);
+ }
+ return {
+ points: "0.000",
+ unclaimed_points: "0.000"
+ };
+};
- return new Promise((resolve) => {
- resolve([]);
- });
-}
+export const getPointTransactions = (
+ username: string,
+ type?: number
+): Promise => {
+ if (window.usePrivate) {
+ const data = { username, type };
+ return axios.post(apiBase(`/private-api/point-list`), data).then((resp) => resp.data);
+ }
+
+ return new Promise((resolve) => {
+ resolve([]);
+ });
+};
export const claimPoints = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/points-claim`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/points-claim`), data).then((resp) => resp.data);
+};
-export const calcPoints = (username: string, amount: string): Promise<{ usd: number, estm: number }> => {
- const data = {code: getAccessToken(username), amount};
- return axios.post(apiBase(`/private-api/points-calc`), data).then(resp => resp.data);
-}
+export const calcPoints = (
+ username: string,
+ amount: string
+): Promise<{ usd: number; estm: number }> => {
+ const data = { code: getAccessToken(username), amount };
+ return axios.post(apiBase(`/private-api/points-calc`), data).then((resp) => resp.data);
+};
export interface PromotePrice {
- duration: number,
- price: number
+ duration: number;
+ price: number;
}
export const getPromotePrice = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/promote-price`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/promote-price`), data).then((resp) => resp.data);
+};
-export const getPromotedPost = (username: string, author: string, permlink: string): Promise<{ author: string, permlink: string } | ''> => {
- const data = {code: getAccessToken(username), author, permlink};
- return axios.post(apiBase(`/private-api/promoted-post`), data).then(resp => resp.data);
-}
+export const getPromotedPost = (
+ username: string,
+ author: string,
+ permlink: string
+): Promise<{ author: string; permlink: string } | ""> => {
+ const data = { code: getAccessToken(username), author, permlink };
+ return axios.post(apiBase(`/private-api/promoted-post`), data).then((resp) => resp.data);
+};
export const getBoostOptions = (username: string): Promise => {
- const data = {code: getAccessToken(username)};
- return axios.post(apiBase(`/private-api/boost-options`), data).then(resp => resp.data);
-}
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/boost-options`), data).then((resp) => resp.data);
+};
-export const getBoostedPost = (username: string, author: string, permlink: string): Promise<{ author: string, permlink: string } | ''> => {
- const data = {code: getAccessToken(username), author, permlink};
- return axios.post(apiBase(`/private-api/boosted-post`), data).then(resp => resp.data);
-}
+export const getBoostedPost = (
+ username: string,
+ author: string,
+ permlink: string
+): Promise<{ author: string; permlink: string } | ""> => {
+ const data = { code: getAccessToken(username), author, permlink };
+ return axios.post(apiBase(`/private-api/boosted-post`), data).then((resp) => resp.data);
+};
export interface CommentHistoryListItem {
- title: string;
- body: string;
- tags: string[];
- timestamp: string;
- v: number;
+ title: string;
+ body: string;
+ tags: string[];
+ timestamp: string;
+ v: number;
}
interface CommentHistory {
- meta: {
- count: number;
- },
- list: CommentHistoryListItem[];
+ meta: {
+ count: number;
+ };
+ list: CommentHistoryListItem[];
}
-export const commentHistory = (author: string, permlink: string, onlyMeta: boolean = false): Promise => {
- const data = {author, permlink, onlyMeta: onlyMeta ? '1' : ''};
- return axios.post(apiBase(`/private-api/comment-history`), data).then(resp => resp.data);
-}
+export const commentHistory = (
+ author: string,
+ permlink: string,
+ onlyMeta: boolean = false
+): Promise => {
+ const data = { author, permlink, onlyMeta: onlyMeta ? "1" : "" };
+ return axios.post(apiBase(`/private-api/comment-history`), data).then((resp) => resp.data);
+};
export const getPromotedEntries = (): Promise => {
- if (window.usePrivate) {
- return axios.get(apiBase(`/private-api/promoted-entries`)).then((resp) => resp.data);
+ if (window.usePrivate) {
+ return axios.get(apiBase(`/private-api/promoted-entries`)).then((resp) => resp.data);
+ }
+
+ return new Promise((resolve) => resolve([]));
+};
+
+export const saveNotificationsSettings = (
+ username: string,
+ notifyTypes: NotifyTypes[],
+ isEnabled: boolean,
+ token: string
+) => {
+ return saveNotificationSetting(
+ username,
+ isElectron() ? "desktop" : "web",
+ Number(isEnabled),
+ notifyTypes as number[],
+ token
+ );
+};
+
+export interface ReferralItem {
+ id: number;
+ username: string;
+ referrer: string;
+ created: string;
+ rewarded: number;
+ v: number;
+}
+
+export interface ReferralItems {
+ data: ReferralItem[];
+}
+
+export const getReferrals = (username: any, maxId: any): Promise => {
+ return axios.get(apiBase(`/private-api/referrals/${username}`), {
+ params: {
+ max_id: maxId
}
+ });
+};
- return new Promise(resolve => resolve([]));
+export interface ReferralStat {
+ total: number;
+ rewarded: number;
}
+export const getReferralsStats = async (username: any): Promise => {
+ try {
+ const res = await axios.get(apiBase(`/private-api/referrals/${username}/stats`));
+ if (!res.data) {
+ throw new Error("No Referrals for this user!");
+ }
+ const convertReferralStat = (rawData: any) => {
+ return {
+ total: rawData.total || 0,
+ rewarded: rawData.rewarded || 0
+ } as ReferralStat;
+ };
+ return convertReferralStat(res.data);
+ } catch (error) {
+ console.warn(error);
+ throw error;
+ }
+};
+export interface Announcement {
+ id: number;
+ title: string;
+ description: string;
+ button_text: string;
+ button_link: string;
+ path: string | Array;
+ auth: boolean;
+}
+
+export const getAnnouncementsData = async (): Promise => {
+ try {
+ const res = await axios.get(apiBase(`/private-api/announcements`));
+ if (!res.data) {
+ return [];
+ }
+ return res.data;
+ } catch (error) {
+ console.warn(error);
+ throw error;
+ }
+};
+export interface Recoveries {
+ username: string;
+ email: string;
+ publicKeys: Record;
+}
+export interface GetRecoveriesEmailResponse extends Recoveries {
+ _id: string;
+}
+export const getRecoveries = (username: string): Promise => {
+ const data = { code: getAccessToken(username) };
+ return axios.post(apiBase(`/private-api/recoveries`), data).then((resp) => resp.data);
+};
+
+export const addRecoveries = (
+ username: string,
+ email: string,
+ publicKeys: Object
+): Promise<{ recoveries: Recoveries }> => {
+ const data = { code: getAccessToken(username), email, publicKeys };
+ return axios.post(apiBase(`/private-api/recoveries-add`), data).then((resp) => resp.data);
+};
+
+export const deleteRecoveries = (username: string, recoveryId: string): Promise => {
+ const data = { code: getAccessToken(username), id: recoveryId };
+ return axios.post(apiBase(`/private-api/recoveries-delete`), data).then((resp) => resp.data);
+};
+
+export const onboardEmail = (username: string, email: string, friend: string): Promise => {
+ const dataBody = {
+ username,
+ email,
+ friend
+ };
+ return axios
+ .post(apiBase(`/private-api/account-create-friend`), dataBody)
+ .then((resp) => resp.data);
+};
diff --git a/src/common/api/queries.ts b/src/common/api/queries.ts
new file mode 100644
index 00000000000..545c3d54c02
--- /dev/null
+++ b/src/common/api/queries.ts
@@ -0,0 +1,37 @@
+import { useQuery } from "@tanstack/react-query";
+import { QueryIdentifiers } from "../core";
+import { getPoints, getPointTransactions } from "./private-api";
+import { useMappedStore } from "../store/use-mapped-store";
+
+const DEFAULT = {
+ points: "0.000",
+ uPoints: "0.000",
+ transactions: []
+};
+
+export function usePointsQuery(username: string, filter = 0) {
+ const { global } = useMappedStore();
+
+ return useQuery(
+ [QueryIdentifiers.POINTS, username, filter],
+ async () => {
+ const name = username.replace("@", "");
+
+ try {
+ const points = await getPoints(name, global.usePrivate);
+ const transactions = await getPointTransactions(name, filter);
+ return {
+ points: points.points,
+ uPoints: points.unclaimed_points,
+ transactions
+ };
+ } catch (e) {
+ return DEFAULT;
+ }
+ },
+ {
+ initialData: DEFAULT,
+ retryDelay: 30000
+ }
+ );
+}
diff --git a/src/common/api/search-api.ts b/src/common/api/search-api.ts
index b188f98b510..f42c3c0ea68 100644
--- a/src/common/api/search-api.ts
+++ b/src/common/api/search-api.ts
@@ -1,88 +1,118 @@
import axios from "axios";
+import { EntryVote } from "../store/entries/types";
import { dataLimit } from "./bridge";
-import {apiBase} from "./helper";
+import { apiBase } from "./helper";
export interface SearchResult {
- id: number;
- title: string;
- title_marked: string | null;
- category: string;
- author: string;
- permlink: string;
- author_rep: number | string;
- children: number;
- body: string;
- body_marked: string | null;
- img_url: string;
- created_at: string;
- payout: number;
- total_votes: number;
- up_votes: number;
- tags: string[];
- depth: number;
- app: string;
+ id: number;
+ title: string;
+ title_marked: string | null;
+ category: string;
+ author: string;
+ permlink: string;
+ author_rep: number | string;
+ author_reputation?: number | string;
+ children: number;
+ body: string;
+ body_marked: string | null;
+ img_url: string;
+ created_at: string;
+ created?: string;
+ payout: number;
+ total_votes: number;
+ up_votes: number;
+ tags: string[];
+ json_metadata?: any;
+ depth: number;
+ app: string;
+ active_votes?: EntryVote[];
+ pending_payout_value?: string;
}
export interface SearchResponse {
- hits: number;
- results: SearchResult[];
- scroll_id?: string;
- took: number;
+ hits: number;
+ results: SearchResult[];
+ scroll_id?: string;
+ took: number;
}
-export const search = (q: string, sort: string, hideLow: string, since?: string, scroll_id?: string): Promise => {
- const data: { q: string, sort: string, hide_low: string, since?: string, scroll_id?: string } = {q, sort, hide_low: hideLow};
+export const search = (
+ q: string,
+ sort: string,
+ hideLow: string,
+ since?: string,
+ scroll_id?: string,
+ votes?: number
+): Promise => {
+ const data: {
+ q: string;
+ sort: string;
+ hide_low: string;
+ since?: string;
+ scroll_id?: string;
+ votes?: number;
+ } = { q, sort, hide_low: hideLow };
- if (since) data.since = since;
- if (scroll_id) data.scroll_id = scroll_id;
+ if (since) data.since = since;
+ if (scroll_id) data.scroll_id = scroll_id;
+ if (votes) data.votes = votes;
- return axios.post(apiBase(`/search-api/search`), data).then(resp => resp.data);
-}
+ return axios.post(apiBase(`/search-api/search`), data).then((resp) => resp.data);
+};
export interface FriendSearchResult {
- name: string;
- full_name: string;
- reputation: number
+ name: string;
+ full_name: string;
+ lastSeen: string;
+ reputation: number;
}
export const searchFollower = (following: string, q: string): Promise => {
- const data = {following, q};
+ const data = { following, q };
- return axios.post(apiBase(`/search-api/search-follower`), data).then(resp => resp.data);
-}
+ return axios.post(apiBase(`/search-api/search-follower`), data).then((resp) => resp.data);
+};
export const searchFollowing = (follower: string, q: string): Promise => {
- const data = {follower, q};
+ const data = { follower, q };
- return axios.post(apiBase(`/search-api/search-following`), data).then(resp => resp.data);
-}
+ return axios.post(apiBase(`/search-api/search-following`), data).then((resp) => resp.data);
+};
export interface AccountSearchResult {
- name: string;
- full_name: string;
- about: string;
- reputation: number
+ name: string;
+ full_name: string;
+ about: string;
+ reputation: number;
}
-export const searchAccount = (q: string = "", limit: number = dataLimit, random: number = 1): Promise => {
- const data = {q, limit, random};
+export const searchAccount = (
+ q: string = "",
+ limit: number = dataLimit,
+ random: number = 1
+): Promise => {
+ const data = { q, limit, random };
- return axios.post(apiBase(`/search-api/search-account`), data).then(resp => resp.data);
-}
+ return axios.post(apiBase(`/search-api/search-account`), data).then((resp) => resp.data);
+};
export interface TagSearchResult {
- tag: string;
- repeat: number;
+ tag: string;
+ repeat: number;
}
-export const searchTag = (q: string = "", limit: number = dataLimit, random: number = 0): Promise