Repository: ontio/OWallet
Branch: master
Commit: 434b97d71cb4
Files: 141
Total size: 754.2 KB
Directory structure:
gitextract_cdm3kmul/
├── .browserslistrc
├── .editorconfig
├── .eslintrc.js
├── .github/
│ └── workflows/
│ └── publish.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_cn.md
├── babel.config.js
├── build/
│ ├── after-sign.js
│ └── entitlements.mac.plist
├── package.json
├── public/
│ └── index.html
├── src/
│ ├── App.vue
│ ├── assets/
│ │ ├── fonts/
│ │ │ └── avenirnextregular.otf
│ │ └── icons/
│ │ └── icon.icns
│ ├── background.js
│ ├── components/
│ │ ├── Breadcrumb.vue
│ │ ├── Common/
│ │ │ ├── CommonSignShared.vue
│ │ │ ├── Oep4Home.vue
│ │ │ ├── Oep4Selection.vue
│ │ │ ├── SelectWallet.vue
│ │ │ └── SignSendTx.vue
│ │ ├── CommonWallet/
│ │ │ ├── CommonReceive.vue
│ │ │ ├── CommonRedeem.vue
│ │ │ ├── CommonTokenSwap.vue
│ │ │ ├── SendConfirm.vue
│ │ │ └── SendHome.vue
│ │ ├── Dapps.vue
│ │ ├── Dashboard.vue
│ │ ├── Exchange/
│ │ │ ├── Changelly/
│ │ │ │ └── Changelly.vue
│ │ │ └── Cryptonex/
│ │ │ └── Cryptonex.vue
│ │ ├── Home.vue
│ │ ├── Identitys/
│ │ │ ├── Create/
│ │ │ │ ├── BasicInfo.vue
│ │ │ │ └── ConfirmInfo.vue
│ │ │ ├── CreateIdentity.vue
│ │ │ ├── IdentityView.vue
│ │ │ ├── Import/
│ │ │ │ └── BasicInfo.vue
│ │ │ └── ImportIdentity.vue
│ │ ├── Identitys.vue
│ │ ├── JsonWallet/
│ │ │ ├── Create/
│ │ │ │ ├── BasicInfo.vue
│ │ │ │ └── ConfirmInfo.vue
│ │ │ ├── CreateJsonWallet.vue
│ │ │ ├── Import/
│ │ │ │ └── BasicInfo.vue
│ │ │ ├── ImportJsonWallet.vue
│ │ │ └── View/
│ │ │ └── Details.vue
│ │ ├── LedgerWallet/
│ │ │ ├── Import/
│ │ │ │ ├── BasicInfo.vue
│ │ │ │ └── ConnectLedger.vue
│ │ │ ├── ImportLedgerWallet.vue
│ │ │ └── LoginLedger.vue
│ │ ├── Modals/
│ │ │ ├── Loading.vue
│ │ │ └── SetPath.vue
│ │ ├── Node/
│ │ │ ├── Node.vue
│ │ │ ├── NodeApply/
│ │ │ │ ├── Register.vue
│ │ │ │ └── RegisterSuccess.vue
│ │ │ ├── NodeAuthorize/
│ │ │ │ ├── AuthorizationMgmt.vue
│ │ │ │ ├── AuthorizeLogin.vue
│ │ │ │ ├── NewAuthorization.vue
│ │ │ │ ├── NodeList.vue
│ │ │ │ ├── Sesameseed/
│ │ │ │ │ ├── AuthorizationMgmtSesameseed.vue
│ │ │ │ │ ├── AuthorizeLoginSesameseed.vue
│ │ │ │ │ ├── NewAuthorizationSesameseed.vue
│ │ │ │ │ └── SesameseedVars.js
│ │ │ │ └── StakeHistory.vue
│ │ │ ├── NodeManagement/
│ │ │ │ ├── MyNode.vue
│ │ │ │ ├── NodeStakeAuthorization.vue
│ │ │ │ └── NodeStakeManagement.vue
│ │ │ ├── NodeStake/
│ │ │ │ ├── NodeInfo.vue
│ │ │ │ ├── NodeStakeInfo.vue
│ │ │ │ ├── NodeStakeIntro.vue
│ │ │ │ └── NodeStakeRegister.vue
│ │ │ └── Vote/
│ │ │ ├── Create.vue
│ │ │ ├── Detail.vue
│ │ │ ├── List.vue
│ │ │ ├── Login.vue
│ │ │ └── index.vue
│ │ ├── RedeemInfoIcon.vue
│ │ ├── Setting.vue
│ │ ├── SharedWallet/
│ │ │ ├── Create/
│ │ │ │ ├── BasicInfo.vue
│ │ │ │ ├── ConfirmSigNum.vue
│ │ │ │ └── CreateSuccess.vue
│ │ │ ├── CreateSharedWallet.vue
│ │ │ ├── Import/
│ │ │ │ ├── InputPass.vue
│ │ │ │ └── QuerySharedWallet.vue
│ │ │ ├── ImportSharedWallet.vue
│ │ │ ├── PAX/
│ │ │ │ ├── PaxMgmt.vue
│ │ │ │ ├── SignProcess.vue
│ │ │ │ └── StartProcess.vue
│ │ │ ├── PendingTxHome.vue
│ │ │ ├── SharedWalletDetail.vue
│ │ │ ├── SharedWalletHome.vue
│ │ │ ├── SharedWalletSend.vue
│ │ │ ├── Transfer/
│ │ │ │ ├── InputPassword.vue
│ │ │ │ ├── PendingConfirm.vue
│ │ │ │ ├── PendingTxSign.vue
│ │ │ │ ├── SendAsset.vue
│ │ │ │ └── SendConfirm.vue
│ │ │ ├── Tx/
│ │ │ │ ├── SharedTxMgmt.vue
│ │ │ │ ├── SignSharedTx.vue
│ │ │ │ └── StartSharedTx.vue
│ │ │ └── View/
│ │ │ ├── Details.vue
│ │ │ └── SharedWalletCopayer.vue
│ │ ├── TopLeftNav.vue
│ │ └── Wallets.vue
│ ├── core/
│ │ ├── asyncHelper.js
│ │ ├── consts.js
│ │ ├── dbService.js
│ │ ├── fileHelper.js
│ │ ├── lang.js
│ │ ├── network.js
│ │ ├── nodes.json
│ │ ├── ontLedger.js
│ │ ├── ontLedgerNew.js
│ │ ├── runtime.js
│ │ └── utils.js
│ ├── lang/
│ │ ├── en.js
│ │ ├── index.js
│ │ └── zh.js
│ ├── main.js
│ ├── router/
│ │ └── index.js
│ └── store/
│ ├── index.js
│ └── modules/
│ ├── CreateIdentity.js
│ ├── CreateJsonWallet.js
│ ├── CreateSharedWallet.js
│ ├── CurrentWallet.js
│ ├── Identities.js
│ ├── ImportSharedWallet.js
│ ├── LedgerConnector.js
│ ├── LedgerWallet.js
│ ├── LoadingModal.js
│ ├── NodeAuthorization.js
│ ├── NodeAuthorizationSesameseed.js
│ ├── NodeStake.js
│ ├── Oep4s.js
│ ├── PaxMgmt.js
│ ├── Setting.js
│ ├── Tokens.js
│ ├── Vote.js
│ ├── Wallets.js
│ └── index.js
└── vue.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .browserslistrc
================================================
> 1%
last 2 versions
not dead
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
================================================
FILE: .eslintrc.js
================================================
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-unused-vars': 'off',
'no-empty': 'off',
'no-empty-pattern': 'off',
}
}
================================================
FILE: .github/workflows/publish.yml
================================================
name: Release on Tag
on:
push:
tags:
- '*' # Listen for any tag push events
jobs:
build-and-release:
runs-on: macos-latest
# permissions: # Add this permissions block
# contents: write
# packages: write
# issues: write
# pull-requests: write
permissions: write-all
steps:
# Check out the code
- name: Checkout code
uses: actions/checkout@v3
# Set up Node.js and Yarn environment
- name: Setup Node.js and Yarn
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'yarn'
- name: 🔐 Setup Temporary Keychain and Import Certificate
run: |
KEYCHAIN_NAME="temp.keychain"
NODE_PATH=$(which node)
echo "Found Node executable at: $NODE_PATH"
# 1. Create a new temporary keychain
security create-keychain -p ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME
# 2. Set the new keychain as the default for the session
security default-keychain -s $KEYCHAIN_NAME
security unlock-keychain -p ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME
# 3. Increase the keychain search timeout
security set-keychain-settings -t 3600 $KEYCHAIN_NAME
# 4. Decode the P12 file content from the secret and save it to a file
echo "${{ secrets.DEV_ID_CERTIFICATE_P12 }}" | base64 --decode > dev_cert.p12
# 6. Set the partition list to ensure automated tools can access the key
# This is crucial for CI environments.
CERT_ID='Developer ID Application: Ontology Foundation Ltd (29B4VVVVKM)' # <-- Replace with your exact Identity name
#security set-key-partition-list -S apple-tool: -S apple: -k $KEYCHAIN_NAME -p ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME
curl https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer -o DeveloperIDG2CA.cer
sudo security add-trusted-cert -d -r unspecified -k $KEYCHAIN_NAME DeveloperIDG2CA.cer
rm -f DeveloperIDG2CA.cer
# 5. Import the certificate and private key into the new keychain
security import dev_cert.p12 -k $KEYCHAIN_NAME -P "${{ secrets.P12_PASSWORD }}" -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/xcodebuild -T $NODE_PATH
echo "import success!"
security set-key-partition-list -S apple-tool:,apple: -s -k ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME
echo "partition list success"
# Set the temporary keychain as the default for the session
security default-keychain -s $KEYCHAIN_NAME
echo "default keychain success"
# Unlock the keychain
security unlock-keychain -p ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME
# Set lock timeout to the maximum (3600 seconds) and ensure it's always searched
security set-keychain-settings -l -u -t 3600 $KEYCHAIN_NAME
if security find-identity -p codesigning $KEYCHAIN_NAME | grep -q "$CERT_ID"; then
echo "✅ SUCCESS: Code Signing Identity '$CERT_ID' found in the temporary keychain."
else
echo "❌ FAILURE: Code Signing Identity '$CERT_ID' NOT found. Codesign will likely fail."
exit 1 # Exit the job immediately if the identity isn't found
fi
# Install dependencies
- name: Install dependencies
run: |
yarn install
# # Build all packages (macOS, Linux, and Windows)
- name: Build macos packages
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
TEAM_ID: ${{ secrets.TEAM_ID }}
PASSWORD: ${{ secrets.PASSWORD }}
run: |
yarn build:mac
- name: Build Windows App
# if: matrix.os == 'windows-latest'
run: |
yarn build:win
- name: Build Linux App
# if: matrix.os == 'ubuntu-latest'
run: |
yarn build:linux
# - name: Create Release v1
# id: create_release
# uses: actions/create-release@latest
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
# with:
# tag_name: ${{ github.ref }}
# release_name: Release ${{ github.ref }}
# body: |
# Change Log
# - TODO
# draft: false
# prerelease: false
# --- Cleanup ---
- name: 🗑️ Clean Up Keychain and Files
if: always() # Ensure cleanup runs even on failure
run: |
security delete-keychain temp.keychain
rm dev_cert.p12
- name: Generate Checksums
run: |
brew install coreutils
#echo "# OWallet ${{ github.ref_name }}" > CHECKSUMS.md
echo "" > CHECKSUMS.md
echo "CHANGELOG: $(git log -1 --format=%s ${{ github.ref_name }})" >> CHECKSUMS.md
echo "## SHA256 Checksums" >> CHECKSUMS.md
echo "| File | SHA256 Checksum |" >> CHECKSUMS.md
echo "|------|----------------|" >> CHECKSUMS.md
# find dist_electron/ -type f -name OWallet\*.AppImage -o -name OWallet\*.dmg -o -name OWallet\*.exe -o -name OWallet\*.deb -exec sh -c '
# for file; do
# echo "| $(basename "$file") | \`$(sha256sum "$file" | cut -d " " -f1)\` |" >> CHECKSUMS.md
# done
# ' sh {} +
echo "| $(ls dist_electron/OWallet-*.deb | sed -e 's#dist_electron/##') | \`$(sha256sum dist_electron/OWallet-*.deb | cut -d " " -f1)\` |" >> CHECKSUMS.md
echo "| $(ls dist_electron/OWallet-*.exe | sed -e 's#dist_electron/##') | \`$(sha256sum dist_electron/OWallet-*.exe | cut -d " " -f1)\` |" >> CHECKSUMS.md
echo "| $(ls dist_electron/OWallet-*.AppImage | sed -e 's#dist_electron/##') | \`$(sha256sum dist_electron/OWallet-*.AppImage | cut -d " " -f1)\` |" >> CHECKSUMS.md
for dmg in dist_electron/OWallet-*.dmg; do
echo "| $(basename "$dmg") | \`$(sha256sum "$dmg" | cut -d " " -f1)\` |" >> CHECKSUMS.md
done
- name: Create Release v2
uses: softprops/action-gh-release@v1
with:
name: Release ${{ github.ref_name }}
body_path: CHECKSUMS.md
files: |
dist_electron/*.deb
dist_electron/*.AppImage
dist_electron/*.dmg
dist_electron/*.exe
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
/dist
.sign
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
#Electron-builder output
/dist_electron
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 Ontology
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
[中文版](./README_cn.md)
OWallet - a comprehensive Ontology desktop wallet
Version 0.10.0
## Introduction
OWallet is a comprehensive Ontology desktop wallet. OWallet supports standard wallet management, shared wallet management based on multi-signature technology, and will also connect with various hard wallets such as Ledger, Trezor, and so on. In the next phase, OWallet will integrate more applications, providing developers with smart contract compilation, invocation, and other comprehensive services.
Support Windows/MacOS/Linux,get it [Here](https://github.com/ontio/OWallet/releases),also welcome to join [our community on Discord](https://discord.gg/4TQujHj).
Core features of OWallet are as follows:
* Create wallet/import wallet using keystore,mnemonic phrase,WIF private key,HEX private key
* Support shared wallet based on multi-signature technology
* Ledger support
* View balance and record
* Send ONG and ONT
* Withdraw (redeem) ONG
* Node stake and stake authorization management
* ONT ID support
* Integrate gateway provided by changelly and cryptonex

## Get started
1. Clone the repo
```
git clone https://github.com/ontio/OWallet.git
```
2. Install packages
**yarn** is recommended.
```
yarn
```
3. Run in Development
```
yarn serve
```
4. Build
```
yarn build
```
## Install released app
Please download the latest version that is compatiable with your platform.
## Default keystore.db file path
Default points to:
* %APPDATA% on `Windows`
* $XDG_CONFIG_HOME or ~/.config on `Linux`
* ~/Library/Application Support on `macOS`
================================================
FILE: README_cn.md
================================================
[English Version](./README.md)
OWallet - 本体综合性桌面版钱包
Version 0.10.0
## 总体介绍
OWallet是本体综合性桌面版钱包,支持标准的钱包管理、基于多重签名技术的共享钱包管理,同时将连接Ledger、Trezor多种硬件钱包。未来,OWallet将持续集成更加丰富的应用功能,为开发者提供智能合约编译、运行等综合性服务。
支持Windows/MacOS/Linux,下载请到[这里](https://github.com/ontio/OWallet/releases),也欢迎加入我们的[技术讨论社区](https://discord.gg/4TQujHj)!
OWallet核心功能如下:
* 创建钱包/导入钱包(支持使用Keystore,助记词,WIF私钥,明文私钥)
* 支持共享钱包(基于多重签名技术)
* 支持硬件钱包Ledger
* 查看余额和交易明细
* 发送ONG和ONT
* 提取ONG
* 节点质押和质押授权管理
* 支持ONT ID功能
* 集成changelly和cryptonex网关

## 如何开始
1. 克隆repo
```
git clone https://github.com/ontio/OWallet.git
```
2. 安装依赖
推荐使用**yarn**
```
yarn
```
3. 开发模式运行
```
yarn serve
```
4. 打包
```
yarn build
```
## 安装发布的客户端
请下载适合于您的操作系统的最新版本客户端。
## keystore.db文件的默认保存路径
在不同系统上指向如下位置:
* %APPDATA% on `Windows`
* $XDG_CONFIG_HOME or ~/.config on `Linux`
* ~/Library/Application Support on `macOS`
================================================
FILE: babel.config.js
================================================
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
["import", { libraryName: "ant-design-vue", libraryDirectory: "es", style: "css" }]
]
}
================================================
FILE: build/after-sign.js
================================================
// build/after-sign.js
const { execSync } = require("child_process");
const path = require("path");
const fs = require("fs");
const DEV_ID = "Developer ID Application: Ontology Foundation Ltd (29B4VVVVKM)";
const ENTITLEMENTS = "build/entitlements.mac.plist";
function run(cmd) {
console.log(`\n> ${cmd}`);
execSync(cmd, { stdio: "inherit" });
}
exports.default = async function afterSign(context) {
if (context.electronPlatformName !== "darwin") {
console.log("!Skipping afterSign: not macOS build.");
return;
}
if (process.env.CI !== 'true' || process.env.GITHUB_ACTIONS!=='true') {
return
}
const appPath = path.join(
context.appOutDir,
`${context.packager.appInfo.productFilename}.app`
);
if (!fs.existsSync(appPath)) {
console.error("!!App not found:", appPath);
return;
}
console.log(`\nStarting manual signing for: ${appPath}`);
console.log("[1/6] Signing Electron Framework Libraries...");
const libsPath = path.join(
appPath,
"Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries"
);
if (fs.existsSync(libsPath)) {
const libs = fs.readdirSync(libsPath).filter((f) => f.endsWith(".dylib"));
for (const lib of libs) {
const libPath = path.join(libsPath, lib);
run(
`codesign -fs "${DEV_ID}" --options runtime --timestamp -v "${libPath}"`
);
}
}
console.log("[2/6] Signing Binaries of Helpers and Squirrel...");
const crashpadHandler = path.join(
appPath,
"Contents/Frameworks/Electron Framework.framework/Versions/A/Helpers/chrome_crashpad_handler"
);
const shipIt = path.join(
appPath,
"Contents/Frameworks/Squirrel.framework/Versions/A/Resources/ShipIt"
);
if (fs.existsSync(crashpadHandler))
run(
`codesign -fs "${DEV_ID}" --options runtime --timestamp -v "${crashpadHandler}"`
);
if (fs.existsSync(shipIt))
run(
`codesign -fs "${DEV_ID}" --options runtime --timestamp -v "${shipIt}"`
);
console.log("[3/6] Signing Frameworks...");
const frameworks = [
"Electron Framework.framework",
"Squirrel.framework",
"Mantle.framework",
"ReactiveObjC.framework",
];
for (const fw of frameworks) {
const fwPath = path.join(appPath, "Contents/Frameworks", fw);
if (fs.existsSync(fwPath)) {
run(
`codesign -fs "${DEV_ID}" --options runtime --timestamp -v "${fwPath}"`
);
}
}
console.log("[4/6] Signing Helper Apps...");
const helpers = [
"OWallet Helper.app",
"OWallet Helper (Renderer).app",
"OWallet Helper (Plugin).app",
"OWallet Helper (GPU).app",
];
for (const helper of helpers) {
const helperPath = path.join(appPath, "Contents/Frameworks", helper);
if (fs.existsSync(helperPath)) {
console.log(`Signing executables in ${helperPath}`);
const helperExePath = path.join(helperPath, "Contents/MacOS");
const exes = fs.existsSync(helperExePath)
? fs.readdirSync(helperExePath)
: [];
for (const exe of exes) {
run(
`codesign -fs "${DEV_ID}" --options runtime --timestamp -v "${path.join(
helperExePath,
exe
)}"`
);
}
console.log(`Signing helper app itself ${helperPath}`);
run(
`codesign -fs "${DEV_ID}" --options runtime --timestamp --deep --entitlements ${ENTITLEMENTS} -v "${helperPath}"`
);
}
}
console.log("[5/6] Signing Main Binary...");
const mainExePath = path.join(appPath, "Contents/MacOS/OWallet");
if (fs.existsSync(mainExePath)) {
run(
`codesign -fs "${DEV_ID}" --options runtime --timestamp --deep -v --entitlements ${ENTITLEMENTS} "${mainExePath}"`
);
}
console.log("[6/6] Signing .app...");
run(
`codesign -fs "${DEV_ID}" --options runtime --timestamp --deep --entitlements ${ENTITLEMENTS} -v "${appPath}"`
);
console.log("\nVerifying Signature...");
run(`codesign -vvv --deep --strict "${appPath}"`);
run(`codesign -dvv "${appPath}"`);
console.log("\nManual signing completed successfully!");
console.log("\nSubmitting to Apple for notarization...");
const ZIP_FILE = path.join(
context.appOutDir,
`${context.packager.appInfo.productFilename}.zip`
);
run(`ditto -c -k --keepParent "${appPath}" "${ZIP_FILE}"`);
run(
`xcrun notarytool submit --apple-id ${process.env.APPLE_ID} --team-id ${process.env.TEAM_ID} --password ${process.env.PASSWORD} --wait "${ZIP_FILE}"`
);
console.log("Notarization complete.");
run(`xcrun stapler staple "${appPath}"`);
console.log("\nSigning & notarization finished successfully!");
};
================================================
FILE: build/entitlements.mac.plist
================================================
com.apple.security.cs.allow-jit
com.apple.security.cs.disable-library-validation
================================================
FILE: package.json
================================================
{
"name": "owallet",
"homepage": "http://ont.io",
"version": "v0.10.4",
"author": "Ontology Foundation Ltd. ",
"description": "OWallet is a comprehensive Ontology desktop wallet",
"license": "Apache-2.0",
"private": true,
"scripts": {
"serve": "vue-cli-service electron:serve",
"build": "vue-cli-service electron:build -mlw --publish=never",
"build:mac": "vue-cli-service electron:build -m --publish=never",
"build:linux": "vue-cli-service electron:build -l --publish=never",
"build:win": "vue-cli-service electron:build -w --publish=never",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps"
},
"main": "background.js",
"dependencies": {
"@electron/remote": "^2.1.2",
"@ledgerhq/hw-transport-node-hid": "^5.19.1",
"@xkeshi/vue-qrcode": "^1.0.0",
"ant-design-vue": "^1.1.9",
"axios": "^0.21.1",
"bignumber.js": "^7.2.1",
"bootstrap": "^4.1.1",
"caniuse-lite": "^1.0.30001749",
"clipboard": "^2.0.1",
"core-js": "^3.6.5",
"dateformat": "^3.0.3",
"delay": "^4.4.0",
"elliptic": "^6.5.4",
"font-awesome": "^4.7.0",
"lodash": "^4.17.21",
"nedb": "^1.8.0",
"node-hid": "^2.1.1",
"numeral": "^2.0.6",
"ontology-ts-sdk": "^1.1.14-alpha.5",
"opn": "^5.4.0",
"popper.js": "^1.14.3",
"sass": "^1.83.1",
"usb": "1.7.1",
"vee-validate": "^2.2.15",
"vue": "^2.7.0",
"vue-axios": "^2.1.1",
"vue-clipboard2": "^0.2.1",
"vue-electron": "^1.0.6",
"vue-i18n": "^8.0.0",
"vue-router": "^3.2.0",
"vuedraggable": "^2.16.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.4.0",
"@vue/cli-plugin-eslint": "^4.4.0",
"@vue/cli-plugin-router": "^4.4.0",
"@vue/cli-plugin-vuex": "^4.4.0",
"@vue/cli-service": "^4.4.0",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.11.0",
"electron": "^33.0.0",
"electron-devtools-installer": "^3.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"jquery": "^3.3.1",
"sass-loader": "^10.0.0",
"vue-cli-plugin-electron-builder": "^2.0.0",
"vue-template-compiler": "^2.6.11"
},
"resolutions": {
"usb": "1.7.1",
"node-hid": "2.1.1",
"app-builder-bin": "3.5.13",
"electron-builder": "23.6.0"
}
}
================================================
FILE: public/index.html
================================================
<%= process.env.VUE_APP_TITLE %>
We're sorry but <%= process.env.VUE_APP_TITLE %> doesn't work properly without JavaScript enabled. Please enable it to continue.
================================================
FILE: src/App.vue
================================================
================================================
FILE: src/background.js
================================================
'use strict'
import { app, protocol, BrowserWindow, Menu } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
require('@electron/remote/main').initialize()
const isDevelopment = process.env.NODE_ENV !== 'production'
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
useContentSize: true,
width: 1110,
minWidth: 1110,
height: 675,
minHeight: 635,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
webSecurity: false,
enableRemoteModule: true,
// TODO: Expose only necessary modules.
contextIsolation: false,
}
})
require('@electron/remote/main').enable(win.webContents);
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
win.on('closed', () => {
win = null
})
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
createWindow()
}
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
// Menu template
const template = [
{
label: 'Edit ( 操作 )',
submenu: [{
label: 'Select All ( 全选 )',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
}, {
label: 'Copy ( 复制 )',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
}, {
label: 'Cut ( 剪切 )',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
}, {
label: 'Paste ( 粘贴 )',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
}, {
label: 'Reload ( 重新加载 )',
accelerator: 'CmdOrCtrl+R',
click: function (item, focusedWindow) {
if (focusedWindow) {
// on reload, start fresh and close any old
// open secondary windows
if (focusedWindow.id === 1) {
BrowserWindow.getAllWindows().forEach(function (win) {
if (win.id > 1) {
win.close()
}
})
}
focusedWindow.reload()
}
}
},
{
label: 'Quit ( 退出 )',
accelerator: 'CmdOrCtrl+Q',
role: 'quit'
},
]
},
{
label: 'Window ( 窗口 )',
role: 'window',
submenu: [{
label: 'Minimize ( 最小化 )',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
}, {
label: 'Close ( 关闭 )',
accelerator: 'CmdOrCtrl+W',
role: 'close'
}, {
label: 'Developer Tools (切换开发者工具)',
accelerator: (function () {
if (process.platform === 'darwin') {
return 'Alt+Command+I'
} else {
return 'Ctrl+Shift+I'
}
})(),
click: function (item, focusedWindow) {
if (focusedWindow) {
focusedWindow.toggleDevTools()
}
}
}, {
type: 'separator'
}]
}
]
================================================
FILE: src/components/Breadcrumb.vue
================================================
================================================
FILE: src/components/Common/CommonSignShared.vue
================================================
{{$t('sharedTx.signTx')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
{{$t('pax.ledgerSignMultiTimes')}}
================================================
FILE: src/components/Common/Oep4Home.vue
================================================
{{token.symbol}} - {{token.name}}
{{$t('commonWalletHome.balance')}}:
{{token.balance}}
{{$t('commonWalletHome.scriptHash')}}:
{{token.scriptHash}}
{{$t('commonWalletHome.add')}}
{{$t('sharedWalletHome.send')}}
{{$t('sharedWalletHome.receive')}}
{{tx.txHash}}
{{tx.amount}} {{tx.asset}}
{{$t('sharedWalletHome.checkMore')}}>>
{{$t('commonWalletHome.enterScripthash')}}
================================================
FILE: src/components/Common/Oep4Selection.vue
================================================
================================================
FILE: src/components/Common/SelectWallet.vue
================================================
================================================
FILE: src/components/Common/SignSendTx.vue
================================================
{{$t('nodeStake.enterWalletPass')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/CommonWallet/CommonReceive.vue
================================================
{{$t('commonWalletHome.walletQrCode')}}
{{$t('commonWalletHome.walletAddress')}}
{{address}}
{{$t('commonWalletHome.publicKey')}}
{{pk}}
================================================
FILE: src/components/CommonWallet/CommonRedeem.vue
================================================
{{$t('commonWalletHome.redeemCharge')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/CommonWallet/CommonTokenSwap.vue
================================================
{{$t('commonWalletHome.swapText')}}
{{$t('commonWalletHome.stepFollow')}}
{{$t('commonWalletHome.step1')}}
{{$t('commonWalletHome.step2')}}
{{$t('commonWalletHome.step3')}}
{{$t('commonWalletHome.swapAmount')}}
{{$t('commonWalletHome.nep5Balance')}}
{{nep5Ont}}
{{$t('commonWalletHome.password')}}
{{$t('commonWalletHome.cancel')}}
{{$t('commonWalletHome.swap')}}
================================================
FILE: src/components/CommonWallet/SendConfirm.vue
================================================
{{$t('sharedWalletHome.send')}}
{{$t('sharedWalletHome.amount')}}
{{transfer.amount}} {{transfer.asset}}
{{$t('sharedWalletHome.recipient')}}
{{transfer.to}}
{{$t('sharedWalletHome.fee')}}: {{transfer.gas}} ONG
{{$t('sharedWalletHome.confirmation')}}
{{$t('sharedWalletHome.agreeToSend')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
{{$t('sharedWalletHome.back')}}
{{$t('sharedWalletHome.submit')}}
================================================
FILE: src/components/CommonWallet/SendHome.vue
================================================
================================================
FILE: src/components/Dapps.vue
================================================
{{$t('exchange.changelly')}}
Cryptocurrency Exchange Platform
{{$t('exchange.cryptonex')}}
Buy Bitcoin, Ethereum, Cryptonex
Quick online purchase using a bank card
ONT ID
{{$t('dapps.ontidMgmt')}}
================================================
FILE: src/components/Dashboard.vue
================================================
{{$t('sharedWalletHome.address')}}: {{address}}
{{$t('sharedWalletHome.balance')}}
ONT
{{balance.ont}}
ONG
{{balance.ong}}
{{item.symbol}}
{{item.balance}}
{{tx.txHash.substring(0, 40) + '...'}}
{{tx.amount}} {{tx.asset}}
{{$t('sharedWalletHome.checkMore')}}
{{$t('redeemInfo.noClaimableOng')}}
================================================
FILE: src/components/Exchange/Changelly/Changelly.vue
================================================
================================================
FILE: src/components/Exchange/Cryptonex/Cryptonex.vue
================================================
================================================
FILE: src/components/Home.vue
================================================
OWallet
A comprehensive Ontology desktop wallet.
================================================
FILE: src/components/Identitys/Create/BasicInfo.vue
================================================
{{ errors.first('label') }}
{{ errors.first('password') }}
{{ errors.first('rePassword') }}
{{$t('createIdentity.selectWallet')}}
{{$t('createIdentity.commonWallet')}}
{{$t('createIdentity.ledgerWallet')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
{{$t('createIdentity.cancel')}}
{{$t('createIdentity.next')}}
================================================
FILE: src/components/Identitys/Create/ConfirmInfo.vue
================================================
{{$t('createIdentity.label')}}: {{label}}
{{$t('createIdentity.ontid')}}: {{ ontid }}
{{ $t('createJsonWallet.back') }}
{{ $t('createJsonWallet.next') }}
================================================
FILE: src/components/Identitys/CreateIdentity.vue
================================================
================================================
FILE: src/components/Identitys/IdentityView.vue
================================================
{{ $t('identitys.identity')}}
{{identity.label}}
{{$t('identitys.ontid')}} :
{{identity.ontid}}
Copied
{{$t('common.exportIdentity')}}
{{$t('common.deleteIdentity')}}
{{$t('common.more')}}
{{option==='EXPORT_ONTID' ? $t('wallets.exportOntid') : '' }}
{{identity.ontid}}
{{$t('common.enterIdentityPassword')}}
================================================
FILE: src/components/Identitys/Import/BasicInfo.vue
================================================
{{ errors.first('keystore') }}
{{ errors.first('keystorePassword') }}
{{$t('createIdentity.cancel')}}
{{$t('createIdentity.next')}}
================================================
FILE: src/components/Identitys/ImportIdentity.vue
================================================
================================================
FILE: src/components/Identitys.vue
================================================
{{$t('identitys.createIdentity')}}
{{$t('identitys.importIdentity')}}
================================================
FILE: src/components/JsonWallet/Create/BasicInfo.vue
================================================
{{ errors.first('label') }}
{{ errors.first('password') }}
{{ errors.first('rePassword') }}
{{$t('createJsonWallet.cancel')}}
{{$t('createJsonWallet.next')}}
================================================
FILE: src/components/JsonWallet/Create/ConfirmInfo.vue
================================================
{{$t('createJsonWallet.labelN')}}: {{label}}
{{$t('createJsonWallet.addressN')}}: {{ address }}
{{$t('createJsonWallet.pubKeyN')}}: {{publicKey}}
{{$t('createJsonWallet.signatureSchemeN')}}: SHA256withECDSA
{{$t('createJsonWallet.priavteKeywif')}}: {{wif}}
{{$t('createJsonWallet.backupWallet')}}
{{$t('createJsonWallet.download')}}
{{ $t('createJsonWallet.back') }}
{{ $t('createJsonWallet.next') }}
================================================
FILE: src/components/JsonWallet/CreateJsonWallet.vue
================================================
================================================
FILE: src/components/JsonWallet/Import/BasicInfo.vue
================================================
{{ errors.first('wifLabel') }}
{{ errors.first('wif') }}
{{ errors.first('wifPassword') }}
{{ errors.first('wifRePassword')
}}
{{ errors.first('pk') }}
{{ errors.first('pkPassword') }}
{{ errors.first('pkRePassword')
}}
{{ errors.first('mnemonic') }}
{{ errors.first('mnemonicPassword')
}}
{{
errors.first('mnemonicRePassword') }}
{{ $t('importJsonWallet.confirmImportExist') }}
{{ $t('importJsonWallet.cancel') }}
{{ $t('importJsonWallet.next') }}
================================================
FILE: src/components/JsonWallet/ImportJsonWallet.vue
================================================
================================================
FILE: src/components/JsonWallet/View/Details.vue
================================================
{{ isCommonWallet ? $t('common.normalWallet') : $t('common.hardwareWallet') }}
{{$t('common.neoCompatible')}}
{{wallet.label}}
{{$t('common.walletAddress')}}:
{{wallet.address}}
Copied
{{$t('common.exportDat')}}
{{$t('common.exportWIF')}}
{{$t('common.changePassword')}}
{{$t('common.deleteWallet')}}
{{$t('common.more')}}
{{option==='TO_DELETE' ? $t('wallets.deleteingWallet') : '' }}
{{option === 'TO_EXPORT' ? $t('wallets.exportingWallet') : ''}}
{{option === 'EXPORT_WIF' ? $t('wallets.exportingWIF') : ''}}
{{wallet.address}}
{{$t('common.enterWalletPassword')}}
{{$t('common.changePassSuccessTip')}}
{{$t('common.download')}}
================================================
FILE: src/components/LedgerWallet/Import/BasicInfo.vue
================================================
{{ $t("ledgerWallet.info") }}
{{ $t("ledgerWallet.selectAccount") }}
{{ `${pk.acct}. ${getAddressFromPubKey(pk.publicKey)}` }}
{{ $t('ledgerWallet.specifyPath') }}
44'/1024'/0'/0/
44'/888'/0'/0/
{{ getAddressFromPubKey(advancedModePublicKey.publicKey) }}
{{ $t('ledgerWallet.advancedMode')
}}
{{ $t('ledgerWallet.normalMode')
}}
{{
$t("importJsonWallet.cancel")
}}
{{
$t("importLedgerWallet.next")
}}
================================================
FILE: src/components/LedgerWallet/Import/ConnectLedger.vue
================================================
{{ $t("ledgerWallet.info") }}
{{ $t("ledgerWallet.connectApp") }}
{{ $t("ledgerWallet.status") }}:
{{ ledgerStatus }}
{{
$t("importJsonWallet.cancel")
}}
{{ $t("importLedgerWallet.next") }}
================================================
FILE: src/components/LedgerWallet/ImportLedgerWallet.vue
================================================
================================================
FILE: src/components/LedgerWallet/LoginLedger.vue
================================================
Back
Login with Ledger
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/Modals/Loading.vue
================================================
================================================
FILE: src/components/Modals/SetPath.vue
================================================
{{ $t('SetPaths.name') }}
{{ $t('SetPaths.tips') }}
================================================
FILE: src/components/Node/Node.vue
================================================
{{$t('vote.node')}}
{{$t('nodeMgmt.nodeStakeMgmt')}}
{{$t('nodeMgmt.nodeUser')}}
{{$t('nodeMgmt.stakeAuthorizaton')}}
{{$t('nodeMgmt.normalUser')}}
{{$t('vote.vote')}}
{{$t('vote.voteTip')}}
{{$t('nodeMgmt.newNodeApply')}}
{{$t('nodeMgmt.nodeApplyTip')}}
================================================
FILE: src/components/Node/NodeApply/Register.vue
================================================
{{$t('nodeApply.registerSuccess')}}
{{$t('nodeApply.completeNodeInfo')}}
{{$t('nodeApply.later')}}
================================================
FILE: src/components/Node/NodeApply/RegisterSuccess.vue
================================================
{{$t('nodeApply.registerSuccess')}}
{{$t('nodeApply.completeNodeInfo')}}
{{$t('nodeApply.later')}}
================================================
FILE: src/components/Node/NodeAuthorize/AuthorizationMgmt.vue
================================================
{{$t('nodeMgmt.nodeName')}}:
{{current_node.name}}
{{$t('nodeMgmt.walletAddress')}}:
{{stakeWallet.address}}
{{$t('nodeMgmt.newStakeAuthorization')}}
{{$t('nodeMgmt.inAuthorization')}}:
{{authorizationInfo.inAuthorization}} ONT
{{$t('nodeMgmt.getProfitPart')}}:
{{authorizationInfo.receiveProfitPortion}} ONT
{{$t('nodeMgmt.newStakePart')}}:
{{authorizationInfo.newStakePortion}} ONT
{{$t('nodeMgmt.authorizeTip')}}
{{$t('nodeMgmt.cancelAuthorization')}}
{{$t('nodeMgmt.locked')}}:
{{authorizationInfo.locked}} ONT
{{$t('nodeMgmt.claimable')}}:
{{authorizationInfo.claimable}} ONT
{{$t('nodeMgmt.redeem')}}
{{$t('nodeMgmt.unboundOng')}}:
{{unboundOng}} ONG
{{$t('nodeMgmt.rewards')}}
{{$t('nodeMgmt.profit')}}:
{{splitFee.amount}} ONG
{{$t('nodeMgmt.redeem')}}
{{$t('nodeMgmt.rewardTip')}}
{{$t('nodeMgmt.nodeName')}}:
{{current_node.name}}
{{$t('nodeMgmt.inAuthorization')}}:
{{authorizationInfo.inAuthorization}} ONT
{{$t('nodeMgmt.unitToCancel')}}:
{{$t('nodeMgmt.cancelUnits')}}
{{$t('nodeMgmt.amountToCancel')}}:
{{cancelAmount}} ONT
================================================
FILE: src/components/Node/NodeAuthorize/AuthorizeLogin.vue
================================================
{{$t('nodeStake.selectStakeWallet')}}
================================================
FILE: src/components/Node/NodeAuthorize/NewAuthorization.vue
================================================
{{$t('nodeMgmt.nodeName')}}:
{{current_node.name}}
{{$t('nodeMgmt.allowedStakeAmount')}}:
{{current_node.maxAuthorizeStr}} ONT
{{$t('nodeMgmt.totalStakeAmount')}}:
{{current_node.totalPosStr}} ONT
{{$t('nodeMgmt.walletAddress')}}:
{{stakeWallet.address}}
{{$t('nodeMgmt.units')}}:
{{$t('nodeMgmt.stakeAmountTip')}}
{{$t('nodeMgmt.stakeAmount')}}:
{{amount}} ONT
================================================
FILE: src/components/Node/NodeAuthorize/NodeList.vue
================================================
{{$t('nodeMgmt.stakeHistory')}}
{{$t('nodeMgmt.toNextRound')}}
{{countdown}}
{{$t('nodeMgmt.blocks')}}
{{$t('nodeMgmt.proportionNextRound')}}
{{record.nodeProportion}} / {{record.userProportion}}
{{text}}
================================================
FILE: src/components/Node/NodeAuthorize/Sesameseed/AuthorizationMgmtSesameseed.vue
================================================
{{$t('nodeMgmt.nodeName')}}:
Sesameseed
{{$t('nodeMgmt.walletAddress')}}:
{{stakeWallet.address}}
{{$t('nodeMgmt.newStakeAuthorization')}}
{{$t('nodeMgmt.inAuthorization')}}:
{{ssInfo.votes}} ONT
{{$t('sesameseed.authorizeTip')}}
{{$t('nodeMgmt.cancelAuthorization')}}
{{$t('sesameseed.pendingWithdrawals')}}:
{{ssInfo.pendingWithdrawals}} ONT
{{$t('nodeMgmt.nodeName')}}:
{{current_node.name}}
{{$t('nodeMgmt.inAuthorization')}}:
{{ssInfo.votes}} ONT
{{$t('nodeMgmt.unitToCancel')}}:
{{$t('nodeMgmt.cancelUnits')}}
{{$t('nodeMgmt.amountToCancel')}}:
{{cancelAmount}} ONT
================================================
FILE: src/components/Node/NodeAuthorize/Sesameseed/AuthorizeLoginSesameseed.vue
================================================
{{$t('nodeStake.selectStakeWallet')}}
{{$t('createIdentity.commonWallet')}}
{{$t('createIdentity.ledgerWallet')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/Node/NodeAuthorize/Sesameseed/NewAuthorizationSesameseed.vue
================================================
{{$t('nodeMgmt.nodeName')}}:
{{current_node.name}}
{{$t('nodeMgmt.allowedStakeAmount')}}:
{{current_node.maxAuthorizeStr}} ONT
{{$t('nodeMgmt.totalStakeAmount')}}:
{{current_node.totalPosStr}} ONT
{{$t('nodeMgmt.walletAddress')}}:
{{stakeWallet.address}}
{{$t('nodeMgmt.units')}}:
{{$t('sesameseed.stakeAmountTip')}}
{{$t('nodeMgmt.stakeAmount')}}:
{{amount}} ONT
================================================
FILE: src/components/Node/NodeAuthorize/Sesameseed/SesameseedVars.js
================================================
export const CONTRACT_HASH = 'a63c33d2209854feafbf40685a33d4846ee82556'
export const SESAMESEED_NODE_ADDRESS = 'ANRRE8xKwKzuaCeAjP6eZYDnVi7n2x6byE'
================================================
FILE: src/components/Node/NodeAuthorize/StakeHistory.vue
================================================
{{$t('nodeStake.selectStakeWallet')}}
{{$t('nodeStake.search')}}
================================================
FILE: src/components/Node/NodeManagement/MyNode.vue
================================================
{{item.name}}
{{$t('myNode.stakeWalletAddress')}}
{{item.stakeAddress}}
{{$t('myNode.operationWalletPk')}}
{{item.publicKey}}
{this.showCreate = true;}"
@mouseleave="()=>{this.showCreate = false;}">
{{$t('myNode.applyNode')}}
================================================
FILE: src/components/Node/NodeManagement/NodeStakeAuthorization.vue
================================================
{{$t('nodeMgmt.allowedStakeUnits')}}:
{{$t('nodeMgmt.allowedStakeAmount')}}:
{{unit*unitVal}} ONT
({{$t('nodeMgmt.current')}} {{peer_attrs.maxAuthorizeStr}} ONT)
{{$t('nodeMgmt.stakeAmountTip')}}
{{$t('nodeMgmt.confirm')}}
{{$t('nodeMgmt.yourStakeAmount')}}
{{initPosStr}} ONT
{{$t('nodeMgmt.stakeLimit')}}
{{maxStakeLimit}} ONT
{{$t('nodeMgmt.userStakeAmount')}}
{{current_peer.totalPosStr}} ONT
{{$t('nodeMgmt.rewardsTip')}}
{{$t('nodeMgmt.rewardProportion')}}
{{$t('nodeMgmt.nodeRewardProportion')}}
{{peer_attrs.tPeerCost}}% ({{$t('nodeMgmt.activeT')}})
{{peer_attrs.t1PeerCost}}% ({{$t('nodeMgmt.activeT1')}})
{{peer_attrs.t2PeerCost}}% ({{$t('nodeMgmt.activeT2')}})
{{$t('nodeMgmt.userRewardProportion')}}
{{peer_attrs.tStakeCost}}% ({{$t('nodeMgmt.activeT')}})
{{peer_attrs.t1StakeCost}}% ({{$t('nodeMgmt.activeT1')}})
{{peer_attrs.t2StakeCost}}% ({{$t('nodeMgmt.activeT2')}})
{{$t('nodeMgmt.edit')}}
{{$t('nodeMgmt.profit')}}:
{{splitFee.amount}} ONG
{{$t('nodeMgmt.redeem')}}
{{$t('nodeMgmt.unboundOng')}}:
{{peerUnboundOng}} ONG
{{$t('nodeMgmt.redeem')}}
{{$t('nodeMgmt.nodeRewardProportion')}}:
%
{{$t('nodeMgmt.userRewardProportion')}}:
%
{{$t('nodeMgmt.nodeRewardProportionTip')}}
{{$t('nodeMgmt.userRewardProportionTip')}}
{{$t('nodeMgmt.changesTakeEffect')}}
================================================
FILE: src/components/Node/NodeManagement/NodeStakeManagement.vue
================================================
================================================
FILE: src/components/Node/NodeStake/NodeInfo.vue
================================================
================================================
FILE: src/components/Node/NodeStake/NodeStakeInfo.vue
================================================
{{status1}}
{{status2}}
{{status3}}
{{$t('nodeStake.stakeWalletAddress')}}
{{detail.stakewalletaddress}}
{{$t('nodeStake.nodePk')}}
{{nodePublicKey}}
{{$t('nodeStake.contract')}}
{{detail.contract}}
{{$t('nodeStake.commitmentQuantity')}}
{{detail.commitmentquantity}}
{{$t('nodeStake.stakeQuantity')}}
{{current_peer.initPos}}
{{$t('nodeStake.claimableQuantity')}}
{{authorizationInfo.claimable}}
{{$t('nodeMgmt.addInitPos')}}
{{$t('nodeMgmt.reduceInitPos')}}
{this.redeemPosVisible = true;}">{{$t('nodeMgmt.redeemInitPos')}}
{{$t('nodeMgmt.amountToAdd')}}:
ONT
{{$t('nodeMgmt.amountToReduce')}}:
ONT
{{$t('nodeMgmt.initPosInLock')}}: {{authorizationInfo.locked}} ONT
{{$t('nodeMgmt.initPosRedeemable')}}: {{authorizationInfo.claimable}} ONT
{{$t('nodeStake.quitWarmMsg')}}
{{$t('nodeStake.enterWalletPass')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/Node/NodeStake/NodeStakeIntro.vue
================================================
{{$t('nodeStake.selectOntid')}}
{{$t('nodeStake.selectStakeWallet')}}
{{$t('createIdentity.commonWallet')}}
{{$t('createIdentity.ledgerWallet')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/Node/NodeStake/NodeStakeRegister.vue
================================================
{{$t('nodeStake.ontid')}}
{{detail.ontid}}
{{$t('nodeStake.stakeWalletAddress')}}
{{detail.stakewalletaddress}}
{{$t('nodeStake.nodePk')}}
{{detail.publickey}}
{{$t('nodeStake.contract')}}
{{detail.contract}}
{{$t('nodeStake.commitmentQuantity')}}
{{detail.commitmentquantity}}
{{$t('nodeStake.stakeQuantity')}}
{{$t('nodeStake.enterOntidPass')}}
{{$t('nodeStake.enterWalletPass')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/Node/Vote/Create.vue
================================================
{{$t('vote.votingStarts')}}
{{$t('vote.votingEnds')}}
{{ $t('vote.back') }}
{{ $t('vote.submit') }}
================================================
FILE: src/components/Node/Vote/Detail.vue
================================================
{{vote.title}}
{{vote.approves}}
votes
Vote Up
Voted +{{my_weight}}
{{vote.rejects}}
votes
Voted +{{my_weight}}
Vote Down
{{$t('vote.stopVote')}}
{{vote.content}}
{{$t('vote.info')}}
{{$t('vote.startTime')}}
{{formatTime(vote.startTime)}}
{{$t('vote.endTime')}}
{{formatTime(vote.endTime)}}
{{$t('vote.hash')}}
{{reverseHash(vote.hash)}}
{{$t('vote.creatorAddress')}}
{{vote.admin}}
{{$t('vote.votingStatus')}}
{{formatStatus(vote)}}
{{$t('vote.myVotes')}}
{{my_weight}}
================================================
FILE: src/components/Node/Vote/List.vue
================================================
{{item.title}}
{{$t('vote.duration')}}
{{formatDuration(item)}}
{{item.title}}
{{$t('vote.duration')}}
{{formatDuration(item)}}
================================================
FILE: src/components/Node/Vote/Login.vue
================================================
{{$t('vote.selectWallet')}}
{{$t('createIdentity.commonWallet')}}
{{$t('createIdentity.ledgerWallet')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
{{$t('vote.notSeeWallet')}}
{{$t('vote.importHere')}}
{{$t('nodeStake.next')}}
================================================
FILE: src/components/Node/Vote/index.vue
================================================
================================================
FILE: src/components/RedeemInfoIcon.vue
================================================
{{$t('redeemInfo.claimableOngName')}} {{$t('redeemInfo.claimableOng')}}
{{$t('redeemInfo.unboundOngName')}} {{$t('redeemInfo.unboundOng')}}
================================================
FILE: src/components/Setting.vue
================================================
================================================
FILE: src/components/SharedWallet/Create/BasicInfo.vue
================================================
{{$t('createSharedWallet.copayers2_12')}}
{{$t('createSharedWallet.invalidPk')}}
{{$t('createSharedWallet.add')}}
{{$t('createSharedWallet.cancel')}}
{{$t('createSharedWallet.next')}}
================================================
FILE: src/components/SharedWallet/Create/ConfirmSigNum.vue
================================================
{{label}}
{{$t('createSharedWallet.copayers')}}({{copayers.length}})
{{index+1}}
{{pk.name}}
{{pk.address}}
{{pk.publickey}}
{{$t('createSharedWallet.requiredSigNum')}}
{{$t('createSharedWallet.back')}}
{{$t('createSharedWallet.next')}}
================================================
FILE: src/components/SharedWallet/Create/CreateSuccess.vue
================================================
{{$t('createSharedWallet.label')}}: {{label}}
{{$t('createSharedWallet.address')}}: {{address}}
{{$t('createSharedWallet.next')}}
================================================
FILE: src/components/SharedWallet/CreateSharedWallet.vue
================================================
================================================
FILE: src/components/SharedWallet/Import/InputPass.vue
================================================
================================================
FILE: src/components/SharedWallet/Import/QuerySharedWallet.vue
================================================
================================================
FILE: src/components/SharedWallet/ImportSharedWallet.vue
================================================
================================================
FILE: src/components/SharedWallet/PAX/PaxMgmt.vue
================================================
{{$t('pax.toVarify')}}
{{$t('pax.toProcess')}}
{{$t('pax.selectedNum')}} {{selectedNum}}
{{$t('pax.totalAmount')}} {{totalAmount}}
{{$t('pax.failedTxhashes')}}
{{item.txhash}}
================================================
FILE: src/components/SharedWallet/PAX/SignProcess.vue
================================================
{{$t('sharedWalletHome.signSequence')}}
{{index+1}}
{{payer.name}}
{{payer.address}}
{{$t('pax.currentSign')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
{{$t('pax.ledgerSignMultiTimes')}}
{{$t('pax.back')}}
{{$t('pax.confirm')}}
{{$t('pax.txToSend')}} {{txToSend}}
{{$t('pax.txSent')}} {{txSent}}
================================================
FILE: src/components/SharedWallet/PAX/StartProcess.vue
================================================
{{$t('sharedWalletHome.dragDecide')}}
{{index+2}}
{{payer.name}}
{{payer.address}}
{{$t('pax.sponsorSign')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
{{$t('pax.ledgerSignMultiTimes')}}
{{$t('pax.back')}}
{{$t('pax.confirm')}}
================================================
FILE: src/components/SharedWallet/PendingTxHome.vue
================================================
================================================
FILE: src/components/SharedWallet/SharedWalletDetail.vue
================================================
================================================
FILE: src/components/SharedWallet/SharedWalletHome.vue
================================================
{{$t('sharedWalletHome.walletAddress')}}: {{this.sharedWallet.sharedWalletAddress}}
{{$t('sharedWalletHome.balance')}}
ONT
{{balance.ont}}
ONG
{{balance.ong}}
{{item.symbol}}
{{item.balance}}
{{tx.transactionidhash}}
{{tx.receiveaddress === sharedWallet.sharedWalletAddress ? '+' : '-'}}
{{tx.amount}} {{tx.assetName}}
{{tx.txHash.substring(0,40)+'...'}}
{{tx.amount}} {{tx.asset}}
{{$t('sharedWalletHome.checkMore')}}
{{$t('redeemInfo.noClaimableOng')}}
================================================
FILE: src/components/SharedWallet/SharedWalletSend.vue
================================================
================================================
FILE: src/components/SharedWallet/Transfer/InputPassword.vue
================================================
{{$t('sharedWalletHome.confirmation')}}
{{$t('sharedWalletHome.agreeToSend')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/SharedWallet/Transfer/PendingConfirm.vue
================================================
{{$t('sharedWalletHome.send')}}
{{$t('sharedWalletHome.redeemOng')}}
{{$t('sharedWalletHome.amount')}}
{{pendingTx.amount}} {{pendingTx.assetName}}
{{$t('sharedWalletHome.recipient')}}
{{pendingTx.receiveaddress}}
{{$t('sharedWalletHome.fee')}}: {{gas}} ONG
{{$t('sharedWalletHome.signSequence')}}
{{index+1}}
{{payer.name}}
{{payer.address}}
{{$t('sharedWalletHome.sign')}}
================================================
FILE: src/components/SharedWallet/Transfer/PendingTxSign.vue
================================================
{{$t('sharedWalletHome.confirmation')}}
{{$t('sharedWalletHome.agreeToSend')}}
{{$t('ledgerWallet.connectApp')}}
{{$t('ledgerWallet.status')}}:
{{ledgerStatus}}
================================================
FILE: src/components/SharedWallet/Transfer/SendAsset.vue
================================================
{{$t('sharedWalletHome.send')}}
ONT
ONG
{{oep4.symbol}}
Fee:
ONG
{{$t('sharedWalletHome.to')}}
================================================
FILE: src/components/SharedWallet/Transfer/SendConfirm.vue
================================================
{{$t('sharedWalletHome.redeemOng')}}
{{$t('sharedWalletHome.amount')}}
{{redeem.claimableOng}} ONG
{{$t('sharedWalletHome.fee')}}: 0.01 ONG
{{$t('sharedWalletHome.send')}}
{{$t('sharedWalletHome.amount')}}
{{transfer.amount}} {{transfer.asset}}
{{$t('sharedWalletHome.recipient')}}
{{transfer.to}}
{{$t('sharedWalletHome.fee')}}: {{transfer.gas}} ONG
{{$t('sharedWalletHome.dragDecide')}}
{{index+2}}
{{payer.name}}
{{payer.address}}
{{$t('sharedWalletHome.back')}}
{{$t('sharedWalletHome.next')}}
================================================
FILE: src/components/SharedWallet/Tx/SharedTxMgmt.vue
================================================
================================================
FILE: src/components/SharedWallet/Tx/SignSharedTx.vue
================================================
{{$t('sharedTx.addSign')}}
{{$t('sharedTx.currentSign')}}
{{$t('sharedTx.selectSigner')}}
{{$t('sharedTx.copy')}}
{{$t('sharedTx.send')}}
{{$t('sharedTx.txSerialized')}}
{{serializedTx}}
{{$t('sharedTx.isSendTxTip')}}
================================================
FILE: src/components/SharedWallet/Tx/StartSharedTx.vue
================================================
{{$t('sharedTx.createTx')}}
{{$t('sharedTx.starterSign')}}
{{$t('sharedTx.selectSponsor')}}
{{$t('sharedTx.copy')}}
{{$t('sharedTx.txSerialized')}}
{{serializedTx}}
================================================
FILE: src/components/SharedWallet/View/Details.vue
================================================
{{ $t('common.sharedWallet') }}
{{wallet.sharedWalletName}}
Wallet Address:
{{wallet.sharedWalletAddress}}
Copied
{{$t('wallets.deleteingWallet') }}
{{wallet.sharedWalletAddress}}
================================================
FILE: src/components/SharedWallet/View/SharedWalletCopayer.vue
================================================
{{sharedWallet.sharedWalletName}}
{{sharedWallet.sharedWalletAddress}}
{{$t('importSharedWallet.totalCopayerNumber')}}
{{sharedWallet.totalNumber}}
{{$t('importSharedWallet.requiredCopayerNumber')}}
{{sharedWallet.requiredNumber}}
{{index+1}}
{{pk.name}}
{{pk.address}}
================================================
FILE: src/components/TopLeftNav.vue
================================================
{{network}}
================================================
FILE: src/components/Wallets.vue
================================================
{{
$t('wallets.createCommonWallet') }}
{{
$t('wallets.importCommonWallet') }}
{{
$t('wallets.createSharedWallet') }}
{{
$t('wallets.joinSharedWallet') }}
{{ $t('wallets.ledgerHelpLink') }}
{{
$t('wallets.importLedgerWallet') }}
================================================
FILE: src/core/asyncHelper.js
================================================
export default function asyncWrap (promise) {
return promise.then(data => {
return [null, data]
}).catch(err => [err])
}
================================================
FILE: src/core/consts.js
================================================
// export const GAS_PRICE = '0';for test
export const GAS_PRICE = '500';
export const GAS_LIMIT = '20000';
export const ONT_CONTRACT = '0000000000000000000000000000000000000001';
export const TEST_NET = 'http://polaris1.ont.io';
export const MAIN_NET = 'http://dappnode1.ont.io';
export const TEST_NET_LIST = [
'http://polaris1.ont.io',
'http://polaris2.ont.io',
'http://polaris3.ont.io',
'http://polaris4.ont.io',
'http://polaris5.ont.io'
]
export const MAIN_NET_LIST = [
'http://dappnode1.ont.io',
'http://dappnode2.ont.io',
'http://dappnode3.ont.io',
'http://dappnode4.ont.io',
]
//test environment
export const ONT_PASS_NODE = 'https://service-test.onto.app'
//prod
export const ONT_PASS_NODE_PRD = 'https://service.onto.app'
export const ONT_PASS_URL = {
CreateSharedWallet: '/S5/api/v1/ontpass/SharedWallet/create',
QuerySharedWallet: '/S5/api/v1/ontpass/SharedWallet/getBySharedWalletAddress', //get
CreateSharedTransfer: '/S5/api/v1/ontpass/SharedTransfer/create',
SignSharedTransfer: '/S5/api/v1/ontpass/SharedTransfer/sign',
SendSharedTransfer: '/S5/api/v1/ontpass/SharedTransfer/isSendToChain', //get
QueryPendingTransfer: '/S5/api/v1/ontpass/SharedTransfer/listSigningBeforeTime',
// sharedAddress={sharedAddress}&assetName={assetName}&beforeTimeStamp={beforeTimeStamp},
ExchangeCurrency: '/S5/api/v1/ontpass/api/v1/onto/exchangerate/reckon/'
///api/v1/onto/exchangerate/reckon/{currency}/{goaltype}/{amount}
//for node stake
,
GetQualifiedState: '/S4/NodePledgeApi/v1/Nodepledge/getQuailifiedState',
// /NodePledgeApi/v1/Nodepledge/getQuailifiedState?ontid={ontid}&address={address}'
DelegateSendTx: '/S4/NodePledgeApi/v1/Nodepledge/delegateSendTransaction',
SetStakeInfo: '/S4/NodePledgeApi/v1/Nodepledge/setInfo',
GetStakeInfo: '/S4/NodePledgeApi/v1/Nodepledge/info',
// /NodePledgeApi/v1/Nodepledge/info?ontid={ontid}
GetVoteContract: '/S4/NodePledgeApi/v1/Nodepledge/vote-contract-address' // /{net_type}
}
export const WALLET_TYPE = {
CommonWallet: 'CommonWallet',
SharedWallet: 'SharedWallet',
HardwareWallet: 'HardwareWallet'
}
export const DEFAULT_SCRYPT = {
cost: 16384, // 除以2时间减半
blockSize: 8,
parallel: 8,
size: 64
};
export const SWAP_ADDRESS = 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM'
export const NODE_DETAIL = 'https://explorer.ont.io/nodes/detail/'
export const NODE_NAME_LIST = 'https://ont.io/api/v1/candidate/info/All'
export const OFF_CHAIN_NODES = {
TEST_NET: 'https://polarisexplorer.ont.io/v2/nodes/off-chain-infos',
MAIN_NET: 'https://explorer.ont.io/v2/nodes/off-chain-infos'
}
export const QUERY_NODE_INFO_API = {
TEST_NET: 'https://polarisexplorer.ont.io/v2/nodes/off-chain-info/public',
// TEST_NET: 'http://18.136.65.213:8585/v2/nodes/off-chain-info',
MAIN_NET: 'https://explorer.ont.io/v2/nodes/off-chain-info/public'
}
export const UPDATE_NODE_INFO_API = {
TEST_NET: 'https://polarisexplorer.ont.io/v2/offchain/off-chain-info',
// TEST_NET: 'http://18.136.65.213:8585/v2/nodes/off-chain-info',
MAIN_NET: 'https://explorer.ont.io/v2/offchain/off-chain-info'
}
export const UPDATE_LEDGER_NODE_INFO_API = {
TEST_NET: 'https://polarisexplorer.ont.io/v2/offchain/off-chain-info/ledger',
// TEST_NET: 'http://18.136.65.213:8585/v2/nodes/off-chain-info',
MAIN_NET: 'https://explorer.ont.io/v2/offchain/off-chain-info/ledger'
}
export const NODE_CURRENT_STAKES = {
TEST_NET: 'https://polarisexplorer.ont.io/v2/nodes/current-stakes',
MAIN_NET: 'https://explorer.ont.io/v2/nodes/current-stakes'
}
export const PAX_API = {
Host: 'http://18.138.83.180:20800',
// TestHost: 'http://172.168.3.61:20800',
TestHost: 'http://18.139.19.52:20800',
fetchApprovalList: '/api/v1/approvals',
updateApprovals: '/api/v1/processapplist',
validateTx: '/api/v1/validatetx',
EthScanTest: 'https://ropsten.etherscan.io/tx/',
EthScanMain: 'https://etherscan.io/tx/'
}
export const PAX_SC_HASH = {
MAIN: '6bbc07bae862db0d7867e4e5b1a13c663e2b4bc8',
TEST: 'b06f8eaf757030c7a944ce2a072017bde1e72308'
}
export const VOTE_ROLE = {
ADMIN: 'ADMIN',
VOTER: 'VOTER',
VISITOR: 'VISITOR'
}
export const VALIDATE_DICTIONARY = {
zh: {
messages: {
required: (field, val) => `字段 ${field} 是必填项`,
min: (field, val) => `字段 ${field} 的长度不能少于${val[0]}`,
length: (field, val) => `字段 ${field} 的长度必须是${val[0]}`,
confirmed: (field, val) => `${field}的输入匹配错误`,
is: (field, val) => `${field}的输入匹配错误`
},
attributes: {
password: '密码',
name: '名称',
label: '名称',
rePassword: '确认密码',
keystore: 'keystore',
keystorePassword: ''
}
},
en: {
messages: {
required: (field, val) => `${field} is required`,
min: (field, val) => `The length of ${field} must be larger than ${val[0]}`,
length: (field, val) => `The length of ${field} must be ${val[0]}`,
confirmed: (field, val) => `Those two inputs didn't match.`,
is: (field, val) => `Those two inputs didn't match.`
},
attributes: {
password: 'Password',
name: 'Name',
label: 'Label',
rePassword: 'Confirm password',
keystore: 'keystore',
keystorePassword: ''
}
}
}
//申请注册 候选 共识 共识退出 候选退出 拉黑 已退出
export const GovernanceStatus = {
REGISTER: 0,
CANDIDATE: 1,
CONSENSUS: 2,
QUIT_CANDIDATE: 3,
QUIT_CONSENSUS: 4,
BLACKLIST: 5,
EXIXTED: 6
}
================================================
FILE: src/core/dbService.js
================================================
// import path, { resolve } from 'path'
import electron from 'electron'
// const app = electron.remote.app;
import { app } from '@electron/remote';
const userData = app.getPath('userData')
console.log('appPath: ' + userData)
if(!localStorage.getItem('savePath')) {
localStorage.setItem('savePath', userData)
}
//create db
var Datastore = require('nedb');
const savePath = localStorage.getItem('savePath')
const db = new Datastore({filename: savePath + '/keystore.db', autoload:true});
//indexing
db.ensureIndex({fieldName: 'address', unique: true}, function(err) {
console.log(err)
if (err && err.code === 'ENOENT') {
localStorage.setItem('savePath', userData);
alert('Cannot find the keystore.db file. Please set the keystore.db file path.');
}
});
db.loadDatabase();
const dbFind = (db, opt) => {
return new Promise((resolve, reject) => {
db.find(opt, function(err, docs) {
if (err) {
reject(err)
} else {
resolve(docs)
}
})
})
}
const dbInsert = (db, doc) => {
return new Promise((resolve, reject) => {
db.insert(doc, function(err, newDoc) {
if(err) {
reject(err)
} else {
resolve(newDoc)
}
})
})
}
const dbUpsert = (db, index ,doc) => {
return new Promise((resolve, reject) => {
db.update({[index] : doc.indexKey}, doc, {upsert: true}, function(err, numReplaced, upsert) {
if(err) {
reject(err)
} else {
resolve(upsert)
}
})
})
}
export default db;
export {dbFind, dbUpsert};
================================================
FILE: src/core/fileHelper.js
================================================
export default {
downloadFile(json, fileName) {
let content = new Blob([JSON.stringify(json)], { type: "text/plain;charset=utf-8" })
let urlObject = window.URL || window.webkitURL || window
let url = urlObject.createObjectURL(content)
let el = document.createElement('a')
el.href = url
el.download = fileName? `${fileName}.dat` : "wallet.dat"
document.body.appendChild(el)
el.click()
urlObject.revokeObjectURL(url)
},
readWalletFile($file) {
return new Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function (params) {
resolve(reader.result)
}
reader.onerror = reject
reader.readAsText($file)
})
}
}
================================================
FILE: src/core/lang.js
================================================
export default {
setLang(lang) {
window.localStorage.setItem('user_lang', lang)
},
getLang(defaultLang) {
let localLang = window.localStorage.getItem('user_lang') || 'en'
if (localLang === null) {
return defaultLang
} else {
return localLang
}
}
}
================================================
FILE: src/core/network.js
================================================
import {WebsocketClient} from 'ontology-ts-sdk';
import store from '../store'
import { MAIN_NET_LIST, TEST_NET_LIST } from './consts'
let client;
let net = localStorage.getItem('net'); // 'TEST_NET' or 'MAIN_NET'
if(!net) {
net = 'MAIN_NET'
localStorage.setItem('net', net)
}
let node = localStorage.getItem('nodeAddress')
if(!node) {
node = MAIN_NET_LIST[0]
localStorage.setItem('nodeAddress', node)
}
const WS_PORT = '20335'
export function initNetwork() {
reconnect()
window.setInterval(async () => {
try {
await client.sendHeartBeat();
store.commit('NETWORK_CONNECTED')
} catch (e) {
if (net) {
reconnect();
}
store.commit('NETWORK_DISCONNECTED');
}
}, 5000);
}
function reconnect() {
if (client !== undefined) {
try {
client.close();
} catch (e) {
// ignored
}
}
const url = `${node}:${WS_PORT}`;
client = new WebsocketClient(url, false, false);
}
export function getClient() {
return client;
}
================================================
FILE: src/core/nodes.json
================================================
[
{
"name": "Dubhe",
"pk": "02bcdd278a27e4969d48de95d6b7b086b65b8d1d4ff6509e7a9eab364a76115af7",
"isConsensus": true
},
{
"name": "Merak",
"pk": "0251f06bc247b1da94ec7d9fe25f5f913cedaecba8524140353b826cf9b1cbd9f4",
"isConsensus": true
},
{
"name": "Phecda",
"pk": "022e911fb5a20b4b2e4f917f10eb92f27d17cad16b916bce8fd2dd8c11ac2878c0",
"isConsensus": true
},
{
"name": "Megrez",
"pk": "0253719ac66d7cafa1fe49a64f73bd864a346da92d908c19577a003a8a4160b7fa",
"isConsensus": true
},
{
"name": "Alioth",
"pk": "022bf80145bd448d993abffa237f4cd06d9df13eaad37afce5cb71d80c47b03feb",
"isConsensus": true
},
{
"name": "Mixar",
"pk": "02765d98bb092962734e365bd436bdc80c5b5991dcf22b28dbb02d3b3cf74d6444",
"isConsensus": true
},
{
"name": "Alkaid",
"pk": "03c8f63775536eb420c96228cdccc9de7d80e87f1b562a6eb93c0838064350aa53",
"isConsensus": true
},
{
"name": "Jumple Foundation",
"pk": "038602b1b03637be0de5305639756db44da31b5241acde4cff86f2a181f76d9fee",
"isConsensus": false
},
{
"name": "Hashed",
"pk": "03ee9fd0557e56dab1eb7d9720e749d581fb0ebfd0a15f31bc973834c36e0b9c46",
"isConsensus": false
},
{
"name": "Infinity Stones",
"pk": "0244c959ed3bcd0f96da35d4c615bcf99c8a2d7ddb875142fa8f731bbf681eee44",
"isConsensus": false
},
{
"name": "ONEROOT Foundation",
"pk": "025222dc49b168d47c12a77aa9ae3370f6319cfe97eab4f92b0e7f61597ebcc158",
"isConsensus": false
},
{
"name": "Martview",
"pk": "03a0cf8494ef9901c7a78df98abb9a8a245961da77c157cb3f31e67db0325f070c",
"isConsensus": false
},
{
"name": "DAD",
"pk": "02872b863b9bee7a1bd15692330af591603bc3db3444272c00e51997a74ac1756c",
"isConsensus": false
},
{
"name": "SunStar",
"pk": "02584b9aa8d871017ff7d19fb8c7c934eeffbdc6b7de5501855e11c65ffbb67774",
"isConsensus": false
},
{
"name": "G&Q TECH LIMITED",
"pk": "036f29e06e57f36432ad6bb89dbfd8f81d12e42e7a1a5d454c322ac8e3b94a4bf0",
"isConsensus": false
},
{
"name": "InWeCrypto",
"pk": "026dd0e7b95843181e0f986ecb292f32a2165261ca62d097bba8c54195d527f73f",
"isConsensus": false
},
{
"name": "gf.network",
"pk": "031554b64b4145fb33e83f686081e9148188c2176aaf6a55c874b38fd093e1bc0c",
"isConsensus": false
},
{
"name": "J&D TECH LIMITED",
"pk": "033ad721e2443998bc036710b0415ac6ae67e2d490307ba9f4f8f41af62726f34d",
"isConsensus": false
},
{
"name": "ont-huobipool",
"pk": "03c793b05687137803952cb0327aaed8cfb1a7199badd23a34b2fa8417f614faae",
"isConsensus": false
},
{
"name": "Accomplice",
"pk": "034a7069c3ba649a762191b62e29992f6b4ba4b670d6502259e15597199cea17d2",
"isConsensus": false
},
{
"name": "Matrix Partners China",
"pk": "035e470667371300f87090c3410cfbb24a4b40c6955574ed7dd053644f94922632",
"isConsensus": false
},
{
"name": "CloudDesk",
"pk": "0349a0e3e018d275a09bb6d4237cb95ee199cf38c81c9a1228ecb72f2c6ab8fdfe",
"isConsensus": false
},
{
"name": "Collider",
"pk": "02da86115d1c2450eb5780da3ffd21c0e68c9094f990f3c7c489e0c5d50b72ec43",
"isConsensus": false
},
{
"name": "CertiK",
"pk": "02b9000043dba3a3c91185a963babbb975daf73ebfc4f07ab7cb80dc7172145c3d",
"isConsensus": false
},
{
"name": "Avocado",
"pk": "034b87ac6f457e44a33284fcd60d2b2f6ea2a508e553462bba5bf526a0dd285300",
"isConsensus": false
},
{
"name": "Ontology Universe",
"pk": "02a0ca41d2544cdea25fe98102157ea9ca051ac1e565e43847c3f006c9caedc297",
"isConsensus": false
},
{
"name": "ONTLabo",
"pk": "037acf1bb88200138b44f5d645d0e0c063043addc30db0102eea508db2585f9171",
"isConsensus": false
},
{
"name": "Blockchain Global Limited",
"pk": "03e96d1b80bfa4895763d640e6278c3e31323ba395cb32c9c578d54374e092e134",
"isConsensus": false
},
{
"name": "HZF Web",
"pk": "0292c695bb734f849d17ee65977d048ff8a9efae8317ee40589a944eb2bbcd9998",
"isConsensus": false
},
{
"name": "Crypto World",
"pk": "0280d0bfde8e6b73e48c15ee062728f890e41f125339d5f36ed8a29430d41c6d57",
"isConsensus": false
},
{
"name": "Points Foundation",
"pk": "035960c0a6b07532e149fd8e92d19f4670732735df5c0a419a9d79c1a06df8fc23",
"isConsensus": false
},
{
"name": "Trio Bravo",
"pk": "0287fe995c6f27ad0c1a7640f9cc6c2537ed47126cc430e738d96f0390583ac2d2",
"isConsensus": false
}
]
================================================
FILE: src/core/ontLedger.js
================================================
import LedgerNode from '@ledgerhq/hw-transport-node-hid'
import asyncWrap from './asyncHelper'
import { utils, Crypto } from 'ontology-ts-sdk'
import * as elliptic from 'elliptic';
import {message} from 'ant-design-vue'
import i18n from '../lang'
import OntLedgerNew from './ontLedgerNew'
const VALID_STATUS = 0x9000
const MSG_TOO_BIG = 0x6d08
const APP_CLOSED = 0x6e00
const TX_DENIED = 0x6985
const TX_PARSE_ERR = 0x6d07
/**
* Evaluates Transport Error thrown and rewrite the error message to be more user friendly.
* @param {Error} err
* @return {Error}
*/
const evalTransportError = err => {
switch (err.statusCode) {
case APP_CLOSED:
err.message = 'Your ONT app is closed! Please login.'
break
case MSG_TOO_BIG:
err.message = 'Your transaction is too big for the ledger to sign!'
break
case TX_DENIED:
err.message = 'You have denied the transaction on your ledger.'
break
case TX_PARSE_ERR:
err.message = 'Error parsing transaction. Make sure your ONT app version is up to date.'
break
}
return err
}
const BIP44 = (acct = 0, neo = false, usePath = false) => {
const acctNumber = acct.toString(16)
if (usePath) {
const coinType = neo ? 888 : 1024; // NEO 或 ONT 的币种类型
return `44'/${coinType}'/0'/0/${acct}`;
}
const coinType = neo ? '80000378' : '80000400';
return (
'8000002C' +
coinType +
'80000000' +
'00000000' +
'0'.repeat(8 - acctNumber.length) +
acctNumber
)
}
export default class OntLedger {
path;
device;
constructor(path) {
this.path = path
}
/**
* Initialises by listing devices and trying to find a ledger device connected. Throws an error if no ledgers detected or unable to connect.
* @return {Promise}
*/
static async init() {
const supported = await LedgerNode.isSupported()
// if (!supported) { throw new Error(`Your computer does not support the ledger!`) }
if (!supported) { throw 'NOT_SUPPORT' }
const paths = await OntLedger.list()
// if (paths.length === 0) throw new Error('USB Error: No device found.')
if (paths.length === 0) throw 'NOT_FOUND'
const ledger = new OntLedger(paths[0])
return ledger.open()
}
static async list() {
return LedgerNode.list()
}
/**
* Opens an connection with the selected ledger.
* @return {Promise}this
*/
async open() {
try {
this.device = await LedgerNode.open(this.path)
return this
} catch (err) {
throw evalTransportError(err)
}
}
/**
* Closes the connection between the Ledger and the wallet.
* @return {Promise}}
*/
close() {
if (this.device) return this.device.close()
return Promise.resolve()
}
/**
* Retrieves the public key of an account from the Ledger.
* @param {number} [acct] - Account that you want to retrieve the public key from.
* @return {string} Public Key (Unencoded)
*/
async getPublicKey(acct = 0, neo) {
const ledger = new OntLedgerNew(this.device)
const uncompressed = await ledger.getPublicKey(BIP44(acct, neo, true))
// const res = await this.send('80040000', BIP44(acct, neo), [VALID_STATUS])
// const uncompressed = res.toString('hex').substring(0, 130)
const ec = new elliptic.ec(Crypto.CurveLabel.SECP256R1.preset);
const keyPair = ec.keyFromPublic(uncompressed, 'hex');
const compressed = keyPair.getPublic(true, 'hex');
console.log("compressed", compressed);
return compressed;
}
getDeviceInfo() {
try {
return this.device.device.getDeviceInfo()
} catch (err) {
throw evalTransportError(err)
}
}
/**
* Sends an message with params over to the Ledger.
* @param {string} params - params as a hexstring
* @param {string} msg - Message as a hexstring
* @param {number[]} statusList - Statuses to return
* @return {Promise} return value decoded to ASCII string
*/
async send(params, msg, statusList) {
if (params.length !== 8) throw new Error(`params requires 4 bytes`)
// $FlowFixMe
const [cla, ins, p1, p2] = params
.match(/.{1,2}/g)
.map(i => parseInt(i, 16))
try {
return await this.device.send(
cla,
ins,
p1,
p2,
Buffer.from(msg, 'hex'),
statusList
)
} catch (err) {
throw evalTransportError(err)
}
}
/**
* Gets the ECDH signature of the data from Ledger using acct
* @param {string} data
* @param {number} [acct]
* @return {Promise}
*/
async getSignature(data, acct = 0, neo = false) {
const ledger = new OntLedgerNew(this.device)
const res = await ledger.signMessage(BIP44(acct, neo, true), data)
return res;
// old logic
// data += BIP44(acct, neo)
// let response = null
// const chunks = data.match(/.{1,510}/g) || [];
// if (!chunks.length) throw new Error(`Invalid data provided: ${data}`)
// for (let i = 0; i < chunks.length; i++) {
// const p = i === chunks.length - 1 ? '80' : '00'
// // $FlowFixMe
// const chunk = chunks[i]
// const params = `8002${p}00`
// let [err, res] = await asyncWrap(
// this.send(params, chunk, [VALID_STATUS])
// )
// if (err) throw evalTransportError(err)
// response = res
// }
// if (response === 0x9000) {
// throw new Error(`No more data but Ledger did not return signature!`)
// }
// // $FlowFixMe
// return assembleSignature(response.toString('hex'))
}
}
/**
* The signature is returned from the ledger in a DER format
* @param {string} response - Signature in DER format
*/
const assembleSignature = (response) => {
let ss = new utils.StringReader(response)
// The first byte is format. It is usually 0x30 (SEQ) or 0x31 (SET)
// The second byte represents the total length of the DER module.
ss.read(2)
// Now we read each field off
// Each field is encoded with a type byte, length byte followed by the data itself
ss.read(1) // Read and drop the type
const r = ss.readNextBytes()
ss.read(1)
const s = ss.readNextBytes()
// We will need to ensure both integers are 32 bytes long
const integers = [r, s].map(i => {
if (i.length < 64) {
i = i.padStart(64, '0')
}
if (i.length > 64) {
i = i.substr(-64)
}
return i
})
return integers.join('')
}
export const getPublicKey = async (acct = 0, neo = false) => {
const ledger = await OntLedger.init()
try {
return await ledger.getPublicKey(acct, neo)
}
catch (err) {
return Promise.reject(err)
}
finally {
await ledger.close()
}
}
export const getDeviceInfo = async () => {
const ledger = await OntLedger.init()
try {
return await ledger.getDeviceInfo()
} finally {
await ledger.close()
}
}
export const legacySignWithLedger = async (unsignedTx, neo = false, acct = 0) => {
const ledger = await OntLedger.init()
try {
const signData = await ledger.getSignature(unsignedTx, acct, neo)
return signData;
} catch (err) {
return Promise.reject(err)
}
finally {
await ledger.close()
}
}
export const checkPublicKeyIsInTheConnectedLedger = async (acct = 0, neo = false, publicKey) => {
try {
// 当前连接的Ledger需要和之前导入钱包的Ledger是同一个
const pk = await getPublicKey(acct, neo);
const isCorrect = pk === publicKey;
if (!isCorrect) {
throw i18n.t('common.invalidLedger');
}
return true;
} catch (err) {
console.error(err);
message.warning(err?.message || err);
throw err;
}
}
================================================
FILE: src/core/ontLedgerNew.js
================================================
import { convertPathToBuffer } from "./utils";
import i18n from '../lang'
const STATUS_CODES = {
SW_DENY: 0x6985,
SW_WRONG_P1P2: 0x6a86,
SW_WRONG_DATA_LENGTH: 0x6a87,
SW_INS_NOT_SUPPORTED: 0x6d00,
SW_CLA_NOT_SUPPORTED: 0x6e00,
SW_WRONG_RESPONSE_LENGTH: 0xb000,
SW_DISPLAY_BIP32_PATH_FAIL: 0xb001,
SW_DISPLAY_ADDRESS_FAIL: 0xb002,
SW_DISPLAY_AMOUNT_FAIL: 0xb003,
SW_WRONG_TX_LENGTH: 0xb004,
SW_TX_PARSING_FAIL: 0xb005,
SW_TX_HASH_FAIL: 0xb006,
SW_BAD_STATE: 0xb007,
SW_SIGNATURE_FAIL: 0xb008,
SW_PERSON_MSG_PARSING_FAIL: 0xb009,
SW_PERSON_MSG_HASH_FAIL: 0xb00a,
SW_WRONG_PERSON_MSG_LENGTH: 0xb00b,
SW_TX_PAYLOAD_PARSING_FAIL: 0xb00c,
SW_OEP4_TX_PARSING_FAIL: 0xb00d,
SW_OEP4_TX_PAYLOAD_PARSING_FAIL: 0xb00e,
OK: 0x9000,
};
const MAX_PAYLOAD = 255;
const LEDGER_CLA = 0x80;
const P1_NON_CONFIRM = 0x00;
const P1_CONFIRM = 0x01;
const P2_MORE = 0x80;
const P2_EXTEND = 0x00;
const INS = {
GET_VERSION: 0x03,
GET_ADDR: 0x04,
SIGN: 0x02,
SIGN_OFFCHAIN: 0x07,
};
class OntLedgerNew {
constructor(transport, scrambleKey = "ONT") {
this.transport = transport;
transport.decorateAppAPIMethods(
this,
["getPublicKey", "signMessage", "signOffchainMessage"],
scrambleKey
);
}
async #sendToDevice(path, instruction, msgBuffer) {
console.log("sendToDevice");
console.log(path, instruction, msgBuffer);
const checkedVersion = await this.checkVersion();
if (!checkedVersion) {
throw new Error("Unsupported app version");
}
try {
const acceptStatusList = [STATUS_CODES.OK];
const pathBuffer = this.pathToBuffer(path);
// const msgBuffer = Buffer.from(msg, "hex");
let custom_p1 = 0x00;
const firstReply = await this.transport.send(
LEDGER_CLA,
instruction,
custom_p1,
P2_MORE,
pathBuffer,
acceptStatusList
);
console.log("firstReply", firstReply);
custom_p1++;
if (msgBuffer.length > MAX_PAYLOAD) {
while (msgBuffer.length - (custom_p1 - 1) * MAX_PAYLOAD > MAX_PAYLOAD) {
const buf = msgBuffer.slice(
(custom_p1 - 1) * MAX_PAYLOAD,
custom_p1 * MAX_PAYLOAD
);
await this.transport.send(
LEDGER_CLA,
instruction,
custom_p1,
P2_MORE,
buf,
acceptStatusList
);
custom_p1++;
}
}
const lastBuf = msgBuffer.slice((custom_p1 - 1) * MAX_PAYLOAD);
const reply = await this.transport.send(
LEDGER_CLA,
instruction,
custom_p1,
P2_EXTEND,
lastBuf,
[STATUS_CODES.OK]
);
return reply;
} catch (error) {
throw this._convertTransportError(error);
}
}
pathToBuffer(path) {
const PATH_REGEX = /^(\d+'?(\/\d+'?)*)$/;
if (!PATH_REGEX.test(path.trim())) {
throw new Error("Invalid path format");
}
const segments = path
.replace(/^m\//, "") // delete "m/"
.split("/")
.map((segment) => {
if (segment.endsWith("'")) {
return (parseInt(segment.slice(0, -1), 10) | 0x80000000) >>> 0;
} else {
return parseInt(segment, 10) >>> 0;
}
});
const length = segments.length;
const uint8Array = new Uint8Array(1 + length * 4);
uint8Array[0] = length;
segments.forEach((value, index) => {
const offset = 1 + index * 4;
uint8Array[offset] = (value >> 24) & 0xff;
uint8Array[offset + 1] = (value >> 16) & 0xff;
uint8Array[offset + 2] = (value >> 8) & 0xff;
uint8Array[offset + 3] = value & 0xff;
});
return uint8Array;
}
getSignFromRelay(reply) {
const dataLength = reply[0];
const dataBuf = reply.slice(1, dataLength + 1);
let r_length = dataBuf[3];
let r = dataBuf.slice(4, 4 + r_length);
if (r_length === 33 && r[0] === 0) {
r = r.slice(1);
}
let s_length = dataBuf[r_length + 5];
let s = dataBuf.slice(r_length + 6);
if (s_length === 33 && s[0] === 0) {
s = s.slice(1);
}
const sign = Buffer.concat([r, s]).toString("hex");
return sign;
}
async getVersion() {
try {
const result = await this.transport.send(
LEDGER_CLA,
INS.GET_VERSION,
P1_NON_CONFIRM,
P2_EXTEND,
Buffer.alloc(0),
[STATUS_CODES.OK]
);
return result;
} catch (error) {
if (error.statusCode === STATUS_CODES.SW_INS_NOT_SUPPORTED) {
return "0000009000";
}
throw this._convertTransportError(error);
}
}
/**
* Checks if the version meets the required criteria.·
* This function retrieves the version, converts it to a hexadecimal string,
* and checks if the first two characters represent a number greater than or equal to 2.
*
* @returns {Promise} - A Promise that resolves to a boolean indicating
* whether the version is greater than or equal to 2.
*/
async checkVersion() {
const versionReply = await this.getVersion();
const versionString = versionReply.toString("hex");
console.log("versionString", versionString);
const first = versionString.slice(0, 2);
if (Number(first) >= 2) {
return true;
}
return false;
}
async getPublicKey(path, showAddress = false) {
try {
const checkedVersion = await this.checkVersion();
console.log("checkedVersion", checkedVersion);
if (!checkedVersion) {
let pathBuffer = convertPathToBuffer(path);
const result = await this.transport.send(
LEDGER_CLA,
INS.GET_ADDR,
showAddress ? P1_CONFIRM : P1_NON_CONFIRM,
P2_EXTEND,
pathBuffer,
[STATUS_CODES.OK]
);
return result.toString("hex").substring(0, 130);
} else {
const pathBuffer = this.pathToBuffer(path);
let result = await this.transport.send(
LEDGER_CLA,
INS.GET_ADDR,
showAddress ? P1_CONFIRM : P1_NON_CONFIRM,
P2_EXTEND,
pathBuffer,
[STATUS_CODES.OK]
);
result = result.slice(1, result[0] + 1);
return result.toString("hex");
}
} catch (error) {
console.log(error);
throw this._convertTransportError(error);
}
}
async signMessage(path, msg) {
const checkedVersion = await this.checkVersion();
console.log("checkedVersion", checkedVersion);
if (!checkedVersion) {
const pathBuffer = convertPathToBuffer(path);
const data = msg + pathBuffer.toString("hex");
const chunks = data.match(/.{1,500}/g) || [];
if (chunks.length === 0) {
throw new Error(`Invalid data provided: ${data}`);
}
let result = null;
for (let i = 0; i < chunks.length; i++) {
const p1 = i === chunks.length - 1 ? 0x80 : 0x00;
const chunk = Buffer.from(chunks[i], "hex");
result = await this.transport.send(0x80, 0x02, p1, 0x00, chunk, [
STATUS_CODES.OK,
]);
}
const dataLength = result[1];
const dataBuf = result.slice(2, dataLength + 2);
const r_length = dataBuf[1];
let r = dataBuf.slice(2, 2 + r_length);
if (r_length === 33 && r[0] === 0) {
r = r.slice(1);
}
let s = dataBuf.slice(r_length + 4);
if (s.length === 33 && s[0] === 0) {
s = s.slice(1);
}
const sign = Buffer.concat([r, s]).toString("hex");
return sign;
}
const msgBuffer = Buffer.from(msg, "hex");
const reply = await this.#sendToDevice(path, INS.SIGN, msgBuffer);
if (reply <= 2) {
throw new Error("No more data but Ledger did not return signature!");
}
console.log("reply", reply.toString("hex"));
const sign = this.getSignFromRelay(reply);
return sign;
}
async signOffchainMessage(path, msg) {
const checkedVersion = await this.checkVersion();
if (!checkedVersion) {
throw new Error("Unsupported app version");
}
const msgBuffer = Buffer.from(msg, "hex");
const relay = await this.#sendToDevice(path, INS.SIGN_OFFCHAIN, msgBuffer);
const sign = this.getSignFromRelay(relay);
return sign;
}
_convertTransportError(error) {
switch (error.statusCode) {
case STATUS_CODES.SW_DENY:
error.message = i18n.t("common.rejectedByUser");
break;
default:
error.message = `${i18n.t("common.transactionFailed")}: 0x${error.statusCode?.toString(16)?.toUpperCase()}`;
break;
}
return error;
}
}
export default OntLedgerNew;
================================================
FILE: src/core/runtime.js
================================================
import {get} from 'lodash'
import {
Crypto
} from 'ontology-ts-sdk';
import {
getClient
} from './network';
export async function getBalance(addr) {
let address = new Crypto.Address(addr);
const client = getClient();
const response = await client.getBalance(address);
const ont = Number(get(response, 'Result.ont'));
const ong = Number(get(response, 'Result.ong'));
return {
ong,
ont,
};
}
export async function getUnboundOng(addr) {
let address = new Crypto.Address(addr);
const client = getClient();
const response = await client.getUnboundong(address);
const unboundOng = Number(get(response, 'Result'));
return unboundOng;
}
export async function getGrantOng(addr) {
let address = new Crypto.Address(addr);
const client = getClient();
const response = await client.getGrantOng(address);
const grantOng = Number(get(response, 'Result'));
return grantOng;
}
export async function invokeTx(tx) {
const client = getClient();
await client.sendRawTransaction(tx.serialize(), false, true);
}
export async function invokeReadTx(tx) {
const client = getClient();
await client.sendRawTransaction(tx.serialize(), true, true);
}
================================================
FILE: src/core/utils.js
================================================
import {
TEST_NET,
MAIN_NET,
MAIN_NET_LIST,
DEFAULT_SCRYPT,
TEST_NET_LIST
} from './consts'
import axios from 'axios'
import store from '../store'
import {message} from 'ant-design-vue'
import i18n from './lang'
import {
BigNumber
} from 'bignumber.js'
import numeral from 'numeral'
import {Crypto, RestClient} from 'ontology-ts-sdk'
const opn = require('opn')
const {
BrowserWindow
} = require('@electron/remote');
const os = require('os')
const fs = require('fs')
export function open(url) {
try {
opn(url)
} catch(err) {
let win = new BrowserWindow({width: 800, height: 600, center: true});
win.on('closed', () => {
win = null
})
// Load a remote URL
win.loadURL(url)
}
}
export function varifyPositiveInt(value) {
if (!/^[1-9]\d*$/.test(value)) {
return false;
}
return true;
}
export function varifyOngValue(value) {
if (!/^[0-9]+(\.[0-9]{1,9})?$/.test(value)) {
return false;
}
return true;
}
export function varifyOpe4Value(value, decimal) {
if (decimal > 0) {
if (!new RegExp(`^[0-9]+(\\.[0-9]{1,${decimal}})?$`).test(value)) {
return false;
}
} else {
return varifyPositiveInt(value);
}
return true;
}
export function isHexString(str) {
const regexp = /^[0-9a-fA-F]+$/;
return regexp.test(str) && (str.length % 2 === 0);
}
export function getNodeUrl() {
// const net = localStorage.getItem('net');
// return net === 'TEST_NET' ? TEST_NET + ':20334' : MAIN_NET + ':20334'
// return 'http://139.219.128.220:20334' //for test
const net = localStorage.getItem('net')
let node = localStorage.getItem('nodeAddress');
if(!node) {
node = net === 'TEST_NET' ? TEST_NET_LIST[0] : MAIN_NET_LIST[0]
}
// const node = localStorage.getItem('nodeAddress') || MAIN_NET_LIST[0]
// node = 'http://172.168.3.151'
return node + ':20334';
}
export function getRestClient() {
let url = getNodeUrl();
const restClient = new RestClient(url);
return restClient;
}
export function convertNumber2Str(num, decimal = 0, division) {
const val = new BigNumber(num).dividedBy(Math.pow(10, decimal))
if(division) {
return val.toFixed(8);
}
return val.toString();
}
export function convertStr2Number(str, decimal = 0) {
const val = new BigNumber(str).times(Math.pow(10, decimal))
return val.toNumber();
}
export function decryptWallet(wallet, password, scrypt = DEFAULT_SCRYPT) {
const enc = new Crypto.PrivateKey(wallet.key)
let pri;
try {
pri = enc.decrypt(password, new Crypto.Address(wallet.address), wallet.salt, scrypt)
} catch (err) {
console.log(err);
store.dispatch('hideLoadingModals')
message.error(i18n.t('common.pwdErr'))
return;
}
return pri;
}
export function validateAddress(address) {
try {
const addr = new Crypto.Address(address)
addr.serialize();
return true;
}catch(err) {
return false;
}
}
export function convertScryptParams({n, r, p, dkLen}) {
return {
cost: n,
blockSize: r,
parallel: p,
size: dkLen
}
}
// 创建axios实例
const service = axios.create({
timeout: 15000 // 请求超时时间
});
// request拦截器
service.interceptors.request.use(
config => {
if(config.method !== 'get') { // 定时查询的时候不希望页面显示loading
store.dispatch('showLoadingModals')
}
return config;
},
error => {
console.log('e')
store.dispatch('hideLoadingModals')
Promise.reject(error);
}
);
// respone拦截器
service.interceptors.response.use(
response => {
store.dispatch('hideLoadingModals')
const data = response.data;
return data;
},
error => {
store.dispatch('hideLoadingModals')
const response = error.response;
message.error(i18n.t('commonWalletHome.networkError'))
return Promise.reject((response && response.data) || error);
}
);
export default service;
export function getExplorerUrl() {
const net = localStorage.getItem('net');
const url = net === 'TEST_NET' ? 'https://polarisexplorer.ont.io' : 'https://explorer.ont.io';
return url;
}
export function getTransactionListUrl(address, page_size = 10, page_number =1) {
const api = `/v2/addresses/${address}/transactions?page_size=${page_size}&page_number=${page_number}`
const url = getExplorerUrl() + api;
return url;
}
export function getBalanceUrl(address, token_type = 'NATIVE') {
const api = `/v2/addresses/${address}/${token_type}/balances`
const url = getExplorerUrl() + api;
return url;
}
export function getTokenListUrl(token_type = 'oep4', page_size = 10, page_number = 1) {
const api = `/v2/tokens/${token_type}?page_size=${page_size}&page_number=${page_number}`
const url = getExplorerUrl() + api;
return url;
}
export function getTokenBalanceUrl(token_type, address) {
const api = `/v2/addresses/${address}/${token_type}/balances`
const url = getExplorerUrl() + api;
return url;
}
export function validateKeystorePath(path) {
const system = os.platform();
if(system.indexOf('win') > -1 && system !== 'darwin') {
const files = fs.readdirSync(path)
if(files && files.indexOf('resources') > -1 && files.indexOf('OWallet.exe') > -1) {
return false;
}
const cwd = process.cwd();
if(path && cwd !== '/' && (path === cwd || path.indexOf(cwd) > -1)) {
return false;
}
}
return true;
}
export function formatScryptParams(scrypt) {
return {
cost: scrypt.n || 16384, // 除以2时间减半
blockSize: scrypt.r || 8,
parallel: scrypt.p || 8,
size: scrypt.dkLen || 64
}
}
export function splitPath(path) {
let result = [];
let components = path.split('/');
components.forEach(element => {
let number = parseInt(element, 10);
if (isNaN(number)) {
throw Error(`Path ${path} is invalid.`);
}
if (element.length > 1 && element[element.length - 1] === "'") {
number += 0x80000000;
}
result.push(number);
});
return result;
}
export function convertPathToBuffer(path) {
const paths = splitPath(path);
const buffer = Buffer.alloc(paths.length * 4);
paths.forEach((element, index) => {
buffer.writeUInt32BE(element, 4 * index);
});
return buffer;
}
================================================
FILE: src/lang/en.js
================================================
export default {
common: {
testNet: 'TestNet',
mainNet: 'MainNet',
copied: 'Copied!',
confirmPwdTips: 'Please confirm and input the password your wallet.',
confirmTips: 'Please confirm the transfer.',
transSentSuccess: 'Transaction has been sent successfully!',
pwdErr: 'Password error',
ongNoEnough: 'Transaction does not have enough ONG to process',
transferFailed: 'Transfer failed. ',
networkErr: 'Network error!',
normalWallet: 'Individual wallet',
sharedWallet: 'Shared wallet',
hardwareWallet: 'Ledger wallet',
export: 'Export',
ledgerNotOpen: 'Ledger not open',
ledgerNotSupported: 'Ledger not supported',
pluginDevice: 'Please plugin the device and login.',
readyToSubmit: 'Ready to submit',
waitForSign: 'Waiting for sign',
readyToImport: 'Ready to connect',
existLocal: 'The wallet is already in local',
importLedgerSuccess: 'Import ledger wallet successfully.',
readyToLogin: 'Ready to login',
walletAddress: 'Wallet Address',
authentication: 'Authentication',
confirmation: 'Confirmation',
enterWalletPassword: 'Please enter your wallet password',
enterIdentityPassword: 'Please enter your ONT ID password',
password: 'Password',
invalidLedger: 'The current ledger dose not match with the wallet.Please try with another ledger device.',
exportDat: 'Export .dat',
exportWIF: 'Export WIF',
changePassword: 'Change Password',
deleteWallet: 'Delete Wallet',
more: 'More',
neoCompatible: 'NEO Address Compatible',
versionUpdate: 'You can upgrade your OWallet.',
getLatestVersion: 'Get the latest version here.',
changePassSuccess: 'Change password successfully',
changePassSuccessTip: 'You have already changed the password of the wallet. We recommend you to download and backup the .dat file.(Please replace or delete the old .dat file of this wallet.)',
download: 'Download .dat',
balanceInsufficient: 'Sorry, your balance is insufficient.',
exportIdentity: 'Export keystore',
deleteIdentity: 'Delete ONT ID',
savedbFailed: 'Save to db file failed.Please make sure you have set the path to save the keystore.db file and try again.',
selectOep4: 'Select OEP-4 token',
contractHash: 'Contract hash: ',
txFailed: 'Transaction failed',
availableNewVersion: 'A new version is available. In order to get a better user experience, please upgrade OWallet.',
toUpdate: 'Upgrade now',
cancel: 'Cancel',
transactionFailed: 'Transaction failed',
rejectedByUser: 'Rejected by user'
},
FormField: {
label: 'name',
password: 'password',
passwordConfirmation: 'password confirmation',
mnemonic: 'mnemonic',
privateKey: 'private key',
oldPassword: 'old password',
newPassword: 'new password',
newPasswordConfirmation: 'new password confirmation'
},
TopNav: {
new: 'New',
edit: 'Edit'
},
basicInfo: {
InvalidMnemonic: 'Invalid mnemonic.',
errWif: 'Please enter a valid WIF.'
},
SetPaths: {
name: 'Keystore File Path',
tips: '*The keystore.db file stores your encrypted private keys. Please make sure your computer is safe and make a backup of your keystore.db file. You need to set a file path for your keystore. Please do not set to the installation location of OWallet.',
close: 'Close',
enter: 'Set file path'
},
identitys: {
pageTit: 'ONT ID',
createIdentity: 'Create ONT ID',
importIdentity: 'Import ONT ID',
identity: 'Identity',
ontid: 'ONT ID'
},
createIdentity: {
create: 'Create ONT ID',
basicInfo: 'Basic info',
confirmInfo: 'Confirm info',
label: 'Name of Identity (ONT ID)',
password: 'Password',
rePassword: 'Repeat password',
cancel: 'Cancel',
next: 'Next',
ontid: 'ONT ID',
selectWallet: 'Select Wallet to pay for the transaction fee',
commonWallet: 'Individual Wallet',
ledgerWallet: 'Ledger Wallet',
payerPassword: 'Input the password of your selected wallet',
selectCommonWallet: 'Select local individual wallet',
selectOneWallet: 'Please select one individual wallet',
enterPassword: 'Please enter the password of your selected wallet',
createSuccess: 'Create ONT ID successfully!'
},
importIdentity: {
import: 'Import ONT ID',
basicInfo: 'Basic info',
keystore: 'ONT ID Keystore',
ontidPassword: 'ONT ID Password',
label: '',
passError: 'Password error',
ontidNotExist: 'The ONT ID to import does not exist on the blockchain',
keystoreImport: 'ONT ID Keystore Import',
invalidKeystore: 'The keystore you input is invalid.',
ontidExist: 'The identity already exists in local.',
importSuccess: 'Import Identity succeed!'
},
wallets: {
all: 'All Wallets',
common: 'Individual Wallet',
shared: 'Shared Wallet',
temp: 'TEMP',
createCommonWallet: 'Create Wallet',
importCommonWallet: 'Import Wallet',
createSharedWallet: 'Create Wallet',
joinSharedWallet: 'Join Wallet',
importLedgerWallet: 'Connect Ledger',
ledger: 'Ledger Wallet',
comingSoon: 'Coming soon...',
ledgerHelpLink: 'How to use?',
deleteSucceess: 'Delete wallet successfully.',
deleteFailed: 'Delete wallet failed.',
deleteingWallet: 'You are about to delete wallet with address: ',
exportingWallet: 'You are about to export the .dat file of wallet with address: ',
exportingWIF: 'You are about to export the private key(WIF) of wallet with address: ',
oldPassword: 'Old password',
newPassword: 'New password',
reNewPassword: 'Repeat new password',
changePassSuccess: 'Change password successfully!',
exportOntid: 'You are about to export the keystore of identity with ONT ID:',
deleteIdentityFailed: 'Delete ONT ID failed',
deleteIdentitySuccess: 'Delete ONT ID successfully',
exportedWIF: 'Your private key (WIF) is:'
},
dashboard: {
getTransErr: 'Fetch transaction history failed. Network error. Please try later.',
getBalanceErr: 'Fetch balance failed. Network error. Please try later.'
},
createJsonWallet: {
create: 'Create Individual Wallet',
basicInfo: 'Basic info',
label: 'Name of Individual Wallet',
password: 'Password',
rePassword: 'Repeat password',
next: 'Next',
cancel: 'Cancel',
back: 'Back',
details: '',
confirmInfo: 'Confirm info',
labelN: 'Label',
addressN: 'Address',
pubKeyN: 'Public key',
signatureSchemeN: 'Signature scheme',
wif: 'WIF',
mnemonic: 'Mnemonic phrase',
privateKey: 'Private Key',
backupWallet: 'Please make a backup of the above information and save the .dat file. If you forget your wallet password, your private key (WIF) will be the only way for you to recover your wallet.',
createSuccess: 'Create individual wallet successfully.',
createFail: 'Create individual wallet failed. Please try again.',
download: "Download .dat",
privateKey64Hex: 'Private key (64 Hex)',
priavteKeywif: 'Private key (WIF)',
keystoreDat: 'Keystore (.dat)'
},
importJsonWallet: {
datFile: 'Select file',
invalidDatFile: 'Please select the valid keystore (.dat) file.',
selectedDatFile: 'Selected file: ',
dat: '.dat File',
datImportPassword: 'Password to decrypt keystore (.dat)',
create: 'Import Individual Wallet',
basicInfo: 'Basic info',
label: 'Set a new name for the wallet',
wif: 'WIF',
wifTip: 'Please enter 52-bit WIF',
privateKeyTip: 'Please enter private key with 64 byte hex format',
datPassword: 'New Password',
datRePassword: 'Repeat New password',
password: 'Password',
rePassword: 'Repeat password',
next: 'Import',
cancel: 'Cancel',
back: 'Back',
details: '',
confirmInfo: 'Confirm info',
mnemonic: 'Please use a space to separate each of the words.',
privateKey: 'Private Key',
createSuccess: 'Create Individual wallet successfully!',
confirmImport: 'Confirm Import',
confirmImportExist: 'The wallet to import is already in your local. Still want to import it?',
success: 'Import wallet successfully!',
saveDbFailed: 'Save to keystore failed. Please try later.',
invalidPrivateKey: 'Please enter valid private key.',
setPassword: 'Set password',
importFirstDefault: 'Will only import the default wallet or the first wallet in the .dat file'
},
createSharedWallet: {
basicInfo: 'Basic info',
copayers: 'Co-payers',
processing: 'Processing',
label: 'Name of shared wallet',
copayers2_12: 'Co-payers(2-12)',
address: 'Address',
inputPks: 'Input 2 - 12 public keys\' info',
name: 'Name',
publicKey: 'Public key',
add: '+ Add',
next: 'Next',
cancel: 'Cancel',
back: 'Back',
importSharedWallet: 'Import shared wallet',
requiredSigNum: 'Number of required signatures ',
success: 'Success',
duplicateCreate: 'The shared wallet is already existed.Please import it.',
createFailed: 'Failed. Please try later.',
createSuccess: 'Create shared wallet successfully.',
create: 'Create Shared Wallet',
walletNameErr: 'Wallet name can not be more than 12 characters',
emptyLabel: 'Wallet name can not be empty',
pksLte2: 'The number of co-payers can not be less than 2. ',
invalidPk: 'Invalid public key',
duplicatePks: 'There must be no duplicate public key among the co-payers',
duplicateNames: 'There must be no duplicate names key among the co-payers'
},
importSharedWallet: {
import: 'Join shared wallet',
basicInfo: 'Basic info',
inputPass: 'Input password',
importSuccess: 'Success',
inputAddress: 'Address of shared wallet',
search: 'Search',
name: 'Shared wallet name',
totalCopayerNumber: 'Total number of co-payers',
requiredCopayerNumber: 'Required number of co-payers',
allCopayers: 'Address of all Co-payers',
noResult: 'No result',
address: 'Address',
chooseLocalWallet: 'Select local wallet to join',
localWalletInfo: 'Local wallet detail',
walletName: 'Wallet name',
pk: 'Public key',
next: 'Next',
cancel: 'Cancel',
back: 'Back',
join: 'Join',
inputPassword: 'Enter password to join',
joinBefore: 'You have joined this wallet before.',
success: 'Join shared wallet succeed!',
passwordError: 'Password error.',
sorry: 'Sorry!',
notFound: 'The shared wallet you are looking for is not found.'
},
importLedgerWallet: {
import: 'Connect Ledger Wallet',
label: 'Name of Ledger Wallet',
next: 'Connect',
neoCompatible: 'NEO Address Compatible'
},
sharedWalletHome: {
send: 'Send',
receive: 'Receive',
claim: 'Claim',
rule: 'Rule',
copayers: 'Co-payers',
pendingTx: 'Pending transactions',
completedTx: 'Completed transactions',
owners: 'Owners',
address: 'Address',
amount: 'Amount',
max: 'MAX',
to: 'To',
recipient: 'Recipient address',
cancel: 'Cancel',
next: "Next",
back: 'Back',
submit: 'Submit',
asset: 'Asset',
sponsor: 'Sponsor',
dragDecide: 'Drag to decide sign sequence',
fee: 'Fee',
inputPassword: 'Input Password',
inputPassToTransfer: 'Input password to complete transfer',
walletAddress: 'Wallet address',
createTime: 'Creation time',
balance: 'Balance',
confirmation: 'Confirmation',
agreeToSend: 'I confirm the asset amount and recipient address are correct.',
signSequence: 'Sign sequence',
sign: 'Sign',
checkMore: 'Check more',
publicKey: 'Public key',
redeemOng: 'Redeem ONG',
paxMgmt: 'PAX management',
unprocessed: 'Unprocessed',
processing: 'In processing',
completed: 'Completed',
txMgmt: 'Transaction management',
createTransferFailed: 'Create transfer transaction failed.',
createTransferSuccess: 'Create transfer transaction succeed.',
txSendingTochain: 'This transaction is sending to the blockchain now.'
},
pax: {
ethAddress: 'Eth Address',
ontAddress: 'Ont Address',
amount: 'Amount',
date: 'Date',
toProcess: 'To process',
paxStart: 'Start',
paxSign: 'Sign',
selectCurrentSigner: 'Select current signer: ',
back: 'Back',
confirm: 'Confirm',
sponsorSign: 'Sponsor sign',
inputPassword: 'Input the password of current signer',
queryEthScan: 'Query Total Eth amount',
currentSign: 'Current signer sign',
txToSend: 'Number of transactions to send: ',
txSent: 'Number of transactions sent succeed: ',
sendingTx: 'Sending transactions',
selectedNum: 'Number of selected orders: ',
totalAmount: 'Total amount of selected orders: ',
ethTotal: 'Total amount of received ETH: ',
startProcessSuccess: 'Start process succeed.',
signSuccess: 'Sign transactions succeed.',
ledgerSignMultiTimes: 'You may have to sign multi times on your ledger device',
hasSignedSent: 'These transactions has been signed and sent. Please review the completed data.',
toEthScan: 'To Eth Scan',
txCompleted: 'Transaction completed',
txDetail: 'Detail',
toVarify: 'Verify',
varifySuccess: 'Verify succeed!',
varifyFailed: 'Verify failed!',
varifyResult: 'Verified result',
failedTxhashes: 'Failed transaction hash:'
},
sharedTx: {
startTx: 'Start multi-sign transaction',
signTx: 'Sign multi-sign transaction',
selectSponsor: 'Select sponsor',
createTx: 'Create Transaction',
contractHash: 'Contract hash',
method: 'Method',
parameters: 'Parameters',
starterSign: 'Start sign',
txSerialized: 'Signed and serialized transaction:',
addSign: 'Add signature',
txContent: 'Transaction data',
currentSign: 'Current signer',
selectSigner: 'Select wallet to sign',
copy: 'Copy',
send: 'Send now',
isSendTxTip: 'The transaction can be sent to the blockchain now. Confirm to send?',
txSentSuccess: 'Send transaction succeed.',
paramsError: 'Error parameters. Please check the input.'
},
commonWalletHome: {
claimableOng: 'Claimable ONG',
unboundOng: 'Unbound ONG',
redeem: 'Redeem',
receive: 'Receive',
swap: 'Swap',
walletQrCode: 'Wallet QR code',
walletAddress: 'Wallet address',
publicKey: 'Public key',
redeemCharge: 'Each redeem charges 0.01 ONG',
inputPass: 'Please input your wallet password',
emptyPass: 'Password can not be empty',
cancel: 'Cancel',
submit: 'Submit',
swapText: 'Here you can perform the MainNet ONT token swap.Users can exchange Nep-5 ONT for ONT for ONT on the Ontology MainNet.Swap takes up to 1 month, you can check the status on https://swap.ont.io',
stepFollow: 'Just do as follows:',
step1: '1. Import your private key(from your NEO wallet) to create a wallet',
step2: '2. Press [Swap] button to start the swap',
step3: '3. View the status of your token swap',
swapAmount: 'Swap Amount',
nep5Balance: 'Balance of NEP-5 ONT:',
password: 'Password',
validAmount: 'Please input valid amount',
checkMore: 'Check more',
balance: 'Balance',
scriptHash: 'Script hash',
add: '+ Add',
addOep4: 'Add OEP-4 Token',
enterScripthash: 'Please enter the OEP-4 token script hash',
invalidScriptHash: 'The script hash is invalid',
addOep4Success: 'Add OEP-44 token succeed!',
noOep4Contract: 'The OEP-44 contract is not found',
networkError: 'Network error! Please try later.',
oep4Exists: 'You have already added this OEP-4 token.',
go: 'Go'
},
transfer: {
inputValidAmount: 'Please input valid transfer amount.',
inputValidAddress: 'Please input valid receiver address.',
exceedBalance: 'Amount of transfer can not exceed your balance.',
ongBalanceNotEnough: 'Your ONG balance is not enough for transfer and fee.',
warningTransferAllONG: 'Transferring this amount of ONG means you will not have enough ONG to pay\r\nfor further transaction fees (including claiming unbound ONG). \r\n\r\nContinue?'
},
setting: {
name: 'Setting',
net: 'Network',
lang: 'Language',
testNet: 'TestNet',
mainNet: 'MainNet',
en: 'English',
zh: '中文',
pathTit: 'Path: ',
path: 'Save keystore file path(Please do not set to the installation location of OWallet!)',
change: 'Change',
setNetworkSuccess: 'The network has been set to: ',
wallets: 'Wallets',
ontid: 'ONT ID',
nodeStake: 'Node Stake',
help: 'Help',
settings: 'Settings',
nodeAddress: 'Node address',
setNodeSuccess: 'The node address has been set t: ',
notInstallationPath: 'Please do not set to the installation location of OWallet.',
notSetPath: 'You did not set the keystore path.'
},
ledgerWallet: {
nameOfLedgerWallet: 'Name of your ledger wallet',
info: 'Ledger Info',
connectApp: 'Please connect to your ledger device and open the ONT app on it.',
status: 'Device Status',
labelEmpty: 'Label can not be empty.',
deviceError: 'Can not connect to device.Please try again.',
signFailed: 'Sign with ledger failed.',
selectAccount:"Please select the account(s) on your Ledger device.",
normalMode:'Normal Mode',
advancedMode:'Advanced Mode',
alreadyImported:"Some selected accounts already imported",
specifyPath:"Please select and specify the path to import the account",
pleaseSelectWallet:"Please select the wallet you want to import and enter a name",
},
ledgerStatus: {
NOT_FOUND: 'Ledger not open',
NOT_SUPPORT: 'Ledger not supported',
NO_DEVICE: 'Please plugin the device and login.',
READY: 'Ledger is Ready',
NOT_OPEN: 'The ONT app on ledger is not open.'
},
nodeStake: {
iHaveKnown: 'I Have Known',
ontid: 'ONT ID',
nodeStake: 'Node Stake',
stakeWalletAddress: 'Stake Wallet Address',
nodePk: 'Node Public Key',
contract: 'Contract',
commitmentQuantity: 'Commitment Amount',
stakeQuantity: 'Stake Amount',
claimableQuantity: 'Claimable Amount',
stake: 'Stake',
feeTip: 'Stake needs 500 ONG for service fee',
selectOntid: 'Select ONT ID',
selectStakeWallet: 'Select stake wallet',
next: 'Next',
selectIdentity: 'Please select your ONT ID',
selectIndividualWallet: 'Please select your individual wallet',
selectLedgerWallet: 'Please connect your ledger and open ONT app on it.',
invalidOntid: 'Invalid ONT ID ',
invalidAddress: 'Invalid stake wallet address',
stakeQuantityEmpty: 'Please enter valid stake quantity',
password: 'Enter Password',
signWithOntid: 'Sign with ONT ID',
signWithWallet: 'Select wallet',
enterOntidPass: 'Please enter the password of your ONT ID',
enterWalletPass: 'Please enter the password of the selected wallet',
quitWarmMsg: 'If you choose to quit the node, all the initial staked amount will be returned. The candidate node can get the staked amount returned after one cycle, and the consensus node can get it returned after two cycles. After quitting the node, if you want to run a node again, you have to sign up again.',
back: 'Back',
recall: 'Recall',
refund: 'Refund',
quitNode: 'Quit Node',
newStake: 'New Stake',
passwordEmpty: 'Password can not be empty',
search: 'Search'
},
nodeStakeStatus: {
transfering: 'Transferring',
transfered: 'Transferred',
transferFailed: 'Transfer Failed',
audit: 'Audit',
auditing: 'Auditing',
audited: 'Audited',
auditFailed: 'Audit Failed',
stake: 'Stake',
staked: 'Staked',
nodeExited: 'Node Exited',
refund: 'Refund',
refunding: 'Refunding',
refunded: 'Refunded',
refundFailed: 'Refund Failed',
stakeExited: 'Stake Exited',
quitStake: 'Quit Stake',
unfrozenToRefund: 'Unfreeze successfully, you can refund now',
transferNeedTime: 'Transfer needs a period of time',
serviceFee: 'Stake needs 500 ONG for service fee',
auditNeedTime: 'Audit needs a period of time',
refundNeedTime: 'Refund needs a period of time',
txFailed: 'Transaction failed.'
},
redeemInfo: {
info: 'Redeem Info',
claimableOng: `Claimable ONG is the amount of ONG you can claim for a 0.01 ONG fee. This balance will update each time a transaction is made in your wallet address.`,
unboundOng: `Unbound ONG is an amount of ONG which has not been added to your claimable ONG balance yet (since it only updates each you make a transaction in your wallet address). When a transaction is made in your address, the claimable ONG balance will update (adding your unbound ONG amount to your claimable ONG amount).`,
claimableOngName: 'Claimable ONG: ',
unboundOngName: 'Unbound ONG: ',
noClaimableOng: 'Your claimable ONG is 0. When a transaction of ONT is made in your address, the claimable ONG balance will update'
},
nodeMgmt: {
nodeUser: 'If you are a candidate node, you can stake and manage your stake here.',
nodeStakeMgmt: 'Node Stake Management',
normalUser: 'If you are a normal user, you can participate in stake authorization here.',
stakeAuthorizaton: 'Stake Authorization',
nodeStake: 'Node Stake',
userStakeAuthorization: 'User Stake Authorization',
newStake: 'Submit A New Stake',
allowStakes: 'Allow stakes from other users',
deny: 'Deny',
permit: 'Permit',
yourStakeAmount: 'Your node stake amount',
stakeLimit: 'Total max stake limit',
userNumber: 'Current number of users staking',
userStakeAmount: 'Current total stake of users',
rewardsPerMonth: 'Estimate total rewards per month',
rewardsTip: 'Estimate total rewards per month includes your rewards and the rewards of other uesrs staking.',
rewardProportion: 'Fee Sharing Ratio: ',
nodeRewardProportion: 'Fee Sharing Ratio (Node)',
userRewardProportion: 'Fee Sharing Ratio (User)',
current: 'current',
nodeRewardProportionTip: 'Fee Sharing Ratio (Node): Node will receive x percentage of the transaction fees and released ONG yield of the total amount of node’s own initial ONT stake (excl. ONT staked by users).',
userRewardProportionTip: 'Fee Sharing Ratio (User): Node will receive x percentage of the transaction fees and released ONG yield of the total amount of ONT staked by users (excl. node’s own initial stake).',
confirm: 'Confirm',
changesTakeEffect: ' Changes will take effect in two consensus rounds (each round is approximately every 30 days). ',
stakeAuthorization: 'Stake Authorization',
toNextRound: 'Next round in',
rank: 'Rank',
name: 'Name',
currentStake: 'Current total stake',
process: 'Stake progress',
changes: 'Changes',
userParticipate: 'Only proceed if you want to participate in stake authorization!',
nodeName: 'Node name',
walletAddress: 'Your wallet address',
inAuthorization: 'Total authorized stake',
cancelStakeAuthorization: 'Cancel stake authorization',
locked: 'Canceled(locked)',
claimable: 'Redeemable',
redeem: 'Redeem',
profit: 'Profit',
rewards: 'Rewards',
newStakeAuthorization: 'Submit new stake authorization',
cancelAuthorization: 'Cancel stake authorization',
units: 'Units of stake authorization',
stakeAmountTip: 'Stake amount = input number * 1 ONT/unit.',
stakeAmount: 'Stake amount',
submit: 'Submit',
allowedStakeUnits: 'Allowed stake unit',
allowedStakeAmount: 'Allowed stake amount',
noChange: 'You did not make a change.',
noRewards: 'No rewards to redeem.',
switchWallet: 'Switch wallet',
noClaimableOnt: 'No redeemable ONT',
amountToCancel: 'Amount to cancel',
unitToCancel: 'Units to cancel',
invalidInput: 'Please enter valid value.',
peerNotAllowAuthorize: 'This peer does not allow authorization now.',
addInitPos: 'Add to stake',
reduceInitPos: 'Reduce stake',
amountToAdd: 'Amount To Add',
amountToReduce: 'Amount To Reduce',
notThanCommitment: 'Stake quantity can not be less than the commitment stake quantity.',
notLessTotalPos: 'The initial stake amount is too small.',
notThanMax: 'Allowed stake can not be more than the max stake limit.',
refresh: 'Refresh',
totalStakeAmount: 'Total Authorization Amount',
blocks: 'Blocks',
proportionNextRound: "Fee Sharing Ratio (Node/User)",
proportionNextRoundTip: 'This is the percentage of the transactions fees and released ONG yield of the total amount of stake yield for node’s own initial stake and the total user’s stake, that the node has chosen to share with their stakers in the next consensus round.\nPlease note that not all nodes share the Ontology Foundation bonus with stakers. Click the below link for more details.',
authorizationFAQ: 'OWallet Stake Authorization FAQ',
nodeAndUser: 'Node / User',
authorizeTip: `If new stake is cancelled it will be cancelled immediately and be shown as redeemable ONT. If authorized ONT from previous consensus rounds is cancelled it will be redeemable only at the beginning of the next consensus round for candidate nodes (or one round later for consensus nodes). If a user has both authorized ONT from this consensus round and a previous consensus round and cancels an ONT amount exceeding the amount from this consensus round, they will receive authorized ONT from this consensus round first and the remaining authorized ONT in the next consensus round.`,
rewardTip: `All transactions fees received by Ontology are distributed to all candidate nodes and consensus nodes - 50% to each group.
Within their 50% share each candidate node will receive their share linearly according to their stake amount.
Within their 50% share each consensus node will receive their share according to their stake amount, which is subject to the incentive curve that discourages too high stakes.
`,
unboundOng: 'Unbound ONG',
activeT: 'Active in current round',
activeT1: 'Active in next round',
activeT2: 'Active in next 2 round',
changeRewardProportion: 'Change Fee Sharing Ratio',
edit: 'Edit',
stakeHistory: 'My Stake',
cancelUnits: 'units',
stakeWalletAddress: 'Stake wallet address',
lastUpdate: 'Last update time',
walletRewardTip: 'This is all the reward of your wallet in current round.',
switchMainnet: 'Please switch to MainNet.',
consensusNode: 'Consensus node',
candidateNode: 'Candidate consensus node',
lockedONT: 'This is your canceled authorized stake amount currently held in a smart contract. Once it is available to be withdrawn, it will appear as redeemable ONT.',
unboundONG: 'This is the unbound ONG amount of your authorized ONT stake.',
profitONG: 'This is the transaction fee profit you have made. This will update at the beginning of each new consensus round.',
getProfitPart: 'Already receiving profit portion',
newStakePart: 'New stake portion',
claimableONT: 'Claimable ONT',
redeemInitPos: 'Redeem claimable stake',
initPosInLock: "Locked",
initPosRedeemable: 'Claimable',
noClaimbleInitPos: 'No claimable ONT.',
redeemInitPosOk: 'Redeem',
hasClaimableInitPos: 'You have redeemable init pos. Please redeem this part first.',
noClaimbleToRefund: 'No redeemable ONT to refund.',
newNodeApply: 'New Node Apply',
nodeApplyTip: ''
},
vote: {
node: 'Node',
vote: 'Vote',
voteTip: "For authorized users, vote here",
login: 'Sign in',
notSeeWallet: "Didn't see your wallet? Import one ",
importHere: 'here',
notStart: 'Not started',
inProgress: 'In Progress',
finished: 'Finished',
canceled: 'Canceled',
nodeCanVoteOnly: '*Only users from consensus nodes are allowed to vote.',
title: 'Title',
detail: 'Detail',
votingStarts: 'Vote start time',
votingEnds: 'Vote end time',
back: 'Back',
submit: 'Submit',
submitVoteSuccess: 'Vote succeeded',
submitVoteFail: 'Vote failed',
stopVoteSuccess: 'Vote cancelled',
stopVoteFail: 'Vote cancellation failed',
createVoteSuccess: 'Vote created',
createVoteFail: 'Vote creation failed',
onlySupportEnglish: 'Only English is allowed',
fillBlanks: 'Please fill in the blanks.',
endTimeError: "The vote must end in a future time.",
votingTopics: 'Voting Topics',
votingDetail: 'Voting Detail',
stopVote: 'Cancel Voting',
info: 'Info',
startTime: 'Starting time',
endTime: 'Ending time',
hash: 'Hash',
creatorAddress: 'Creator address',
votingStatus: 'Vote status',
myVotes: 'My vote(s)',
approval: 'Approved',
opposition: 'Denied',
allVotes: 'All votes',
created: 'Created by me',
duration: 'Duration',
notAllowVote: 'You cannot vote now, the vote is: ',
notAllowStop: 'You cannot stop the vote now, the vote is : ',
name: 'Name',
address: 'Address',
votes: 'Number of votes',
selectWallet: 'Select node operation wallet',
startTimeError: 'Start time cannot be later than end time.',
new: 'New'
},
nodeApply: {
newNodeApply: 'New node apply',
stakeWallet: 'Stake wallet',
operationWallet: 'Node operation wallet',
selectOperationWallet: 'Select operation wallet',
operationPk: 'Operation wallet public key',
enterOperationPk: 'Enter operation wallet public key',
invalidOperationPk: 'Invalid operation wallet',
stakeAmount: 'Stake amount',
inputStakeAmount: 'Enter stake amount',
next: 'Next',
ok: 'OK',
cancel: 'Cancel',
operationWalletPublickey: 'Node operation wallet publickey',
registerSuccess: 'Congratulations on the successful node registration',
completeNodeInfo: 'Complete node info now',
later: 'Later',
sameWalletNotAllowed: 'The operation wallet and staking wallet can not be the same',
operationWalletRequired: 'Operation wallet is required',
stakeWalletRequired: 'Stake wallet is required',
stakeAmountRequired: 'Stake amount is required',
minStateAmount: 'The stake amount is at least 10,000 ONT',
proxyServiceTip: 'The Ontology community now provides node operation by proxy service.',
proxyServiceLink: 'Click here to find out more.',
unsupportedLedger:"Ledger hardware wallet is currently not supported as operation wallet for node registration.",
},
myNode: {
myNode: 'My nodes',
stakeWalletAddress: 'Stake wallet address',
operationWalletPk: 'Operation wallet public key',
manage: 'Manage',
applyNode: 'Apply new node'
},
nodeInfo: {
nodeInfo: 'Node info',
name: 'Name',
enterName: 'Name',
logo: 'Logo',
enterLogo: 'Url of logo',
location: 'Region',
enterLocation: 'Region of node',
ip: 'IP',
enterIp: 'Ip of node',
description: 'Description',
enterDesc: 'Description of node',
website: 'Website',
enterWebsite: 'Website of node',
telegram: 'Telegram',
enterTelegram: 'Telegram of node',
twitter: 'Twitter',
enterTwitter: 'Twitter',
facebook: 'Facebook',
enterFacebook: 'Facebook',
contactOntologyEmail: 'Email to contact with Ontology',
enterContactEmail: 'Email to contact with Ontology',
openEmail: 'Open email',
enterOpenEmail: 'Open email',
ifOpenInfo: 'Switch to open info',
submit: 'Submit',
updateSuccess: 'Update node info succeed',
updateFailed: 'Update node info failed',
ledgerWalletNotSupportForNow: 'Nodes registered with ledger currently do not support updating node-related information. Please email to: '
},
exchange: {
exchange: 'Exchange',
changelly: 'Changelly',
cryptonex: 'Cryptonex',
loading: 'Loading latest pricing information, please wait..'
},
dapps: {
dapps: 'DApps',
sesameSeed: 'Sesameseed',
sesameseedDesc: 'Sesameseed voting management',
notification: 'Notification',
userPolicy: 'You will be redirected to the third party dApp. Use of the third party dApp will be subject to their User Agreement and Privacy Policy. You will be liable to the third party dApp only.',
ontidMgmt: 'ONT ID management. This feature will be removed in the future. Please backup ONT ID related data'
},
sesameseed: {
stakeAmountTip: 'Stake amount for Sesameseed is 1 unit equals 1 ONT',
authorizeTip: 'If a new stake is canceled, it will add to the “canceled” ONT and be directly deposited in the users account within 24 hours. If authorized ONT from a previous consensus round is canceled it will be added to the “canceled” ONT and be directly deposited in the originating users account within 24 hours of the beginning of the next consensus round if Sesameseed is a candidate node (or one round later if Sesameseed is a consensus node). If a user has both authorized ONT from this consensus round and a previous round and cancels an ONT amount exceeding the amount from this round, they will receive authorized ONT from this consensus round first and the remaining authorized ONT in the next round.',
rewardTip: 'Sesameseed rewards Ontology Stake Authorizations in SEED for both foundation rewards created as a candidate or consensus node as an OEP-4 token “SEED”. This token is rewarded directly to Staking participants. In addition to node rewards, 100% of ONG unbound while staking is pooled by all stake authorizations and added to the total “Node Reward”, as a result this node reward is also provided in the form of “SEED” Token. Rewards are distributed daily without the need to redeem. Find out more at https://sesameseed.org.',
pendingWithdrawals: 'Pending canceled stake authorization'
}
}
================================================
FILE: src/lang/index.js
================================================
import Vue from "vue";
import VueI18n from "vue-i18n";
import en from "./en";
import zh from "./zh";
import LangStorage from "../core/lang";
Vue.use(VueI18n);
const messages = {
en,
zh
};
const i18n = new VueI18n({
locale: "en", //LangStorage.getLang("en"),
messages
});
export default i18n;
================================================
FILE: src/lang/zh.js
================================================
export default {
common: {
testNet: 'TestNet',
mainNet: 'Main Net',
copied: '已复制!',
confirmPwdTips: '请确认并输入钱包密码。',
confirmTips: '请确认转账',
transSentSuccess: '交易已成功发送',
pwdErr: '密码错误',
ongNoEnough: 'ONG不足,无法支付转账手续费。',
transferFailed: '交易失败。',
networkErr: '网络错误!',
normalWallet: '普通钱包',
sharedWallet: '共享钱包',
hardwareWallet: 'Ledger钱包',
export: '导出',
ledgerNotOpen: 'Ledger未打开',
ledgerNotSupported: 'Ledger不支持',
pluginDevice: '请连接设备并登录.',
readyToSubmit: '可以提交',
waitForSign: '等待签名',
readyToImport: '可以连接Ledger钱包',
existLocal: '本地已有此钱包',
importLedgerSuccess: '导入Ledger钱包成功',
readyToLogin: '可以登录',
walletAddress: '钱包地址',
authentication: '验证',
confirmation: '确认',
enterWalletPassword: '请输入钱包密码',
enterIdentityPassword: '请输入ONT ID密码',
password: '密码',
invalidLedger: '当前Ledger设备与要打开的钱包不匹配,请尝试正确的ledger设备。',
exportDat: '导出.dat',
exportWIF: '导出WIF',
changePassword: '修改密码',
deleteWallet: '删除钱包',
more: '更多',
neoCompatible: '兼容NEO地址',
versionUpdate: '您可以升级OWallet。',
getLatestVersion: '下载最新版本。',
changePassSuccess: '修改密码成功',
changePassSuccessTip: '您已经修改了钱包密码。我们建议您下载并备份钱包的.dat文件。(旧的.dat文件可以被替换或者删除)',
download: 'Download',
balanceInsufficient: '抱歉,您的余额不足',
exportIdentity: '导出keystore',
deleteIdentity: '删除ONT ID',
savedbFailed: '保存到keystore.db文件失败。请确保已设置keystore.db保存路径后重新尝试。',
selectOep4: '选择OEP-4 Token',
contractHash: '合约哈希:',
txFailed: '该交易在区块链上失败。',
availableNewVersion: '有新版本可用。为了获得更好的使用体验,请升级OWallet。',
toUpdate: '立即升级',
cancel: '取消',
transactionFailed: '交易失败',
rejectedByUser: '用户拒绝'
},
FormField: {
label: '名称',
password: '密码',
passwordConfirmation: '确认密码',
mnemonic: '助记词',
privateKey: '私钥',
oldPassword: '旧密码',
newPassword: '新密码',
newPasswordConfirmation: '确认新的密码'
},
TopNav: {
new: '新建',
edit: '编辑'
},
basicInfo: {
InvalidMnemonic: '无效的助记词。',
errWif: '无效的WIF'
},
SetPaths: {
name: '钱包文件存储路径',
tips: '* 钱包文件keystore.db保存着您的加密私钥,请确保您的PC安全和做好keystore.db文件的备份。您需要设置keystore文件的保存路径。请不要设置到OWallet的安装位置以免更新时被覆盖。',
close: '关闭',
enter: '去设置'
},
identitys: {
pageTit: 'ONT ID',
createIdentity: '创建ONT ID账户',
importIdentity: '导入ONT ID账户',
identity: 'Identity',
ontid: 'ONT ID'
},
createIdentity: {
create: '创建ONT ID账户',
basicInfo: '基本信息',
confirmInfo: '确认信息',
label: 'ONT ID账户昵称',
password: '账户密码',
rePassword: '确认密码',
cancel: '取消',
next: '继续',
ontid: 'ONT ID',
selectWallet: '请选择钱包来支付交易费用',
commonWallet: '普通钱包',
ledgerWallet: 'Ledger钱包',
payerPassword: '输入所选钱包的密码',
selectCommonWallet: '选择本地普通钱包',
selectOneWallet: '请选择一个本地钱包',
enterPassword: '请输入钱包密码',
createSuccess: '创建ONT ID成功!'
},
importIdentity: {
import: '导入ONT ID',
basicInfo: '基本信息',
keystore: 'ONT ID Keystore',
ontidPassword: 'ONT ID 密码',
label: '',
passError: '密码错误',
ontidNotExist: '要导入的ONT ID不存在于区块链上',
keystoreImport: '导入ONT ID Keystore',
invalidKeystore: '您输入的keystore不正确。',
ontidExist: '要导入的ONT ID本地已存在。',
importSuccess: '导入ONT ID成功。'
},
wallets: {
all: '全部钱包',
common: '普通钱包',
shared: '共享钱包',
temp: '之前的临时功能',
createCommonWallet: '创建钱包',
importCommonWallet: '导入钱包',
createSharedWallet: '创建钱包',
joinSharedWallet: '加入钱包',
importLedgerWallet: '连接Ledger钱包',
ledger: 'Ledger钱包',
comingSoon: '敬请期待',
ledgerHelpLink: '如何使用',
deleteSucceess: '删除钱包成功.',
deleteFailed: '删除钱包失败.',
deleteingWallet: '您正在删除钱包,钱包地址是:',
exportingWallet: '您正在导出钱包.dat文件,钱包地址是:',
exportingWIF: '您正在导出钱包的私钥(WIF), 钱包地址是:',
oldPassword: '旧密码',
newPassword: '新密码',
reNewPassword: '重复新密码',
changePassSuccess: '修改密码成功!',
exportOntid: '您正要导出ONT ID的keystore:',
deleteIdentityFailed: '删除ONT ID失败',
deleteIdentitySuccess: '删除ONT ID成功。',
exportedWIF: '您的私钥(WIF)是:'
},
dashboard: {
getTransErr: '交易记录获取失败,网络错误。请稍后重试。',
getBalanceErr: '余额获取失败。网络错误,请稍后重试。'
},
createJsonWallet: {
create: '新建普通钱包',
basicInfo: '基本信息',
label: '钱包名称',
password: '输入密码',
rePassword: '重复密码',
next: '继续',
cancel: '取消',
back: '返回',
details: '详情',
confirmInfo: '确认信息',
labelN: '名称',
addressN: '地址',
pubKeyN: '公钥',
signatureSchemeN: '签名算法',
wif: 'WIF',
mnemonic: '助记词',
privateKey: '私钥',
backupWallet: '请备份好以上数据并保存好.dat文件。如果您忘记了钱包密码,您的私钥(WIF)将会是恢复钱包的唯一方式。',
createSuccess: '创建普通钱包成功!',
createFail: '创建普通钱包失败。请重试。',
download: '下载.dat文件',
privateKey64Hex: '私钥(64 Hex格式)',
priavteKeywif: '私钥(WIF格式)',
keystoreDat: 'Keystore(.dat)'
},
importJsonWallet: {
datFile: '选择文件',
invalidDatFile: '请选择正确的keystore(.dat)文件',
selectedDatFile: '已选择文件: ',
dat: '.dat文件',
datImportPassword: '解密keystore文件(.dat)的密码',
create: '导入普通钱包',
basicInfo: '基本信息',
label: '钱包名称',
wif: 'WIF',
wifTip: '请输入52位的WIF文本',
privateKeyTip: '请输入64位HEX格式的密钥',
datPassword: '输入新密码',
datRePassword: '重复新密码',
password: '输入密码',
rePassword: '重复密码',
next: '继续',
cancel: '取消',
back: '返回',
details: '详情',
confirmInfo: '确认信息',
mnemonic: '请用空格分隔助记词',
privateKey: '私钥',
confirmImport: '确认导入',
confirmImportExist: '要导入的钱包本地已存在。仍然要导入?',
success: '导入钱包成功',
saveDbFailed: '保存到Keystore失败。请稍后重试。',
invalidPrivateKey: '请输入正确的私钥',
setPassword: '设置密码',
importFirstDefault: '只导入.dat文件中的默认钱包或第一个钱包'
},
createSharedWallet: {
basicInfo: '基本信息',
copayers: '联合支付人',
processing: '处理中',
label: '共享钱包名称',
copayers2_12: '联合支付人(2-12)',
address: '地址',
inputPks: '输入 2 - 12 公钥\' 信息',
name: '名字',
publicKey: '公钥',
add: '+ 增加',
next: '继续',
cancel: '取消',
back: '返回',
importSharedWallet: '导入共享钱包',
requiredSigNum: '选择签名数量',
success: '成功',
duplicateCreate: '共享钱包已存在,请导入.',
createFailed: '错误,请稍后重试。',
createSuccess: '创建共享钱包成功',
create: '创建共享钱包',
walletNameErr: '钱包名称长度不可超过12个字符。',
emptyLabel: '钱包名称不能为空.',
pksLte2: '联合支付人数量不能少于2人。',
invalidPk: '输入的公钥不正确',
duplicatePks: '联合支付人中不能有重复的公钥',
duplicateNames: '联合支付人中不能有重复的名称'
},
importSharedWallet: {
import: '加入共享钱包',
basicInfo: '基本信息',
inputPass: '输入密码',
importSuccess: '成功',
inputAddress: '共享钱包地址',
search: '查询',
name: 'Shared Wallet 名字',
totalCopayerNumber: '联合支付人数',
requiredCopayerNumber: '最少签名数',
allCopayers: '全部联合支付人地址',
noResult: '没有结果',
address: '地址',
chooseLocalWallet: '选择本地钱包加入',
localWalletInfo: '本地钱包详情',
walletName: '钱包名字',
pk: '公钥',
next: '继续',
cancel: '取消',
back: '返回',
join: '加入',
inputPassword: '输入密码加入',
joinBefore: '你已经加入过这个钱包。',
success: '已经成功加入钱包!',
passwordError: '密码错误。',
sorry: '对不起!',
notFound: '找不到该共享钱包。'
},
importLedgerWallet: {
import: '连接Ledger钱包',
label: '钱包名称',
next: '连接',
neoCompatible: '兼容NEO地址'
},
sharedWalletHome: {
send: '发送',
receive: '接收',
claim: '认领',
rule: '规则',
copayers: '联合支付人',
pendingTx: '待处理交易',
completedTx: '已完成交易',
owners: '所属人',
address: '地址',
amount: '数量',
max: '最大',
to: '接收',
recipient: '接收方地址',
cancel: '取消',
next: '继续',
back: '返回',
submit: '提交',
asset: '资产',
sponsor: '发起人',
dragDecide: '拖动序号决定顺序',
fee: '费用',
inputPassword: '输入密码',
inputPassToTransfer: '输入密码完成转账',
walletAddress: '钱包地址',
createTime: '创建时间',
balance: '余额',
confirmation: '确认',
agreeToSend: '我同意发送资产',
signSequence: '签名顺序',
sign: '签名',
checkMore: '查看更多',
publicKey: '公钥',
redeemOng: '提取ONG',
paxMgmt: 'PAX管理',
unprocessed: '未处理',
processing: '处理中',
completed: '已完成',
txMgmt: '多签交易管理',
createTransferFailed: '创建转账交易失败',
createTransferSuccess: '创建转账交易成功',
txSendingTochain: '该交易正在发送上链。'
},
pax: {
ethAddress: 'Eth 地址',
ontAddress: 'ONT 地址',
amount: '数额',
date: '日期',
toProcess: '去处理',
paxStart: '发起',
paxSign: '签名',
selectCurrentSigner: '选择当前签名钱包: ',
back: '返回',
confirm: '确认',
sponsorSign: '发起人签名',
inputPassword: '输入当前签名钱包密码',
queryEthScan: '查询Eth转出总额',
currentSign: '当前签名者签名',
txToSend: '要发送上链的交易个数:',
txSent: '已发送上链的交易个数: ',
sendingTx: '正在发送交易上链:',
selectedNum: '已选择条目数量: ',
totalAmount: '已选择条目的PAX总额: ',
ethTotal: '已收到的ETH总额: ',
startProcessSuccess: '发起处理流程成功',
signSuccess: '签名交易成功',
ledgerSignMultiTimes: '您可能需要在ledger设备上进行多次签名',
hasSignedSent: '注意!这些交易已经被签名并已发送到链上。请检查已完成的数据。',
toEthScan: '查看ETH Scan',
txCompleted: '已上链',
txDetail: '查看交易',
toVarify: '验证',
varifySuccess: '验证通过',
varifyFailed: '验证失败',
varifyResult: '验证结果',
failedTxhashes: '验证失败的交易哈希'
},
sharedTx: {
startTx: '发起多签交易',
signTx: '签名多签交易',
selectSponsor: '选择发起人',
createTx: '构建多签交易',
contractHash: '合约哈希',
method: '方法名',
parameters: '参数列表',
starterSign: '发起人签名',
txSerialized: '签名后的交易:',
addSign: '增加签名',
txContent: '交易内容',
currentSign: '当前签名地址',
selectSigner: '选择签名地址',
copy: '复制',
send: '立即发送',
isSendTxTip: '该交易的签名数量已满足要求。是否立即发送交易上链?',
txSentSuccess: '发送交易上链成功。',
paramsError: '输入参数有误。请检查。'
},
commonWalletHome: {
claimableOng: '可提取的ONG',
unboundOng: '未绑定的ONG',
redeem: '提取',
receive: '接收',
swap: '映射',
walletQrCode: '钱包地址二维码',
walletAddress: '钱包地址',
publicKey: '公钥',
redeemCharge: '提取ONG需要支付0.01ONG',
inputPass: '请输入钱包密码',
emptyPass: '密码不能为空',
cancel: '取消',
submit: '提交',
swapText: '欢迎使用“一站式”主网ONT切换。用户可以在这里将NEP-5 ONT映射成主网ONT。映射将在一个月内完成,您可以登录swap.ont.io查询映射状态。',
stepFollow: '您只需要使用以下步骤执行操作:',
step1: '导入NEO钱包的私钥创建钱包',
step2: '点击映射按钮发起映射',
step3: '查看映射进度',
swapAmount: '映射数额',
nep5Balance: 'NEP-5 ONT 余额:',
password: '密码',
validAmount: "请输入正确数额",
checkMore: '查看更多',
balance: '余额',
scriptHash: '合约哈希',
add: '+ 添加',
addOep4: '添加OEP-4 Token',
enterScripthash: '请输入OEP-4的合约哈希',
invalidScriptHash: '请输入正确的合约哈希',
addOep4Success: '添加OEP-4 token成功!',
noOep4Contract: '在链上找不到该OEP4合约',
networkError: '网络错误!请稍后重试。',
oep4Exists: '您已经添加过该OEP-4 Token。',
go: '查看详情'
},
transfer: {
inputValidAmount: '请输入有效的转账金额。',
inputValidAddress: '请输入有效的转账地址。',
exceedBalance: '转账金额不能超余额',
ongBalanceNotEnough: '您的ONG余额不足以支付转账和手续费。',
//Needs translation
warningTransferAllONG: 'Transferring this amount of ONG means you will not have enough ONG to pay\r\nfor further transaction fees (including claiming unbound ONG). \r\n\r\nContinue?'
},
setting: {
name: '设置',
net: '网络',
lang: '语言',
testNet: 'ONT测试网络',
mainNet: 'ONT主网',
en: 'English',
zh: '中文',
pathTit: '当前路径: ',
path: '钱包保存路径(请不要设到OWallet的安装位置!)',
change: '修改',
setNetworkSuccess: '网络成功设置为:',
wallets: '钱包',
ontid: 'ONT ID',
nodeStake: '节点质押',
help: '帮助',
settings: '设置',
nodeAddress: '节点',
setNodeSuccess: '节点成功设置为:',
notInstallationPath: '请不要设置到Owallet的安装位置。',
notSetPath: '未设置keystore保存路径。'
},
ledgerWallet: {
nameOfLedgerWallet: 'Ledger钱包名称',
info: 'Ledger钱包信息',
connectApp: '请连接您的ledger设备并打开ONT app.',
status: '设备状态',
labelEmpty: '钱包名称不能为空.',
deviceError: '不能连接到设备,请重试.',
signFailed: '使用ledger签名交易失败。',
selectAccount:"请选择您Ledger设备里的账户(可多选)",
normalMode:'普通模式',
advancedMode:'高级模式',
alreadyImported:"部分选中账户已导入",
specifyPath:"请选择并指定导入帐户的路径",
pleaseSelectWallet:"请选择想导入的钱包并输入名称",
},
ledgerStatus: {
NOT_FOUND: 'Ledger没有打开',
NOT_SUPPORT: 'Ledger不支持',
NO_DEVICE: '请连接Ledger并打开',
READY: 'Ledger准备就绪',
NOT_OPEN: 'Ledger上的ONT app没有打开'
},
nodeStake: {
iHaveKnown: '我已知晓',
ontid: 'ONT ID',
nodeStake: '节点质押',
stakeWalletAddress: '质押钱包地址',
nodePk: '节点公钥',
contract: '质押合约',
commitmentQuantity: '承诺质押数量',
stakeQuantity: '实际质押数量',
claimableQuantity: '可提取质押数量',
stake: '质押',
feeTip: '质押需要收取500ONG作为服务费',
selectOntid: '选择ONT ID',
selectStakeWallet: '选择质押钱包',
next: '下一步',
selectIdentity: '选择你的ONT ID',
selectIndividualWallet: '请选择普通钱包',
selectLedgerWallet: '请连接您的ledger设备并打开ONT',
invalidOntid: '无效的ONT ID',
invalidAddress: '无效的质押钱包地址',
stakeQuantityEmpty: '请输入质押数量',
password: '输入密码',
signWithOntid: '使用ONT ID签名',
signWithWallet: '选择钱包',
enterOntidPass: '请输入ONT ID的密码',
enterWalletPass: '请输入钱包的密码',
quitWarmMsg: '选择退出节点,则可退回所有初始质押。候选节点退出后一周期可以退回质押,共识节点需要两周期。退出节点后,如果想要再次运行节点,需要重新注册。',
back: '返回',
recall: '撤销',
refund: '退款',
quitNode: '退出节点',
newStake: '新质押',
passwordEmpty: '密码不能为空',
search: 'Search'
},
nodeStakeStatus: {
transfering: '转账中',
transfered: '转账完成',
transferFailed: '转账失败',
audit: '审核',
auditing: '审核中',
audited: '审核完成',
auditFailed: '审核失败',
stake: '质押',
staked: '质押完成',
nodeExited: '节点退出',
refund: '退款',
refunding: '退款中',
refunded: '退款完成',
refundFailed: '退款失败',
stakeExited: '质押退出',
quitStake: '退出质押',
unfrozenToRefund: '解除冻结成功,可以申请退款',
transferNeedTime: '转账需要一定时间',
serviceFee: '质押需要收取500ONG作为服务费',
auditNeedTime: '审核需要一定时间',
refundNeedTime: '退款需要一定时间',
txFailed: '交易失败'
},
redeemInfo: {
info: '提取ONG',
claimableOng: '可提取ONG是您可以提取的ONG的数量,手续费为0.01个ONG。每次钱包中完成一笔交易后,该余额会更新。',
unboundOng: '已解绑的ONG是指尚未添加到您的可提取ONG余额(仅会在您钱包做出一笔ONT交易后更新)中的ONG。当您的地址完成一笔交易后,您可提取的ONG余额将会更新(即将已解绑的ONG数额将添加到您可提取的ONG余额中去。)',
claimableOngName: '可提取ONG:',
unboundOngName: '已解绑的ONG:',
noClaimableOng: '您没有可提取的ONG。当您地址上完成一笔ONT转出交易后,可提取的ONG余额将会更新。'
},
nodeMgmt: {
nodeUser: '您是节点用户,从这里可以管理节点质押',
nodeStakeMgmt: '节点质押管理',
normalUser: '您是普通用户,从这里可以参加授权质押',
stakeAuthorizaton: '节点授权质押',
nodeStake: '节点质押',
userStakeAuthorization: '用户授权质押',
newStake: '提交新的节点质押',
allowStakes: '允许其他用户授权质押',
deny: '拒绝',
permit: '允许',
yourStakeAmount: '您的节点质押数额',
stakeLimit: '节点质押数额上限',
userNumber: '当前参与授权质押的用户数量',
userStakeAmount: '当前用户授权质押数额',
rewardsPerMonth: '预计每月收益总额',
rewardsTip: '预计每月收益总额包括节点的和参与授权质押用户的收益总额',
rewardProportion: '收益分配比例: ',
nodeRewardProportion: '节点质押收益分配比例',
userRewardProportion: '用户质押收益分配比例',
current: '当前',
nodeRewardProportionTip: '节点质押收益分配比例:表示节点获得节点质押部分的ONT收到的交易手续费和解绑ONG收益的百分比。',
userRewardProportionTip: '用户质押收益分配比例:表示节点获得用户质押部分的ONT收到的交易手续费和解绑ONG收益的百分比。',
confirm: '确认',
changesTakeEffect: '更改需在经过两轮共识周期后生效(每轮周期大约30天)。',
stakeAuthorization: '授权质押',
toNextRound: '到下一轮还有',
rank: '排名',
name: '节点名称',
currentStake: '当前质押总额',
process: '进度',
changes: '排名变化',
userParticipate: '请确保您是想要参与授权质押的用户。',
nodeName: '节点名称',
walletAddress: '您的钱包地址',
inAuthorization: '授权质押中',
cancelStakeAuthorization: '取消授权质押',
locked: '取消的授权质押(锁定中)',
claimable: '可提取',
redeem: '提取',
profit: '收益',
rewards: '收益',
newStakeAuthorization: '提交新的授权质押',
cancelAuthorization: '取消授权质押',
units: '授权质押份数',
stakeAmountTip: '质押数额 = 份数 * 1 ONT/每份.',
stakeAmount: '质押数额',
submit: '提交',
allowedStakeUnits: '允许授权质押份数',
allowedStakeAmount: '允许授权质押数额',
noChange: '您没有修改',
noRewards: '没有可提取的收益',
switchWallet: '切换钱包',
noClaimableOnt: '没有可提取的ONT',
amountToCancel: '要取消的质押数额',
unitToCancel: '要取消的质押份数',
invalidInput: '请输入合理的值',
peerNotAllowAuthorize: '此节点当前不允许授权质押',
addInitPos: '增加初始质押',
reduceInitPos: '减少初始质押',
amountToAdd: '要增加的质押数额',
amountToReduce: '要减少的质押数额',
notThanCommitment: '质押数额不能少于承诺质押数额。',
notLessTotalPos: '初始质押数太小。',
notThanMax: '允许授权质押数额不能超过节点质押数额上限。',
refresh: '刷新',
totalStakeAmount: '授权质押总额',
blocks: '区块',
proportionNextRound: '质押用户收益分配比例(节点/用户)',
proportionNextRoundTip: '这是节点选择的在下一轮共识中,分享给授权质押用户的节点自身质押部分ONT和用户质押部分ONT收到的手续费收益和解绑ONG收益的比例。\n请注意,并非所有节点都与授权质押用户分享本体基金会的奖励。点击下面的链接查看更多相关信息。',
authorizationFAQ: '节点授权质押常见问题解答',
nodeAndUser: '节点 / 用户',
authorizeTip: '用户对该节点的授权抵押金额,包括本轮新授权的ONT和已生效的授权ONT,取消授权会优先取消本轮新授权的ONT,取消后进入用户的可提取ONT中。本轮新授权的ONT不足则会取消已生效的授权ONT,按照节点是候选/共识状态分别锁定1轮或2轮,之后进入用户的可提取ONT中。',
rewardTip: '本体网络收到的所有手续费按照50%/50%的比例分给所有候选节点和共识节点,其中候选节点部分按照节点总抵押大小线性分配到每个候选节点,每个候选节点先拿走自己的部分(百分比),剩下的按照每个地址授权ONT的多少线性分配到每个地址。其中共识节点部分按照分润曲线分配到每个共识节点,每个共识节点先拿走自己的部分(百分比),剩下的按照每个地址授权ONT的多少线性分配到每个地址。',
unboundOng: '解绑的 ONG',
activeT: '本轮生效',
activeT1: '下一轮生效',
activeT2: '下下轮生效',
changeRewardProportion: '修改收益分配比例',
edit: '修改',
stakeHistory: '我的质押',
cancelUnits: '份',
stakeWalletAddress: '质押钱包地址',
lastUpdate: '上次更新时间',
walletRewardTip: '这是当前周期内您的钱包所有的授权质押收益',
switchMainnet: '请切换到主网。',
consensusNode: '共识节点',
candidateNode: '候选节点',
lockedONT: '当前锁定的ONT是由智能合约暂时持有的用户授权质押数额。锁定期满后,会在可提取的ONT中显示并可提取',
unboundONG: '这是用户授权质押的ONT所解绑的ONG。',
profitONG: '这是您已获得的交易费收益。该收益会在每轮共识周期开始时更新。',
getProfitPart: '产生收益中',
newStakePart: '新的质押',
claimableONT: '可提取ONT',
redeemInitPos: '提取可提取质押',
initPosInLock: "锁定中",
initPosRedeemable: '可提取',
noClaimbleInitPos: '没有可提取的初始质押。',
redeemInitPosOk: '确认提取',
hasClaimableInitPos: '您还有可提取的初始质押。请先提取该部分ONT。',
noClaimbleToRefund: '没有可提取的ONT。无法提款。',
newNodeApply: '注册新节点',
nodeApplyTip: '注册成为本体的节点',
},
vote: {
node: 'Node',
vote: '治理投票',
voteTip: "如果您是已授权的用户,从这里可以参与Ontology的治理投票",
login: '登录',
notSeeWallet: '没有看到您的钱包?导入一个。',
importHere: '由此导入',
notStart: '未开始',
inProgress: '进行中',
finished: '已结束',
canceled: '已取消',
nodeCanVoteOnly: '当前仅北斗共识节点用户可以参与投票',
title: '标题',
detail: '内容',
votingStarts: '投票开始时间',
votingEnds: '投票结束时间',
back: '返回',
submit: '提交',
submitVoteSuccess: '投票成功!',
submitVoteFail: '投票失败!',
stopVoteSuccess: '取消投票成功!',
stopVoteFail: '取消投票失败!',
createVoteSuccess: '创建投票成功!',
createVoteFail: '创建投票失败!',
onlySupportEnglish: '目前仅支持输入英文内容',
fillBlanks: '请填写空白',
endTimeError: "投票结束时间必须是将来时间",
votingTopics: '投票主题',
votingDetail: '投票内容',
stopVote: '停止投票',
info: '信息',
startTime: '开始时间',
endTime: '结束时间',
hash: 'Hash',
creatorAddress: '创建者地址',
votingStatus: '投票状态',
myVotes: '我的投票',
approval: '赞成',
opposition: '反对',
allVotes: '所有投票',
created: '我创建的',
duration: '持续时间',
notAllowVote: '您现在不能投票。该项投票现在是: ',
notAllowStop: '您现在不能结束投票。该项投票现在是: ',
name: '名称',
address: '地址',
votes: '投票数',
selectWallet: '请选择节点运营钱包',
startTimeError: '投票开始时间不能晚于结束时间',
new: '新建'
},
nodeApply: {
newNodeApply: '注册新节点',
stakeWallet: '节点质押钱包',
operationWallet: '节点运营钱包',
selectOperationWallet: '选择运营钱包',
operationPk: '运营钱包公钥',
enterOperationPk: '输入运营钱包公钥',
invalidOperationPk: '错误的运营钱包',
stakeAmount: '质押金额',
inputStakeAmount: '输入质押金额',
next: '下一步',
ok: '确认',
cancel: '取消',
operationWalletPublickey: '运营钱包公钥',
registerSuccess: '恭喜注册节点成功',
completeNodeInfo: '立刻完善节点信息',
later: '稍后再说',
sameWalletNotAllowed: '运营钱包和质押钱包不能是同一个钱包',
operationWalletRequired: '运营钱包是必需的',
stakeWalletRequired: '质押钱包是必需的',
stakeAmountRequired: '质押金额是必需的',
minStateAmount: '质押金额至少是10,000 ONT',
proxyServiceTip: '本体社区提供了节点代运营服务。',
proxyServiceLink: '点击这里查看详情。',
unsupportedLedger:"节点启动时,暂不支持选择Ledger硬件钱包作为运营钱包",
},
myNode: {
myNode: '我的节点',
stakeWalletAddress: '质押钱包地址',
operationWalletPk: '运营钱包公钥',
manage: '管理',
applyNode: '注册新节点'
},
nodeInfo: {
nodeInfo: '节点信息',
name: '名称',
enterName: '节点名称',
logo: 'Logo',
enterLogo: 'Logo链接',
location: '地区',
enterLocation: '节点所在地区',
ip: 'IP',
enterIp: '节点的IP',
description: '描述',
enterDesc: '节点的描述',
website: '网站',
enterWebsite: '节点网站',
telegram: 'Telegram',
enterTelegram: '节点的Telegram',
twitter: 'Twitter',
enterTwitter: '节点的Twitter',
facebook: 'Facebook',
enterFacebook: '节点的Facebook',
contactOntologyEmail: '联系Ontology的邮箱',
enterContactEmail: '联系邮箱',
openEmail: '公开的邮箱',
enterOpenEmail: '公开的邮箱',
ifOpenInfo: '是否公开节点信息',
submit: '提交',
updateSuccess: '更新成功',
updateFailed: '更新失败',
ledgerWalletNotSupportForNow: '使用Ledger注册的节点,暂时不支持更新节点相关信息.请发送邮件至:'
},
exchange: {
exchange: 'Exchange',
changelly: 'Changelly',
cryptonex: 'Cryptonex',
loading: 'Loading latest pricing information, please wait..'
},
dapps: {
dapps: 'DApps',
sesameSeed: '芝麻籽',
sesameseedDesc: 'Sesameseed voting management',
notification: '注意',
userPolicy: '您将跳转至第三方dApp页面,在第三方dApp上的使用行为将适用该第三方dApp的《用户协议》和《隐私政策》,由该第三方dApp直接并单独向您承担责任',
ontidMgmt: '管理ONT ID。该功能以后会被移除。请备份ONT ID相关数据。'
},
sesameseed: {
stakeAmountTip: 'Stake amount for Sesameseed is 1 unit equals 1 ONT',
authorizeTip: 'If a new stake is canceled, it will add to the “canceled” ONT and be directly deposited in the users account within 24 hours. If authorized ONT from a previous consensus round is canceled it will be added to the “canceled” ONT and be directly deposited in the originating users account within 24 hours of the beginning of the next consensus round if Sesameseed is a candidate node (or one round later if Sesameseed is a consensus node). If a user has both authorized ONT from this consensus round and a previous round and cancels an ONT amount exceeding the amount from this round, they will receive authorized ONT from this consensus round first and the remaining authorized ONT in the next round.',
rewardTip: 'Sesameseed rewards Ontology Stake Authorizations in SEED for both foundation rewards created as a candidate or consensus node as an OEP-4 token “SEED”. This token is rewarded directly to Staking participants. In addition to node rewards, 100% of ONG unbound while staking is pooled by all stake authorizations and added to the total “Node Reward”, as a result this node reward is also provided in the form of “SEED” Token. Rewards are distributed daily without the need to redeem. Find out more at https://sesameseed.org.',
pendingWithdrawals: 'Pending canceled stake authorization'
}
}
================================================
FILE: src/main.js
================================================
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import App from './App'
import router from './router'
import store from './store'
import 'font-awesome/css/font-awesome.css'
import {Button, message, Steps, Input ,Form, Icon, Select, Spin, Alert, Modal, Slider,Radio, Pagination,Switch, DatePicker, TimePicker,
Row, Col, InputNumber, Layout, Menu, Breadcrumb, Checkbox, Tooltip, Table, Dropdown, Card, Tabs,Space } from 'ant-design-vue'
import VueClipboard from 'vue-clipboard2'
VueClipboard.config.autoSetContainer = true // add this line
Vue.use(VueClipboard)
import i18n from './lang'
import VeeValidate from 'vee-validate'
import { VALIDATE_DICTIONARY } from './core/consts'
import validationMessages_en from 'vee-validate/dist/locale/en';
import validationMessages_zh from 'vee-validate/dist/locale/zh_CN';
Vue.use(VeeValidate, {
i18n,
dictionary: {
en: Object.assign({},validationMessages_en, VALIDATE_DICTIONARY.en),
zh: Object.assign({},validationMessages_zh, VALIDATE_DICTIONARY.zh)
}
})
import service from './core/utils'
Vue.prototype.httpService = service;
import { VOTE_ROLE } from './core/consts'
const mixin = {
data () {
return {
VOTE_ROLE: VOTE_ROLE
}
}
}
Vue.mixin(mixin)
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
Vue.http = Vue.prototype.$http = axios
Vue.config.productionTip = false
Vue.use(VueAxios, axios)
Vue.component(Button.name, Button)
Vue.component(Steps.name, Steps)
Vue.component(Steps.Step.name, Steps.Step)
Vue.component(Input.name, Input)
Vue.component(Input.TextArea.name, Input.TextArea)
Vue.component(Form.name, Form)
Vue.component(Form.Item.name, Form.Item)
Vue.component(Icon.name, Icon)
Vue.component(Select.name, Select)
Vue.component(Select.Option.name, Select.Option)
Vue.component(Spin.name, Spin)
Vue.component(Alert.name, Alert)
Vue.component(Input.Search.name, Input.Search)
Vue.component(InputNumber.name, InputNumber)
Vue.component(Modal.name, Modal)
Vue.component(Slider.name, Slider)
Vue.component(Row.name, Row)
Vue.component(Col.name, Col)
Vue.component(Layout.name, Layout)
Vue.component(Layout.Header.name, Layout.Header)
Vue.component(Layout.Footer.name, Layout.Footer)
Vue.component(Layout.Sider.name, Layout.Sider)
Vue.component(Layout.Content.name, Layout.Content)
Vue.component(Menu.name, Menu)
Vue.component(Menu.Item.name, Menu.Item)
Vue.component(Menu.SubMenu.name, Menu.SubMenu)
Vue.component(Menu.Divider.name, Menu.Divider)
Vue.component(Menu.ItemGroup.name, Menu.ItemGroup)
Vue.component(Breadcrumb.name, Breadcrumb)
Vue.component(Breadcrumb.Item.name, Breadcrumb.Item)
// Vue.component(Checkbox.name, Checkbox)
Vue.component(Radio.name, Radio)
Vue.component(Radio.Group.name, Radio.Group)
Vue.component(Radio.Button.name, Radio.Button)
Vue.component(Tooltip.name, Tooltip)
Vue.component(Table.name, Table)
Vue.component(Dropdown.name, Dropdown)
Vue.component(Pagination.name, Pagination)
Vue.component(Switch.name, Switch)
Vue.component(Card.name, Card)
Vue.component(DatePicker.name, DatePicker)
Vue.component(TimePicker.name, TimePicker)
Vue.use(Tabs)
Vue.use(Checkbox)
Vue.use(Space)
Vue.prototype.$message = message
Vue.prototype.$confirm = Modal.confirm
Vue.prototype.$success = Modal.success
Vue.prototype.$info = Modal.info
/* eslint-disable no-new */
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount('#app')
================================================
FILE: src/router/index.js
================================================
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [{
path: '/Dashboard',
name: 'Dashboard',
component: require('@/components/Dashboard').default
},
{
path: '/identitys',
name: 'Identitys',
component: require('@/components/Identitys').default
},
{
path: '/Wallets',
name: 'Wallets',
component: require('@/components/Wallets').default
},
{
path: '/loginLedger',
name: 'LoginLedger',
component: require('@/components/LedgerWallet/LoginLedger').default
},
{
path: '/setting',
name: 'Setting',
component: require('@/components/Setting').default
},
{
path: '/dapps',
name: 'Dapps',
component: require('@/components/Dapps').default
},
{
path: '/identitys/createIdentity',
name: 'CreateIdentity',
component: require('@/components/Identitys/CreateIdentity').default
},
{
path: '/identitys/importIdentity',
name: 'ImportIdentity',
component: require('@/components/Identitys/ImportIdentity').default
},
{
path: '/Wallets/createJsonWallet',
name: 'CreateJsonWallet',
component: require('@/components/JsonWallet/CreateJsonWallet').default
},
{
path: '/Wallets/importJsonWallet',
name: 'ImportJsonWallet',
component: require('@/components/JsonWallet/ImportJsonWallet').default
},
{
path: '/Wallets/importLedgerWallet',
name: 'ImportLedgerWallet',
component: require('@/components/LedgerWallet/ImportLedgerWallet').default
},
{
path: '/Wallets/createSharedWallet',
name: 'CreateSharedWallet',
component: require('@/components/SharedWallet/CreateSharedWallet').default
},
{
path: '/Wallets/importSharedWallet',
name: 'ImportSharedWallet',
component: require('@/components/SharedWallet/ImportSharedWallet').default
},
{
path: '/sharedWallet',
name: 'SharedWalletDetail',
component: require('@/components/SharedWallet/SharedWalletDetail').default,
children: [{
path: 'home',
name: 'SHaredWalletHome',
component: require('@/components/SharedWallet/SharedWalletHome').default,
},
{
path: '/sharedWallet/sendTransfer',
component: require('@/components/SharedWallet/SharedWalletSend').default
},
{
path: '/sharedWallet/pendingTxHome',
component: require('@/components/SharedWallet/PendingTxHome').default
},
{
path: '/sharedWallet/copayers',
name: 'SharedWalletCopayer',
component: require('@/components/SharedWallet/View/SharedWalletCopayer').default,
},
{
path: '/sharedWallet/paxMgmt',
name: 'PaxMgmt',
component: require('@/components/SharedWallet/PAX/PaxMgmt').default,
},
{
path: '/sharedWallet/startProcess',
name: 'StartProcess',
component: require('@/components/SharedWallet/PAX/StartProcess').default,
},
{
path: '/sharedWallet/signProcess',
name: 'SignProcess',
component: require('@/components/SharedWallet/PAX/SignProcess').default,
},
{
path: '/sharedWallet/txMgmt',
name: 'SharedTxMgmt',
component: require('@/components/SharedWallet/Tx/SharedTxMgmt').default
}
]
},
{
path: '/vote',
name: 'NodeVote',
component: require('@/components/Node/Vote/index').default,
children: [
{
path: 'login',
name: 'VoteLogin',
component: require('@/components/Node/Vote/Login').default
},
{
path: 'votes',
name: 'VoteList',
component: require('@/components/Node/Vote/List').default
},
{
path: 'create',
name: 'VoteCreate',
component: require('@/components/Node/Vote/Create').default
},
{
path: 'detail',
name: 'VoteDetail',
component: require('@/components/Node/Vote/Detail').default
},
]
},
{
path: '/node/apply',
name: 'NodeApply',
component: require('@/components/Node/NodeApply/Register').default
},
{
path: '/node/applysuccess',
name: 'NodeApplySuccess',
component: require('@/components/Node/NodeApply/RegisterSuccess').default
},
{
path: '/node/mynode',
name: 'MyNode',
component: require('@/components/Node/NodeManagement/MyNode').default
},
{
path: '/commonWalletSend',
name: 'CommonSendHome',
component: require('@/components/CommonWallet/SendHome').default
},
{
path: '/commonWalletReceive/:walletType',
name: 'CommonReceive',
component: require('@/components/CommonWallet/CommonReceive').default
},
{
path: '/commonWalletRedeem/:walletType',
name: 'CommonRedeem',
component: require('@/components/CommonWallet/CommonRedeem').default
},
{
path: '/commonTokenSwap',
name: 'CommonTokenSwap',
component: require('@/components/CommonWallet/CommonTokenSwap').default
},
{
path: '/node/nodeStakeIntro',
name: 'NodeStakeIntro',
component: require('@/components/Node/NodeStake/NodeStakeIntro').default
},
{
path: '/node/nodeStakeRegister',
name: 'NodeStakeRegister',
component: require('@/components/Node/NodeStake/NodeStakeRegister').default
},
{
path: '/node/nodeStakeInfo',
name: 'NodeStakeInfo',
component: require('@/components/Node/NodeStake/NodeStakeInfo').default
},
{
path: '/node',
name: 'NodeManagement',
component: require('@/components/Node/Node').default
},
// {
// path: '/node/nodeLogin',
// name: 'NodeLogin',
// component: require('@/components/Node/NodeManagement/NodeLogin').default
// },
{
path: '/node/nodeStakeMgmt',
name: 'NodeStakeManagement',
component: require('@/components/Node/NodeManagement/NodeStakeManagement').default
},
{
path: '/node/nodeList',
name: 'NodeList',
component: require('@/components/Node/NodeAuthorize/NodeList').default
},
{
path: '/node/stakeHistory',
name: 'StakeHistory',
component: require('@/components/Node/NodeAuthorize/StakeHistory').default
},
{
path: '/node/authorizeLogin',
name: 'AuthorizeLogin',
component: require('@/components/Node/NodeAuthorize/AuthorizeLogin').default
},
{
path: '/dapps/authorizeLoginSesameseed',
name: 'AuthorizeLoginSesameseed',
component: require('@/components/Node/NodeAuthorize/Sesameseed/AuthorizeLoginSesameseed').default
},
{
path: '/node/authorizationMgmt',
name: 'AuthorizationMgmt',
component: require('@/components/Node/NodeAuthorize/AuthorizationMgmt').default
},
{
path: '/dapps/authorizationMgmtSesameseed',
name: 'AuthorizationMgmtSesameseed',
component: require('@/components/Node/NodeAuthorize/Sesameseed/AuthorizationMgmtSesameseed').default
},
{
path: '/node/newAuthorization',
name: 'NewAuthorization',
component: require('@/components/Node/NodeAuthorize/NewAuthorization').default
},
{
path: '/dapps/newAuthorizationSesameseed',
name: 'NewAuthorizationSesameseed',
component: require('@/components/Node/NodeAuthorize/Sesameseed/NewAuthorizationSesameseed').default
},
{
path: '/oep4Home',
name: 'Oep4Home',
component: require('@/components/Common/Oep4Home').default
},
{
path: '*',
redirect: '/'
},
{
path: '/',
name: 'Home',
component: require('@/components/Home').default
},
]
})
================================================
FILE: src/store/index.js
================================================
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
Vue.use(Vuex)
export default new Vuex.Store({
modules,
strict: process.env.NODE_ENV !== 'production'
})
================================================
FILE: src/store/modules/CreateIdentity.js
================================================
import { Wallet, Identity, Crypto, OntidContract, TransactionBuilder } from "ontology-ts-sdk";
import {GAS_PRICE, GAS_LIMIT} from '../../core/consts'
const state = {
currentStep: 0,
label: '',
ontid: '',
identity: '',
tx: ''
}
const mutations = {
ADD_CREATE_IDENTITY_STEP(state, payload) {
state.currentStep += 1;
},
SUB_CREATE_IDENTITY_STEP(state, payload) {
if(state.currentStep > 0) {
state.currentStep -= 1;
}
},
CREATE_IDENTITY(state, payload) {
state.label = payload.label
state.ontid = payload.ontid
state.identity = payload.identity,
state.tx = payload.tx
},
INIT_CREATE_IDENTITY(state, payload) {
state.currentStep = 0
state.label = ''
state.ontid = ''
state.identity = '',
state.tx = ''
}
}
const actions = {
createIdentityWithPrivateKey({commit}, body) {
// wallet.scrypt.n = 16384;
// let params = {
// cost: 16384,
// blockSize: 8,
// parallel: 8,
// size: 64
// };
let identity = Identity.create(body.privateKey, body.password, body.label)
const publicKey = body.privateKey.getPublicKey();
const tx = OntidContract.buildRegisterOntidTx(identity.ontid, publicKey, GAS_PRICE, GAS_LIMIT);
tx.payer = body.payer;
TransactionBuilder.signTransaction(tx, body.privateKey);
identity = identity.toJsonObj();
commit('CREATE_IDENTITY', {
label: body.label,
ontid: identity.ontid,
identity,
tx: tx
})
return tx
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/CreateJsonWallet.js
================================================
import { Wallet, Account, Crypto } from "ontology-ts-sdk";
const state = {
currentStep: 0,
label: '',
address: '',
publicKey: '',
account: '',
downloadContent: '',
wif: ''
}
const mutations = {
ADD_CREATE_JSON_STEP(state, payload) {
state.currentStep += 1;
},
SUB_CREATE_JSON_STEP(state, payload) {
if(state.currentStep > 0) {
state.currentStep -= 1;
}
},
CREATE_JSON_WALLET(state, payload) {
state.label = payload.label
state.account = payload.account
state.downloadContent = payload.content
state.address = payload.account.address
state.publicKey = payload.account.publicKey,
state.wif = payload.wif
},
INIT_JSON_WALLET(state, payload) {
state.currentStep = 0
state.label = ''
state.account = ''
state.downloadContent = ''
state.address = ''
state.publicKey = '',
state.wif = ''
}
}
const actions = {
createJsonWalletWithPrivateKey({commit}, body) {
let wallet = Wallet.create(body.label || "")
wallet.scrypt.n = 16384;
let params = {
cost: 16384,
blockSize: 8,
parallel: 8,
size: 64
};
let account = Account.create(body.privateKey, body.password, body.label, params)
account.isDefault = true;
// 生成下载钱包的内容
wallet.addAccount(account);
account = account.toJsonObj();
commit('CREATE_JSON_WALLET', {
label: body.label,
account: account,
content: wallet.toJsonObj(),
wif: body.wif
})
return account
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/CreateSharedWallet.js
================================================
import axios from 'axios';
import { ONT_PASS_NODE, ONT_PASS_NODE_PRD, ONT_PASS_URL } from '../../core/consts'
import dbService from '../../core/dbService'
const state = {
currentStep: 0,
label: '',
address: '',
copayers: [
{ name: '', publickey: ''},
{ name: '', publickey: '' }
],
requiredSigNum:2
}
const mutations = {
CREATE_SHARED_WALLET(state, payload) {
state.label = payload.sharedWalletName,
state.address = payload.sharedWalletAddress
},
UPDATE_CREATE_SHARED_LABEL(state, payload) {
state.label = payload.label;
},
UPDATE_REQUIRED_SIG_NUMBER(state, payload) {
state.requiredSigNum = payload.requiredSigNum;
},
ADD_CREATE_SHARED_STEP(state, payload) {
state.currentStep += 1;
},
SUB_CREATE_SHARED_STEP(state, payload) {
if(state.currentStep > 0) {
state.currentStep -= 1;
}
},
UPDATE_CREATE_SHARED_COPAYERS(state, payload) {
state.copayers = payload.copayers
},
CLEAR_CREATE_SHARED_STATE(state,payload) {
state.currentStep = 0;
state.label = '';
state.address = '';
state.copayers = [
{ name: '', publickey: '' },
{ name: '', publickey: '' }
],
state.requiredSigNum = 2;
}
}
const actions = {
createSharedWallet({ commit, dispatch }, body) {
const net = localStorage.getItem('net')
const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD
dispatch('showLoadingModals')
return axios.post(ontPassNode + ONT_PASS_URL.CreateSharedWallet, body).then(res => {
if (res.status === 200 && res.data.Error === 0) {
commit('CREATE_SHARED_WALLET', {
label: body.sharedWalletName,
address: body.sharedWalletAddress
})
//save to db
const wallet = {
type: 'SharedWallet',
address: body.sharedWalletAddress,
wallet: body
}
dbService.insert(wallet);
dispatch('hideLoadingModals')
return res.data.Error;
} else {
dispatch('hideLoadingModals')
return res.data.Error;
}
}).catch(err => {
console.log(err)
dispatch('hideLoadingModals')
return err;
})
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/CurrentWallet.js
================================================
import axios from 'axios'
import {
getBalanceUrl
} from '../../core/utils'
const state = {
wallet : {
// for json and hardware wallet
publicKey: '',
address: '',
name: '',
//for shared wallet
coPayers: [],
requiredNumber:'',
totalNumber:''
},
balance: {
ont: 0,
ong: 0,
waitBoundOng:0,
unboundOng: 0
},
transfer: {
balance : {
ont: 0,
ong: 0
},
oep4s:[],
from:'',
to: '',
amount:0,
asset:'ONT',
gas:0.01,
coPayers : [],
sponsorPayer:'',
isRedeem: false
},
pendingTx: {
},
currentSigner: '',
localCopayers : [],
redeem: {
claimableOng: 0,
balanceOng: 0
},
nep5Ont: 0
}
const mutations = {
UPDATE_CURRENT_WALLET(state, payload){
state.wallet = Object.assign({}, state.wallet, payload.wallet);
},
UPDATE_TRANSFER(state, payload) {
state.transfer = Object.assign({}, state.transfer, payload.transfer)
},
UPDATE_LOCAL_COPAYERS(state, payload) {
state.localCopayers = payload.localCopayers
},
UPDATE_PENDINGTX(state, payload) {
state.pendingTx = payload.pendingTx
},
UPDATE_CURRENT_SIGNER(state, payload) {
state.currentSigner = payload.account
},
UPDATE_NATIVE_BALANCE(state, payload) {
state.balance = payload.balance
},
CLEAR_NATIVE_BALANCE(state, payload) {
state.balance = {}
},
CLEAR_CURRENT_TRANSFER(state, payload) {
state.transfer = {
balance: {
ont: 0,
ong: 0
},
oep4s: [],
from: '',
to: '',
amount: 0,
asset: 'ONT',
gas: 0.01,
coPayers: [],
sponsorPayer: ''
}
},
UPDATE_CURRENT_REDEEM(state, payload) {
state.redeem = payload.redeem
},
UPDATE_NEP5_ONT(state, payload) {
state.nep5Ont = payload.nep5Ont
},
UPDATE_TRANSFER_REDEEM_TYPE(state, payload) {
state.transfer.isRedeem = payload.type;
state.transfer.asset = payload.type ? 'ONG' : 'ONT'
}
}
const actions = {
clearTransferBalance({commit}) {
commit('CLEAR_CURRENT_TRANSFER')
},
getNativeBalance({commit}, {address}) {
const url = getBalanceUrl(address, 'NATIVE');
const balance = {}
return axios.get(url).then(res => {
if (res.data.result) {
for (let r of res.data.result) {
if (r.asset_name === 'ong') {
balance.ong = r.balance;
}
if (r.asset_name === 'waitboundong') {
balance.waitBoundOng = r.balance;
}
if (r.asset_name === 'unboundong') {
balance.unboundOng = r.balance;
}
if (r.asset_name === 'ont') {
balance.ont = r.balance;
}
}
commit('UPDATE_NATIVE_BALANCE', {
balance
})
return balance; // get balance succeed
}
}).catch(err => {
console.log(err)
return null; // get balance failed
})
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/Identities.js
================================================
import dbService, { dbFind } from '../../core/dbService';
const state = {
Identities: []
}
const mutations = {
FETCH_IDENTITIES(state, payload) {
state.Identities = payload.identities
},
DELETE_IDENTITY(state, payload) {
const identities = state.Identities.slice();
const index = identities.findIndex((w) => w.ontid === payload.ontid)
identities.splice(index, 1)
state.Identities = identities;
}
}
const actions = {
async fetchIdentitiesFromDb({ commit }, pk) {
try {
const IdentityDocs = await dbFind(dbService, { type: 'Identity' });
const identities = IdentityDocs.map(item => item.wallet)
commit('FETCH_IDENTITIES', { identities });
} catch (err) {
alert(err)
}
return true;
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/ImportSharedWallet.js
================================================
import axios from 'axios';
import { ONT_PASS_NODE, ONT_PASS_URL } from '../../core/consts'
import dbService from '../../core/dbService'
const state = {
currentStep: 0,
localCopayers: [],
sharedWallet:{}
}
const mutations = {
ADD_IMPORT_SHARED_STEP(state, payload) {
state.currentStep += 1;
},
SUB_IMPORT_SHARED_STEP(state, payload) {
if (state.currentStep > 0) {
state.currentStep -= 1;
}
},
UPDATE_LOCAL_COPAYERS(state, payload) {
state.localCopayers = payload.localCopayers
},
UPDATE_SHARED_WALLET(state, payload) {
state.sharedWallet = payload.sharedWallet;
},
CLEAR_IMPORT_SHARED_STATE(state, payload) {
state.currentStep = 0;
state.sharedWallet = {}
}
}
const actions = {
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/LedgerConnector.js
================================================
import { getDeviceInfo, getPublicKey } from '../../core/ontLedger'
import en from '../../lang/en'
import zh from '../../lang/zh'
import { Crypto } from 'ontology-ts-sdk'
function formatLedgerStatus(status) {
const lang = localStorage.getItem('user_lang') || 'en'
return lang === 'en' ? en.ledgerStatus[status] : zh.ledgerStatus[status]
}
function getDevice(commit, state) {
// if(state.publicKey) {
// return;
// }
getDeviceInfo().then(res => {
console.log('device: ' + res)
getLedgerPublicKey(commit, state)
commit('UPDATE_LEDGER_DEVICE_INFO', {deviceInfo: res});
}).catch(err => {
console.log(err)
commit('UPDATE_LEDGER_PUBLICKEY', { publicKey: '' })
const ledgerWallet = {
address: '',
publicKey: ''
}
commit('UPDATE_LEDGER_CONNECTOR_WALLET', {ledgerWallet})
if (err === 'NOT_FOUND') {
commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('NOT_FOUND')})
} else if (err === 'NOT_SUPPORT') {
commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('NOT_SUPPORT') })
} else {
commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('NO_DEVICE') })
}
})
}
function getLedgerPublicKey(commit, state) {
// if (state.publicKey) {
// return;
// }
getPublicKey().then(res => {
console.log('pk info: ' + res);
commit('UPDATE_LEDGER_PUBLICKEY', { publicKey: res })
commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('READY') })
getLedgerWallet(commit, res)
}).catch(err => {
console.log(err.message)
commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('NOT_OPEN') })
})
}
function getLedgerWallet(commit, pk) {
const publicKey = new Crypto.PublicKey(pk);
const address = Crypto.Address.fromPubKey(publicKey).toBase58();
const ledgerWallet = {
publicKey: pk,
address: address
}
commit('UPDATE_LEDGER_CONNECTOR_WALLET', {ledgerWallet: ledgerWallet})
}
const state = {
ledgerStatus: '',
deviceInfo: '',
publicKey: '',
intervalId:'',
ledgerWallet: {
address: '',
publicKey: ''
}
}
const mutations = {
UPDATE_LEDGER_DEVICE_INFO(state, payload){
state.deviceInfo = payload.deviceInfo
},
UPDATE_LEDGER_PUBLICKEY(state, payload) {
state.publicKey = payload.publicKey
},
UPDATE_LEDGER_STATUS(state, payload) {
state.ledgerStatus = payload.ledgerStatus
},
UPDATE_LEDGER_CONNECTOR_INTERVALID(state, payload) {
state.intervalId = payload.intervalId
},
UPDATE_LEDGER_CONNECTOR_WALLET(state, payload) {
state.ledgerWallet = payload.ledgerWallet;
}
}
const LEDGER_CONNECTOR_INTERVAL = 'ledger_connector_intervalId'
const actions = {
getLedgerStatus({dispatch,commit,state}, interval) {
dispatch('stopGetLedgerStatus');
let time = interval || 5000;
getDevice(commit, state)
const intervalId = setInterval(() => {
getDevice(commit, state)
}, time)
localStorage.setItem(LEDGER_CONNECTOR_INTERVAL, intervalId)
},
stopGetLedgerStatus({commit, state}) {
const intervalId = localStorage.getItem(LEDGER_CONNECTOR_INTERVAL) || ''
clearInterval(intervalId)
localStorage.removeItem(LEDGER_CONNECTOR_INTERVAL)
commit('UPDATE_LEDGER_PUBLICKEY', {publicKey: ''})
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/LedgerWallet.js
================================================
import { Crypto } from 'ontology-ts-sdk'
import { WALLET_TYPE} from '../../core/consts'
import dbService from '../../core/dbService'
const state = {
publicKey: '',
address: '',
isHardwareLogin: true
}
const mutations = {
LOGIN_WITH_LEDGER(state, payload) {
state.publicKey = payload.publicKey;
state.address = payload.address;
}
}
const actions = {
someAsyncTask({ commit }) {
// do something async
commit('INCREMENT_MAIN_COUNTER')
},
loginWithLedger({ commit }, pk) {
const publicKey = new Crypto.PublicKey(pk);
const address = Crypto.Address.fromPubKey(publicKey).toBase58();
const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'))
if(currentWallet.address !== address) {
return false;
} else {
commit('LOGIN_WITH_LEDGER', { publicKey:pk, address })
return true;
}
},
createLedgerWalletWithPk({commit}, body) {
const publicKey = new Crypto.PublicKey(body.pk);
const address = Crypto.Address.fromPubKey(publicKey).toBase58();
const ledgerWallet = {
publicKey: body.pk,
address,
neo: body.neo || false,
acct:body.acct,
timestamp: new Date().getTime(),
}
return ledgerWallet;
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/LoadingModal.js
================================================
// import $ from 'jquery'
const state = {
showLoading: false
}
const mutations = {
SHOW_LOADING_MODALS(state) {
state.showLoading = true;
},
HIDE_LOADING_MODALS(state) {
state.showLoading = false
}
}
const actions = {
showLoadingModals({commit}) {
// $("#loadingModal").modal('show')
commit('SHOW_LOADING_MODALS')
},
hideLoadingModals({commit}) {
// Wait for the animation to end
const tid = setTimeout( () => {
commit('HIDE_LOADING_MODALS')
clearTimeout(tid)
}, 500)
// setTimeout(()=>{
// $("#loadingModal").modal('hide')
// $('body').removeClass('modal-open');
// if ($('.modal-backdrop')) {
// $('.modal-backdrop').remove();
// }
// }, 500)
}
}
export default {
actions,
mutations,
state
}
================================================
FILE: src/store/modules/NodeAuthorization.js
================================================
import { getNodeUrl} from '../../core/utils'
import {NODE_DETAIL, NODE_NAME_LIST, OFF_CHAIN_NODES, NODE_CURRENT_STAKES} from '../../core/consts'
import numeral from 'numeral'
import { Crypto, RestClient, utils, GovernanceTxBuilder} from 'ontology-ts-sdk'
import {BigNumber} from 'bignumber.js'
import {dbUpsert, dbFind} from '../../core/dbService'
import axios from 'axios';
import {
message
} from 'ant-design-vue'
import i18n from '../../lang';
var dateFormat = require('dateformat');
// import nodes from '../../core/nodes.json'
//@Deprecated
async function matchNodeName(list) {
let nodes = []
const net = localStorage.getItem('net');
try {
if(net === 'MAIN_NET') { // only MainNet nodes have names
const res = await axios.get(NODE_NAME_LIST)
if (res && res.data && res.data.Result) {
nodes = res.data.Result
}
}
} catch(err) {
console.log(err)
}
console.log(nodes)
if (net === 'TEST_NET') {
list.forEach(item => {
item.name = 'Node_' + item.pk.substr(0, 6);
})
return;
}
for(const item of list) {
for (const cnode of nodes) {
if (cnode.PublicKey === item.pk || cnode.PublicKey === item.peerPubkey) {
item.name = cnode.Name
break;
}
else if (!cnode || !cnode.PublicKey) {
if (item.address) {
item.name = 'Node_' + (item.address.toBase58 ? item.address.toBase58().substr(0, 6) : item.address.substr(0, 6));
} else {
item.name = 'Node_' + item.pk.substr(0, 6)
}
}
}
}
}
async function fetchRoundBlocks() {
const net = localStorage.getItem('net');
let url = net === 'TEST_NET' ? 'https://polarisexplorer.ont.io/v2/nodes/block-count-to-next-round'
: 'https://explorer.ont.io/v2/nodes/block-count-to-next-round'
const res = await axios.get(url);
if (res.data && res.data.result) {
const {max_staking_change_count, count_to_next_round} = res.data.result
return Number(count_to_next_round);
} else {
throw new Error('Network error when fetch block counts.')
}
}
function delay(s) {
return new Promise((resolve, reject) => {
setTimeout(resolve, s);
})
}
function formatAuthorizationInfo(info) {
const authorizationInfo = info;
let inAuthorization = authorizationInfo.consensusPos + authorizationInfo.freezePos
+ authorizationInfo.newPos;
inAuthorization = numeral(inAuthorization).format('0,0');
const newStakePortion = numeral(authorizationInfo.newPos).format('0,0')
const receiveProfitPortion = numeral(authorizationInfo.consensusPos + authorizationInfo.freezePos).format('0,0')
let locked = authorizationInfo.withdrawPos + authorizationInfo.withdrawFreezePos;
locked = numeral(locked).format('0,0')
let claimableVal = authorizationInfo.withdrawUnfreezePos;
const claimable = numeral(claimableVal).format('0,0')
return {
inAuthorization,
locked,
claimable,
claimableVal,
newStakePortion,
receiveProfitPortion
}
}
const state = {
current_peer:{ // for node user
peerPubkey: '',
address: '',
status: 0,
initPos: 0,
initPosStr: '0',
totalPos: 0,
totalPosStr: '0'
},
peer_attrs: {
peerPubkey: '',
maxAuthorize: 0,
maxAuthorizeStr: '0',
t2PeerCost: 0,
t1PeerCost: 0,
tPeerCost: 0,
t2StakeCost: 0,
t1StakeCost: 0,
tStakeCost: 0,
},
current_node: '',
authorizationInfo:'',
splitFee: {
address: '',
amount: 0
},
countdown: 0,
node_list: [],
posLimit: 10,
peerUnboundOng: 0,
stakeHistory: [],
stake_authorization_wallet: '',
peerPoolMap:[],
sortedNodeList: []
}
const mutations = {
UPDATE_CURRENT_PEER(state, payload) {
state.current_peer = {
peerPubkey: payload.peerItem.peerPubkey,
address: payload.peerItem.address?payload.peerItem.address.toBase58() : '',
status: payload.peerItem.status,
initPos: payload.peerItem.initPos,
initPosStr: numeral(payload.peerItem.initPos).format('0,0'),
totalPos: payload.peerItem.totalPos,
totalPosStr: numeral(payload.peerItem.totalPos).format('0,0')
}
},
UPDATE_PEER_ATTRS(state, payload) {
state.peer_attrs = {
peerPubkey: payload.peerAttrs.peerPubkey,
maxAuthorize: payload.peerAttrs.maxAuthorize,
maxAuthorizeStr: numeral(payload.peerAttrs.maxAuthorize).format('0,0'),
t2PeerCost: payload.peerAttrs.t2PeerCost,
t1PeerCost: payload.peerAttrs.t1PeerCost,
tPeerCost: payload.peerAttrs.tPeerCost,
t2StakeCost: payload.peerAttrs.t2StakeCost,
t1StakeCost: payload.peerAttrs.t1StakeCost,
tStakeCost: payload.peerAttrs.tStakeCost
}
},
UPDATE_CURRENT_NODE(state, payload) {
state.current_node = payload.current_node
},
UPDATE_AUTHORIZATION_INFO(state, payload) {
const {
inAuthorization,
locked,
claimable,
claimableVal,
newStakePortion,
receiveProfitPortion
} = formatAuthorizationInfo(payload.info)
state.authorizationInfo = {
...payload.info,
inAuthorization,
locked,
claimable,
claimableVal,
newStakePortion,
receiveProfitPortion
}
},
UPDATE_SPLIT_FEE(state, payload) {
state.splitFee = payload.splitFee
},
UPDATE_COUNTDOWN_BLOCK(state, payload) {
state.countdown = payload.countdown;
},
UPDATE_NODE_LIST(state, payload) {
state.node_list = payload.list
},
UPDATE_POS_LIMIT(state, payload) {
state.posLimit = payload.posLimit
},
UPDATE_PEER_UNBOUND_ONG(state, payload) {
state.peerUnboundOng = payload.peerUnboundOng
},
UPDATE_STAKE_HISTORY(state, payload) {
state.stakeHistory = payload.history
},
UPDATE_STAKE_AUTHORIZATION_WALLET(state, payload) {
state.stake_authorization_wallet = payload.stakeWallet
},
UPDATE_PEER_POOL_MAP(state, payload) {
state.peerPoolMap = payload.peerMap
},
CLEAR_STAKE_HISTORY(state, payload) {
state.stakeHistory = []
},
UPDATE_SORTED_NODE_LIST(state, {list}) {
state.sortedNodeList = list;
}
}
const actions = {
async fetchPeerItem({commit}, pk){
const url = getNodeUrl();
const peerMap = await GovernanceTxBuilder.getPeerPoolMap(url);
if(!pk) {
return peerMap;
}
if(pk && peerMap[pk]) {
commit('UPDATE_CURRENT_PEER', {peerItem: peerMap[pk]})
return peerMap[pk]
} else {
const peerItem = {
peerPubkey: '',
address: '',
status: 0,
initPos: 0,
initPosStr: '0',
totalPos: 0,
totalPosStr: '0'
}
commit('UPDATE_CURRENT_PEER', { peerItem })
return null;
}
},
async fetchPeerAttributes({commit}, pk) {
const url = getNodeUrl();
const peerAttrs = await GovernanceTxBuilder.getAttributes(pk, url);
if (peerAttrs) {
commit('UPDATE_PEER_ATTRS', {peerAttrs})
return peerAttrs;
}
},
async fetchAuthorizationInfo({commit}, {pk, address}) {
const url = getNodeUrl();
const userAddr = new Crypto.Address(address);
const authorizeInfo = await GovernanceTxBuilder.getAuthorizeInfo(pk, userAddr, url)
if(authorizeInfo) {
commit('UPDATE_AUTHORIZATION_INFO', {info: authorizeInfo})
return authorizeInfo
}
},
async fetchSplitFee({commit}, address) {
const url = getNodeUrl();
const userAddr = new Crypto.Address(address);
const splitFee = await GovernanceTxBuilder.getSplitFeeAddress(userAddr, url)
if(splitFee) {
if(splitFee.amount) {
splitFee.amount = new BigNumber(splitFee.amount).div(1e9).toFixed(9)
}
commit('UPDATE_SPLIT_FEE', {splitFee})
return splitFee
}
},
async searchStakeHistory({commit, dispatch, state}, {address}) {
const url = getNodeUrl();
const list = []
const net = localStorage.getItem('net')
const off_chain_nodes_url = OFF_CHAIN_NODES[net];
const userAddr = new Crypto.Address(address);
try {
const res = await axios.get(off_chain_nodes_url);
const nodes = res.data.result.filter(node => node.public_key.indexOf('00aaaaaaaaa') < 0); //00aaaaaaaaa开头是无效的公钥
const infoTemp = await Promise.all(nodes.map(async item => {
const authorizeInfo = await GovernanceTxBuilder.getAuthorizeInfo(item.public_key, userAddr, url)
return {
...authorizeInfo,
nodeAddress: item.address
}
}))
infoTemp.forEach(item => {
if (item.nodeAddress === address) {
return;
}
let inAuthorization = item.consensusPos + item.freezePos +
item.newPos;
let locked = item.withdrawPos + item.withdrawFreezePos;
let claimableVal = item.withdrawUnfreezePos;
if (inAuthorization > 0 || locked > 0 || claimableVal > 0) {
const record = formatAuthorizationInfo(item)
record.name = '';
record.pk = item.peerPubkey;
record.stakeWallet = address;
list.push(record)
}
})
list.forEach(item => {
for (let i = 0; i < nodes.length; i++) {
if (item.pk === nodes[i].public_key) {
item.name = nodes[i].name ? nodes[i].name : 'Node_' + nodes[i].public_key.substr(0, 6)
}
}
})
commit('UPDATE_STAKE_HISTORY', {history: list})
dispatch('hideLoadingModals')
return list;
} catch(err) {
dispatch('hideLoadingModals')
console.log(err)
message.error(i18n.t('commonWalletHome.networkError'))
return [];
}
},
//@Deprecated
async fetchAllSortedNodeList({commit, dispatch}) {
const url = getNodeUrl();
try {
const peerMap = await GovernanceTxBuilder.getPeerPoolMap(url);
const list = []
for (let k in peerMap) {
let item = peerMap[k];
if (item.status !== 1 && item.status !== 2) { // consensus nodes and candidate nodes
continue;
}
item.pk = item.peerPubkey;
list.push(item)
}
list.sort((v1, v2) => {
if ((v2.initPos + v2.totalPos) > (v1.initPos + v1.totalPos)) {
return 1;
} else if ((v2.initPos + v2.totalPos) < (v1.initPos + v1.totalPos)) {
return -1;
} else {
return 0;
}
})
list.forEach((item, index) => {item.rank = index + 1})
await matchNodeName(list);
commit('UPDATE_SORTED_NODE_LIST', {list})
dispatch('hideLoadingModals')
return list;
} catch(err) {
console.log(err)
dispatch('hideLoadingModals')
message.error(i18n.t('commonWalletHome.networkError'))
return [];
}
},
//Deprecated
async fetchNodeList({commit, dispatch, state}, {pageSize, pageNum}) {
const url = getNodeUrl();
if(state.sortedNodeList.length === 0) {
await dispatch('fetchAllSortedNodeList')
}
try{
const nodes = state.sortedNodeList.slice(pageNum*pageSize, (pageNum+1) * pageSize).filter(item => item.peerPubkey)
console.log(nodes)
const listTemp = await Promise.all(nodes.map((item) => {
return GovernanceTxBuilder.getAttributes(item.peerPubkey, url)
}))
nodes.forEach((item, i) => {
const attr = listTemp[i];
item.maxAuthorize = attr.maxAuthorize;
item.maxAuthorizeStr = numeral(item.maxAuthorize).format('0,0')
item.totalPosStr = numeral(item.totalPos).format('0,0')
const nodeProportion = attr.t1PeerCost + '%'
const userProportion = (100 - attr.t1PeerCost) + '%'
// item.nodeProportion = nodeProportion + ' / ' + userProportion
item.nodeProportion = userProportion
})
const list = nodes;
list.forEach((item, index) => {
item.currentStake = numeral(item.initPos + item.totalPos).format('0,0');
let process = Number((item.totalPos + item.initPos) * 100 / (item.initPos + item.maxAuthorize)).toFixed(2)
if(process > 100) {
process = 100;
}
item.process = process + '%'
item.detailUrl = NODE_DETAIL + item.peerPubkey;
})
console.log(JSON.stringify(list))
commit('UPDATE_NODE_LIST', {list});
dispatch('hideLoadingModals')
return list.length;
} catch(err) {
console.log(err)
commit('UPDATE_NODE_LIST', {list: []});
dispatch('hideLoadingModals')
return 0;
}
},
async fetchNodeListNew({commit, dispatch}, {pageSize, pageNum}) {
const net = localStorage.getItem('net')
const url = NODE_CURRENT_STAKES[net];
try {
const res = await axios.get(url)
console.log(res)
if(res.data.code === 0 && res.data.result) {
const result = res.data.result;
const total = result.length;
const list = result.slice(pageNum * pageSize, (pageNum + 1) * pageSize).map(item => {
item.rank = item.node_rank;
item.nodeProportion = item.node_proportion;
item.userProportion = item.user_proportion;
item.currentStake = numeral(item.current_stake).format('0,0');
item.process = item.progress;
item.maxAuthorize = item.max_authorize;
item.maxAuthorizeStr = numeral(item.max_authorize).format('0,0')
item.totalPos = item.total_pos;
item.initPos = item.init_pos;
item.pk = item.public_key;
item.detailUrl = item.detail_url;
item.totalPosStr = numeral(item.totalPos).format('0,0')
if (!item.name) {
item.name = 'Node_' + item.public_key.substr(0, 6)
}
return item;
})
commit('UPDATE_NODE_LIST', {list})
return total;
} else {
throw new Error('Network error when fetch node list.')
// return 0;
}
}catch(err) {
console.log(err)
commit('UPDATE_NODE_LIST', {list: []});
dispatch('hideLoadingModals')
message.error(i18n.t('commonWalletHome.networkError'))
return 0;
}
},
async fetchBlockCountdown({commit}) {
const url = getNodeUrl();
const rest = new RestClient(url);
try {
// const view = await GovernanceTxBuilder.getGovernanceView(url);
// const blockRes = await rest.getBlockHeight();
// const blockHeight = blockRes.Result;
// const blockCounts = await fetchRoundBlocks()
// const countdown = blockCounts - (blockHeight - view.height);
// if (countdown < 0) {
// throw new Error('Network error for fetch block countdown.')
// }
const countdown = await fetchRoundBlocks()
commit('UPDATE_COUNTDOWN_BLOCK', {countdown})
return countdown;
}catch(err) {
// alert('Network error.')
console.log(err)
}
},
async fetchPosLimit({commit}) {
const url = getNodeUrl();
try {
const globalParams = await GovernanceTxBuilder.getGlobalParam(url);
if(globalParams.posLimit) {
commit('UPDATE_POS_LIMIT', {posLimit: globalParams.posLimit});
return globalParams.posLimit;
}
}catch(err) {
console.log(err);
}
},
async fetchPeerUnboundOng({commit}, address) {
const url = getNodeUrl();
const addr = new Crypto.Address(address);
try {
let peerUnboundOng = await GovernanceTxBuilder.getPeerUnboundOng(addr, url);
peerUnboundOng = new BigNumber(peerUnboundOng).div(1e9).toNumber();
commit('UPDATE_PEER_UNBOUND_ONG', {peerUnboundOng})
return peerUnboundOng;
} catch(err) {
console.log(err);
}
},
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/NodeAuthorizationSesameseed.js
================================================
import { utils } from 'ontology-ts-sdk'
import axios from 'axios';
const state = {
sesameseed: { // for node user
votes: 0,
pendingWithdrawals: 0
}
}
const mutations = {
UPDATE_CURRENT_SS_PEER(state, payload) {
state.sesameseed = {
votes: payload.votes,
pendingWithdrawals: payload.pendingWithdrawals
}
}
}
const actions = {
async fetchSSPerInfo({ commit }, address) {
try {
const baseUrl = 'https://api.sesameseed.org/voting/v1/address/'
const pendingWithdrawalsPromise = axios.get(baseUrl + 'unstaked/' + address)
const votesPromise = axios.get(baseUrl + 'staked/' + address)
const [pendingWithdrawalsResponse, votesResponse] = await Promise.all([pendingWithdrawalsPromise, votesPromise])
let votes = 0
let pendingWithdrawals = 0
if (pendingWithdrawalsResponse.status === 200 && pendingWithdrawalsResponse.data) {
const resultPending = pendingWithdrawalsResponse.data
pendingWithdrawals = resultPending.value ? resultPending.value : 0
}
if (votesResponse.status === 200 && votesResponse.data) {
const resultVotes = votesResponse.data
votes = resultVotes.value ? resultVotes.value : 0
}
commit('UPDATE_CURRENT_SS_PEER', { votes, pendingWithdrawals })
return { votes, pendingWithdrawals };
} catch (err) {
console.log(err)
return 0;
}
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/NodeStake.js
================================================
import axios from 'axios'
import en from '../../lang/en'
import zh from '../../lang/zh'
import { ONT_PASS_NODE, ONT_PASS_NODE_PRD, ONT_PASS_URL, QUERY_NODE_INFO_API,
UPDATE_NODE_INFO_API, UPDATE_LEDGER_NODE_INFO_API } from '../../core/consts'
const state = {
detail: {
publickey: ''
},
nodePublicKey: '',
stakeWallet: {
address: '',
key: ''
},
stakeIdentity: {
ontid: ''
},
status: '',
status1: '',
status2: '',
status3: '',
current: 0,
statusTip: '',
btnText: '',
menuTabIndex: 1
}
const mutations = {
UPDATE_STAKE_IDENTITY(state, payload) {
state.stakeIdentity = payload.stakeIdentity
},
UPDATE_STAKE_WALLET(state, payload) {
state.stakeWallet = payload.stakeWallet
},
UPDATE_NODE_PUBLICKEY(state, payload) {
state.nodePublicKey = payload.nodePublicKey
},
UPDATE_NODE_STATUS(state, payload) {
state.status = payload.status
},
UPDATE_STAKE_STATUS(state, payload) {
state.status1 = payload.status1
state.status2 = payload.status2
state.status3 = payload.status3
state.current = payload.current
state.statusTip = payload.statusTip
},
UPDATE_STAKE_DETAIL(state, payload) {
state.detail = payload.detail
},
UPDATE_MENU_TAB_INDEX(state, index) {
state.menuTabIndex = index
}
}
function formatStatusText(status){
const lang = localStorage.getItem('user_lang') || 'en'
return lang === 'en' ? en.nodeStakeStatus[status] : zh.nodeStakeStatus[status]
}
function getStatus(status) {
let status1 = '',
status2 = '',
status3 = '',
current = 0,
statusTip = '',
btnText = ''
switch (status) {
case 0: // 没了
status1 = formatStatusText('transfering')
status2 = formatStatusText('audit')
status3 = formatStatusText('stake')
current = 0
statusTip = formatStatusText('transferNeedTime')
break;
case 1: // 没了
status1 = formatStatusText('transferFailed')
status2 = formatStatusText('audit')
status3 = formatStatusText('stake')
statusTip = ''
current = 0
break;
case 2: // 没了
status1 = formatStatusText('transfered')
status2 = formatStatusText('auditing')
status3 = formatStatusText('stake')
statusTip = formatStatusText('auditNeedTime')
current = 1
break;
case 3: // 没了
status1 = formatStatusText('transfered')
status2 = formatStatusText('auditFailed')
status3 = formatStatusText('stake')
statusTip = ''
current = 1
break;
case 4: // 没了
status1 = formatStatusText('nodeExited')
status2 = formatStatusText('refund')
status3 = formatStatusText('quitStake')
statusTip = formatStatusText('unfrozenToRefund')
current = 0
break;
case 5:
status1 = formatStatusText('nodeExited')
status2 = formatStatusText('refunding')
status3 = formatStatusText('quitStake')
current = 1
statusTip = formatStatusText('refundNeedTime')
break;
case 6:
status1 = formatStatusText('nodeExited')
status2 = formatStatusText('refunded')
status3 = formatStatusText('stakeExited')
current = 2
statusTip = ''
break;
case 7:
status1 = formatStatusText('nodeExited')
status2 = formatStatusText('refundFailed')
status3 = formatStatusText('stakeExited')
current = 1
statusTip = ''
break;
case 8:
status1 = formatStatusText('transfered')
status2 = formatStatusText('audited')
status3 = formatStatusText('staked')
current = 2
statusTip = ''
break;
case 9:
status1 = formatStatusText('nodeExited')
status2 = formatStatusText('refund')
status3 = formatStatusText('quitStake')
current = 0
statusTip = ''
break;
case 10:
status1 = formatStatusText('nodeExited')
status2 = formatStatusText('refund')
status3 = formatStatusText('quitStake')
current = 0
statusTip = ''
break;
default:
break;
}
return {
status1, status2, status3, current, statusTip
}
}
const actions = {
fetchStakeDetail({commit}, {address, public_key}){
const net = localStorage.getItem("net");
const ontPassNode =
net === "TEST_NET" ? ONT_PASS_NODE : ONT_PASS_NODE_PRD;
axios.get(ontPassNode + ONT_PASS_URL.GetStakeInfo, {
params: {
address,
publickey: public_key
}
}).then(res => {
commit('UPDATE_STAKE_DETAIL', { detail:res.data})
const status = getStatus(res.data.status);
commit('UPDATE_STAKE_STATUS', status)
return res.data;
})
// const status = getStatus(2);
// commit('UPDATE_STAKE_STATUS', status)
},
async fetchNodeInfo({ }, public_key) {
const net = localStorage.getItem("net");
const url = QUERY_NODE_INFO_API[net]
const res = await axios.get(url, {
params: {
public_key
}
})
return res.data.result
},
async updateNodeInfo({ }, info) {
const net = localStorage.getItem("net");
const url = UPDATE_NODE_INFO_API[net]
const res = await axios.post(url, info)
return res.data
},
async updateLedgerNodeInfo({ }, info) {
const net = localStorage.getItem("net");
const url = UPDATE_LEDGER_NODE_INFO_API[net]
const res = await axios.post(url, info)
return res.data
},
async newStakeInfo({ }, info) {
const net = localStorage.getItem("net");
const url = UPDATE_NODE_INFO_API[net] + '/new'
const res = await axios.post(url, info)
return res.data
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/Oep4s.js
================================================
import {Oep4, RestClient, Crypto, utils} from 'ontology-ts-sdk'
import {TEST_NET, MAIN_NET} from '../../core/consts'
import { BigNumber } from 'bignumber.js';
import axios from 'axios';
import {
getRestClient,
getTokenListUrl
} from '../../core/utils'
// Deprecated
const oep4s = localStorage.getItem('oep4s')? JSON.parse(localStorage.getItem('oep4s')) : [];
const oep4_selected = {
'TEST_NET': [],
'MAIN_NET': []
}
const state = {
oep4s,
completedTx: []
}
const mutations = {
ADD_OEP4(state, payload) {
const oep4s = [...state.oep4s, payload.newOep4]
localStorage.setItem('oep4s', JSON.stringify(oep4s))
state.oep4s = oep4s;
},
UPDATE_OEP4S(state, payload) {
state.oep4s = payload.oep4s
},
UPDATE_OEP4_TX_LIST(state, payload) {
state.completedTx = payload.txList
}
}
const actions = {
async addOep4Token({commit, dispatch, state}, {scriptHash, address}) {
try {
const restClient = getRestClient()
const res = await restClient.getContract(scriptHash);
console.log(res)
if (!res.Result) {
return 'NO_CONTRACT'
} else {
const name = await dispatch('queryOep4Name', scriptHash)
const symbol = await dispatch('queryOep4Symbol', scriptHash)
const decimal = await dispatch('queryOep4Decimal', scriptHash)
const balance = await dispatch('queryOep4Balance', {scriptHash, address, decimal})
const net = localStorage.getItem('net')
const newOep4 = {name, symbol, scriptHash, decimal, balance, net}
commit('ADD_OEP4', {newOep4})
dispatch('registerOep4Info', scriptHash)
dispatch('queryTxForOep4', {address, oep4s: [...state.oep4s, newOep4]})
return 'ADD_SUCCESS'
}
} catch(err) {
console.log(err)
return 'NETWORK_ERROR'
}
},
async registerOep4Info({commit, dispatch}, scriptHash) {
const net = localStorage.getItem('net');
let url = ''
if(net === 'TEST_NET') {
url = 'https://polarisexplorer.ont.io/api/v1/explorer/oep4/info'
} else {
url = 'https://explorer.ont.io/api/v1/explorer/oep4/info'
}
axios.post(url, {
scriptHash
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
},
async queryOep4Name({commit}, scriptHash) {
const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));
const oep4 = new Oep4.Oep4TxBuilder(contractAddr);
const tx = oep4.queryName();
const restClient = getRestClient()
const res = await restClient.sendRawTransaction(tx.serialize(), true);
if(res.Result.Result) {
const val = utils.hexstr2str(res.Result.Result);
return val;
} else {
return 'OEP4'
}
},
async queryOep4Symbol({ commit }, scriptHash) {
const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));
const oep4 = new Oep4.Oep4TxBuilder(contractAddr);
const tx = oep4.querySymbol();
const restClient = getRestClient()
const res = await restClient.sendRawTransaction(tx.serialize(), true);
if (res.Result.Result) {
const val = utils.hexstr2str(res.Result.Result);
return val;
} else {
return 'OEP4'
}
},
async queryOep4Decimal({ commit }, scriptHash) {
const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));
const oep4 = new Oep4.Oep4TxBuilder(contractAddr);
const tx = oep4.queryDecimals();
const restClient = getRestClient()
const res = await restClient.sendRawTransaction(tx.serialize(), true);
if (res.Result.Result) {
const val = parseInt(res.Result.Result, 16);
return val;
} else {
return 0
}
},
async queryOep4Balance({commit}, {scriptHash, address, decimal=0}) {
const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));
const oep4 = new Oep4.Oep4TxBuilder(contractAddr);
const tx = oep4.queryBalanceOf(new Crypto.Address(address));
const restClient = getRestClient()
const res = await restClient.sendRawTransaction(tx.serialize(), true);
if(res.Result.Result) {
const bi = new BigNumber(utils.reverseHex(res.Result.Result), 16)
const val = bi.dividedBy(Math.pow(10,decimal)).toNumber()
return val;
} else {
return 0;
}
},
async queryBalanceForOep4({commit, dispatch, state}, address) {
dispatch('showLoadingModals');
try {
const net = localStorage.getItem('net');
const temp = await Promise.all(state.oep4s.map((item) => {
if(item.net !== net) { // 避免多余的查询
return Promise.resolve(0)
}
return dispatch('queryOep4Balance', {
scriptHash: item.scriptHash,
address,
decimal: item.decimal
})
})
)
console.log(temp);
const newOep4s = state.oep4s.map((item, index) => ({
...item,
balance: temp[index]
}))
commit('UPDATE_OEP4S', {oep4s: newOep4s})
dispatch('hideLoadingModals');
} catch(err) {
dispatch('hideLoadingModals');
console.log(err);
alert('Network error.Please try later.')
}
},
async queryTxForOep4({commit, dispatch}, {address,oep4s}) {
const net = localStorage.getItem('net')
const url = net === 'TEST_NET' ? 'https://polarisexplorer.ont.io' : 'https://explorer.ont.io';
axios.get(url + '/api/v1/explorer/address/' + address + '/10/1').then(response => {
if (response.status === 200 && response.data && response.data.Result) {
const txlist = response.data.Result.TxnList;
const completed = []
for (const t of txlist) {
// if(t.TransferList.length === 1 && t.TransferList[0].ToAddress === ONG_GOVERNANCE_CONTRACT) {
// continue;
// }
for (const tx of t.TransferList) {
if(tx.AssetName === 'ong'){
continue;
}
for(let o of oep4s) {
let amount = tx.Amount
if(o.symbol === tx.AssetName || tx.AssetName === 'LCY') { // They give the wrong symbol for token LUCKY
if (tx.FromAddress === address) {
amount = '-' + amount;
} else {
amount = '+' + amount;
}
completed.push({
txHash: t.TxnHash,
asset: tx.AssetName,
amount: amount
})
break;
}
}
}
}
commit('UPDATE_OEP4_TX_LIST', {txList: completed})
}
}).catch(err => {
dispatch('hideLoadingModals');
console.log(err)
})
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/PaxMgmt.js
================================================
const state = {
unprocess_list: [
],
processing_list: [
{
cosigners: []
}
],
currentSigner: ''
}
const mutations = {
UPDATE_UNPROCESS_LIST(state, {list}) {
state.unprocess_list = list;
},
UPDATE_PROCESSING_LIST(state, {list}) {
state.processing_list = list;
},
UDPATE_CURRENT_SIGNER(state, {signer}) {
state.currentSigner = signer
}
}
const actions = {}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/Setting.js
================================================
import dbService, { dbFind } from '../../core/dbService';
const net = localStorage.getItem('net');
const state = {
network:net,
connected: false
}
const mutations = {
UPDATE_SETTING_NETWORK(state, payload) {
state.network = payload.network
},
NETWORK_CONNECTED(state, payload) {
state.connected = true;
},
NETWORK_DISCONNECTED(state, payload) {
state.connected = false;
}
}
const actions = {
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/Tokens.js
================================================
import httpService, {
getRestClient,
getTokenListUrl,
getTokenBalanceUrl
} from '../../core/utils'
// should contain native, oep4, oep5, oep8 tokens
const oep4_default = {
'TEST_NET': {},
'MAIN_NET': {}
}
const oep4Tokens = localStorage.getItem('oep4Tokens') ? JSON.parse(localStorage.getItem('oep4Tokens')) : oep4_default;
/*
*/
const state = {
oep4Tokens,
oep4WithBalances: []
}
const mutations = {
UPDATE_OEP4_TOKENS(state, {oep4s}) {
const net = localStorage.getItem('net')
state.oep4Tokens[net] = oep4s;
localStorage.setItem('oep4Tokens', JSON.stringify(state.oep4Tokens))
},
UPDATE_OEP4_TOKEN(state, {oep4}) {
const net = localStorage.getItem('net')
const oep4s = Object.assign({}, state.oep4Tokens[net]);
if(oep4s[oep4.contract_hash]) {
for (let k of Object.keys(oep4s)) {
if (oep4s[k].contract_hash === oep4.contract_hash) {
if(oep4.selected) {
oep4s[k].selected = oep4.selected;
} else {
delete oep4s[k];
}
break;
}
}
} else {
oep4s[oep4.contract_hash] = oep4;
}
state.oep4Tokens[net] = oep4s;
localStorage.setItem('oep4Tokens', JSON.stringify(state.oep4Tokens))
},
UPDATE_OEP4_BALANCES(state, {balances}) {
state.oep4WithBalances = balances;
},
CLEAR_OEP4S_BALANCES(state) {
state.oep4WithBalances = []
}
}
const actions = {
async fetchOep4Selections({commit, state}, {page_size, page_number}) {
const url = getTokenListUrl('oep4', page_size, page_number);
const net = localStorage.getItem('net')
const res = await httpService.get(url)
console.log(res)
const list = res.result.records.map(item => {
item.selected = false;
for(let k of Object.keys(state.oep4Tokens[net])) {
const o = state.oep4Tokens[net][k]
if(o.contract_hash === item.contract_hash) {
item.selected = o.selected;
break;
}
}
return item;
})
const total = res.result.total;
// commit('UPDATE_OEP4_SELECTIONS', {list, total})
return {list, total}
},
async fetchTokenBalances({commit,state}, {address}) {
const url = getTokenBalanceUrl('oep4',address)
const net = localStorage.getItem('net')
const res = await httpService.get(url)
const balances = [];
const oep4s = state.oep4Tokens[net];
for (let k of Object.keys(oep4s)) {
const oep4 = oep4s[k]
const item = Object.assign({}, oep4)
item.balance = 0;
for(let r of res.result) {
console.log(r.asset_name, oep4.symbol)
if (r.asset_name === oep4.symbol) {
item.balance = r.balance;
break;
}
}
balances.push(item)
}
console.log(balances)
commit('UPDATE_OEP4_BALANCES', {
balances
})
return balances
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/Vote.js
================================================
import { NODE_CURRENT_STAKES,OFF_CHAIN_NODES, VOTE_ROLE, DEFAULT_SCRYPT, ONT_PASS_NODE, ONT_PASS_NODE_PRD,
ONT_PASS_URL } from '../../core/consts'
import httpService, { getRestClient } from '../../core/utils'
import { TransactionBuilder, Crypto, utils, Parameter, ParameterType, TxSignature, WebsocketClient } from 'ontology-ts-sdk'
import {
message
} from 'ant-design-vue'
import i18n from '../../lang';
import axios from 'axios';
const gasPrice = '500'
const gasLimit = '200000'
const contract_hash = {
MAIN_NET: 'c0df752ca786a99755b2e8950060ade9fa3d4e1b',
TEST_NET: '32a7403e17eb9a2bbeeb7bc3eaa6dee7b0ae3829'
}
const contract_hash_old = {
MAIN_NET: 'c0df752ca786a99755b2e8950060ade9fa3d4e1b',
TEST_NET: 'a088ae3b508794e666ab649d890213e66e0c3a2e'
}
const state = {
contract_hash: '',
voteWallet: '',
voteWalletType: '', // commonWallet or ledgerWallet
role: [], // 可能同时是admin和voter
all_votes: [],
admin_votes: [], // admin 创建的votes
all_votes_hash: [],
admin_votes_hash: [],
currentVote: {},
my_weight: 0,
all_voters: [], // 当前是所有节点用户
current_vote_records: [] // 当前vote的投票情况
}
export const VOTE_STATUS_TEXT = {
NOT_START: 'NOT_START',
IN_PROGRESS: 'IN_PROGRESS',
FINISHED: 'FINISHED',
CANCELED: 'CANCELED'
}
export const MY_VOTED = {
'APPROVED': 'APPROVED',
'REJECTED': 'REJECTED',
'NOT_VOTED': 'NOT_VOTED'
}
const formatNumber = function (val) {
return parseInt(utils.reverseHex(val), 16)
}
const formatOldVoteInfo = function (infos) {
if (!infos) {
return [];
}
const votes = []
for (const info of infos) {
let item = info;
if (info && info.Result && info.Result.Result) {
item = info.Result.Result
}
const vote = {
admin: new Crypto.Address(item[0]).toBase58(),
title: utils.hexstr2str(item[1]),
content: utils.hexstr2str(item[2]),
voters: item[3] ? item[3].map(i => {
return {
address: new Crypto.Address(i[0]).toBase58(),
weight: parseInt(utils.reverseHex(i[1]), 16)
}
}) : [],
startTime: String(formatNumber(item[4])).length <= 10 ? formatNumber(item[4]) * 1000 : formatNumber(item[4]),
endTime: String(formatNumber(item[5])).length <= 10 ? formatNumber(item[5]) * 1000 : formatNumber(item[5]),
approves: formatNumber(item[6]),
rejects: formatNumber(item[7]),
status: formatNumber(item[8]),
hash: item[9]
}
if (vote.status === 0) {
vote.statusText = VOTE_STATUS_TEXT.CANCELED
} else {
const now = Date.now()
if (vote.startTime > now) {
vote.statusText = VOTE_STATUS_TEXT.NOT_START
} else if (vote.startTime <= now && vote.endTime >= now) {
vote.statusText = VOTE_STATUS_TEXT.IN_PROGRESS
} else if (vote.endTime < now) {
vote.statusText = VOTE_STATUS_TEXT.FINISHED
}
}
votes.push(vote)
}
return votes;
}
function formatVoteInfo(infos) {
if (!infos) {
return []
}
const votes = []
for (const data of infos) {
const sr = new utils.StringReader(data);
const hasValue = sr.readVarUint() > 0;
if (hasValue) {
const admin = new Crypto.Address(sr.read(20)).toBase58();
// tslint:disable:variable-name
const topic_title_length = sr.readVarUint();
const topic_title = utils.hexstr2str(sr.read(topic_title_length));
const topic_detail_length = sr.readVarUint();
const topic_detail = utils.hexstr2str(sr.read(topic_detail_length));
const voters_length = sr.readVarUint();
const voters = [];
for (let i = 0; i < voters_length; i++) {
const voter_addr = new Crypto.Address(sr.read(20)).toBase58();
const weight = sr.readUint128();
voters.push({
address: voter_addr,
weight
});
}
const start_time = sr.readUint64();
const end_time = sr.readUint64();
const approves = sr.readUint64();
const rejects = sr.readUint64();
const status = sr.readUint8();
const hash = sr.readH256();
const vote = {
admin,
title: topic_title,
content: topic_detail,
voters,
startTime: start_time * 1000,
endTime: end_time * 1000,
approves,
rejects,
status,
hash
};
if (vote.status === 0) {
vote.statusText = VOTE_STATUS_TEXT.CANCELED
} else {
const now = Date.now()
if (vote.startTime > now) {
vote.statusText = VOTE_STATUS_TEXT.NOT_START
} else if (vote.startTime <= now && vote.endTime >= now) {
vote.statusText = VOTE_STATUS_TEXT.IN_PROGRESS
} else if (vote.endTime < now) {
vote.statusText = VOTE_STATUS_TEXT.FINISHED
}
}
votes.push(vote)
}
}
return votes
}
const handleSignTx = async function (tx, wallet, password, walletType = 'commonWallet') {
if (walletType === 'commonWallet') {
const enc = new Crypto.PrivateKey(wallet.key);
let pri;
try {
pri = enc.decrypt(
password,
new Crypto.Address(wallet.address),
wallet.salt,
DEFAULT_SCRYPT
);
} catch (err) {
console.log(err);
message.error(i18n.t('common.pwdErr'))
return;
}
TransactionBuilder.signTransaction(tx, pri);
} else {
const pk = new Crypto.PublicKey(wallet.publicKey);
const txSig = new TxSignature();
txSig.M = 1;
txSig.pubKeys = [pk];
const txData = tx.serializeUnsignedData();
// TODO
// eslint-disable-next-line no-undef
const res = await legacySignWithLedger(txData)
// console.log('txSigned: ' + res);
const sign = '01' + res; //ECDSAwithSHA256
txSig.sigData = [sign]
tx.sigs.push(txSig);
}
return tx;
}
const mutations = {
UPDATE_VOTE_WALLET(state, { voteWallet }) {
state.voteWallet = voteWallet
},
UPDATE_VOTE_ROLE(state, { role }) {
state.role = role
},
UPDATE_ALL_VOTES(state, { votes }) {
state.all_votes = votes
},
UPDATE_ADMIN_VOTES(state, { votes }) {
state.admin_votes = votes
},
UPDATE_VOTE_WALLET_TYPE(state, { type }) {
state.voteWalletType = type
},
UPDATE_CURRENT_VOTE(state, { vote }) {
state.currentVote = vote
},
UPDATE_MY_WEIGHT(state, { weight }) {
state.my_weight = weight
},
UPDATE_ALL_VOTERS(state, { all_voters }) {
state.all_voters = all_voters
},
UPDATE_CURRENT_VOTE_RECORDS(state, { records }) {
state.current_vote_records = records
},
UPDATE_VOTE_CONTRACT(state, contract_hash) {
state.contract_hash = contract_hash
}
}
const actions = {
async fetchVoteContract({commit}) {
const net = localStorage.getItem('net')
const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD
const url = ontPassNode + ONT_PASS_URL.GetVoteContract + '/' + net;
const res = await axios.get(url)
if(res && res.data && res.data.vote_contract_address) {
commit('UPDATE_VOTE_CONTRACT', res.data.vote_contract_address)
}
},
//从接口获取节点钱包地址,和从合约获取amdin地址,判断role
async getVoteRole({ commit, dispatch, state }, { address }) {
dispatch('showLoadingModals')
const net = localStorage.getItem('net');
const url = NODE_CURRENT_STAKES[net]
try {
//从接口查询admin信息
const res1 = await httpService({
url,
method: 'get'
})
// console.log(res1)
const client = getRestClient()
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const tx = TransactionBuilder.makeWasmVmInvokeTransaction('listGovNodes', [], contract, gasPrice, gasLimit) // 从链上查询admin信息
const res2 = await client.sendRawTransaction(tx.serialize(), true);
console.log(res2)
let is_voter = false
let is_admin = false
let weight = 0
const all_voters = []
const sr1 = new utils.StringReader(res2.Result.Result)
const all_voters_length = sr1.readVarUint()
for(let i = 0; i< all_voters_length; i++) {
all_voters.push({
name: '',
weight: 0,
address: new Crypto.Address(sr1.read(20)).toBase58() // 节点运营钱包
})
}
for(const admin_from_chain of all_voters) {
for(const admin_from_api of res1.result) {
const pk_address = Crypto.Address.fromPubKey(new Crypto.PublicKey(admin_from_api.public_key)).toBase58()
if(pk_address === admin_from_chain.address) {
admin_from_chain.name = admin_from_api.name
admin_from_chain.weight = admin_from_api.current_stake
break;
} else {
admin_from_chain.name = admin_from_chain.address.substr(0,8)
}
}
}
// const all_voters = res1.result.map(item => ({ name: item.name, address: item.address, weight: item.current_stake }))
commit('UPDATE_ALL_VOTERS', { all_voters })
for (let node of all_voters) {
if (node.address === address) {
is_voter = true;
is_admin = true;
weight = node.weight
break;
}
}
// let is_admin = false
// const result = res2.Result.Result
// const sr = new utils.StringReader(result);
// const addr_length = sr.readVarUint();
// for (let i = 0; i < addr_length; i++) {
// if (new Crypto.Address(sr.read(20)).toBase58() === address) {
// is_admin = true;
// break;
// }
// }
// for (let voter of all_voters) {
// if (new Crypto.Address(addr).toBase58() === address) {
// is_admin = true;
// break;
// }
// }
let role = [];
if (is_voter) role.push(VOTE_ROLE.VOTER)
if (is_admin) role.push(VOTE_ROLE.ADMIN)
console.log(role)
commit('UPDATE_VOTE_ROLE', { role })
commit('UPDATE_MY_WEIGHT', { weight })
dispatch('hideLoadingModals')
} catch (err) {
console.log(err)
dispatch('hideLoadingModals')
message.error(i18n.t('common.networkErr'))
}
},
async getAllVotes({ commit, dispatch, state }, {showLoading}) {
showLoading && dispatch('showLoadingModals')
const net = localStorage.getItem('net');
const client = getRestClient()
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const tx = TransactionBuilder.makeWasmVmInvokeTransaction('listTopics', [], contract, gasPrice, gasLimit)
try {
const res2 = await client.sendRawTransaction(tx.serialize(), true);
if (res2.Error !== 0) {
throw res2;
}
// 处理结果
const result = res2.Result.Result
const sr = new utils.StringReader(result);
const hash_length = sr.readVarUint();
const hashes = []
for (let i = 0; i < hash_length; i++) {
hashes.push(sr.read(32))
}
// const hashes = res2.Result.Result || []
console.log(hashes)
const txes = hashes.map(hash => {
return TransactionBuilder.makeWasmVmInvokeTransaction('getTopicInfo', [new Parameter('', ParameterType.H256, hash)], contract, gasPrice, gasLimit)
})
let infos = await Promise.all(txes.map(tx => { return client.sendRawTransaction(tx.serialize(), true) }))
// infos = infos.map(item => item.Result.Result)
let infoList = []
for(const info of infos) {
if(info && info.Result && info.Result.Result) {
infoList.push(info.Result.Result)
}
}
console.log(infos)
let votes = formatVoteInfo(infoList)
// 根据hash过滤出查询失败的topic,从老的neo合约中继续查找
const oldHashes = []
for(const hash of hashes) {
let used = false;
for(const vote of votes) {
if(hash === vote.hash) {
used = true;
break;
}
}
if(!used){
oldHashes.push(hash)
}
}
if(oldHashes.length > 0) {
const contractOld = new Crypto.Address(utils.reverseHex(contract_hash_old[net]))
const old_txes = oldHashes.map(hash => {
return TransactionBuilder.makeInvokeTransaction('getTopicInfo', [new Parameter('', ParameterType.ByteArray, hash)], contractOld, gasPrice, gasLimit)
})
let infosOld = await Promise.all(old_txes.map(tx => { return client.sendRawTransaction(tx.serialize(), true) }))
// infos = infos.map(item => item.Result.Result)
let infoListOld = []
for(const info_old of infosOld) {
if(info_old && info_old.Result && info_old.Result.Result) {
infoListOld.push(info_old)
}
}
const votesOld = formatOldVoteInfo(infoListOld)
votes = votes.concat(votesOld)
}
// console.log(votes)
commit('UPDATE_ALL_VOTES', { votes })
dispatch('hideLoadingModals')
} catch (err) {
console.log(err)
dispatch('hideLoadingModals')
message.error(i18n.t('common.networkErr'))
}
},
async getAdminVotes({ commit, dispatch, state }) {
// dispatch('showLoadingModals')
const address = state.voteWallet.address;
const all_votes = state.all_votes
let admin_votes = []
for(let item of all_votes) {
if(item.admin === address) {
admin_votes.push(item)
}
}
console.log(admin_votes)
commit('UPDATE_ADMIN_VOTES', { votes: admin_votes })
},
submitVote({ commit, state }, { type, hash }) {
const net = localStorage.getItem('net');
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const address = state.voteWallet.address
const addr = new Crypto.Address(address)
const params = [
new Parameter('', ParameterType.H256, hash),
new Parameter('', ParameterType.Address, addr),
new Parameter('', ParameterType.Boolean, type)
]
let tx = TransactionBuilder.makeWasmVmInvokeTransaction('voteTopic', params, contract, gasPrice, gasLimit, addr)
return tx;
},
stopVote({ commit, dispatch, state }, { hash }) {
const net = localStorage.getItem('net');
const client = getRestClient()
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const address = state.voteWallet.address
const addr = new Crypto.Address(address)
const params = [
new Parameter('', ParameterType.H256, hash)
]
let tx = TransactionBuilder.makeWasmVmInvokeTransaction('cancelTopic', params, contract, gasPrice, gasLimit, addr)
return tx;
},
createVote({ commit, dispatch, state }, { vote }) {
const net = localStorage.getItem('net');
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const address = state.voteWallet.address
const addr = new Crypto.Address(address)
const voters = state.all_voters;
const params = [
new Parameter('', ParameterType.Address, addr),
new Parameter('', ParameterType.String, vote.title),
new Parameter('', ParameterType.String, vote.content),
new Parameter('', ParameterType.Integer, vote.startTime),
new Parameter('', ParameterType.Integer, vote.endTime)
]
let tx = TransactionBuilder.makeWasmVmInvokeTransaction('createTopic', params, contract, gasPrice, gasLimit, addr)
return tx;
},
async setVoters({ commit, dispatch, state }, { hash, voters }) {
dispatch('showLoadingModals')
const net = localStorage.getItem('net');
const client = getRestClient()
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const address = state.voteWallet.address
const addr = new Crypto.Address(address)
const params = [
new Parameter('', ParameterType.H256, hash),
new Parameter('', ParameterType.Array, voters) //TODO format voters to arrays
]
let tx = TransactionBuilder.makeWasmVmInvokeTransaction('setVoterForTopic', params, contract, gasPrice, gasLimit, addr)
// TODO
// eslint-disable-next-line no-undef
tx = await handleSignTx(tx, state.voteWallet, password, state.voteWalletType);
if (!tx) {
return;
}
// TODO change to websocket
const res = await client.sendRawTransaction(tx.serialize(), false);
dispatch('hideLoadingModals')
return res;
},
// 查询
async getVoters({ commit, state }, { hash }) {
const net = localStorage.getItem('net');
const client = getRestClient()
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const param = new Parameter('', ParameterType.H256, hash)
const tx = TransactionBuilder.makeWasmVmInvokeTransaction('getVoters', [param], contract, gasPrice, gasLimit)
const res = await client.sendRawTransaction(tx.serialize(), true);
if (res.Error === 0) {
const voters = res.Result.Result.map(i => {
return {
address: new Crypto.Address(i[0]).toBase58(),
weight: parseInt(utils.reverseHex(i[1]), 16)
}
})
console.log(voters)
return voters;
} else {
console.log(res)
return []
}
},
async isVoter({ commit, dispatch, state }, { hash }) {
// const voters = await dispatch('getVoters', {hash})
const all_voters = state.all_voters
const address = state.voteWallet.address;
if (all_voters.find(item => item.address === address)) {
return true;
} else {
return false;
}
},
async getVotedInfo({ commit, state }, { hash, address }) {
const net = localStorage.getItem('net');
const client = getRestClient()
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const params = [
new Parameter('', ParameterType.H256, hash),
new Parameter('', ParameterType.Address, new Crypto.Address(address))
]
const tx = TransactionBuilder.makeWasmVmInvokeTransaction('getVotedInfo', params, contract, gasPrice, gasLimit)
const res = await client.sendRawTransaction(tx.serialize(), true);
console.log(res)
if (res.Error === 0) {
// return res.Result.Result // 1 赞成;2反对;其他:未投票
const sr = new utils.StringReader(res.Result.Result)
const result = sr.readVarUint()
if (result == 1) {
return MY_VOTED.APPROVED
} else if (result == 2) {
return MY_VOTED.REJECTED
} else {
return MY_VOTED.NOT_VOTED
}
}
return;
},
async getVotedRecords({ commit, dispatch, state }, { hash }) {
const net = localStorage.getItem('net');
const client = getRestClient()
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const params = [
new Parameter('', ParameterType.H256, hash)
]
const tx = TransactionBuilder.makeWasmVmInvokeTransaction('getVotedAddress', params, contract, gasPrice, gasLimit)
const res = await client.sendRawTransaction(tx.serialize(), true);
console.log(res)
if (res.Error === 0) {
const result = res.Result.Result
const sr = new utils.StringReader(result)
const records_length = sr.readVarUint()
const records = []
if(records_length > 0) {
for(let i = 0; i < records_length; i++) {
const address = new Crypto.Address(sr.read(20)).toBase58()
const weight = sr.readUint64()
const isApproval = sr.readBoolean()
records.push({
address,
weight,
isApproval
})
}
for (let item of records) {
const voter_with_name = state.all_voters.find(voter => item.address === voter.address)
item.name = voter_with_name ? voter_with_name.name : ''
}
}
commit('UPDATE_CURRENT_VOTE_RECORDS', {records})
}
return;
},
setCurrentVote({ commit }, { vote }) {
commit('UPDATE_CURRENT_VOTE', {vote})
},
async updateCurrentVote({ commit, state }, { hash }) {
const net = localStorage.getItem('net');
const client = getRestClient()
const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))
const params = [
new Parameter('', ParameterType.H256, hash)
]
const tx = TransactionBuilder.makeWasmVmInvokeTransaction('getTopicInfo', params, contract, gasPrice, gasLimit)
const res = await client.sendRawTransaction(tx.serialize(), true);
console.log(res)
if (res.Error === 0) {
const votes = formatVoteInfo([res.Result.Result])
console.log('updateCurrentVote',JSON.stringify(votes))
commit('UPDATE_CURRENT_VOTE', { vote: votes[0]})
} else { // 从老的合约查询
const contractOld = new Crypto.Address(utils.reverseHex(contract_hash_old[net]))
const paramsOld = [
new Parameter('', ParameterType.ByteArray, hash)
]
const txOld = TransactionBuilder.makeInvokeTransaction('getTopicInfo', paramsOld, contractOld, gasPrice, gasLimit)
const resOld = await client.sendRawTransaction(txOld.serialize(), true);
if(resOld.Error === 0) {
const votesOld = formatOldVoteInfo([resOld])
console.log('updateCurrentVote',JSON.stringify(votesOld))
commit('UPDATE_CURRENT_VOTE', { vote: votesOld[0]})
}
}
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/Wallets.js
================================================
import dbService, {dbFind} from '../../core/dbService';
const state = {
NormalWallet:[],
SharedWallet: [],
HardwareWallet: []
}
const mutations = {
FETCH_WALLETS(state, payload) {
state.NormalWallet = payload.NormalWallet;
state.SharedWallet = payload.SharedWallet;
state.HardwareWallet = payload.HardwareWallet;
},
DELETE_COMMON_WALLET(state, payload) {
const normalWallet = state.NormalWallet.slice();
const index = normalWallet.findIndex((w) => w.address === payload.address )
normalWallet.splice(index,1)
state.NormalWallet = normalWallet;
},
DELETE_SHARED_WALLET(state, payload) {
const normalWallet = state.SharedWallet.slice();
const index = normalWallet.findIndex((w) => w.sharedWalletAddress === payload.address)
normalWallet.splice(index, 1)
state.SharedWallet = normalWallet;
},
DELETE_HARDWARE_WALLET(state, payload) {
const normalWallet = state.HardwareWallet.slice();
const index = normalWallet.findIndex((w) => w.address === payload.address)
normalWallet.splice(index, 1)
state.HardwareWallet = normalWallet;
}
}
const actions = {
async fetchWalletsFromDb({ commit }, pk) {
try {
const NormalWalletDocs = await dbFind(dbService, {type:'CommonWallet'});
const SharedWalletDocs = await dbFind(dbService, {type:'SharedWallet'});
const HardwareWalletDocs = await dbFind(dbService, {type:'HardwareWallet'});
const NormalWallet = NormalWalletDocs.map(item => item.wallet)
const SharedWallet = SharedWalletDocs.map(item => item.wallet)
const HardwareWallet = HardwareWalletDocs.map(item => item.wallet)
commit('FETCH_WALLETS', { NormalWallet, SharedWallet, HardwareWallet });
}catch(err) {
alert(err)
}
return true;
}
}
export default {
state,
mutations,
actions
}
================================================
FILE: src/store/modules/index.js
================================================
/**
* The file enables `@/store/index.js` to import all vuex modules
* in a one-shot manner. There should not be any reason to edit this file.
*/
const files = require.context('.', false, /\.js$/)
const modules = {}
files.keys().forEach(key => {
if (key === './index.js') return
modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})
export default modules
================================================
FILE: vue.config.js
================================================
module.exports = {
pluginOptions: {
electronBuilder: {
nodeIntegration: true,
externals: ["node-hid", "usb", "nedb"],
builderOptions: {
productName: process.env.VUE_APP_TITLE,
appId: "com.ontio.owallet",
nsis: {
oneClick: false,
perMachine: true,
allowToChangeInstallationDirectory: true,
},
afterSign: "build/after-sign.js",
win: {
target: [
{
target: "nsis",
arch: ["x64"],
},
],
icon: "src/assets/icons/icon.ico",
artifactName: "${productName}-${version}-${os}.${ext}",
},
linux: {
target: [
{
target: "deb",
arch: ["x64"],
},
{
target: "AppImage",
arch: ["x64"],
},
],
category: "Utility",
icon: "src/assets/icons",
artifactName: "${productName}-${version}-${os}.${ext}",
},
mac: {
target: [
{
target: "dmg",
arch: ["x64", "arm64"],
},
],
forceCodeSigning: false,
identity: null,
icon: "src/assets/icons/icon.icns",
artifactName: "${productName}-${version}-${os}-${arch}.${ext}",
},
},
},
},
css: {
loaderOptions: {
sass: {},
},
},
};