[
  {
    "path": ".browserslistrc",
    "content": "> 1%\nlast 2 versions\nnot dead\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  env: {\n    node: true\n  },\n  'extends': [\n    'plugin:vue/essential',\n    'eslint:recommended'\n  ],\n  parserOptions: {\n    parser: 'babel-eslint'\n  },\n  rules: {\n    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',\n    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',\n    'no-unused-vars': 'off',\n    'no-empty': 'off',\n    'no-empty-pattern': 'off',\n  }\n}\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Release on Tag\n\non:\n  push:\n    tags:\n      - '*' # Listen for any tag push events\n\njobs:\n  build-and-release:\n    runs-on: macos-latest\n\n    # permissions: # Add this permissions block\n    #   contents: write\n    #   packages: write\n    #   issues: write\n    #   pull-requests: write\n\n    permissions: write-all\n\n    steps:\n    # Check out the code\n    - name: Checkout code\n      uses: actions/checkout@v3\n\n    # Set up Node.js and Yarn environment\n    - name: Setup Node.js and Yarn\n      uses: actions/setup-node@v3\n      with:\n        node-version: '16'\n        cache: 'yarn'\n\n    - name: 🔐 Setup Temporary Keychain and Import Certificate\n      run: |\n        KEYCHAIN_NAME=\"temp.keychain\"\n        NODE_PATH=$(which node)\n        echo \"Found Node executable at: $NODE_PATH\"\n\n        # 1. Create a new temporary keychain\n        security create-keychain -p ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME\n\n        # 2. Set the new keychain as the default for the session\n        security default-keychain -s $KEYCHAIN_NAME\n        security unlock-keychain -p ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME\n\n        # 3. Increase the keychain search timeout\n        security set-keychain-settings -t 3600 $KEYCHAIN_NAME\n\n        # 4. Decode the P12 file content from the secret and save it to a file\n        echo \"${{ secrets.DEV_ID_CERTIFICATE_P12 }}\" | base64 --decode > dev_cert.p12\n\n\n        # 6. Set the partition list to ensure automated tools can access the key\n        #    This is crucial for CI environments.\n        CERT_ID='Developer ID Application: Ontology Foundation Ltd (29B4VVVVKM)' # <-- Replace with your exact Identity name\n\n        #security set-key-partition-list -S apple-tool: -S apple: -k $KEYCHAIN_NAME -p ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME\n        curl https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer -o DeveloperIDG2CA.cer\n        sudo security add-trusted-cert -d -r unspecified -k $KEYCHAIN_NAME DeveloperIDG2CA.cer\n        rm -f DeveloperIDG2CA.cer\n\n        # 5. Import the certificate and private key into the new keychain\n        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\n        echo \"import success!\"\n        security set-key-partition-list -S apple-tool:,apple: -s -k ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME\n        echo \"partition list success\"\n\n\n        # Set the temporary keychain as the default for the session\n        security default-keychain -s $KEYCHAIN_NAME\n        echo \"default keychain success\"\n\n        # Unlock the keychain\n        security unlock-keychain -p ${{ secrets.KEYCHAIN_PASSWORD }} $KEYCHAIN_NAME\n\n        # Set lock timeout to the maximum (3600 seconds) and ensure it's always searched\n        security set-keychain-settings -l -u -t 3600 $KEYCHAIN_NAME\n        if security find-identity -p codesigning $KEYCHAIN_NAME | grep -q \"$CERT_ID\"; then\n        echo \"✅ SUCCESS: Code Signing Identity '$CERT_ID' found in the temporary keychain.\"\n        else\n        echo \"❌ FAILURE: Code Signing Identity '$CERT_ID' NOT found. Codesign will likely fail.\"\n        exit 1 # Exit the job immediately if the identity isn't found\n        fi\n\n\n\n\n    # Install dependencies\n    - name: Install dependencies\n      run: |\n        yarn install\n\n    # # Build all packages (macOS, Linux, and Windows)\n    - name: Build macos packages\n      env:\n        APPLE_ID: ${{ secrets.APPLE_ID }}\n        TEAM_ID: ${{ secrets.TEAM_ID }}\n        PASSWORD: ${{ secrets.PASSWORD }}\n      run: |\n        yarn build:mac\n\n    - name: Build Windows App\n      # if: matrix.os == 'windows-latest'\n      run: |\n        yarn build:win\n\n    - name: Build Linux App\n      # if: matrix.os == 'ubuntu-latest'\n      run: |\n        yarn build:linux\n\n    # - name: Create Release v1\n    #   id: create_release\n    #   uses: actions/create-release@latest\n    #   env:\n    #     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token\n    #   with:\n    #     tag_name: ${{ github.ref }}\n    #     release_name: Release ${{ github.ref }}\n    #     body: |\n    #       Change Log\n    #       - TODO\n    #     draft: false\n    #     prerelease: false\n\n\n    # --- Cleanup ---\n    - name: 🗑️ Clean Up Keychain and Files\n      if: always() # Ensure cleanup runs even on failure\n      run: |\n        security delete-keychain temp.keychain\n        rm dev_cert.p12\n\n\n    - name: Generate Checksums\n      run: |\n        brew install coreutils\n        #echo \"# OWallet ${{ github.ref_name }}\" > CHECKSUMS.md\n        echo \"\" > CHECKSUMS.md\n        echo \"CHANGELOG: $(git log -1 --format=%s ${{ github.ref_name }})\" >> CHECKSUMS.md\n        echo \"## SHA256 Checksums\" >> CHECKSUMS.md\n        echo \"| File | SHA256 Checksum |\" >> CHECKSUMS.md\n        echo \"|------|----------------|\" >> CHECKSUMS.md\n        # find dist_electron/ -type f -name OWallet\\*.AppImage -o -name OWallet\\*.dmg -o -name OWallet\\*.exe -o -name OWallet\\*.deb -exec sh -c '\n        #   for file; do\n        #     echo \"| $(basename \"$file\") | \\`$(sha256sum \"$file\" | cut -d \" \" -f1)\\` |\" >> CHECKSUMS.md\n        #   done\n        # ' sh {} +\n        echo \"| $(ls dist_electron/OWallet-*.deb | sed -e 's#dist_electron/##') | \\`$(sha256sum dist_electron/OWallet-*.deb | cut -d \" \" -f1)\\` |\" >> CHECKSUMS.md\n        echo \"| $(ls dist_electron/OWallet-*.exe | sed -e 's#dist_electron/##') | \\`$(sha256sum dist_electron/OWallet-*.exe | cut -d \" \" -f1)\\` |\" >> CHECKSUMS.md\n        echo \"| $(ls dist_electron/OWallet-*.AppImage | sed -e 's#dist_electron/##') | \\`$(sha256sum dist_electron/OWallet-*.AppImage | cut -d \" \" -f1)\\` |\" >> CHECKSUMS.md\n        for dmg in dist_electron/OWallet-*.dmg; do\n          echo \"| $(basename \"$dmg\") | \\`$(sha256sum \"$dmg\" | cut -d \" \" -f1)\\` |\" >> CHECKSUMS.md\n        done\n\n    - name: Create Release v2\n      uses: softprops/action-gh-release@v1\n      with:\n        name: Release ${{ github.ref_name }}\n        body_path: CHECKSUMS.md\n        files: |\n          dist_electron/*.deb\n          dist_electron/*.AppImage\n          dist_electron/*.dmg\n          dist_electron/*.exe\n\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\n/dist\n.sign\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\n\n# Editor directories and files\n.idea\n.vscode\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\n#Electron-builder output\n/dist_electron"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Ontology\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[中文版](./README_cn.md)\n\n\n\n<h1 align=\"center\">OWallet - a comprehensive Ontology desktop wallet</h1>\n<h4 align=\"center\">Version 0.10.0</h4>\n\n## Introduction\n\nOWallet 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.\n\nSupport Windows/MacOS/Linux,get it [Here](https://github.com/ontio/OWallet/releases)，also welcome to join [our community on Discord](https://discord.gg/4TQujHj).\n\nCore features of OWallet are as follows:\n\n* Create wallet/import wallet using keystore,mnemonic phrase,WIF private key,HEX private key\n* Support shared wallet based on multi-signature technology\n* Ledger support\n* View balance and record\n* Send ONG and ONT\n* Withdraw (redeem) ONG\n* Node stake and stake authorization management\n* ONT ID support\n* Integrate gateway provided by changelly and cryptonex\n\n![](images/OWallet.jpg)\n\n\n## Get started\n\n1. Clone the repo\n\n```\ngit clone https://github.com/ontio/OWallet.git\n```\n\n2. Install packages\n**yarn** is recommended.\n```\nyarn\n```\n\n3. Run in Development\n\n```\nyarn serve\n```\n\n4. Build\n\n```\nyarn build\n```\n\n## Install released app\n\nPlease download the latest version that is compatiable with your platform.\n\n## Default keystore.db file path\n\nDefault points to:\n\n* %APPDATA% on `Windows`\n\n* $XDG_CONFIG_HOME or ~/.config on `Linux`\n\n* ~/Library/Application Support on `macOS`\n"
  },
  {
    "path": "README_cn.md",
    "content": "[English Version](./README.md)\n\n\n\n<h1 align=\"center\">OWallet - 本体综合性桌面版钱包 </h1>\n<h4 align=\"center\">Version 0.10.0</h4>\n\n## 总体介绍\n\nOWallet是本体综合性桌面版钱包，支持标准的钱包管理、基于多重签名技术的共享钱包管理，同时将连接Ledger、Trezor多种硬件钱包。未来，OWallet将持续集成更加丰富的应用功能，为开发者提供智能合约编译、运行等综合性服务。\n\n支持Windows/MacOS/Linux,下载请到[这里](https://github.com/ontio/OWallet/releases)，也欢迎加入我们的[技术讨论社区](https://discord.gg/4TQujHj)!\n\nOWallet核心功能如下:\n\n* 创建钱包/导入钱包（支持使用Keystore，助记词，WIF私钥，明文私钥）\n* 支持共享钱包（基于多重签名技术）\n* 支持硬件钱包Ledger\n* 查看余额和交易明细\n* 发送ONG和ONT\n* 提取ONG\n* 节点质押和质押授权管理\n* 支持ONT ID功能\n* 集成changelly和cryptonex网关\n\n![](images/OWallet.jpg)\n\n\n## 如何开始\n\n1. 克隆repo\n\n```\ngit clone https://github.com/ontio/OWallet.git\n```\n\n2. 安装依赖\n推荐使用**yarn**\n\n```\nyarn\n```\n\n3. 开发模式运行\n\n```\nyarn serve\n```\n\n4. 打包\n\n```\nyarn build\n```\n\n## 安装发布的客户端\n\n请下载适合于您的操作系统的最新版本客户端。\n\n\n## keystore.db文件的默认保存路径\n\n在不同系统上指向如下位置：\n\n* %APPDATA% on `Windows`\n\n* $XDG_CONFIG_HOME or ~/.config on `Linux`\n\n* ~/Library/Application Support on `macOS`\n"
  },
  {
    "path": "babel.config.js",
    "content": "module.exports = {\n  presets: [\n    '@vue/cli-plugin-babel/preset'\n  ],\n  plugins: [\n    [\"import\", { libraryName: \"ant-design-vue\", libraryDirectory: \"es\", style: \"css\" }]\n  ]\n}\n"
  },
  {
    "path": "build/after-sign.js",
    "content": "// build/after-sign.js\n\nconst { execSync } = require(\"child_process\");\nconst path = require(\"path\");\nconst fs = require(\"fs\");\n\nconst DEV_ID = \"Developer ID Application: Ontology Foundation Ltd (29B4VVVVKM)\";\nconst ENTITLEMENTS = \"build/entitlements.mac.plist\";\n\nfunction run(cmd) {\n  console.log(`\\n> ${cmd}`);\n  execSync(cmd, { stdio: \"inherit\" });\n}\n\nexports.default = async function afterSign(context) {\n\n  \n  if (context.electronPlatformName !== \"darwin\") {\n    console.log(\"!Skipping afterSign: not macOS build.\");\n    return;\n  }\n  if (process.env.CI !== 'true' || process.env.GITHUB_ACTIONS!=='true') {\n    return\n  }\n\n  const appPath = path.join(\n    context.appOutDir,\n    `${context.packager.appInfo.productFilename}.app`\n  );\n  if (!fs.existsSync(appPath)) {\n    console.error(\"!!App not found:\", appPath);\n    return;\n  }\n\n  console.log(`\\nStarting manual signing for: ${appPath}`);\n\n  console.log(\"[1/6] Signing Electron Framework Libraries...\");\n  const libsPath = path.join(\n    appPath,\n    \"Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries\"\n  );\n  if (fs.existsSync(libsPath)) {\n    const libs = fs.readdirSync(libsPath).filter((f) => f.endsWith(\".dylib\"));\n    for (const lib of libs) {\n      const libPath = path.join(libsPath, lib);\n      run(\n        `codesign -fs \"${DEV_ID}\" --options runtime --timestamp -v \"${libPath}\"`\n      );\n    }\n  }\n\n  console.log(\"[2/6] Signing Binaries of Helpers and Squirrel...\");\n  const crashpadHandler = path.join(\n    appPath,\n    \"Contents/Frameworks/Electron Framework.framework/Versions/A/Helpers/chrome_crashpad_handler\"\n  );\n  const shipIt = path.join(\n    appPath,\n    \"Contents/Frameworks/Squirrel.framework/Versions/A/Resources/ShipIt\"\n  );\n  if (fs.existsSync(crashpadHandler))\n    run(\n      `codesign -fs \"${DEV_ID}\" --options runtime --timestamp -v \"${crashpadHandler}\"`\n    );\n  if (fs.existsSync(shipIt))\n    run(\n      `codesign -fs \"${DEV_ID}\" --options runtime --timestamp -v \"${shipIt}\"`\n    );\n\n  console.log(\"[3/6] Signing Frameworks...\");\n  const frameworks = [\n    \"Electron Framework.framework\",\n    \"Squirrel.framework\",\n    \"Mantle.framework\",\n    \"ReactiveObjC.framework\",\n  ];\n  for (const fw of frameworks) {\n    const fwPath = path.join(appPath, \"Contents/Frameworks\", fw);\n    if (fs.existsSync(fwPath)) {\n      run(\n        `codesign -fs \"${DEV_ID}\" --options runtime --timestamp -v \"${fwPath}\"`\n      );\n    }\n  }\n\n  console.log(\"[4/6] Signing Helper Apps...\");\n  const helpers = [\n    \"OWallet Helper.app\",\n    \"OWallet Helper (Renderer).app\",\n    \"OWallet Helper (Plugin).app\",\n    \"OWallet Helper (GPU).app\",\n  ];\n  for (const helper of helpers) {\n    const helperPath = path.join(appPath, \"Contents/Frameworks\", helper);\n    if (fs.existsSync(helperPath)) {\n      console.log(`Signing executables in ${helperPath}`);\n      const helperExePath = path.join(helperPath, \"Contents/MacOS\");\n      const exes = fs.existsSync(helperExePath)\n        ? fs.readdirSync(helperExePath)\n        : [];\n      for (const exe of exes) {\n        run(\n          `codesign -fs \"${DEV_ID}\" --options runtime --timestamp -v \"${path.join(\n            helperExePath,\n            exe\n          )}\"`\n        );\n      }\n      console.log(`Signing helper app itself ${helperPath}`);\n      run(\n        `codesign -fs \"${DEV_ID}\" --options runtime --timestamp --deep --entitlements ${ENTITLEMENTS} -v \"${helperPath}\"`\n      );\n    }\n  }\n\n  console.log(\"[5/6] Signing Main Binary...\");\n  const mainExePath = path.join(appPath, \"Contents/MacOS/OWallet\");\n  if (fs.existsSync(mainExePath)) {\n    run(\n      `codesign -fs \"${DEV_ID}\" --options runtime --timestamp --deep -v --entitlements ${ENTITLEMENTS} \"${mainExePath}\"`\n    );\n  }\n\n  console.log(\"[6/6] Signing .app...\");\n  run(\n    `codesign -fs \"${DEV_ID}\" --options runtime --timestamp --deep --entitlements ${ENTITLEMENTS} -v \"${appPath}\"`\n  );\n\n  console.log(\"\\nVerifying Signature...\");\n  run(`codesign -vvv --deep --strict \"${appPath}\"`);\n  run(`codesign -dvv \"${appPath}\"`);\n\n  console.log(\"\\nManual signing completed successfully!\");\n\n  console.log(\"\\nSubmitting to Apple for notarization...\");\n\n  const ZIP_FILE = path.join(\n    context.appOutDir,\n    `${context.packager.appInfo.productFilename}.zip`\n  );\n  run(`ditto -c -k --keepParent \"${appPath}\" \"${ZIP_FILE}\"`);\n  run(\n    `xcrun notarytool submit --apple-id ${process.env.APPLE_ID} --team-id ${process.env.TEAM_ID} --password ${process.env.PASSWORD}  --wait  \"${ZIP_FILE}\"`\n  );\n  console.log(\"Notarization complete.\");\n\n  run(`xcrun stapler staple \"${appPath}\"`);\n  console.log(\"\\nSigning & notarization finished successfully!\");\n};\n"
  },
  {
    "path": "build/entitlements.mac.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \n\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n    <key>com.apple.security.cs.allow-jit</key>\n    <true/>\n    <key>com.apple.security.cs.disable-library-validation</key>\n    <true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"owallet\",\n  \"homepage\": \"http://ont.io\",\n  \"version\": \"v0.10.4\",\n  \"author\": \"Ontology Foundation Ltd. <devops@ont.io>\",\n  \"description\": \"OWallet is a comprehensive Ontology desktop wallet\",\n  \"license\": \"Apache-2.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"serve\": \"vue-cli-service electron:serve\",\n    \"build\": \"vue-cli-service electron:build -mlw --publish=never\",\n    \"build:mac\": \"vue-cli-service electron:build -m --publish=never\",\n    \"build:linux\": \"vue-cli-service electron:build -l --publish=never\",\n    \"build:win\": \"vue-cli-service electron:build -w --publish=never\",\n    \"postinstall\": \"electron-builder install-app-deps\",\n    \"postuninstall\": \"electron-builder install-app-deps\"\n  },\n  \"main\": \"background.js\",\n  \"dependencies\": {\n    \"@electron/remote\": \"^2.1.2\",\n    \"@ledgerhq/hw-transport-node-hid\": \"^5.19.1\",\n    \"@xkeshi/vue-qrcode\": \"^1.0.0\",\n    \"ant-design-vue\": \"^1.1.9\",\n    \"axios\": \"^0.21.1\",\n    \"bignumber.js\": \"^7.2.1\",\n    \"bootstrap\": \"^4.1.1\",\n    \"caniuse-lite\": \"^1.0.30001749\",\n    \"clipboard\": \"^2.0.1\",\n    \"core-js\": \"^3.6.5\",\n    \"dateformat\": \"^3.0.3\",\n    \"delay\": \"^4.4.0\",\n    \"elliptic\": \"^6.5.4\",\n    \"font-awesome\": \"^4.7.0\",\n    \"lodash\": \"^4.17.21\",\n    \"nedb\": \"^1.8.0\",\n    \"node-hid\": \"^2.1.1\",\n    \"numeral\": \"^2.0.6\",\n    \"ontology-ts-sdk\": \"^1.1.14-alpha.5\",\n    \"opn\": \"^5.4.0\",\n    \"popper.js\": \"^1.14.3\",\n    \"sass\": \"^1.83.1\",\n    \"usb\": \"1.7.1\",\n    \"vee-validate\": \"^2.2.15\",\n    \"vue\": \"^2.7.0\",\n    \"vue-axios\": \"^2.1.1\",\n    \"vue-clipboard2\": \"^0.2.1\",\n    \"vue-electron\": \"^1.0.6\",\n    \"vue-i18n\": \"^8.0.0\",\n    \"vue-router\": \"^3.2.0\",\n    \"vuedraggable\": \"^2.16.0\",\n    \"vuex\": \"^3.4.0\"\n  },\n  \"devDependencies\": {\n    \"@vue/cli-plugin-babel\": \"^4.4.0\",\n    \"@vue/cli-plugin-eslint\": \"^4.4.0\",\n    \"@vue/cli-plugin-router\": \"^4.4.0\",\n    \"@vue/cli-plugin-vuex\": \"^4.4.0\",\n    \"@vue/cli-service\": \"^4.4.0\",\n    \"babel-eslint\": \"^10.1.0\",\n    \"babel-plugin-import\": \"^1.11.0\",\n    \"electron\": \"^33.0.0\",\n    \"electron-devtools-installer\": \"^3.1.0\",\n    \"eslint\": \"^6.7.2\",\n    \"eslint-plugin-vue\": \"^6.2.2\",\n    \"jquery\": \"^3.3.1\",\n    \"sass-loader\": \"^10.0.0\",\n    \"vue-cli-plugin-electron-builder\": \"^2.0.0\",\n    \"vue-template-compiler\": \"^2.6.11\"\n  },\n  \"resolutions\": {\n    \"usb\": \"1.7.1\",\n    \"node-hid\": \"2.1.1\",\n    \"app-builder-bin\": \"3.5.13\",\n    \"electron-builder\": \"23.6.0\"\n  }\n}\n"
  },
  {
    "path": "public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\n    <link rel=\"icon\" href=\"<%= BASE_URL %>favicon.ico\">\n    <title><%= process.env.VUE_APP_TITLE %></title>\n  </head>\n  <body>\n    <noscript>\n      <strong>We're sorry but <%= process.env.VUE_APP_TITLE %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>\n    </noscript>\n    <div id=\"app\"></div>\n    <!-- built files will be auto injected -->\n  </body>\n</html>\n"
  },
  {
    "path": "src/App.vue",
    "content": "<template>\n  <div id=\"app\">\n    <top-left-nav v-if=\"$route.name !== 'Home'\"></top-left-nav>\n\n    <div class=\"container-fluid\">\n      <router-view></router-view>\n    </div>\n\n      <loading-modal></loading-modal>\n  </div>\n</template>\n\n<script>\n  import 'bootstrap/dist/css/bootstrap.min.css'\n  import 'bootstrap/dist/js/bootstrap.min.js'\n  import TopLeftNav from \"./components/TopLeftNav\"\n  import LoadingModal from './components/Modals/Loading'\n\n  export default {\n    name: 'ont-wallet-test',\n    components: {TopLeftNav, LoadingModal},\n    watch: {\n      '$route': 'hideLoadingPage'\n    },\n    created() {\n      if(!localStorage.getItem('net')) { // initialize the network as MAIN_NET\n          localStorage.setItem('net', 'MAIN_NET');\n      }\n    },\n    methods: {\n      hideLoadingPage() {\n        this.$store.dispatch('hideLoadingModals')\n      }\n    }\n  }\n</script>\n\n\n\n<style lang=\"scss\">\n  /* CSS */\n  @font-face {\n    font-family: SourceSansPro;\n    src: url('./assets/fonts/SourceSansPro-Semibold.ttf');\n  }\n\n  @font-face {\n    font-family: AvenirNext-Bold;\n    src: url('./assets/fonts/AvenirNextBold.ttf');\n  }\n  @font-face {\n    font-family: AvenirNext-Medium;\n    src: url('./assets/fonts/AvenirNextMedium.ttf');\n  }\n  @font-face {\n    font-family: AvenirNext-Regular;\n    src: url('./assets/fonts/avenirnextregular.otf');\n  }\n\n  body {\n      p {\n        margin:0;\n    }\n  }\n\n\n\n  .loading {\n    text-align: center;\n    background: rgba(0, 0, 0, 0.05);\n    width: 100%;\n    height: 100%;\n  }\n\n  .container-fluid {\n    padding-left: 5.13rem !important;\n    padding-top: 4rem;\n  }\n\n  .font-regular {\n    font-family: AvenirNext-Regular;\n    color: #000000;\n    font-size: 0.88rem;\n  }\n\n  .font-gray {\n    color: #6F7781;\n  }\n\n  .font-medium {\n    font-family: AvenirNext-Medium;\n    color: #5E6369;\n    font-size: 0.88rem;\n  }\n\n  .font-medium-black {\n    font-family: AvenirNext-Medium;\n    color: #000000;\n    font-size: 0.88rem;\n  }\n\n  .font-bold {\n    font-family: AvenirNext-Bold;\n    color: #5E6369;\n    font-size: 14px;\n  }\n\n  .font-title {\n    font-size:18px;\n    font-family: AvenirNext-Regular,AvenirNext;\n    font-weight:400;\n    color:rgba(0,0,0,1);\n  }\n\n\n  /* Button CSS */\n  .btn-container {\n    width: 540px;\n    margin: 25px auto;\n  }\n\n  .btn-next,\n  .btn-cancel {\n    min-width: 6.25rem !important;\n    height: 2.13rem !important;\n    font-family: AvenirNext-Medium !important;\n    font-size: 14px !important;\n    text-align: center !important;\n  }\n\n  .btn-cancel {\n    background: #F5F7FB !important;\n    border-radius: 0 !important;\n    color: #5E6369 !important;\n    border: none !important;\n  }\n  .btn-cancel:hover {\n      background: #E4E6EA !important;\n  }\n\n  .btn-next {\n    background: #196BD8 !important;\n    color: #ffffff !important;\n    border-radius: 0 !important;\n    border: none !important;\n  }\n  .btn-next:hover {\n      background: #619AE5 !important;\n  }\n\n  .btn-add {\n    width: 80px !important;\n    height: 34px !important;\n    background: #FBE45A !important;\n    border-radius: 0 !important;\n    font-family: 'AvenirNext-Bold' !important;\n    border: none !important;\n    font-size: 18px !important;\n  }\n\n  .btn-add:hover {\n    border: 1px solid #FBE45A !important;\n  }\n\n  .btn-cancel span, .btn-next span {\n    width: 100%;\n  }\n\n  .input {\n    border-radius: 0 !important;\n    background: #FFFFFF !important;\n    border: 1px solid #DFE2E9 !important;\n    height: 34px !important;\n  }\n\n  .error-input {\n    border-color:red !important;\n  }\n\n  .footer-btns {\n    position: fixed;\n    bottom: 0;\n    width: calc(100% - 4rem);\n    height: 85px;\n    left: 4rem;\n    background: #FFFFFF;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    z-index: 1000;\n  }\n\n  .footer-btn-container {\n    width: 540px;\n    margin: 20px auto;\n  }\n\n  .footer-btn-container :last-child {\n    float: right;\n  }\n\n  .ant-spin-text {\n    color: white !important;\n    text-shadow: none !important;\n  }\n\n  /* .ant-spin-dot i {\n    background-color: white !important;\n  } */\n\n  .v-validate-span-errors {\n    color: red;\n    font-size: 12px;\n    display: block;\n  }\n\n  .refresh-icon {\n    display: inline-block;\n    background-image: url('./assets/refresh.svg');\n    background-size: cover;\n  }\n  .add-icon {\n    background-image: url('./assets/add.svg');\n    display:inline-block;\n    background-size: cover;\n  }\n  /* .add-icon:hover {\n    background-image: url('./assets/add-hover.png');\n  } */\n\n  .common-icon {\n    width:20px;\n    height:20px;\n    border-radius: 50%;\n    background-color:#F4F4F6;\n    cursor: pointer;\n  }\n  .common-icon:hover {\n    background-color:#E4E6EA;\n  }\n\n  .copy-icon {\n    display: inline-block;\n    margin-left: 10px;\n    background-image: url('./assets/copy_new.svg');\n    background-size: cover;\n    position: relative;\n    top: 5px;\n}\n\n  .asset-container {\n    height:40vh;\n    overflow:auto;\n  }\n\n.asset-container::-webkit-scrollbar {\n    -webkit-appearance: none;\n}\n\n.asset-container::-webkit-scrollbar:vertical {\n    width: 10px;\n    height:15px;\n}\n\n.asset-container::-webkit-scrollbar-thumb {\n    border-radius: 4px;\n    border: 2px solid white; /* should match background, can't be transparent */\n    background-color:#dddddd;\n}\n\n .wallet-balance {\n    font-size: 16px;\n    color: #000000;\n    font-family: 'AvenirNext-Bold';\n    position: relative;\n    margin-top: 30px;\n    display:flex;\n    justify-content: space-between;\n    padding-bottom: 5px;\n    border-bottom:1px solid #F4F4F6;\n  }\n\n  .wallet-balance :first-child {\n    float: left;\n    margin-right: 20px;\n  }\n\n\n  .asset-item {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    /* margin-top: 10px; */\n    /* padding-right:20px; */\n    width:100%;\n    height:40px;\n    border-bottom:1px solid #F4F4F6;\n  }\n\n  .asset-ong {\n    height: 2.56rem;\n    line-height: 2.56rem;\n    margin-top: 12px;\n  }\n\n  .asset-label {\n    font-family: AvenirNext-Medium;\n    font-size: 0.88rem;\n    color: #515457;\n    float: left;\n    margin-right: 12px;\n  }\n\n  .asset-amount {\n    font-family: AvenirNext-Medium;\n    font-size: 18px;\n    color: #000000;\n  }\n\n  .asset-value {\n    padding-left: 3rem;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #000000;\n    margin-bottom: 20px;\n  }\n\n  .asset-btn {\n    border-radius: 0;\n    background: #196BD8;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #FFFFFF;\n    margin-right: 20px;\n    margin-bottom: 20px;\n    border: none;\n    width:120px;\n    height: 34px;\n  }\n  .asset-btn > i {\n      margin-right:4px;\n  }\n\n  .claim-ong-container {\n    display:flex;\n    justify-content: space-between;\n    align-items: flex-end;\n    padding-bottom:10px;\n    border-bottom: 1px solid #F4F4F6;\n    margin-bottom:20px;\n  }\n\n  .claim-ong-item {\n    margin-bottom: 10px;\n    position: relative;\n  }\n\n  .claim-ong-item :first-child {\n    font-family: AvenirNext-Medium;\n    font-size: 12px;\n    color: #515457;\n    margin-right: 8px;\n    width: 100px;\n    display: block;\n    float: left;\n  }\n\n  .claim-ong-item :nth-child(2) {\n    font-family: AvenirNext-Medium;\n    font-size: 12px;\n    color: #000000;\n    float: left;\n  }\n  .redeem-container {\n    display: flex;\n    align-items: center;\n  }\n\n  .btn-redeem {\n    border: none;\n    color: #227EEC;\n    font-size: 14px;\n    font-family: AvenirNext-Medium;\n    font-weight: 500;\n    padding-right: 0;\n  }\n  .btn-redeem:hover {\n    color:#619AE5;\n  }\n\n  .tx-item {\n    display: flex;\n    justify-content: space-between;\n    margin-bottom:14px;\n    font-family: AvenirNext-Medium;\n    font-size: 12px;\n    width:100%;\n    cursor: pointer;\n  }\n\n  .tx-item:hover span {\n    color:#196BD8 !important;\n  }\n\n  .tx-item :first-child {\n    flex: 0.6;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    color: #6F7781;\n  }\n\n  .tx-item :last-child {\n    flex:0.4;\n    text-align: right;\n    font-family: AvenirNext-Medium;\n    font-size: 12px;\n    color: #000000;\n  }\n\n.left-footer {\n  margin-top:20px;\n}\n.negative-margin-top {\n    margin-top:-4rem;\n}\n\n.ant-tabs-tab-active {\n    color: #000000;\n}\n\n.app-container {\n    width: 550px;\n\tmargin: 0 auto;\n\tmargin-top: 20px;\n}\n</style>\n"
  },
  {
    "path": "src/background.js",
    "content": "'use strict'\n\nimport { app, protocol, BrowserWindow, Menu } from 'electron'\nimport { createProtocol } from 'vue-cli-plugin-electron-builder/lib'\nimport installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'\nrequire('@electron/remote/main').initialize()\nconst isDevelopment = process.env.NODE_ENV !== 'production'\n\n// Keep a global reference of the window object, if you don't, the window will\n// be closed automatically when the JavaScript object is garbage collected.\nlet win\n\n// Scheme must be registered before the app is ready\nprotocol.registerSchemesAsPrivileged([\n  { scheme: 'app', privileges: { secure: true, standard: true } }\n])\n\nfunction createWindow() {\n  // Create the browser window.\n  win = new BrowserWindow({\n    useContentSize: true,\n    width: 1110,\n    minWidth: 1110,\n    height: 675,\n    minHeight: 635,\n    webPreferences: {\n      // Use pluginOptions.nodeIntegration, leave this alone\n      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info\n      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,\n      webSecurity: false,\n      enableRemoteModule: true,\n      // TODO: Expose only necessary modules.\n      contextIsolation: false,\n    }\n  })\n  require('@electron/remote/main').enable(win.webContents);\n\n  const menu = Menu.buildFromTemplate(template)\n  Menu.setApplicationMenu(menu)\n\n  if (process.env.WEBPACK_DEV_SERVER_URL) {\n    // Load the url of the dev server if in development mode\n    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)\n    if (!process.env.IS_TEST) win.webContents.openDevTools()\n  } else {\n    createProtocol('app')\n    // Load the index.html when not in development\n    win.loadURL('app://./index.html')\n  }\n\n  win.on('closed', () => {\n    win = null\n  })\n}\n\n// Quit when all windows are closed.\napp.on('window-all-closed', () => {\n  // On macOS it is common for applications and their menu bar\n  // to stay active until the user quits explicitly with Cmd + Q\n  if (process.platform !== 'darwin') {\n    app.quit()\n  }\n})\n\napp.on('activate', () => {\n  // On macOS it's common to re-create a window in the app when the\n  // dock icon is clicked and there are no other windows open.\n  if (win === null) {\n    createWindow()\n  }\n})\n\n// This method will be called when Electron has finished\n// initialization and is ready to create browser windows.\n// Some APIs can only be used after this event occurs.\napp.on('ready', async () => {\n  if (isDevelopment && !process.env.IS_TEST) {\n    // Install Vue Devtools\n    try {\n      await installExtension(VUEJS_DEVTOOLS)\n    } catch (e) {\n      console.error('Vue Devtools failed to install:', e.toString())\n    }\n  }\n  createWindow()\n})\n\n// Exit cleanly on request from parent process in development mode.\nif (isDevelopment) {\n  if (process.platform === 'win32') {\n    process.on('message', (data) => {\n      if (data === 'graceful-exit') {\n        app.quit()\n      }\n    })\n  } else {\n    process.on('SIGTERM', () => {\n      app.quit()\n    })\n  }\n}\n\n// Menu template\nconst template = [\n  {\n    label: 'Edit ( 操作 )',\n    submenu: [{\n      label: 'Select All ( 全选 )',\n      accelerator: 'CmdOrCtrl+A',\n      role: 'selectall'\n    }, {\n      label: 'Copy ( 复制 )',\n      accelerator: 'CmdOrCtrl+C',\n      role: 'copy'\n    }, {\n      label: 'Cut ( 剪切 )',\n      accelerator: 'CmdOrCtrl+X',\n      role: 'cut'\n    }, {\n      label: 'Paste ( 粘贴 )',\n      accelerator: 'CmdOrCtrl+V',\n      role: 'paste'\n    }, {\n      label: 'Reload ( 重新加载 )',\n      accelerator: 'CmdOrCtrl+R',\n      click: function (item, focusedWindow) {\n        if (focusedWindow) {\n          // on reload, start fresh and close any old\n          // open secondary windows\n          if (focusedWindow.id === 1) {\n            BrowserWindow.getAllWindows().forEach(function (win) {\n              if (win.id > 1) {\n                win.close()\n              }\n            })\n          }\n          focusedWindow.reload()\n        }\n      }\n    },\n      {\n        label: 'Quit ( 退出 )',\n        accelerator: 'CmdOrCtrl+Q',\n        role: 'quit'\n      },\n  ]\n  },\n  {\n    label: 'Window ( 窗口 )',\n    role: 'window',\n    submenu: [{\n      label: 'Minimize ( 最小化 )',\n      accelerator: 'CmdOrCtrl+M',\n      role: 'minimize'\n    }, {\n      label: 'Close ( 关闭 )',\n      accelerator: 'CmdOrCtrl+W',\n      role: 'close'\n    }, {\n      label: 'Developer Tools (切换开发者工具)',\n      accelerator: (function () {\n        if (process.platform === 'darwin') {\n          return 'Alt+Command+I'\n        } else {\n          return 'Ctrl+Shift+I'\n        }\n      })(),\n      click: function (item, focusedWindow) {\n        if (focusedWindow) {\n          focusedWindow.toggleDevTools()\n        }\n      }\n    }, {\n      type: 'separator'\n    }]\n  }\n]\n"
  },
  {
    "path": "src/components/Breadcrumb.vue",
    "content": "<style scoped>\n    .breadcrumb-container {\n        height:4rem;\n        padding:1.1rem 0 1.1rem 15px;\n        padding-left:5.13rem;\n        width:100%;\n        position: fixed;\n        top:0;\n        left:0;\n        background:rgba(255,255,255,1);\n        z-index: 100;\n    }\n    .back-icon-container {\n        height: 1.7rem;\n        line-height: 1.7rem;\n        padding-right: 18px;\n        border-right: 1px solid #dddddd;\n        float: left;\n        cursor: pointer;\n        color: #1C76DD;\n        font-size: 18px;\n    }\n    .back-icon-container:hover {\n        color:#619AE5;\n    }\n    .back-icon {\n        display: inline-block;\n        height:10px;\n        width:18px;\n        background:url(../assets/back.png) center center;\n        background-size: cover;\n        line-height: 1.7rem;\n    }\n    .breadcrumb-routes {\n        float: left;\n        margin-left: 18px;\n        height:1.7rem;\n        line-height: 1.7rem;    \n    }\n    .breadcrumb-routes a {\n        color: #A5A7A9;\n        font-size:16px;\n        font-family: AvenirNext-Bold;\n\n    }\n    .breadcrumb-current {\n        float:left;\n        height:1.7rem;\n        line-height: 1.7rem;\n        margin-left: 18px;\n        color: #000000;\n        font-size:14px; \n        font-family: AvenirNext-Bold;\n    }\n    .left-icon {\n        font-size: 16px;\n        color: #A5A7A9;\n        margin-left: 10px;\n    }\n</style>\n<template>\n    <div class=\"breadcrumb-container\">\n        <div class=\"back-icon-container\" @click=\"back\">\n            <span class=\"fa fa-long-arrow-left\"></span>\n        </div>\n        <div class=\"breadcrumb-routes\" v-for=\"route in routes\" :key=\"route.path\">\n            <router-link :to=\"route.path\">{{route.name}}</router-link>\n            <a-icon type=\"right\" class=\"left-icon\" />\n        </div>\n        <div class=\"breadcrumb-current\">\n            {{current}}\n        </div>\n    </div>\n</template>\n\n<script>\nexport default {\n    name:'Breadcrumb',\n    props:['routes', 'current'],\n    methods:{\n        back() {\n            this.$emit('backEvent');\n            // this.$router.back();\n        }\n    }\n}\n</script>\n\n\n"
  },
  {
    "path": "src/components/Common/CommonSignShared.vue",
    "content": "<style scoped>\n.sign-container {\n    display: flex;\n}\n.label {\n    width:200px;\n     margin-right:10px;\n}\n.sign-content {\n    flex:1;\n\n}\n\n</style>\n<template>\n    <div class=\"sign-container\">\n        <p class=\"label\">{{$t('sharedTx.signTx')}}</p>\n\n        <div class=\"sign-content\">\n            <div v-if=\"wallet.type === 'CommonWallet'\">\n                <a-input type=\"password\" class=\"input-pass\" :placeholder=\"$t('pax.inputPassword')\" v-model=\"password\"></a-input>\n            </div>\n\n            <div class=\"ledger-status\" v-if=\"wallet.type === 'HardwareWallet'\">\n                <div class=\"font-bold\" style=\"margin-bottom: 15px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                <span class=\"font-medium\">{{ledgerStatus}} </span>\n                <p>{{$t('pax.ledgerSignMultiTimes')}}</p>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\nimport {mapState} from 'vuex'\nimport {DEFAULT_SCRYPT} from '../../core/consts'\nimport {decryptWallet} from '../../core/utils'\nimport {legacySignWithLedger} from '../../core/ontLedger'\nimport {Crypto, Transaction, TransactionBuilder, TxSignature, utils, RestClient} from 'ontology-ts-sdk'\n\nexport default {\n    name: 'SignSharedTx',\n    props: ['wallet'],\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        return {\n            password: '',\n            sharedWallet\n        }\n    },\n    mounted(){\n        if(this.wallet.type === 'HardwareWallet') {\n            this.$store.dispatch('getLedgerStatus')\n        }\n    },\n    beforeDestroy() {\n        clearInterval(this.intervalId);\n        this.$store.dispatch('stopGetLedgerStatus')\n    },\n    computed:{\n        ...mapState({\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n            ledgerWallet: state => state.LedgerConnector.ledgerWallet,\n        })\n    },\n    methods: {\n        async signSharedTx(isFirstSign, tx) {\n            if(this.wallet.type === 'CommonWallet' && !this.password\n            || this.wallet.type === 'HardwareWallet' && !this.ledgerPk) {\n                return;\n            }\n            const M = this.sharedWallet.requiredNumber;\n            const pks = this.sharedWallet.coPayers.map(p => new Crypto.PublicKey(p.publickey))\n           const txTemp = Transaction.deserialize(tx)\n            if (this.wallet.type === 'CommonWallet') {\n                const pri = decryptWallet({\n                    key: this.wallet.wallet.key,\n                    address: this.wallet.address,\n                    salt: this.wallet.wallet.salt\n                    }, this.password);\n                if (!pri) {\n                    return;\n                }\n                TransactionBuilder.signTx(txTemp, M, pks, pri)\n            } else {\n                txTemp.payer = new Crypto.Address(this.wallet.sharedWalletAddress);\n                let res;\n                try {\n                    res = await legacySignWithLedger(txTemp.serializeUnsignedData())\n                } catch(err) {\n                    this.ledgerStatus = '';\n                    this.$store.dispatch('hideLoadingModals')\n                    alert(err.message)\n                    return;\n                }\n                const sig = new TxSignature();\n                sig.M = M;\n                sig.pubKeys = pks;\n                if(isFirstSign) {\n                    sig.sigData = ['01' + res];\n                    txTemp.sigs.push(sig);\n                } else {\n                    const sigVal = '01' + res;\n                    txTemp.sigs[0].sigData.push(sigVal);\n                }\n\n            }\n            this.$emit('sharedTxSigned', txTemp.serialize())\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Common/Oep4Home.vue",
    "content": "<style scoped>\n.content-container {\n    display: flex;\n    padding:10px;\n  }\n\n  .left-half {\n    flex-basis: 50%;\n    padding-right: 40px;\n\n  }\n  .oep4-container {\n      max-height:360px;\n      overflow-y:auto;\n  }\n\n  .right-half {\n    flex-basis: 50%;\n  }\n  .home-title {\n      display: flex;\n      align-items: center;\n      margin-bottom:20px;\n  }\n  .home-title p {\n      font-size: 20px;\n      font-weight: 500;\n      margin:0;\n      margin-right:15px;\n  }\n  .oep4-item {\n      margin-bottom: 15px;\n  }\n\n  .oep4-item div {\n      display: flex;\n      align-items: center;\n  }\n   .asset-label {\n    font-family: AvenirNext-Medium;\n    font-size: 16px;\n    color: #515457;\n    float: left;\n    margin-right: 12px;\n  }\n\n  .asset-amount {\n    font-family: AvenirNext-Medium;\n    font-size: 16px;\n    color: #000000;\n  }\n  .asset-scriptHash {\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #000000;\n  }\n  .oep4-btns {\n      margin-top:30px;\n  }\n   .asset-btn {\n    border-radius: 0;\n    background: #196BD8;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #FFFFFF;\n    width: 100px;\n    height: 34px;\n    margin-right: 40px;\n    margin-bottom: 60px;\n    border: none;\n  }\n\n  .txList-header {\n    padding-bottom: 5px;\n    border-bottom: 1px solid #DFE2E9;\n    position: relative;\n  }\n\n  .txList-header :first-child {\n    font-family: AvenirNext-Bold;\n    font-size: 14px;\n    color: #000000;\n    text-align: center;\n  }\n\n  .txList-header :last-child {\n    width: 64px;\n    height: 64px;\n    display: block;\n    float: right;\n    background: url('../../assets/transaction.png');\n    background-size: contain;\n    top: -20px;\n    right: 0;\n    position: absolute;\n  }\n  .tx-item {\n    float: left;\n    margin: 5px 0;\n    cursor: pointer;\n  }\n\n  .tx-item :first-child {\n    width: 65%;\n    display: inline-block;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-family: AvenirNext-Medium;\n    font-size: 12px;\n    color: #6F7781;\n  }\n\n  .tx-item :last-child {\n    width: 30%;\n    text-align: right;\n    float: right;\n    display: block;\n    font-family: AvenirNext-Medium;\n    font-size: 12px;\n    color: #000000;\n  }\n.check-more {\n    font-family: AvenirNext-Medium;\n    font-size: 12px;\n    color: #227EEC;\n    text-align: center;\n    cursor: pointer;\n    width:100%;\n    float:left;\n  }\n</style>\n\n<template>\n    <div>\n        <breadcrumb :current=\"$t('sharedWalletHome.send')\" :routes=\"routes\"\n                v-on:backEvent=\"handleBack\"></breadcrumb>\n\n        <div class=\"content-container\">\n            <div class=\"left-half\">\n                <div class=\"oep4-container\">\n                    <div class=\"home-title\">\n                        <p>OEP-4 Tokens</p>\n                        <a-icon class=\"refresh-icon\" type=\"reload\" @click=\"refresh\"/>\n                    </div>\n\n                    <div class=\"oep4-item\" v-for=\"(token,index) of oep4s.filter(token.net === net)\" :key=\"index\">\n                        <div class=\"font-medium-black\">{{token.symbol}} - {{token.name}}</div>\n                        <div class=\"oep4-balance\">\n                            <span class=\"asset-label\">{{$t('commonWalletHome.balance')}}: </span>\n                            <span class=\"asset-amount\">{{token.balance}}</span>\n                        </div>\n                        <div class=\"\">\n                            <span class=\"asset-label\">{{$t('commonWalletHome.scriptHash')}}: </span>\n                            <span class=\"asset-scriptHash\">{{token.scriptHash}}</span>\n                        </div>\n                    </div>\n\n                    <a-button @click=\"handleAdd\">{{$t('commonWalletHome.add')}}</a-button>\n                </div>\n                <div class=\"oep4-btns\">\n                    <a-button class=\"asset-btn\" type=\"primary\" @click=\"sendAsset\">\n                        <i class=\"arrow-up\"></i>\n                        {{$t('sharedWalletHome.send')}}\n                    </a-button>\n                    <a-button class=\"asset-btn\" type=\"primary\" @click=\"commnReceive\">\n                        <i class=\"arrow-down\"></i>\n                        {{$t('sharedWalletHome.receive')}}\n                    </a-button>\n                </div>\n            </div>\n            <div class=\"right-half\">\n                <div class=\"completed-tx\">\n                    <div class=\"txList-header\">\n                        <span>{{$t('sharedWalletHome.completedTx')}}</span>\n                        <span class=\"transfer-icon\"></span>\n                    </div>\n                    <div v-for=\"(tx,index) in completedTx.slice(0,10)\" :key=\"tx.txHash+index\" class=\"tx-item\"\n                        @click=\"showTxDetail(tx.txHash)\">\n                        <span>{{tx.txHash}}</span>\n                        <span>{{tx.amount}} {{tx.asset}}</span>\n                    </div>\n                    <div class=\"check-more\" v-if=\"completedTx.length > 6\" @click=\"checkMoreTx\">\n                        {{$t('sharedWalletHome.checkMore')}}>>\n                    </div>\n                </div>\n            </div>\n          </div>\n\n        <a-modal\n            :title=\"$t('commonWalletHome.addOep4')\"\n            :visible=\"showModal\"\n            @ok=\"handleAddOep4\"\n            @cancel=\"handleCancel\">\n            <div>\n                <div>\n                    <p>{{$t('commonWalletHome.enterScripthash')}}</p>\n                    <a-input class=\"input\" v-model=\"scriptHash\"  ></a-input>\n                </div>\n            </div>\n        </a-modal>\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from '../Breadcrumb'\nimport {mapState} from 'vuex'\nimport { TEST_NET } from '../../core/consts'\nimport { open } from '../../core/utils'\n\nexport default {\n    name: 'Oep4Home',\n    data() {\n        const net = localStorage.getItem('net')\n        return {\n            showModal: false,\n            scriptHash: '',\n            net: net\n        }\n    },\n    components:{\n        Breadcrumb\n    },\n    mounted() {\n        this.refresh()\n    },\n    computed:{\n        ...mapState({\n            oep4s: state => state.Oep4s.oep4s,\n            completedTx: state => state.Oep4s.completedTx,\n            address: state => state.CurrentWallet.wallet.address,\n            currentWallet: state => state.CurrentWallet.wallet\n        }),\n        routes: function() {\n            const address = this.$store.state.CurrentWallet.wallet.address;\n            let path = '';\n            if(address === this.$store.state.CurrentWallet.wallet.address) {\n                path = '/dashboard'\n            } else {\n                path = '/sharedWallet/home'\n            }\n            return [{name: this.$store.state.CurrentWallet.wallet.name, path}]\n        }\n    },\n    methods: {\n        refresh() {\n            this.$store.dispatch('queryBalanceForOep4', this.address)\n            this.$store.dispatch('queryTxForOep4', {address: this.address, oep4s: this.oep4s})\n        },\n        handleBack() {\n            this.$router.push({name: 'Wallets'})\n        },\n        handleAdd() {\n            this.showModal = true;\n        },\n        handleCancel() {\n            this.showModal = false;\n            this.scriptHash = ''\n        },\n        handleAddOep4(){\n            if(!this.scriptHash || this.scriptHash.trim().length !== 40) {\n                this.$message.error(this.$t('commonWalletHome.invalidScriptHash'))\n                return;\n            }\n            for(let i = 0 ; i < this.oep4s.length; i++) {\n                if(this.oep4s[i].scriptHash === this.scriptHash) {\n                    this.$message.warning(this.$t('commonWalletHome.oep4Exists'))\n                    return;\n                }\n            }\n            this.$store.dispatch('showLoadingModals')\n            this.$store.dispatch('addOep4Token', {\n                scriptHash: this.scriptHash,\n                address: this.address\n            }).then(res => {\n                this.$store.dispatch('hideLoadingModals')\n                if(res === 'ADD_SUCCESS') {\n                    this.showModal = false;\n                    this.scriptHash = '';\n                    this.$message.success(this.$t('commonWalletHome.addOep4Success'))\n                } else if(res === 'NO_CONTRACT') {\n                    this.$message.success(this.$t('commonWalletHome.noOep4Contract'))\n                } else if (res === 'NETWORK_ERROR') {\n                    this.$message.success(this.$t('commonWalletHome.networkError'))\n                }\n            })\n        },\n        sendAsset() {\n            this.$store.commit('CLEAR_CURRENT_TRANSFER');\n            if(this.address === this.currentWallet.address) {\n                this.$router.push({name: 'CommonSendHome'})\n            } else {\n                this.$store.commit('UPDATE_TRANSFER_REDEEM_TYPE', {type: false});\n                this.$router.push({path:'/sharedWallet/sendTransfer'})\n            }\n        },\n        commnReceive() {\n            this.$router.push({path: '/commonWalletReceive/commonWallet'})\n        },\n        showTxDetail(txHash) {\n            let url = `https://explorer.ont.io/transaction/${txHash}`\n            if (this.net === 'TEST_NET') {\n                url += '/testnet'\n            }\n            open(url)\n        },\n        checkMoreTx() {\n        let url = `https://explorer.ont.io/address/${this.address}/10/1`\n            if (this.net === 'TEST_NET') {\n                url += '/testnet'\n            }\n            open(url)\n        },\n    }\n}\n</script>\n\n"
  },
  {
    "path": "src/components/Common/Oep4Selection.vue",
    "content": "<style scoped>\n.selection-container {\n    height:370px;\n    margin-top:-15px;\n}\n.pages {\n    margin:0 auto;\n    margin-top:20px;\n    text-align: center;\n}\n.selection-item {\n    display: flex;\n    justify-content: space-between;\n    padding: 7px 0;\n    border-bottom:1px solid #DFE2E9;\n}\n.selection-item p {\n    margin: 0;\n    font-size:14px;\n    font-family:PingFangSC-Regular;\n    font-weight:400;\n    color:rgba(0,0,0,1);\n}\n.oep4-info {\n    font-size: 12px;\n}\n.oep4-info p {\n    margin:0;\n}\n</style>\n<template>\n    <div>\n        <a-modal\n            :title=\"$t('common.selectOep4')\"\n            :visible=\"visible\"\n            @cancel=\"handleClose\"\n            :footer=\"null\"\n            :width=\"400\">\n\n                <div>\n                    <div class=\"selection-container\">\n                        <div v-for=\"item of oep4s\" :key=\"item.contract_hash\" class=\"selection-item\">\n                            <p>{{item.symbol}}</p>\n                            <!-- <a-checkbox :checked=\"item.selected\" @change=\"onChangeSelection(item)\"></a-checkbox> -->\n                            <a-switch :checked=\"item.selected\" @change='onChangeSelection(item)'/>\n                        </div>\n                    </div>\n\n                    <a-pagination v-model=\"page_number\" :total=\"total\"  @change=\"handlePageChange\" class=\"pages\"/>\n                </div>\n\n        </a-modal>\n    </div>\n</template>\n<script>\n/*\n从后台获取oep4列表，本地缓存用户选择的记录，对比合约hash，显示选择状态，要有分页；\n每次更新选择，触发mutation更新store并更新缓存；\n*/\nimport {mapState} from 'vuex'\nexport default {\n    name: 'Oep4Selection',\n    props: ['visible'],\n    data() {\n        return {\n            oep4s: [],\n            page_size: 10,\n            page_number: 1,\n            total: 0,\n        }\n    },\n\n     mounted() {\n    },\n\n    computed: {\n        ...mapState({\n\n        })\n\n    },\n    watch: {\n        visible: function(newVal) {\n           this.fetchOep4List();\n        }\n    },\n    methods: {\n        handleClose() {\n            this.page_number = 1;\n            this.$emit('closeOep4Selection')\n        },\n        onChangeSelection(item) {\n            item.selected = !item.selected;\n            this.$store.commit('UPDATE_OEP4_TOKEN', {oep4: item})\n        },\n        handlePageChange(page) {\n            this.page_number = page;\n            this.fetchOep4List();\n        },\n        fetchOep4List() {\n            this.$store.dispatch('showLoadingModals')\n            this.$store.dispatch('fetchOep4Selections', {\n                    page_size: this.page_size,\n                    page_number: this.page_number\n                }).then(res => {\n                    console.log('result')\n                    const {list, total } = res;\n                    this.total = total;\n                    this.oep4s = list.map(item => Object.assign({}, {\n                        contract_hash: item.contract_hash,\n                        decimal: item.decimals,\n                        symbol: item.symbol,\n                        selected: item.selected\n                    }))\n                })\n        }\n\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Common/SelectWallet.vue",
    "content": "<template>\n\t<div class=\"select-container\">\n\t\t<a-select :options=\"normalWalletAndLedgerWallet\"\n\t\t\tclass=\"select-ontid\"\n\t\t\t:placeholder=\"$t('createIdentity.selectCommonWallet')\"\n\t\t\t@change=\"handleChangeWallet\">\n\t\t</a-select>\n\n\t\t<!-- <a-radio-group @change=\"changePayerWallet\"\n\t\t\tv-model=\"walletType\"\n\t\t\tclass=\"change-payer-radio\">\n\t\t\t<a-radio value=\"commonWallet\"\n\t\t\t\tclass=\"payer-radio-item\">{{$t('createIdentity.commonWallet')}}</a-radio>\n\t\t\t<a-radio value=\"ledgerWallet\"\n\t\t\t\tclass=\"payer-radio-item\">{{$t('createIdentity.ledgerWallet')}}</a-radio>\n\n\t\t\t<div v-if=\"walletType === 'commonWallet'\">\n\t\t\t\t<a-select :options=\"normalWalletAndLedgerWallet\"\n\t\t\t\t\tclass=\"select-ontid\"\n\t\t\t\t\t:placeholder=\"$t('createIdentity.selectCommonWallet')\"\n\t\t\t\t\t@change=\"handleChangeWallet\">\n\t\t\t\t</a-select>\n\t\t\t</div>\n\n\t\t\t<div v-if=\"walletType === 'ledgerWallet'\">\n\n\t\t\t\t<div class=\"payer-ledger-status\">\n\t\t\t\t\t<div class=\"font-bold\"\n\t\t\t\t\t\tstyle=\"margin-bottom: 10px;\">{{$t('ledgerWallet.connectApp')}}</div>\n\t\t\t\t\t<span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n\t\t\t\t\t<span class=\"font-medium\">{{ledgerStatus}} </span>\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t</a-radio-group> -->\n\t</div>\n</template>\n<script>\nimport { mapState } from \"vuex\";\nimport {WALLET_TYPE}  from '../../core/consts'\n\nexport default {\n\tname: \"SelectWallet\",\n\tdata: () => ({\n\t\twalletType: \"commonWallet\"\n\t}),\n\tprops: {\n\t\twalletSelected: {}\n\t},\n\tcreated() {\n\t\t// this.$store.dispatch(\"fetchWalletsFromDb\");\n\t},\n\tbeforeDestroy() {\n\t\t// this.$store.dispatch(\"stopGetLedgerStatus\");\n\t},\n\tcomputed: {\n\t\t...mapState({\n\t\t\tledgerStatus: state => state.LedgerConnector.ledgerStatus,\n\t\t\tledgerPk: state => state.LedgerConnector.publicKey,\n\t\t\tledgerWallet: state => state.LedgerConnector.ledgerWallet\n\t\t}),\n\t\tnormalWalletAndLedgerWallet: {\n\t\t\tget() {\n\t\t\t\tconst NormalList = this.$store.state.Wallets.NormalWallet.slice();\n\t\t\t\tconst LedgerList = this.$store.state.Wallets.HardwareWallet.slice();\n\n\t\t\t\tconst list1 = NormalList.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address,\n\t\t\t\t\t\tvalue: i.address\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tconst list2 = LedgerList.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\ttype: WALLET_TYPE.HardwareWallet,\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address + \" (Ledger)\",\n\t\t\t\t\t\tvalue: i.address\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tlist2.sort((a,b)=>{\n\t\t\t\t\tif (b.timestamp !== a.timestamp) {\n\t\t\t\t\t\treturn b.timestamp - a.timestamp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn b.acct - a.acct;\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\treturn [...list1, ...list2];\n\t\t\t}\n\t\t}\n\t},\n\twatch: {\n\t\t// ledgerPk(newV, oldV) {\n\t\t// \tif (newV) {\n\t\t// \t\tconst wallet = this.ledgerWallet;\n\t\t// \t\tthis.$emit(\"walletSelected\", {\n\t\t// \t\t\twalletType: this.walletType,\n\t\t// \t\t\twallet\n\t\t// \t\t});\n\t\t// \t}\n\t\t// }\n\t},\n\tmethods: {\n\t\t// changePayerWallet(e) {\n\t\t// \tthis.walletType = e.target.value;\n\t\t// \tif (e.target.value === \"ledgerWallet\") {\n\t\t// \t\tthis.$store.dispatch(\"getLedgerStatus\");\n        //     } else {\n\t\t// \t\tthis.$store.dispatch('stopGetLedgerStatus')\n\t\t// \t}\n        //     this.$emit(\"walletSelected\", {\n\t\t// \t\twalletType: this.walletType,\n\t\t// \t\twallet: null\n\t\t// \t});\n\t\t// },\n\t\thandleChangeWallet(value) {\n\t\t\tconst wallet = this.normalWalletAndLedgerWallet.find(v => {\n\t\t\t\treturn v.address === value;\n\t\t\t});\n\t\t\tthis.$emit(\"walletSelected\", {\n\t\t\t\twalletType: wallet.type === WALLET_TYPE.HardwareWallet ? \"ledgerWallet\" : \"commonWallet\",\n\t\t\t\twallet\n\t\t\t});\n\t\t}\n\t}\n};\n</script>\n<style lang=\"scss\" scoped>\n.label {\n    \n}\n.change-payer-radio {\n    width: 100%;\n}\n.payer-radio-item {\n    margin-bottom: 10px;\n}\n</style>"
  },
  {
    "path": "src/components/Common/SignSendTx.vue",
    "content": "<style scoped>\n\n</style>\n<template>\n    <div>\n    <a-modal\n        :title=\"$t('nodeStake.signWithWallet')\"\n        :visible=\"visible\"\n        @ok=\"handleWalletSignOK\"\n        @cancel=\"handleWalletSignCancel\">\n          <div v-if=\"wallet.key\">\n              <p>{{$t('nodeStake.enterWalletPass')}}</p>\n              <a-input class=\"input\" v-model=\"walletPassword\" :plaecholder=\"$t('nodeStake.password')\" type=\"password\"></a-input>\n          </div>\n          <div v-if=\"!wallet.key\">\n            <div class=\"font-bold\" style=\"margin-bottom: 10px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                    <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}} </span>\n          </div>\n    </a-modal>\n    </div>\n</template>\n<script>\nimport {mapState} from 'vuex'\nimport delay from 'delay'\nimport {DEFAULT_SCRYPT} from '../../core/consts'\nimport { getRestClient } from '../../core/utils'\nimport {legacySignWithLedger, checkPublicKeyIsInTheConnectedLedger} from '../../core/ontLedger'\nimport {Crypto, TransactionBuilder, TxSignature, utils, RestClient, WebsocketClient, Transaction, OntAssetTxBuilder} from 'ontology-ts-sdk'\n// common component to sign tx or messages with wallet or ledger.\n\nexport default {\n    name: 'SignSendTx',\n    // props:['tx', 'wallet', 'visible',],\n    props: {\n        tx: {\n            required: true\n        },\n        wallet: {\n            required: true\n        },\n        visible: {\n            required: true,\n            type: Boolean\n        },\n        sendAfterSign: {\n            required: false,\n            type: Boolean,\n            default: true\n        }\n\n    },\n    mounted(){\n\n    },\n    watch: {\n        visible(newV, oldV) {\n            if(newV) {\n                if(!this.wallet.key) {//common wallet\n                    this.$store.dispatch('getLedgerStatus')\n                }\n            } else {\n                this.$store.dispatch('stopGetLedgerStatus')\n            }\n        }\n    },\n    beforeDestroy() {\n        this.$store.dispatch('stopGetLedgerStatus')\n    },\n    data(){\n        return {\n            walletPassword: ''\n        }\n    },\n    computed:{\n        ...mapState({\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n            ledgerWallet: state => state.LedgerConnector.ledgerWallet,\n        })\n    },\n    methods: {\n        handleWalletSignCancel() {\n            this.walletPassword = '';\n            this.$emit('signClose')\n        },\n        async handleWalletSignOK() {\n            const tx = this.tx;\n            if (this.wallet.key && !this.walletPassword) {\n                //common wallet\n                this.$message.error(this.$t(\"nodeStake.passwordEmpty\"));\n                return;\n            }\n            if (this.wallet.key) {\n                this.$store.dispatch(\"showLoadingModals\");\n                const enc = new Crypto.PrivateKey(this.wallet.key);\n                let pri;\n                try {\n                    pri = enc.decrypt(\n                        this.walletPassword,\n                        new Crypto.Address(this.wallet.address),\n                        this.wallet.salt,\n                        DEFAULT_SCRYPT\n                    );\n                } catch (err) {\n                    console.log(err);\n                    this.$store.dispatch(\"hideLoadingModals\");\n                    this.$message.error(this.$t(\"common.pwdErr\"));\n                    return;\n                }\n                if(typeof tx === 'string') {\n                    const signature =  pri.sign(tx)\n                    this.$store.dispatch(\"hideLoadingModals\");\n                    this.$emit('afterSign', signature) // 返回签名message结果\n                    this.walletPassword = ''\n                } else {\n                    TransactionBuilder.signTransaction(tx, pri);\n                    this.sendTx(tx);\n                    this.walletPassword = ''\n                }\n\n            } else {\n                //ledger sign\n                if (this.ledgerWallet.address) {\n                    this.$store.dispatch(\"showLoadingModals\");\n                    this.$store.dispatch('stopGetLedgerStatus')\n                    await delay(1000);\n                    console.log(this.wallet);\n                    // 当前连接的Ledger需要和之前导入钱包的Ledger是同一个\n                    try {\n                        await checkPublicKeyIsInTheConnectedLedger(this.wallet.acct || 0, this.wallet.neo, this.wallet.publicKey)\n                    } catch (err) {\n                        this.$store.dispatch(\"hideLoadingModals\");\n                        this.$store.dispatch('getLedgerStatus')\n                        return;\n                    }\n                    let txData\n                    if(typeof tx === 'string') {\n                        txData =  tx\n                        // ledger 签名message特殊处理，放到tx的payload里. 先构造个占位的tx\n                        const addr = new Crypto.Address(this.wallet.address)\n                        const txTemp = OntAssetTxBuilder.makeTransferTx('ONT', addr, addr, '1', '500', '20000', addr)\n                        txTemp.payload.code = tx;\n                        const pk = new Crypto.PublicKey(this.wallet.publicKey);\n                        const txSig = new TxSignature();\n                        txSig.M = 1;\n                        txSig.pubKeys = [pk];\n                        txData = txTemp.serializeUnsignedData();\n                        legacySignWithLedger(txData, this.wallet.neo, this.wallet.acct || 0).then(res => {\n                            // console.log('txSigned: ' + res);\n                            const sign = \"01\" + res; //ECDSAwithSHA256\n                            txSig.sigData = [sign];\n                            txTemp.sigs = [txSig];\n                            this.$store.dispatch(\"hideLoadingModals\");\n                            this.$emit('afterSign', txTemp.serialize()) // 返回签名message结果\n                            },\n                            err => {\n                                this.sending = false;\n                                console.log(err)\n                                this.$store.dispatch(\"hideLoadingModals\");\n                                this.$message.error(this.$t('ledgerWallet.signFailed'))\n                            }\n                        ).finally(() => {\n                          this.$store.dispatch('getLedgerStatus')\n                        });\n                    } else {\n                        const pk = new Crypto.PublicKey(this.wallet.publicKey);\n                        const txSig = new TxSignature();\n                        txSig.M = 1;\n                        txSig.pubKeys = [pk];\n                        tx.payer = new Crypto.Address(this.wallet.address);\n                        txData = tx.serializeUnsignedData();\n                        legacySignWithLedger(txData, this.wallet.neo, this.wallet.acct || 0).then(res => {\n                            // console.log('txSigned: ' + res);\n                            const sign = \"01\" + res; //ECDSAwithSHA256\n                            txSig.sigData = [sign];\n                            tx.sigs = [txSig];\n                            this.sendTx(tx);\n                            },\n                            err => {\n                                console.log(err)\n                                this.sending = false;\n                                this.$store.dispatch(\"hideLoadingModals\");\n                                this.$message.error(this.$t('ledgerWallet.signFailed'))\n                            }\n                        ).finally(() => {\n                          this.$store.dispatch('getLedgerStatus')\n                        });\n                    }\n                } else {\n                    this.$store.dispatch(\"hideLoadingModals\");\n                    this.$message.warning(this.$t(\"ledgerWallet.connectApp\"));\n                }\n            }\n            },\n            sendTx(tx){\n                if(!this.sendAfterSign) {\n                    this.$emit('afterSign', tx)\n                    return;\n                }\n                this.walletPassword = '';\n                const client = getRestClient();\n                // const client = new WebsocketClient();\n                // client.sendRawTransaction(tx.serialize(), false, true).then(res => {\n                client.sendRawTransaction(tx.serialize()).then(res => {\n                console.log(res)\n                this.$store.dispatch(\"hideLoadingModals\");\n                if (res.Error === 0) {\n                    this.$message.success(this.$t('common.transSentSuccess'))\n                } else if (res.Error === -1) {\n                    if(res.Result.indexOf('balance insufficient') > -1 ) {\n                        this.$message.error(this.$t('common.balanceInsufficient'))\n                    } else if(res.Result.indexOf('cover gas cost') > -1){\n                        this.$message.error(this.$t('common.ongNoEnough'))\n                    } else {\n                        // this.$message.error(res.Result)\n                        console.log(res.Result)\n                        const msg = typeof res.Result === 'string' ? res.Result : JSON.stringify(res.Result)\n                        this.$message.error(this.$t('common.txFailed') + ' '+ msg)\n                    }\n                    return;\n                } else {\n                    this.$message.error(res.Result)\n                    return;\n                }\n                this.$emit('txSent')\n                const title = this.$t('common.transSentSuccess')\n                setTimeout(() => {\n                    this.$success({\n                        title: title,\n                        content: 'Transaction hash: ' + utils.reverseHex(tx.getHash())\n                    })\n                }, 100)\n                }).catch(err => {\n                    console.log(err)\n                    this.$message.error(this.$t('common.networkError'))\n                })\n            },\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/CommonWallet/CommonReceive.vue",
    "content": "<style scoped>\n.content-container {\n    width:540px;\n    margin:20px auto;\n}\n.label {\n    font-family: AvenirNext-Bold;\n    font-size: 14px;\n    color: #000000;\n    margin-bottom:30px;\n}\n.qrcode {\n    text-align:center;\n    margin-bottom:40px;\n}\n.address-item {\n    margin-bottom: 20px;\n}\n.address-item  :first-child{\n    width:40%;\n    float: left;\n    font-family: AvenirNext-Regular;\n    font-size: 14px;\n    color: #000000;\n}\n\n.value-item {\n    width:60%;\n    float:right;\n}\n.value-item :first-child {\n    width:280px;\n    display: block;\n    float: left;\n    word-break: break-all;\n}\n.font-regular {\n    font-family: AvenirNext-Regular;\n    font-size: 14px;\n    color: #000000;\n}\n.copy-icon {\n    width:18px;\n    height:18px;\n    display: inline-block;\n    margin-left: 10px;\n    background: url('../../assets/copy.png') center center;\n    background-size: cover;\n    cursor: pointer;\n    margin-top:10px;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('commonWalletHome.receive')\" :routes=\"routes\" v-on:backEvent=\"backToWallets\"></breadcrumb>\n        <div class=\"content-container\">\n            <p class=\"label\">{{$t('commonWalletHome.walletQrCode')}}</p>\n            <div class=\"qrcode\">\n                <vue-qrcode :value=\"address\" :options=\"{size:200}\"></vue-qrcode>\n            </div>\n            <div class=\"address-item clearfix\">\n                <span>{{$t('commonWalletHome.walletAddress')}}</span>\n                <div class=\"value-item\">\n                    <span class=\"font-regular\">{{address}}</span>\n                    <span class=\"copy-icon\" @click=\"copy(address)\"></span>\n                </div>\n            </div>\n            <div class=\"address-item clearfix\" v-if=\"pk\">\n                <span>{{$t('commonWalletHome.publicKey')}}</span>\n                <div class=\"value-item\">\n                    <span class=\"font-regular\">{{pk}}</span>\n                    <span class=\"copy-icon\" @click=\"copy(pk)\"></span>\n                </div>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from '../Breadcrumb'\nimport VueQrcode from '@xkeshi/vue-qrcode'\nexport default {\n    name:'CommonReceive',\n    components:{\n        Breadcrumb,\n        VueQrcode\n    },\n    data() {\n        const type = this.$route.params.walletType\n        let wallet, walletName, routes, address, pk;\n        if(type === 'commonWallet') {\n            wallet = JSON.parse(sessionStorage.getItem('currentWallet'))\n            walletName = wallet.label\n            routes = [{name: walletName, path:'/dashboard'}]\n            address = wallet.address\n            pk = wallet.publicKey\n        } else {\n            wallet = JSON.parse(sessionStorage.getItem('sharedWallet'))\n            walletName = wallet.sharedWalletName\n            routes = [{name: walletName, path:'/sharedWallet/home'}]\n            address = wallet.sharedWalletAddress\n            pk = ''\n        }\n\n        return {\n            address,\n            pk,\n            walletName,\n            routes,\n        }\n    },\n    mounted() {\n\n    },\n    methods: {\n        backToWallets() {\n            this.$router.push({name:'Wallets'})\n        },\n        copy(value) {\n            this.$copyText(value);\n            this.$message.success(this.$t('common.copied'))\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/CommonWallet/CommonRedeem.vue",
    "content": "<style scoped>\n.container {\n    width:540px;\n    margin:4rem auto;\n}\n.label {\n    font-family: AvenirNext-Bold;\n    font-size: 20px;\n    color: #5E6369;\n}\n.input-pass {\n    margin-top:12px;\n    padding-left: 4rem;\n}\n.connect-ledger-app {\n    margin-top: 20px;\n    margin-left: 4rem;\n}\n\n.ledger-status {\n    margin-top:10px;\n    margin-left: 4rem;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('commonWalletHome.redeem')\" :routes=\"routes\"\n                v-on:backEvent=\"backToWallets\"></breadcrumb>\n        <div class=\"container\">\n            <div class=\"label\">\n                {{$t('commonWalletHome.redeemCharge')}}\n            </div>\n            <div class=\"input-pass\" v-if=\"type=== 'commonWallet'\">\n                <a-input type=\"password\" class=\"input\" :placeholder=\"$t('commonWalletHome.inputPass')\" v-model=\"password\"></a-input>\n            </div>\n            <div v-if=\"type === 'hardwareWallet'\" class=\"connect-ledger-app font-medium\">\n                {{$t('ledgerWallet.connectApp')}}\n            </div>\n            <div v-if=\"ledgerStatus\" class=\"ledger-status \">\n                <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                <span class=\"font-medium\">{{ledgerStatus}} </span>\n            </div>\n        </div>\n        <div class=\"footer-btns\">\n            <div class=\"footer-btn-container\">\n                <a-button type=\"default\" class=\"btn-cancel\" @click=\"cancel\">{{$t('commonWalletHome.cancel')}}</a-button>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"submit\" :disabled=\"sending\">\n                    {{$t('commonWalletHome.submit')}}\n                    </a-button>\n            </div>\n        </div>\n\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from '../Breadcrumb'\nimport {legacySignWithLedger} from '../../core/ontLedger'\nimport {RestClient, Crypto,OntAssetTxBuilder, TransactionBuilder, utils, TxSignature} from 'ontology-ts-sdk'\nimport { TEST_NET, MAIN_NET, ONT_CONTRACT, ONT_PASS_NODE, DEFAULT_SCRYPT, GAS_PRICE, GAS_LIMIT } from '../../core/consts'\nimport {mapState} from 'vuex'\nimport {getDeviceInfo, getPublicKey, checkPublicKeyIsInTheConnectedLedger} from '../../core/ontLedger'\nimport {BigNumber} from 'bignumber.js'\nimport { getRestClient } from '../../core/utils'\nexport default {\n    name: 'CommonRedeem',\n    components: {\n        Breadcrumb\n    },\n    mounted: function () {\n    const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'));\n      if(currentWallet.key) {\n          return;\n      }\n      let that = this;\n      that.getDevice()\n      this.intervalId = setInterval(() => {\n        that.getDevice()\n      }, this.interval)\n    },\n    beforeDestroy(){\n      clearInterval(this.intervalId)\n    },\n    data() {\n        const net = localStorage.getItem('net');\n        const type = this.$route.params.walletType\n        const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'))\n        const routes = [{name: currentWallet.label, path:'/dashboard'}]\n        return {\n            currentWallet,\n            routes,\n            type,\n            password:'',\n            interval:10000,\n            invervalId:'',\n            publicKey:'',\n            ledgerStatus:'',\n            sending: false\n        }\n    },\n    computed:{\n        ...mapState({\n            redeem: state => state.CurrentWallet.redeem\n        })\n    },\n    methods: {\n        backToWallets() {\n            this.$router.push({name: 'Wallets'})\n        },\n        cancel() {\n            this.$router.push('/dashboard')\n        },\n        getDevice() {\n        if(this.publicKey) {\n            return;\n        }\n            getDeviceInfo().then(res => {\n                console.log('device: ' + res)\n                this.device = res;\n                this.getPublicKey()\n            }).catch(err => {\n                console.log(err)\n                this.publicKey = '';\n                if (err === 'NOT_FOUND') {\n                    this.ledgerStatus = this.$t('common.ledgerNotOpen')\n                } else if (err === 'NOT_SUPPORT') {\n                    this.ledgerStatus = this.$t('common.ledgerNotSupported')\n                } else {\n                    this.ledgerStatus = this.$t('common.pluginDevice')\n                }\n            })\n      },\n      getPublicKey() {\n        if(this.publicKey) {\n            return;\n        }\n        getPublicKey().then(res => {\n          console.log('pk info: ' + res);\n          this.publicKey = res\n          this.ledgerStatus = this.$t('common.readyToSubmit')\n        }).catch(err => {\n          this.ledgerStatus = err.message\n        })\n      },\n      sendTx(tx) {\n          const restClient = getRestClient();\n          restClient.sendRawTransaction(tx.serialize()).then(res => {\n            console.log(res)\n            this.$store.dispatch('hideLoadingModals')\n            if (res.Error === 0) {\n                this.$message.success(this.$t('common.transSentSuccess'))\n            } else if (res.Error === -1) {\n                const err = res.Result.indexOf('cover gas cost') > -1 ? this.$t('common.ongNoEnough') : res.Result\n                this.$message.error(err)\n                return;\n            } else {\n                this.$message.error(res.Result)\n                return;\n            }\n            const title = this.$t('common.transSentSuccess')\n            this.$router.push({path:'/dashboard'})\n            setTimeout(() => {\n                this.$success({\n                    title: title,\n                    content: 'Transaction hash: ' + utils.reverseHex(tx.getHash())\n                })\n            }, 100)\n        }).catch(err => {\n                    console.log(err)\n                    this.$message.error(this.$t('common.networkError'))\n                })\n      },\n        async submit() {\n            if(this.type === 'commonWallet' &&!this.password) {\n                this.$message.error(this.$t('commonWalletHome.emptyPass'))\n                return;\n            }\n            this.sending = true;\n            const from = new Crypto.Address(this.currentWallet.address);\n            const to = from;\n            const value = new BigNumber(this.redeem.claimableOng);\n            const amount = value.multipliedBy(1e9).toString();\n            const tx = OntAssetTxBuilder.makeWithdrawOngTx(from, to, amount, from, GAS_PRICE, GAS_LIMIT);\n            if(this.type === 'commonWallet') {\n                this.$store.dispatch('showLoadingModals')\n                const enc = new Crypto.PrivateKey(this.currentWallet.key)\n                let pri;\n                try {\n                    pri = enc.decrypt(this.password, from, this.currentWallet.salt, DEFAULT_SCRYPT)\n                } catch (err) {\n                    console.log(err);\n                    this.$store.dispatch('hideLoadingModals')\n                    this.$message.error(this.$t('common.pwdErr'))\n                    this.sending = false;\n                    return;\n                }\n                TransactionBuilder.signTransaction(tx, pri);\n                this.sendTx(tx);\n            } else {\n                if(this.publicKey) {\n                    const neo = this.currentWallet.neo;\n                    const acct = this.currentWallet.acct;\n                    await checkPublicKeyIsInTheConnectedLedger(acct, neo, this.currentWallet.publicKey);\n                    this.$store.dispatch('showLoadingModals')\n                    this.sending = true;\n                    this.ledgerStatus = this.$t('common.waitForSign')\n                    const pk = new Crypto.PublicKey(this.currentWallet.publicKey);\n                    const txSig = new TxSignature();\n                    txSig.M = 1;\n                    txSig.pubKeys = [pk];\n                    tx.payer = from;\n                    const txData = tx.serializeUnsignedData();\n                    legacySignWithLedger(txData, neo, acct).then(res => {\n                    // console.log('txSigned: ' + res);\n                        const sign = '01' + res; //ECDSAwithSHA256\n                        txSig.sigData = [sign]\n                        tx.sigs = [txSig];\n                        this.sendTx(tx);\n                    }, err => {\n                        this.sending = false;\n                        this.ledgerStatus = '';\n                        this.$store.dispatch('hideLoadingModals')\n                        alert(err.message)\n                    })\n                } else {\n                    this.$message.warning(this.$t('ledgerWallet.connectApp'))\n                }\n\n\n            }\n        }\n    }\n}\n</script>\n\n\n"
  },
  {
    "path": "src/components/CommonWallet/CommonTokenSwap.vue",
    "content": "<style scoped>\n\n  .content-container {\n    display: flex;\n    margin-top: 40px;\n  }\n\n  .left-half {\n    flex-basis: 50%;\n    padding:10px 15px;\n  }\n\n  .right-half {\n    flex-basis: 50%;\n    padding: 10px 20px;\n  }\n  .swap-btns {\n      width:70%;\n      margin:30px auto;\n  }\n  .swap-btns :last-child {\n      float: right;\n  }\n  .error-amount {\n      border-color:red !important;\n  }\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('commonWalletHome.swap')\" :routes=\"routes\"\n                v-on:backEvent=\"backToWallets\"></breadcrumb>\n        <div class=\"content-container\">\n            <div class=\"left-half\">\n                <p class=\"font-regular\">{{$t('commonWalletHome.swapText')}}</p>\n                <p class=\"font-regular\">{{$t('commonWalletHome.stepFollow')}}</p>\n                <p class=\"font-medium\">{{$t('commonWalletHome.step1')}}</p>\n                <p class=\"font-medium\">{{$t('commonWalletHome.step2')}}</p>\n                <p class=\"font-medium\">{{$t('commonWalletHome.step3')}}</p>\n            </div>\n            <div class=\"right-half\">\n                <p class=\"font-medium-black\">{{$t('commonWalletHome.swapAmount')}}</p>\n                <a-input class=\"input\" v-model=\"amount\"\n                @change=\"validateAmount\" :class=\"validAmount? '': 'error-amount'\"\n                ></a-input>\n                <p class=\"font-regular\">{{$t('commonWalletHome.nep5Balance')}}\n                    <span class=\"font-medium-black\">{{nep5Ont}}</span> </p>\n                <p class=\"font-medium-black\">{{$t('commonWalletHome.password')}}</p>\n                <a-input class=\"input\" v-model=\"password\" type=\"password\"\n                @change=\"validatePass\" :class=\"validPassword? '': 'error-amount'\"\n                ></a-input>\n                <div class=\"swap-btns\">\n                     <a-button type=\"default\" class=\"btn-cancel\" @click=\"cancel\">{{$t('commonWalletHome.cancel')}}</a-button>\n                     <a-button type=\"primary\" class=\"btn-next\" @click=\"submit\" :disabled=\"sending\">{{$t('commonWalletHome.swap')}}</a-button>\n                </div>\n            </div>\n        </div>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../Breadcrumb'\nimport {mapState} from 'vuex'\nimport {varifyPositiveInt} from '../../core/utils.js'\nimport {SWAP_ADDRESS, DEFAULT_SCRYPT} from '../../core/consts'\nimport {Crypto, SDK} from 'ontology-ts-sdk'\n\nexport default {\n    name: 'CommonTokenSwap',\n    data() {\n        const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'))\n        const routes = [{name: currentWallet.label, path:'/dashboard'}]\n        return {\n            currentWallet,\n            routes,\n            amount: 0,\n            password:'',\n            sending:false,\n            validAmount:true,\n            validPassword:true,\n            nep5Ont: 0\n        }\n    },\n    components: {\n        Breadcrumb\n    },\n    computed: {\n    },\n    mounted(){\n        this.getNep5Balance();\n    },\n    methods: {\n        getNep5Balance() {\n            const NEO_TRAN = 100000000;\n            SDK.getNeoBalance(this.currentWallet.address).then(res => {\n                if(res.result) {\n                    const nep5Ont = res.result / NEO_TRAN\n                    this.nep5Ont = nep5Ont;\n                } else {\n                    this.nep5Ont = 0;\n                }\n            })\n        },\n        backToWallets() {\n            this.$router.push({name: 'Wallets'})\n        },\n        cancel() {\n            this.$router.push('/dashboard')\n        },\n        validateAmount(){\n            if(!this.amount || !varifyPositiveInt(this.amount)) {\n                this.validAmount = false;\n                return;\n            }\n            if(Number(this.amount) > Number(this.nep5Ont)) {\n                this.validAmount = false;\n                return;\n            }\n            this.validAmount = true;\n        },\n        validatePass(){\n            if(!this.password ) {\n                this.validPassword = false\n                return;\n            }\n            this.validPassword = true;\n        },\n        submit() {\n            if(!this.amount || !this.validAmount) {\n                this.$message.error(this.$t('commonWalletHome.validAmount'))\n                return;\n            }\n            if(!this.password) {\n                this.$message.error(this.$t('commonWalletHome.emptyPass'))\n                return;\n            }\n            const from = this.currentWallet.address\n            const to = SWAP_ADDRESS\n            const value = this.amount;\n            const encKey = this.currentWallet.key;\n            const salt = this.currentWallet.salt;\n            // must transform password to base when call Ont.SDK's api\n            const password = Buffer.from(this.password).toString('base64');\n            const params = DEFAULT_SCRYPT;\n            const resp =  SDK.neoTransfer(from, to, value, encKey,password,salt,'', params)\n            if(resp.then) {\n                resp.then(res => {\n                    if(res.result) {\n                        const title = this.$t('common.transSentSuccess')\n                        this.$router.push({name:'Dashboard'})\n                        setTimeout(() => {\n                            this.$success({\n                                title: title,\n                                content: 'NEP5 Transaction hash: ' + res.result\n                            })\n                        }, 100)\n                    } else {\n                        this.$message.error(this.$t('common.networkErr'))\n                    }\n                })\n            } else {\n                if(resp.error === 53000 ) {\n                    this.$message.error(this.$t('common.pwdErr'))\n                    return;\n                }\n            }\n\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/CommonWallet/SendConfirm.vue",
    "content": "<style scoped>\n  .confirm-container {\n\n  }\n\n  .drag-item {\n    cursor: pointer;\n  }\n\n  .label-container {\n    position: relative;\n  }\n\n  .label {\n    font-weight: bold;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size: 1.25rem;\n    margin: 0;\n  }\n\n  .asset-table {\n    padding: 5px 50px;\n  }\n\n  .asset-item {\n    border-bottom: 1px solid #dddddd;\n    padding: 10px 20px;\n  }\n\n  .asset-item span {\n    width: 30%;\n    display: inline-block;\n    text-align: left;\n  }\n\n  .asset-item :nth-child(2) {\n    width: 69%;\n    display: inline-block;\n    text-align: right\n  }\n\n  .select-sponsor {\n    margin-left: 20px;\n    width: 80%;\n    margin-bottom: 15px;\n  }\n\n  .circle {\n    display: inline-block;\n    text-align: center;\n    border: 1px solid #dddddd;\n    border-radius: 50%;\n    width: 1.5rem;\n    height: 1.5rem;\n    line-height: 1.5rem;\n    background: #FBE45A;\n  }\n\n  .confirm-btns {\n    position: fixed;\n    bottom: 0;\n    left: 4rem;\n    height: 5.3rem;\n    width: calc(100% - 4rem);\n    /* z-index: 1000; */\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    background: #ffffff;\n  }\n\n  .fee {\n    padding-left: 20px;\n    padding-top: 10px;\n    margin-bottom: 50px;\n  }\n\n  .sponsor-select {\n    padding-left: 4rem;\n  }\n\n  .sponsor-label {\n    margin-bottom: 20px;\n  }\n\n  .sponsor-label :last-child {\n    float: right;\n  }\n\n  .drag-container {\n    margin-top: 20px;\n    padding-left: 4rem;\n  }\n\n  .payer-item {\n    height: 30px;\n  }\n\n  .payer-item:hover {\n    background: #F5F7FB;\n  }\n\n  .payer-item:hover span {\n    color: #196BD8 !important;\n  }\n\n  .payer-item :nth-child(2) {\n    margin-left: 14px;\n  }\n\n  .payer-item :nth-child(3) {\n    float: right;\n    margin-right: 14px;\n  }\n\n  .btns-container {\n    width: 500px;\n    margin: 20px auto;\n  }\n\n  .btns-container :last-child {\n    float: right;\n  }\n\n  .label {\n    font-weight: bold;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size: 1.25rem;\n    margin: 0;\n  }\n\n  .input-content {\n    padding-left: 4rem;\n  }\n\n  .input-check {\n    margin-top: 12px;\n    margin-bottom: 20px;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #000000;\n  }\n\n</style>\n\n<template>\n    <div class=\"confirm-container clearfix\">\n            <p class=\"label\">{{$t('sharedWalletHome.send')}}</p>\n\n        <div class=\"asset-table\">\n            <div class=\"asset-item\">\n                <span class=\"font-medium\">{{$t('sharedWalletHome.amount')}}</span>\n                <span class=\"font-medium-black\">{{transfer.amount}} {{transfer.asset}}</span>\n\n            </div>\n            <div class=\"asset-item\">\n                <span class=\"font-medium\">{{$t('sharedWalletHome.recipient')}}</span>\n                <span class=\"font-medium-black\">{{transfer.to}}</span>\n            </div>\n            <div class=\"fee font-medium-black\">{{$t('sharedWalletHome.fee')}}: {{transfer.gas}} ONG</div>\n        </div>\n\n       <p class=\"label\">{{$t('sharedWalletHome.confirmation')}}</p>\n        <div class=\"input-content\">\n            <div>\n                <a-checkbox @change=\"onChange\" :checked=\"checked\" class=\"input-check\">{{$t('sharedWalletHome.agreeToSend')}}</a-checkbox>\n\n                <a-input type=\"password\" class=\"input\"  v-if=\"isCommonWallet\"\n                :placeholder=\"$t('sharedWalletHome.inputPassToTransfer')\"\n                v-model=\"password\"></a-input>\n\n                <p class=\"font-medium\" v-if=\"!isCommonWallet\">{{$t('ledgerWallet.connectApp')}}</p>\n                <p v-if=\"ledgerStatus\">\n                   <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}}</span>\n                </p>\n            </div>\n        </div>\n\n\n        <div class=\"confirm-btns\">\n            <div class=\"btns-container\">\n                <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{$t('sharedWalletHome.back')}}</a-button>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"submit\" :disabled=\"sending\">{{$t('sharedWalletHome.submit')}}</a-button>\n            </div>\n\n        </div>\n    </div>\n</template>\n<script>\nimport {mapState} from 'vuex'\nimport {legacySignWithLedger} from '../../core/ontLedger'\nimport {Oep4} from 'ontology-ts-sdk'\nimport { TEST_NET, MAIN_NET, ONT_CONTRACT, ONT_PASS_NODE, DEFAULT_SCRYPT } from '../../core/consts'\nimport {Crypto, OntAssetTxBuilder, TransactionBuilder, utils, RestClient, TxSignature} from 'ontology-ts-sdk'\nimport axios from 'axios';\nimport {getDeviceInfo, getPublicKey, checkPublicKeyIsInTheConnectedLedger} from '../../core/ontLedger'\n// import $ from 'jquery'\nimport {BigNumber} from 'bignumber.js'\nimport { getRestClient } from '../../core/utils'\n\nexport default {\n  name: 'SendConfirm',\n  mounted: function () {\n      const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'));\n      if(currentWallet.key) {\n          return;\n      }\n      this.getDevice()\n      let that = this;\n      this.intervalId = setInterval(() => {\n        that.getDevice()\n      }, this.interval)\n    },\n    beforeDestroy(){\n      clearInterval(this.intervalId)\n    },\n  data() {\n    const net = localStorage.getItem('net');\n    const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'));\n    return {\n      interval:10000,\n      invervalId: '',\n      currentWallet,\n      checked: false,\n      password: '',\n      isCommonWallet: currentWallet.key ? true: false,\n      ledgerStatus: '',\n      publicKey: '',\n      sending: false\n    }\n  },\n  computed: {\n    ...mapState({\n      transfer: state => state.CurrentWallet.transfer\n    })\n  },\n  methods: {\n    back() {\n      this.$emit('backEvent')\n    },\n    onChange() {\n      this.checked = !this.checked;\n    },\n    getDevice() {\n        if(this.publicKey) {\n            return;\n        }\n        getDeviceInfo().then(res => {\n          console.log('device: ' + res)\n          this.device = res;\n          this.getPublicKey()\n        }).catch(err => {\n          console.log(err)\n          this.publicKey = '';\n          if (err === 'NOT_FOUND') {\n            this.ledgerStatus = this.$t('common.ledgerNotOpen')\n          } else if (err === 'NOT_SUPPORT') {\n            this.ledgerStatus = this.$t('common.ledgerNotSupported')\n          } else {\n            this.ledgerStatus = this.$t('common.pluginDevice')\n          }\n        })\n      },\n      getPublicKey() {\n        if(this.publicKey) {\n            return;\n        }\n        getPublicKey().then(res => {\n          console.log('pk info: ' + res);\n          this.publicKey = res\n          this.ledgerStatus = this.$t('common.readyToSubmit')\n        }).catch(err => {\n          this.ledgerStatus = this.$t('common.pluginDevice');\n          // this.ledgerStatus = err.message\n        })\n      },\n      sendTx(tx){\n          const restClient = getRestClient();\n          restClient.sendRawTransaction(tx.serialize()).then(res => {\n          console.log(res)\n          this.$store.dispatch('hideLoadingModals')\n          if (res.Error === 0) {\n            this.$message.success(this.$t('common.transSentSuccess'))\n          } else if (res.Error === -1) {\n            const err = res.Result.indexOf('cover gas cost') > -1 ? this.$t('common.ongNoEnough') : res.Result\n            this.$message.error(err)\n            return;\n          } else {\n            this.$message.error(res.Result)\n            return;\n          }\n          this.$emit('sendConfirmSubmit')\n          const title = this.$t('common.transSentSuccess')\n          setTimeout(() => {\n              this.$success({\n                  title: title,\n                  content: 'Transaction hash: ' + utils.reverseHex(tx.getHash())\n              })\n          }, 100)\n        }).catch(err => {\n          console.log(err)\n          this.$message.error(this.$t('common.networkError'))\n        })\n      },\n    async submit() {\n      if (this.isCommonWallet && (!this.password || !this.checked)) {\n        this.$message.warning(this.$t('common.confirmPwdTips'))\n        return;\n      }\n      if(!this.isCommonWallet && !this.checked) {\n          this.$message.warning(this.$t('common.confirmTips'))\n          return;\n      }\n      const asset = this.transfer.asset;\n      const from = new Crypto.Address(this.currentWallet.address);\n      const to = new Crypto.Address(this.transfer.to);\n      const gasLimit = '20000';\n      const gas = (new BigNumber(this.transfer.gas)).multipliedBy(1e9);\n      const gasPrice = gas.div(parseInt(gasLimit)).toString();\n\n      let tx;\n      if(asset === 'ONT' || asset === 'ONG') {\n        const amount = asset === 'ONT' ? this.transfer.amount : (new BigNumber(this.transfer.amount).multipliedBy(1e9)).toString();\n         tx = OntAssetTxBuilder.makeTransferTx(asset, from, to, amount, gasPrice, gasLimit);\n      } else if (this.transfer.scriptHash) {\n        const contractAddr = new Crypto.Address(utils.reverseHex(this.transfer.scriptHash));\n        const oep4 = new Oep4.Oep4TxBuilder(contractAddr);\n        const val = new BigNumber(this.transfer.amount).multipliedBy(Math.pow(10, this.transfer.decimal));\n        console.log(val)\n        const amount = val.toString()\n        console.log(amount)\n         tx = oep4.makeTransferTx(from, to, amount, gasPrice, gasLimit, from);\n      }\n\n      if (this.isCommonWallet) {\n        this.$store.dispatch('showLoadingModals')\n        const enc = new Crypto.PrivateKey(this.currentWallet.key)\n        let pri;\n        try {\n          pri = enc.decrypt(this.password, new Crypto.Address(this.currentWallet.address), this.currentWallet.salt, DEFAULT_SCRYPT)\n        } catch (err) {\n          this.sending = false;\n          console.log(err);\n          this.$store.dispatch('hideLoadingModals')\n          this.$message.error(this.$t('common.pwdErr'))\n          return;\n        }\n        TransactionBuilder.signTransaction(tx, pri);\n        this.sendTx(tx)\n      } else {\n        if(this.publicKey) {\n            const neo = this.currentWallet.neo;\n            const acct = this.currentWallet.acct;\n            await checkPublicKeyIsInTheConnectedLedger(acct, neo, this.currentWallet.publicKey);\n            this.sending = true;\n            this.ledgerStatus = this.$t('common.waitForSign')\n            this.$store.dispatch('showLoadingModals')\n            const pk = new Crypto.PublicKey(this.currentWallet.publicKey);\n            const txSig = new TxSignature();\n            txSig.M = 1;\n            txSig.pubKeys = [pk];\n            tx.payer = from;\n            const txData = tx.serializeUnsignedData();\n            legacySignWithLedger(txData, neo, acct).then(res => {\n            // console.log('txSigned: ' + res);\n            const sign = '01' + res; //ECDSAwithSHA256\n            txSig.sigData = [sign]\n            tx.sigs = [txSig];\n            this.sendTx(tx);\n            }, err => {\n                this.sending = false;\n                this.ledgerStatus = '';\n                this.$store.dispatch('hideLoadingModals')\n                alert(err.message)\n            })\n        } else {\n            this.$message.warning(this.$t('ledgerWallet.connectApp'))\n        }\n      }\n    }\n\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/CommonWallet/SendHome.vue",
    "content": "<template>\n  <div>\n    <breadcrumb :current=\"$t('sharedWalletHome.send')\" :routes=\"routes\"\n                v-on:backEvent=\"backToWallets\"></breadcrumb>\n\n    <div class=\"send-container\">\n      <div class=\"steps\">\n        <a-steps :current=\"current\">\n          <a-step/>\n          <a-step/>\n        </a-steps>\n      </div>\n\n      <send-asset\n        v-on:cancelEvent=\"handleCancel\"\n        v-on:sendAssetNext=\"handleSendAssetNext\"\n        v-if=\"current ===0\">\n      </send-asset>\n\n      <send-confirm\n        v-on:backEvent=\"handleConfirmBack\"\n        v-on:sendConfirmSubmit=\"handleSubmit\"\n        v-if=\"current === 1\">\n      </send-confirm>\n    </div>\n  </div>\n</template>\n\n<script>\n  import Breadcrumb from '../Breadcrumb'\n  import SendAsset from '../SharedWallet/Transfer/SendAsset'\n  import SendConfirm from '../CommonWallet/SendConfirm'\n\n  export default {\n    name: 'CommonSendHome',\n    components: {\n      Breadcrumb,\n      SendAsset,\n      SendConfirm\n    },\n    data() {\n      const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'))\n      return {\n        walletName: currentWallet.label,\n        routes: [{name: currentWallet.label, path: '/dashboard'}],\n        current: 0\n      }\n    },\n    methods: {\n      backToWallets() {\n        this.$router.push({name: 'Wallets'})\n      },\n      handleCancel() {\n        this.$router.go(-1);\n      },\n      handleSendAssetNext() {\n        this.current = 1;\n      },\n      handleConfirmBack() {\n        this.current = 0;\n      },\n      handleSubmit() {\n        this.$router.go(-1);\n      }\n\n    }\n  }\n</script>\n\n<style scoped>\n  .send-container {\n    width: 600px;\n    margin: 0 auto;\n    padding-bottom: 5.3rem;\n  }\n\n  .steps {\n    height: 68px;\n    padding: 0 4rem;\n  }\n</style>\n"
  },
  {
    "path": "src/components/Dapps.vue",
    "content": "\n<style scoped>\n.dapps-container {\n    padding: 20px 20px;\n}\n.dapp-item {\n    margin: 15px;\n    cursor: pointer;\n    background: #f5f7fb;\n    font-family: AvenirNext-Medium;\n    font-size: 18px;\n    color: #515457;\n    line-height: 24px;\n    height:15rem;\n    border: 1px solid #f5f7fb;\n}\n.dapp-item:hover {\n    border:1px solid #196BD8;\n}\n\n.dapp-title {\n    padding: 15px;\n    border-bottom: 1px solid #cccccc;\n    display: flex;\n    justify-content: flex-start;\n    align-items: center;\n}\n.dapp-title > img {\n    width: 30px;\n    height: 30px;\n    margin-right: 10px;\n}\n\n.dapp-content {\n    padding: 15px;\n    text-overflow: ellipsis;\n    overflow: hidden;\n    font-size: 14px;\n}\n</style>\n\n<template>\n    <div class=\"negative-margin-top dapps-container\">\n        <a-row>\n            <a-col :md=\"8\" :lg=\"8\" :xl=\"6\">\n                <div @click=\"handleExchangeChangelly\" class=\"dapp-item\">\n                    <div class=\"dapp-title\">\n                        <img :src=\"require('../assets/changelly.png')\" alt />\n                        <span>{{$t('exchange.changelly')}}</span>\n                    </div>\n                    <p class=\"dapp-content\">Cryptocurrency Exchange Platform</p>\n                </div>\n            </a-col>\n            <a-col :md=\"8\" :lg=\"8\" :xl=\"6\">\n                <div\n                    @click=\"handleExchangeCryptonex\"\n                    class=\"dapp-item\"\n                    :title=\"$t('exchange.cryptonex')\"\n                >\n                    <div class=\"dapp-title\">\n                        <img :src=\"require('../assets/cryptonex.png')\" alt />\n                        <span>{{$t('exchange.cryptonex')}}</span>\n                    </div>\n                    <p class=\"dapp-content\">\n                        Buy Bitcoin, Ethereum, Cryptonex\n                        Quick online purchase using a bank card\n                    </p>\n                </div>\n            </a-col>\n            <!-- <a-col :md=\"8\" :lg=\"8\" :xl=\"6\">\n                <div\n                    class=\"dapp-item\"\n                    @click=\"handleDappSesameseed\"\n                >\n                    <div class=\"dapp-title\">\n                        <img :src=\"require('../assets/sesameseed.png')\" alt />\n                        <span>{{$t('dapps.sesameSeed')}}</span>\n                    </div>\n                    <p class=\"dapp-content\">{{$t('dapps.sesameseedDesc')}}</p>\n                </div>\n            </a-col> -->\n            <a-col :md=\"8\" :lg=\"8\" :xl=\"6\">\n                <div\n                    class=\"dapp-item\"\n                    @click=\"handleOntidMgmt\"\n                >\n                    <div class=\"dapp-title\">\n                        <img :src=\"require('../assets/ontid.svg')\" alt />\n                        <span>ONT ID</span>\n                    </div>\n                    <p class=\"dapp-content\">{{$t('dapps.ontidMgmt')}}</p>\n                </div>\n            </a-col>\n        </a-row>\n    </div>\n</template>\n\n<script>\nimport axios from \"axios\";\nimport { isNumber, isNullOrUndefined } from \"util\";\nimport { open } from \"../core/utils\";\n\nexport default {\n    name: \"Dapps\",\n    components: {},\n    data() {\n        return {\n            result: [],\n            results: [],\n            coin_short: \"\",\n            coin_long: \"\",\n            price: \"\",\n            mcap: \"\",\n            vol: \"\",\n            dailychange: \"\",\n            filteredlist: \"\",\n            interval: 60000,\n            loading: true\n        };\n    },\n    mounted: function() {\n        this.$confirm({\n            title: this.$t('dapps.notification'),\n            content: this.$t('dapps.userPolicy'),\n            onOk() {},\n            onCancel: () => {\n                this.$router.back();\n            }\n        })\n    },\n    computed: {},\n    beforeDestroy() {\n        clearInterval(this.interval);\n    },\n    created: function() {\n        this.getImageData();\n    },\n    methods: {\n        handleExchangeChangelly() {\n            // this.$router.push({ name: \"Changelly\" });\n            const changellyURL =\n                \"https://widget.changelly.com?currencies=&from=btc&to=ont&amount=1&address=&fiat=true&fixedTo=false&theme=default&ref_id=su5srryl1mhz4fno&merchant_id=su5srryl1mhz4fno\";\n            open(changellyURL);\n        },\n        handleExchangeCryptonex() {\n            // this.$router.push({ name: \"Cryptonex\" });\n            const cryptonexURL = \"https://wallet.cryptonex.org/member/sign-in\";\n            open(cryptonexURL);\n        },\n        handleDappSesameseed() {\n            this.$router.push({name: 'AuthorizeLoginSesameseed'});\n        },\n        handleOntidMgmt() {\n            this.$router.push({name:'Identitys'})\n        },\n        formatPrice(value) {\n            if (isNumber(value)) {\n                let val = (value / 1)\n                    .toFixed(2)\n                    .replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n                return \"$\" + val;\n            } else return value;\n        },\n        setColor: num => {\n            return num > 0 ? \"color:green;\" : \"color:red;\";\n        },\n        reorderArray(array, initialIndex, destinationIndex) {\n            const itemOfInterest = array[initialIndex];\n            array.splice(initialIndex, 1);\n            array.splice(destinationIndex, 0, itemOfInterest);\n\n            return array;\n        },\n        getPrices() {\n            this.loading = true;\n            const url = \"http://coincap.io/front\";\n            this.axios\n                .get(url)\n                .then(response => {\n                    if (response.status === 200 && response.data) {\n                        const pricelist = response.data;\n\n                        const filteredlist = pricelist.map(t => {\n                            const coin_short = t.short;\n                            const coin_long = t.long;\n                            const price = t.price;\n                            const mcap = t.mktcap;\n                            const vol = t.volume;\n                            const dailychange = t.cap24hrChange;\n\n                            return {\n                                coin_short,\n                                coin_long,\n                                price,\n                                mcap,\n                                vol,\n                                dailychange\n                            };\n                        });\n\n                        try {\n                            // Find ONT in list and re-order it to top of the list\n                            let ONTindex = filteredlist.findIndex(\n                                filteredlist =>\n                                    filteredlist.coin_long == \"Ontology\"\n                            );\n                            const reorderedArray = this.reorderArray(\n                                filteredlist,\n                                ONTindex,\n                                0\n                            );\n                            this.results = reorderedArray;\n\n                            this.loading = false;\n                        } catch (err) {\n                            this.results = filteredlist;\n                            console.log(err);\n                        }\n                    } else {\n                        console.log(response);\n                    }\n                })\n                .catch(err => {\n                    this.loading = false;\n                    console.log(err);\n                });\n        },\n        test: function(from, to) {\n            this.splice(to, 0, this.splice(from, 1)[0]);\n        },\n        getImageData: function() {\n            let self = this;\n\n            this.axios\n                .get(\"https://min-api.cryptocompare.com/data/all/coinlist\")\n                .then(response => {\n                    if (response.status === 200 && response.data) {\n                        this.imageData = response.data.Data;\n                        this.getPrices();\n                    }\n                })\n                .catch(err => {\n                    this.getPrices();\n                    console.error(err);\n                });\n        },\n        getCoinImage: function(short) {\n            try {\n                if (short.length > 0) {\n                    return (\n                        \"https://www.cryptocompare.com\" +\n                        this.imageData[short].ImageUrl\n                    );\n                } else {\n                    return \"\";\n                }\n            } catch (err) {\n              //\n            }\n        },\n        refresh() {\n            this.$store.dispatch(\"showLoadingModals\");\n            setTimeout(() => {\n                this.$store.dispatch(\"hideLoadingModals\");\n            }, 8000);\n            this.getPrices();\n        }\n    }\n};\n</script>\n"
  },
  {
    "path": "src/components/Dashboard.vue",
    "content": "<style scoped>\n  .header-header {\n    height: 4rem;\n    padding: 1.1rem 0;\n    width: 100%;\n\n  }\n\n  .home-container {\n    padding: 0 20px;\n    height: 100%;\n  }\n\n  .content-container {\n    display: flex;\n  }\n\n  .left-half {\n    flex:1;\n    padding-right: 67px;\n  }\n\n  .right-half {\n    flex:1;\n  }\n\n  .asset {\n    margin: 20px auto;\n    display: flex;\n    flex-direction: row;\n    justify-content: space-around\n  }\n\n  .claim-btn {\n    text-align: center;\n  }\n\n  .rule {\n    text-align: center;\n  }\n\n  .owners-table {\n\n  }\n\n  .table-item {\n    margin: 10px 0;\n  }\n\n  .table-item :first-child {\n    width: 72px;\n    overflow: hidden;\n    display: inline-block;\n    text-overflow: ellipsis;\n  }\n\n  .table-item :last-child {\n    float: right;\n  }\n\n  .wallet-info {\n    position: relative;\n    font-family: AvenirNext-Regular;\n    font-size: 0.88rem;\n  }\n\n  .wallet-info p {\n    margin-bottom: 4px;\n  }\n\n  .wallet-type {\n    position: absolute;\n    width: 4rem;\n    height: 4rem;\n    background: url('../assets/commonwallet.png') center center;\n    background-size: cover;\n    right: 0;\n    top: -12px;\n  }\n\n  .copayer-header {\n    padding-bottom: 5px;\n    border-bottom: 1px solid #DFE2E9;\n  }\n\n  .copayer-header :last-child {\n    float: right;\n    font-family: AvenirNext-Bold;\n    font-size: 14px;\n    color: #6F7781;\n  }\n\n  .copayer-header :first-child {\n    font-family: AvenirNext-Bold;\n    font-size: 14px;\n    color: #000000;\n  }\n\n  .check-more {\n    font-family: AvenirNext-Medium;\n    font-size: 12px;\n    color: #227EEC;\n    text-align: center;\n    cursor: pointer;\n    width:100%;\n    float:left;\n  }\n  .check-more:hover {\n    color:#619AE5;\n  }\n\n  .txList-header {\n    padding-bottom: 5px;\n    border-bottom: 1px solid #F4F4F6;\n    position: relative;\n    margin-bottom:10px;\n  }\n\n  .txList-header :first-child {\n    font-family: AvenirNext-Bold;\n    font-size: 14px;\n    color: #000000;\n    text-align: center;\n  }\n\n  /* .txList-header :last-child {\n    width: 64px;\n    height: 64px;\n    display: block;\n    float: right;\n    background: url('../assets/transaction.png');\n    background-size: contain;\n    top: -20px;\n    right: 0;\n    position: absolute;\n  } */\n\n  .pending-tx {\n    margin-bottom: 50px;\n    height: 30%;\n    overflow: scroll;\n  }\n\n\n\n  .wallet-pk {\n    word-break: break-all;\n  }\n\n\n\n  .commonWallet-btn {\n    width: 70px;\n    height: 28px;\n    border-radius: 0;\n    background: #FBE45A;\n    padding: 0;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #5E6369;\n    border: none;\n  }\n  .btn-swap {\n    margin-left: 30px;\n  }\n\n\n.nep5-label :first-child{\n  display: block;\n  height:16px;\n}\n.nep5-label :last-child {\n  font-size: 12px;\n}\n\n.oep4-container  {\n  display: flex;\n  margin-bottom:30px;\n  align-items:center;\n}\n.icon-add-oep4 {\n  margin-left: 20px;\n  font-size: 20px;\n  cursor: pointer;\n}\n.left-footer {\n  margin-top:20px;\n}\n</style>\n<template>\n  <div class=\"home-container\">\n    <breadcrumb :current=\"currentWallet.label\" v-on:backEvent=\"handleBack\"></breadcrumb>\n    <div class=\"wallet-info\">\n      <p class=\"font-regular\">\n        {{$t('sharedWalletHome.address')}}: <span class=\"font-gray\">{{address}}</span>\n        <span class=\"common-icon copy-icon\" @click=\"copy(address)\"></span>\n      </p>\n    </div>\n    <div class=\"content-container\">\n\n      <div class=\"left-half\">\n        <div class=\"wallet-balance\">\n          <div>\n            <span>{{$t('sharedWalletHome.balance')}}</span>\n            <span class=\"common-icon  refresh-icon\" @click=\"refresh(true)\"></span>\n          </div>\n          <span class=\"common-icon add-icon\" @click=\"addOep4\"></span>\n\n        </div>\n        <div class=\"asset-container\">\n          <div class=\"asset-item\">\n            <span class=\"asset-label\">ONT</span>\n            <span class=\"asset-amount\">{{balance.ont}}</span>\n          </div>\n          <!-- <div class=\"asset-value\">${{balance.ontValue}}</div> -->\n\n          <div class=\"asset-item\">\n            <span class=\"asset-label\">ONG</span>\n            <span class=\"asset-amount\">{{balance.ong}}</span>\n          </div>\n\n          <div class=\"asset-item\" v-for=\"item of oep4s\" :key=\"item.contract_hash\">\n            <span class=\"asset-label\">{{item.symbol}}</span>\n            <span class=\"asset-amount\">{{item.balance}}</span>\n          </div>\n\n          <!-- <div class=\"asset-value\">{{'$900'}}</div> -->\n          <!-- <div class=\"asset-ong\" v-if=\"currentWallet.key\">\n            <div class=\"asset-label nep5-label\">\n              <span>ONT</span>\n              <span>(NEP-5)</span>\n            </div>\n            <span class=\"asset-amount\">{{nep5Ont}}</span>\n            <a-button type=\"default\" class=\"commonWallet-btn btn-swap\"\n          @click=\"toSwap\">{{$t('commonWalletHome.swap')}}</a-button>\n          </div> -->\n\n        </div>\n\n        <div class=\"left-footer\">\n          <div class=\"claim-ong-container\">\n            <div class=\"claim-ong\">\n              <div class=\"claim-ong-item \">\n                <span>{{$t('commonWalletHome.claimableOng')}}: </span>\n                <span>{{balance.unboundOng}}</span>\n              </div>\n              <div class=\"claim-ong-item \">\n                <span>{{$t('commonWalletHome.unboundOng')}}: </span>\n                <span>{{balance.waitBoundOng}}</span>\n              </div>\n            </div>\n            <div class=\"redeem-container\">\n              <a-button type=\"default\" class=\"btn-redeem\"\n              @click=\"redeemOng\">{{$t('commonWalletHome.redeem')}}</a-button>\n              <redeem-info-icon></redeem-info-icon>\n            </div>\n          </div>\n\n          <div>\n            <a-button class=\"asset-btn\" type=\"primary\" @click=\"sendAsset\">\n              <i class=\"fa fa-paper-plane\"></i>\n              {{$t('sharedWalletHome.send')}}\n            </a-button>\n            <a-button class=\"asset-btn\" type=\"primary\" @click=\"commonReceive\">\n              <i class=\"fa fa-qrcode\"></i>\n              {{$t('sharedWalletHome.receive')}}\n            </a-button>\n          </div>\n        </div>\n\n      </div>\n\n      <div class=\"right-half\">\n\n        <div class=\"completed-tx\">\n          <div class=\"txList-header\">\n            <span>{{$t('sharedWalletHome.completedTx')}}</span>\n            <!-- <span class=\"transfer-icon\"></span> -->\n          </div>\n          <div v-for=\"(tx,index) in completedTx\" :key=\"tx.txHash+index\" class=\"tx-item\"\n               @click=\"showTxDetail(tx.txHash)\">\n            <span>{{tx.txHash.substring(0, 40) + '...'}}</span>\n            <span>{{tx.amount}} {{tx.asset}}</span>\n          </div>\n          <div class=\"check-more\" v-if=\"completedTx.length > 6\" @click=\"checkMoreTx\">\n            {{$t('sharedWalletHome.checkMore')}}\n            <i class=\"fa fa-chevron-right icon-arrow\"></i>\n          </div>\n        </div>\n\n      </div>\n    </div>\n\n    <a-modal\n        :title=\"$t('redeemInfo.info')\"\n        v-model=\"redeemInfoVisible\"\n        @ok=\"handleModalOk\"\n        >\n          <p class=\"font-regular\"><span class=\"font-medium\"></span> {{$t('redeemInfo.noClaimableOng')}}</p>\n      </a-modal>\n\n    <oep4-selection :visible=\"showOep4Selection\" @closeOep4Selection=\"closeOep4Selection\" ></oep4-selection>\n\n  </div>\n</template>\n\n<script>\n  import {mapState} from 'vuex'\n  import {TEST_NET, MAIN_NET, ONT_CONTRACT, ONT_PASS_NODE} from '../core/consts'\n  import {Crypto, OntAssetTxBuilder, RestClient, SDK} from 'ontology-ts-sdk'\n  import axios from 'axios';\n  import Breadcrumb from './Breadcrumb'\nimport { BigNumber } from 'bignumber.js';\nimport RedeemInfoIcon from './RedeemInfoIcon'\nimport Oep4Selection from './Common/Oep4Selection'\nimport { open, getRestClient, getTransactionListUrl, getBalanceUrl } from '../core/utils'\nconst ONG_GOVERNANCE_CONTRACT = 'AFmseVrdL9f9oyCzZefL9tG6UbviEH9ugK'\n\n  export default {\n    name: 'Dashboard',\n    components: {\n      Breadcrumb,\n      RedeemInfoIcon,\n      Oep4Selection\n    },\n    data() {\n      const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'));\n      const net = localStorage.getItem('net');\n      const network = net && net === 'TEST_NET' ? this.$t('common.testNet') : this.$t('common.mainNet');\n\n      return {\n        currentWallet,\n        publicKey: currentWallet.publicKey,\n        address: currentWallet.address,\n        amount: 0,\n        toAddress: '',\n        transactions: '',\n        asset: 'ONT',\n        network: network,\n        completedTx: [],\n        intervalId: '',\n        interval:15000,\n        redeemInfoVisible: false,\n        requestStart: false,\n        showOep4Selection: false\n      }\n    },\n    created() {\n      this.$store.commit('CLEAR_NATIVE_BALANCE')\n      this.$store.commit('CLEAR_OEP4S_BALANCES')\n    },\n    mounted: function () {\n      //UPDATE_CURRENT_WALLET\n      const wallet = {\n            address: this.address,\n            name: this.currentWallet.label\n          }\n      this.$store.commit('UPDATE_CURRENT_WALLET', {wallet})\n      this.refresh(true)\n      // this.$store.dispatch('queryBalanceForOep4', this.currentWallet.address)\n      this.intervalId = setInterval(() => {\n          this.refresh(false)\n      }, this.interval)\n    },\n    computed: {\n      ...mapState({\n        nep5Ont : state => state.CurrentWallet.nep5Ont,\n        balance: state => state.CurrentWallet.balance,\n        oep4s: state => state.Tokens.oep4WithBalances\n      })\n    },\n    beforeDestroy(){\n        clearInterval(this.intervalId)\n        this.$store.commit('UPDATE_NEP5_ONT', {nep5Ont:0})\n    },\n    methods: {\n      handleBack() {\n        this.$router.push({name: 'Wallets'})\n      },\n      async getTransactions() {\n        const url = getTransactionListUrl(this.address);\n        try {\n          const res = await this.httpService(url)\n          const txlist = res.result;\n            const completed = []\n            for(const t of txlist) {\n              for(const tx of t.transfers) {\n                const asset = tx.asset_name.toUpperCase()\n                // if(tx.to_address === ONG_GOVERNANCE_CONTRACT && asset === 'ONG') {\n                //   continue;\n                // }\n                let amount = asset === 'ONT' ? parseInt(tx.amount) : tx.amount;\n                if (tx.from_address === this.address) {\n                    amount = '-' + amount;\n                } else {\n                  amount = '+' + amount;\n                }\n                completed.push({\n                  txHash: t.tx_hash,\n                  asset,\n                  amount: amount\n                })\n              }\n\n            }\n            this.completedTx = completed.slice(0,10);\n            return completed; // fetch tx history succeed\n        } catch(err) {\n          console.log(err);\n          this.$message.error(this.$t('dashboard.getTransErr'))\n          return false; // fetch tx history failed\n        }\n        /* return this.axios.get(url + '/api/v1/explorer/address/' + this.address + '/10/1').then(response => {\n          if (response.status === 200 && response.data && response.data.Result) {\n            const txlist = response.data.Result.TxnList;\n            const completed = []\n            for(const t of txlist) {\n              // if(t.TransferList.length === 1 && t.TransferList[0].ToAddress === ONG_GOVERNANCE_CONTRACT) {\n              //   continue;\n              // }\n              for(const tx of t.TransferList) {\n                const asset = tx.AssetName.toUpperCase()\n                if(tx.ToAddress === ONG_GOVERNANCE_CONTRACT && asset === 'ONG' && Number(tx.Amount) == 0.01) {\n                  continue;\n                }\n                let amount = asset === 'ONT' ? parseInt(tx.Amount) : tx.Amount;\n                if (tx.FromAddress === this.address) {\n                    amount = '-' + amount;\n                } else {\n                  amount = '+' + amount;\n                }\n                completed.push({\n                  txHash: t.TxnHash,\n                  asset,\n                  amount: amount\n                })\n              }\n\n            }\n            this.completedTx = completed;\n            return true; // fetch tx history succeed\n          } else {\n            console.log(response)\n            return true;\n          }\n        }).catch(err => {\n          console.log(err);\n          this.$message.error(this.$t('dashboard.getTransErr'))\n          return false; // fetch tx history failed\n        }) */\n      },\n      getUnclaimOng() {\n        const restClient = getRestClient();\n        restClient.getAllowance('ong', new Crypto.Address(ONT_CONTRACT), new Crypto.Address(this.address)).then(res => {\n          console.log(res.Result)\n          this.unclaimOng = new BigNumber(res.Result).div(1e9);\n        }).catch(err => {\n          this.$message.error(this.$t('common.networkErr'))\n        })\n      },\n      getBalance() {\n        return this.$store.dispatch('getNativeBalance', {address: this.address}).then(res => {\n          if(!res){\n            this.$message.error(this.$t('dashboard.getBalanceErr'))\n          }\n          return res;\n        })\n      },\n      getOep4Balances() {\n        this.$store.dispatch('fetchTokenBalances', {address: this.address}).then(res => {\n          if(!res) {\n            this.$message.error(this.$t('dashboard.getBalanceErr'))\n          }\n          return res;\n        })\n      },\n      getNep5Balance() {\n        const NEO_TRAN = 100000000;\n        SDK.getNeoBalance(this.currentWallet.address).then(res => {\n          let nep5Ont = 0;\n          if(res.result) {\n            nep5Ont = res.result / NEO_TRAN\n          }\n          this.$store.commit('UPDATE_NEP5_ONT', {nep5Ont})\n        })\n      },\n      getExchangeCurrency() {\n        const currency = 'ont'\n        const goaltype = 'USD'\n        const amount = this.balance.ont;\n        const url = `https://service.onto.app/S3/api/v1/onto/exchangerate/reckon/${currency}/${goaltype}/${amount}`;\n        axios.get(url).then(res => {\n          console.log(res)\n          if (res.data.Result) {\n            this.balance.ontValue = res.data.Result.Money\n          }\n        })\n      },\n      refresh(showLoading) {\n        // this.$store.dispatch('showLoadingModals')\n        // const that = this\n        // setTimeout(() => {\n        //     that.$store.dispatch('hideLoadingModals')\n        // }, 500)\n        if(showLoading) {\n          this.$store.dispatch('showLoadingModals')\n        }\n        if(this.requestStart) {\n          return;\n        }\n        this.requestStart = true;\n        Promise.all([\n          this.getBalance(),\n          this.getTransactions(),\n          this.getOep4Balances(),\n        ]).then(res => {\n          console.log(res)\n          this.requestStart = false;\n          this.$store.dispatch('hideLoadingModals')\n        })\n\n        // this.getNep5Balance();\n      },\n      sendAsset() {\n        if(Number(this.balance.ong) < 0.01) {\n          this.$message.warning(this.$t('common.ongNoEnough'))\n          return;\n        }\n        this.$store.commit('CLEAR_CURRENT_TRANSFER');\n\n        this.$router.push({name: 'CommonSendHome'})\n      },\n      commonReceive() {\n        this.$router.push({path: '/commonWalletReceive/commonWallet'})\n      },\n      redeemOng() {\n          if(this.balance.unboundOng == 0) {\n            this.redeemInfoVisible = true;\n            return;\n          }\n          const redeem = {\n              claimableOng : this.balance.unboundOng,\n              balance: this.balance.ong\n          }\n        this.$store.commit('UPDATE_CURRENT_REDEEM', {redeem: redeem})\n        if(this.currentWallet.key) {\n            this.$router.push({path:'/commonWalletRedeem/commonWallet'})\n        } else {\n            this.$router.push({path: '/commonWalletRedeem/hardwareWallet'})\n        }\n      },\n      goBack() {\n        this.$router.push({name: 'Wallets'})\n      },\n      checkMoreTx() {\n        let url = `https://explorer.ont.io/address/${this.address}/10/1`\n        if (this.network === 'TestNet') {\n          url += '/testnet'\n        }\n        open(url)\n      },\n      showTxDetail(txHash) {\n        let url = `https://explorer.ont.io/transaction/${txHash}`\n        if (this.network === 'TestNet') {\n          url += '/testnet'\n        }\n        open(url)\n      },\n      copy(value) {\n            this.$copyText(value);\n            this.$message.success(this.$t('common.copied'))\n      },\n      toSwap() {\n        this.$router.push({name: 'CommonTokenSwap'})\n      },\n      handleModalOk() {\n        this.redeemInfoVisible = false;\n      },\n      checkMoreOep4() {\n        this.$router.push({name: 'Oep4Home'})\n      },\n      addOep4() {\n        this.showOep4Selection = true;\n      },\n      closeOep4Selection() {\n        this.showOep4Selection = false;\n        this.$store.dispatch('showLoadingModals')\n        this.$store.dispatch('fetchTokenBalances', {address: this.address})\n      }\n    }\n  }\n</script>\n"
  },
  {
    "path": "src/components/Exchange/Changelly/Changelly.vue",
    "content": "<style scoped>\n.changelly-container {\n  position: relative;\n  padding-bottom: 75%;\n  height: 0;\n  overflow: hidden;\n}\n.changelly-container iframe {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n</style>\n<template>\n    <div>\n      <breadcrumb  :current=\"$t('exchange.exchange')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n      <!-- Remove this div and enable this.loadPage in mounted() to open in a new window -->\n      <!-- <div class=\"changelly\"\n        <iframe src=\"https://widget.changelly.com?currencies=&from=btc&to=ont&amount=1&address=&fiat=true&fixedTo=false&theme=default&ref_id=su5srryl1mhz4fno&merchant_id=su5srryl1mhz4fno\" width=\"100%\" height=\"600\" class=\"changelly\" scrolling=\"no\" onLoad=\"function v(e){var t=e.target,n=t.parentNode,r=t.contentWindow,a=function(){return r.postMessage({width:n.offsetWidth},'https://widget.changelly.com')};window.addEventListener('resize',a),a()};v.apply(this, arguments);\" style=\"overflow-y: hidden; border: none\">Can't load widget</iframe>\n      </div> -->\n      </div>\n</template>\n\n<script>\nimport Breadcrumb from \"../../Breadcrumb\";\nconst changellyURL =\n  \"https://widget.changelly.com?currencies=&from=btc&to=ont&amount=1&address=&fiat=true&fixedTo=false&theme=default&ref_id=su5srryl1mhz4fno&merchant_id=su5srryl1mhz4fno\";\nconst { BrowserWindow } = require('@electron/remote')\nconst open = require('open')\nexport default {\n  name: \"Changelly\",\n  mounted() {\n    //Changelly page set to load as iframe in current window, if new browser\n    //window is preferred, enable method this.loadPage() below and remove reference\n    //to iFrame in <div> above\n    this.loadPage()\n  },\n  data() {\n    return {};\n  },\n  components: {\n    Breadcrumb\n  },\n  methods: {\n    handleRouteBack() {\n      this.$router.push({ name: \"Exchange\" });\n    },\n    loadPage() {\n      open(changellyURL)\n      // let win = new BrowserWindow({ width: 1000, height: 550, center: true });\n      // win.on(\"closed\", () => {\n      //   win = null;\n      // });\n      // win.loadURL(changellyURL);\n    }\n  }\n};\n</script>"
  },
  {
    "path": "src/components/Exchange/Cryptonex/Cryptonex.vue",
    "content": "<style scoped>\n.cryptonex-container {\n  position: relative;\n  padding-bottom: 75%;\n  height: 0;\n  overflow: hidden;\n}\n.cryptonex-container iframe {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n</style>\n<template>\n    <div>\n      <breadcrumb  :current=\"$t('exchange.exchange')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n   </div>\n</template>\n\n<script>\nimport Breadcrumb from \"../../Breadcrumb\";\nconst cryptonexURL = \"https://wallet.cryptonex.org/member/sign-in\";\nconst { BrowserWindow } = require('@electron/remote');\n\nexport default {\n  name: \"Cryptonex\",\n  mounted() {\n    this.loadPage()\n  },\n  data() {\n    return {};\n  },\n  components: {\n    Breadcrumb\n  },\n  methods: {\n    handleRouteBack() {\n      this.$router.push({ name: \"Exchange\" });\n    },\n    loadPage() {\n      let win = new BrowserWindow({ width: 1024, height: 768, center: true });\n      win.on(\"closed\", () => {\n        win = null;\n        this.$router.push({ name: \"Exchange\" });\n      });\n      win.loadURL(cryptonexURL);\n    }\n  }\n};\n</script>"
  },
  {
    "path": "src/components/Home.vue",
    "content": "\n<style scoped>\n  @import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');\n\n  .row-home {\n    margin-left: -5.13rem;\n  }\n\n  .row-home .col-10 {\n    padding: 0;\n  }\n\n  .img-home-page {\n    width: 100%;\n    height: 100%;\n  }\n\n  .div-slogan {\n    margin-top: 30vh;\n    text-align:left;\n  }\n\n  .go-to-wallets {\n    width: 10rem;\n    height: 2.5rem;\n    line-height: 1.8rem;\n    background-color: #196BD8;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #FFFFFF;\n    text-align: center;\n    border-radius: 0;\n    margin-top: 15vh;\n  }\n\n  .div-footer-version {\n    text-align: center;\n    position: absolute;\n    bottom:10px;\n    margin-left: auto;\n    margin-right: auto;\n    left: 0;\n    right:0;\n  }\n  .div-footer-version P {\n    margin:0;\n  }\n  .home-img {\n    width:100%;\n    height:100%;\n    background:url('../assets/home/background@1.5x.png') center center;\n    background-size:cover;\n  }\n  .home-container {\n    position:fixed;\n    width:100%;\n    height: 100%;\n    margin-top: -4rem;\n  }\n  .home-slogan :first-child {\n    font-family: AvenirNext-Medium;\n    font-size: 16px;\n    color: #000000;\n    text-align: left;\n    margin: 0;\n  }\n  .home-slogan :last-child {\n    font-family: AvenirNext-Regular;\n    margin: 0;\n  }\n  .bg-container {\n    position: relative;\n  }\n  .home-upgrade {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    padding: 10px;\n    text-align: center;\n    border:1px solid #FBE45A;\n    background:#FBE45A;\n    font-family: AvenirNext-Regular;\n  }\n  .home-upgrade a {\n    color: #196BD8;\n  }\n  .home-upgrade a:hover {\n    color: rgb(50, 120, 211);\n  }\n</style>\n<template>\n  <div class=\"row row-home home-container\">\n    <div class=\"col-10 bg-container\">\n      <!-- <img class=\"img-home-page\" src=\"./../assets/home/background@1.5x.png\" alt=\"\"> -->\n      <div class=\"home-img\"></div>\n      <div class=\"home-upgrade\" v-if=\"latest_url\">\n        <!-- <a-alert message=\"Warning\" type=\"warning\" showIcon /> -->\n        {{$t('common.versionUpdate')}}\n        <a @click=\"handleUpdate\">{{$t('common.getLatestVersion')}}</a>\n      </div>\n    </div>\n    <div class=\"col-2 text-center\">\n      <div class=\"div-slogan home-slogan\">\n          <p>OWallet</p>\n          <p>A comprehensive Ontology desktop wallet.</p>\n      </div>\n      <div>\n        <router-link class=\"btn btn-default go-to-wallets text-center\" to=\"Wallets\">\n          <div>ENTER →</div>\n        </router-link>\n      </div>\n\n      <div class=\"div-footer-version\">\n        <p>Version: {{version}}</p>\n        <p>Powered by Ontology</p>\n      </div>\n    </div>\n\n\n  </div>\n</template>\n\n<script>\n  import {mapState} from 'vuex'\n  import {TEST_NET, MAIN_NET} from '../core/consts'\n  import axios from 'axios';\n  import pkg from '../../package.json'\n  const { BrowserWindow } = require('@electron/remote')\n  import { open } from '../core/utils'\nimport {Modal} from 'ant-design-vue'\n  export default {\n    name: 'Home',\n    data() {\n      return {\n        version: pkg.version,\n        latest_url: ''\n      }\n    },\n    mounted() {\n      this.$store.dispatch('showLoadingModals');\n      const url = 'https://api.github.com/repos/ontio/OWallet/releases/latest';\n      const version = this.version;\n      axios.get(url).then(res => {\n        this.$store.dispatch('hideLoadingModals');\n        if (res.data && res.data.tag_name !== version){\n          console.log('not latest')\n          this.latest_url = res.data.html_url\n          Modal.confirm({\n                centered: true,\n                okText: this.$t('common.toUpdate'),\n                cancelText: this.$t('common.cancel'),\n                title: this.$t('dapps.notification'),\n                content: this.$t('common.availableNewVersion'),\n                onOk() {open(res.data.html_url)},\n                onCancel(){}\n            })\n        }\n      }).catch(err => {\n        console.log(err);\n        this.$store.dispatch('hideLoadingModals');\n      })\n    },\n    methods: {\n      handleUpdate() {\n        const url = this.latest_url;\n        open(url);\n        // let win = new BrowserWindow({width: 800, height: 600, center: true});\n        // win.on('closed', () => {\n        //   win = null\n        // })\n\n        // // Load a remote URL\n        // win.loadURL(url)\n      }\n    }\n  }\n</script>\n\n"
  },
  {
    "path": "src/components/Identitys/Create/BasicInfo.vue",
    "content": "<template>\n  <div>\n    <div class=\"basic-label\">\n      <a-input class=\"input\" :placeholder=\"$t('createIdentity.label')\" v-model=\"label\"\n          v-validate=\"{required: true}\" name=\"label\"\n      ></a-input>\n      <span class=\"v-validate-span-errors\" v-show=\"errors.has('label')\">{{ errors.first('label') }}</span>\n\n      <a-input type=\"password\" class=\"input input-password\"\n               v-validate=\"{required: true ,min:6}\" name=\"password\"\n               v-model=\"password\" :placeholder=\"$t('createIdentity.password')\"></a-input>\n      <span class=\"v-validate-span-errors\" v-show=\"errors.has('password')\">{{ errors.first('password') }}</span>\n\n      <a-input type=\"password\" class=\"input input-repassword\"\n               v-validate=\"{required: true , min:6, is:password}\" :data-vv-as=\"$t('FormField.passwordConfirmation')\" name=\"rePassword\"\n               v-model=\"rePassword\" :placeholder=\"$t('createIdentity.rePassword')\"></a-input>\n      <span class=\"v-validate-span-errors\" v-show=\"errors.has('rePassword')\">{{ errors.first('rePassword') }}</span>\n\n      <div class=\"create-select-wallet\">\n        <p class=\"font-medium-black\">{{$t('createIdentity.selectWallet')}}</p>\n        <a-radio-group @change=\"changePayerWallet\" v-model=\"payerWalletType\" class=\"change-payer-radio\">\n          <a-radio value=\"commonWallet\">{{$t('createIdentity.commonWallet')}}</a-radio>\n          <a-radio value=\"ledgerWallet\">{{$t('createIdentity.ledgerWallet')}}</a-radio>\n          <div v-if=\"payerWalletType === 'commonWallet'\">\n           <a-select :options=\"localCommonWallet\" class=\"select-payer-wallet\"\n           :placeholder=\"$t('createIdentity.selectCommonWallet')\"\n            @change=\"handleChangePayer\">\n           </a-select>\n           <a-input type=\"password\" class=\"input\" v-model=\"payerPassword\" :placeholder=\"$t('createIdentity.payerPassword')\"></a-input>\n          </div>\n\n          <div v-if=\"payerWalletType === 'ledgerWallet'\">\n\n            <div class=\"payer-ledger-status\">\n              <div class=\"font-bold\" style=\"margin-bottom: 15px;\">{{$t('ledgerWallet.connectApp')}}</div>\n              <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n              <span class=\"font-medium\">{{ledgerStatus}} </span>\n            </div>\n\n          </div>\n\n        </a-radio-group>\n\n\n      </div>\n    </div>\n\n    <div class=\"basic-pk-btns\">\n      <div class=\"btn-container\">\n        <a-button type=\"default\" @click=\"cancel\" class=\"btn-cancel\">{{$t('createIdentity.cancel')}}</a-button>\n        <a-button type=\"primary\" @click=\"next\" class=\"btn-next\">{{$t('createIdentity.next')}}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\n  import {mapState} from 'vuex'\n  import {Wallet, Account, Crypto, TransactionBuilder, TxSignature, RestClient} from \"ontology-ts-sdk\"\n  import FileHelper from \"../../../core/fileHelper\"\n  import dbService from '../../../core/dbService'\n  import {DEFAULT_SCRYPT, TEST_NET, MAIN_NET} from '../../../core/consts'\nimport {legacySignWithLedger} from '../../../core/ontLedger'\nimport { getRestClient } from '../../../core/utils'\n\n  export default {\n    name: 'BasicInfo',\n    data() {\n      const net = localStorage.getItem('net');\n      return {\n        label: \"\",\n        password: \"\",\n        rePassword: \"\",\n        createSuccess: false,\n        payerWalletType: 'commonWallet',\n        payerWallet: '',\n        localCommonWallet:[],\n        payerPassword: ''\n      }\n    },\n    mounted(){\n      this.updateLocalCommonWallets()\n      this.$store.dispatch('getLedgerStatus')\n    },\n    beforeDestroy(){\n      this.$store.dispatch('stopGetLedgerStatus')\n    },\n    computed: {\n      ...mapState({\n        ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n        ledgerPk : state => state.LedgerConnector.publicKey,\n        ledgerWallet: state => state.LedgerConnector.ledgerWallet\n      })\n    },\n    methods: {\n      updateLocalCommonWallets() {\n            var that = this;\n                const localpayers = []\n                dbService.find({type:'CommonWallet'}, function (err, accounts) {\n                    if (err) {\n                        console.log(err)\n                        return;\n                    }\n\n                    for (let ac of accounts) {\n                      localpayers.push(Object.assign({}, ac.wallet,\n                      {value:ac.address, label:ac.wallet.label + ' ' + ac.address}))\n                    }\n                    that.localCommonWallet = localpayers\n                })\n        },\n      next() {\n        if(this.payerWalletType === 'commonWallet' && !this.payerWallet) {\n          this.$message.error(this.$t('createIdentity.selectOneWallet'))\n          return;\n        }\n        if(this.payerWalletType === 'commonWallet' && this.payerWallet && !this.payerPassword) {\n          this.$message.error(this.$t('createIdentity.enterPassword'))\n          return;\n        }\n        let payer;\n        if(this.payerWalletType === 'commonWallet') {\n          payer = new Crypto.Address(this.payerWallet.address)\n        } else {\n          payer = new Crypto.Address(this.ledgerWallet.address)\n        }\n        this.$validator.validateAll().then(result => {\n          if(result) {\n            let privateKey = Crypto.PrivateKey.random()\n            let body = {\n              label: this.label,\n              privateKey: privateKey,\n              password: this.password,\n              payer: payer\n            }\n            this.$store.dispatch('createIdentityWithPrivateKey', body).then(res => {\n              console.log(res)\n              const tx = res;\n              // const tx = Object.assign({}, res);\n              this.$store.dispatch('showLoadingModals')\n              if(this.payerWalletType === 'commonWallet') {\n                const enc = new Crypto.PrivateKey(this.payerWallet.key)\n                let pri;\n                try {\n                  pri = enc.decrypt(this.payerPassword, new Crypto.Address(this.payerWallet.address), this.payerWallet.salt, DEFAULT_SCRYPT)\n                } catch (err) {\n                  console.log(err);\n                  this.$message.error(this.$t('common.pwdErr'))\n                  this.$store.dispatch('hideLoadingModals')\n                  return;\n                }\n                TransactionBuilder.addSign(tx, pri);\n                this.sendTx(tx)\n              } else {\n                if(this.ledgerPk) {\n                  this.$store.dispatch('showLoadingModals')\n                  const pk = new Crypto.PublicKey(this.ledgerWallet.publicKey);\n                  const txSig = new TxSignature();\n                  txSig.M = 1;\n                  txSig.pubKeys = [pk];\n                  const txData = tx.serializeUnsignedData();\n                  legacySignWithLedger(txData).then(res => {\n                  // console.log('txSigned: ' + res);\n                  const sign = '01' + res; //ECDSAwithSHA256\n                  txSig.sigData = [sign]\n                  tx.sigs.push(txSig);\n                  this.sendTx(tx);\n                  }, err => {\n                      this.ledgerStatus = '';\n                      this.$store.dispatch('hideLoadingModals')\n                      alert(err.message)\n                  })\n              } else {\n                  this.$message.warning(this.$t('ledgerWallet.connectApp'))\n              }\n              }\n            })\n\n\n          }\n        })\n      },\n      sendTx(tx){\n        const restClient = getRestClient();\n          restClient.sendRawTransaction(tx.serialize()).then(res => {\n          console.log(res)\n          this.$store.dispatch('hideLoadingModals')\n          console.log('hide')\n\n          if (res.Error === 0) {\n            this.$message.success(this.$t('common.transSentSuccess'))\n          } else if (res.Error === -1) {\n            this.$message.error(this.$t('common.ongNoEnough'))\n            return;\n          } else {\n            this.$message.error(res.Result)\n            return;\n          }\n          this.$store.commit('ADD_CREATE_IDENTITY_STEP')\n          // const title = this.$t('common.transSentSuccess')\n          // setTimeout(() => {\n          //     this.$success({\n          //         title: title,\n          //         content: 'Transaction hash: ' + utils.reverseHex(tx.getHash())\n          //     })\n          // }, 100)\n        }).catch(err => {\n                    console.log(err)\n                    this.$message.error(this.$t('common.networkError'))\n                })\n      },\n      cancel() {\n        this.$router.push({name: 'Identitys'})\n      },\n      changePayerWallet(e) {\n        this.payerWalletType = e.target.value\n      },\n      handleChangePayer(value) {\n        this.payerWallet = this.localCommonWallet.find((v)=>{return v.address === value})\n      }\n    }\n  }\n</script>\n\n<style>\n  .basic-label {\n    width: 540px;\n    margin: 2px auto;\n  }\n\n  .input-password {\n    margin-top: 30px;\n  }\n\n  .input-repassword {\n    margin-top: 10px;\n  }\n\n  .copayer-label {\n    margin-left: 172px;\n    margin-top: 40px;\n  }\n\n  .basic-pks {\n    width: 540px;\n    margin: 0px auto;\n  }\n\n  .pk-item {\n    margin-bottom: 15px;\n  }\n\n  .pk-item :first-child {\n    width: 150px;\n    margin-right: 20px;\n    display: inline-block;\n  }\n\n  .pk-item :nth-child(2) {\n    width: 318px;\n  }\n\n  .delete-icon {\n    height: 34px;\n    width: 34px;\n    /* display: inline-block; */\n    background: url('../../../assets/delete.png') center center;\n    background-size: contain;\n    float: right;\n    margin-right: 10px;\n    cursor: pointer;\n  }\n\n  .basic-pk-box {\n    border: 1px solid #dddddd;\n    width: 100%;\n    height: 300px;\n    padding: 10px;\n    position: relative;\n  }\n\n  .basic-pk-add {\n    border-top: 1px solid #dddddd;\n    width: calc(100% - 20px);\n    position: absolute;\n    bottom: 10px;\n    left: 10px;\n    padding-top: 10px;\n  }\n\n  .basic-pk-item {\n    width: 100%;\n    float: left;\n  }\n\n  .basic-pk-item span {\n    margin-right: 10px;\n  }\n\n  .basic-add-item {\n    display: inline-block;\n    width: 40%;\n  }\n\n  .basic-add-item input {\n    width: 80%;\n  }\n\n  .basic-pk-btns {\n    position: fixed;\n    bottom: 0;\n    width: calc(100% - 4rem);\n    height: 85px;\n    left: 4rem;\n    background: #FFFFFF;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    z-index: 1000;\n  }\n\n  .basic-pk-btns button:first-child {\n    float: left;\n  }\n\n  .basic-pk-btns :nth-child(2) {\n    float: right;\n  }\n\n  .basic-pk-btns :nth-child(3) {\n    float: right;\n    margin-right: 20px;\n  }\n\n  .error-input {\n    border-color: red;\n  }\n  .create-select-wallet {\n    margin-top: 15px;\n  }\n  .select-payer-wallet {\n    width:100%;\n    margin-bottom:10px;\n    margin-top:15px;\n  }\n  .change-payer-radio {\n    width:100%;\n  }\n  .payer-ledger-status {\n    margin-top:10px;\n    padding: 5px 10px;\n  }\n</style>\n\n"
  },
  {
    "path": "src/components/Identitys/Create/ConfirmInfo.vue",
    "content": "<template>\n  <div class=\"container json-confirm-container\">\n    <p><b>{{$t('createIdentity.label')}}: </b> {{label}}</p>\n    <p><b>{{$t('createIdentity.ontid')}}: </b> {{ ontid }}</p>\n\n\n    <div class=\"confirm-btns\">\n      <div class=\"confirm-btn-container\">\n        <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{ $t('createJsonWallet.back') }}</a-button>\n        <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{ $t('createJsonWallet.next') }}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\n  import {mapState} from 'vuex'\n  import {Crypto, Wallet, Account} from 'ontology-ts-sdk'\n  import FileHelper from \"../../../core/fileHelper\"\n  import dbService from '../../../core/dbService'\n  import {WALLET_TYPE,DEFAULT_SCRYPT} from '../../../core/consts'\n  import en from '../../../lang/en'\n  import zh from '../../../lang/zh'\n\n  export default {\n    name: 'ConfirmInfo',\n    data() {\n      const langType = localStorage.getItem('user_lang') || 'en';\n      const lang = langType === 'en' ? en : zh;\n      return {\n        lang: lang,\n        processing: false\n      }\n    },\n    computed: {\n      ...mapState({\n        label: state => state.CreateIdentity.label,\n        ontid: state => state.CreateIdentity.ontid,\n        identity: state => state.CreateIdentity.identity,\n        tx: state => state.CreateIdentity.tx\n      })\n    },\n    beforeDestroy() {\n      console.log('clear')\n      this.$store.commit('INIT_CREATE_IDENTITY')\n    },\n    methods: {\n      back() {\n        this.$store.commit('SUB_CREATE_IDENTITY_STEP')\n      },\n      downloadWallet() {\n        const commonWallet = this.account\n        let wallet = Wallet.create(commonWallet.label || \"\")\n        console.log(wallet)\n        wallet.scrypt.n = 16384;\n        const account = Account.parseJsonObj(commonWallet)\n        wallet.addAccount(account)\n        FileHelper.downloadFile(wallet.toJsonObj(), commonWallet.label);\n      },\n      next() {\n        this.$store.dispatch('showLoadingModals')\n        //Download file\n        // FileHelper.downloadFile(this.downloadContent)\n\n        //save to db\n        const wallet = {\n          type : 'Identity',\n          address: this.ontid,\n          wallet: this.identity\n        }\n        dbService.insert(wallet, (err, newDoc) => {\n          if (err) {\n            console.log(err)\n            this.$store.dispatch('hideLoadingModals')\n            this.$message.error(this.$t('common.savedbFailed'))\n          }\n          // console.log(newDoc)\n        })\n\n        this.$store.commit('INIT_CREATE_IDENTITY')\n        this.$message.success(this.$t('createIdentity.createSuccess'))\n        this.$router.push({name: 'Identitys'})\n      }\n    }\n  }\n</script>\n\n<style scoped>\n  .json-confirm-container {\n    width: 36rem;\n  }\n\n  .confirm-btns {\n    position: fixed;\n    bottom: 0;\n    width: calc(100% - 4rem);\n    height: 85px;\n    left: 4rem;\n    background: #FFFFFF;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    z-index: 1000;\n  }\n\n  .confirm-btn-container {\n    width: 540px;\n    margin: 20px auto;\n  }\n\n  .confirm-btn-container :last-child {\n    float: right;\n  }\n  .backup-text {\n    text-align: center;\n    padding: 20px;\n    border: 1px solid #dddddd;\n    font-size: 16px;\n  }\n  .backup-text p {\n    margin:0;\n    font-size:16px !important;\n  }\n\n</style>\n"
  },
  {
    "path": "src/components/Identitys/CreateIdentity.vue",
    "content": "<template>\n  <div>\n    <breadcrumb :current=\"$t('createIdentity.create')\" v-on:backEvent=\"back\"></breadcrumb>\n    <div class=\"shared-container\">\n      <a-steps :current=\"current\" class=\"create-steps\">\n        <a-step v-for=\"item in steps\" :key=\"item.title\"/>\n      </a-steps>\n      <div class=\"steps-content\">\n        <basic-info v-if=\"current === 0\"></basic-info>\n        <confirm-info v-if=\"current === 1\"></confirm-info>\n      </div>\n    </div>\n  </div>\n\n</template>\n\n<script>\n  import BasicInfo from './Create/BasicInfo'\n  import ConfirmInfo from './Create/ConfirmInfo'\n  import Breadcrumb from '../Breadcrumb'\n  import {mapState} from 'vuex';\n\n  export default {\n    name: 'createIdentity',\n    data() {\n      return {\n        steps: [{\n          title: this.$t('createIdentity.basicInfo'),\n          content: 'First-content',\n        }, {\n          title: this.$t('createIdentity.confirmInfo'),\n          content: 'Second-content',\n        }]\n      }\n    },\n    computed: {\n      ...mapState({\n        current: state => state.CreateIdentity.currentStep,\n      })\n    },\n    components: {\n      BasicInfo,\n      ConfirmInfo,\n      Breadcrumb\n    },\n    methods: {\n      back() {\n        this.$router.push({name: 'Identitys'})\n      }\n    }\n  }\n</script>\n\n<style scoped>\n  .shared-container {\n  }\n\n  .steps-content {\n  }\n\n  .steps-action {\n    margin-top: 24px;\n  }\n\n  .create-steps {\n    width: 520px;\n    height: 4rem;\n    margin: 2px auto;\n  }\n</style>\n"
  },
  {
    "path": "src/components/Identitys/IdentityView.vue",
    "content": "<template>\n  <div class=\"common-detail-container\">\n    <div >\n      <div class=\"div-shared-wallet-sign\">\n        <span>{{ $t('identitys.identity')}}</span>\n      </div>\n      <div class=\"div-wallet-name\">{{identity.label}}</div>\n      <!--<img class=\"img-wallet-edit\" src=\"./../assets/edit.png\" alt=\"\">-->\n      <div class=\"div-wallet-address\">\n        <div>{{$t('identitys.ontid')}} :</div>\n        {{identity.ontid}}\n      </div>\n    </div>\n    <div v-show=\"addressCopied\" class=\"copied-label\">Copied</div>\n    <img class=\"img-wallet-copy\" src=\"../../assets/copy.png\" @click=\"copyAddress(identity)\" alt=\"\">\n    <div class=\"common-topRight-btns\">\n      <a-dropdown >\n        <a-menu slot=\"overlay\" >\n          <a-menu-item key=\"1\" >\n            <span @click=\"handleExportIdentity()\">{{$t('common.exportIdentity')}}</span>\n          </a-menu-item>\n          <a-menu-item key=\"2\">\n            <span  @click=\"deleteIdentity()\">{{$t('common.deleteIdentity')}}</span>\n          </a-menu-item>\n        </a-menu>\n        <a-button style=\"margin-left: 8px\">\n          {{$t('common.more')}}<a-icon type=\"down\" />\n        </a-button>\n      </a-dropdown>\n    </div>\n\n    <a-modal\n        :title=\"modalTitle\"\n        :visible=\"passModal\"\n        @ok=\"handleValidatePassword\"\n        @cancel=\"handleCancel\">\n          <div>\n              <p class=\"font-medium\">\n                {{option==='EXPORT_ONTID' ? $t('wallets.exportOntid') : '' }}\n                 {{identity.ontid}}</p>\n              <div >\n                <p>{{$t('common.enterIdentityPassword')}}</p>\n                <a-input class=\"input\" v-model=\"password\" :plaecholder=\"$t('common.password')\" type=\"password\"></a-input>\n              </div>\n          </div>\n    </a-modal>\n\n    <a-modal\n        :title=\"$t('common.exportIdentity')\"\n        v-model=\"showIdentityKeystore\"\n        @ok=\"handleShowKeystoreOk\"\n        >\n        <div class=\"identity-keystore\">\n          <p class=\"font-medium\">{{keystore}}</p>\n        </div>\n    </a-modal>\n  </div>\n</template>\n\n<script>\n  import {Wallet, Account, Crypto, Identity} from 'ontology-ts-sdk';\n  import dbService from '../../core/dbService'\n  import { formatScryptParams } from '../../core/utils'\n\texport default {\n    name: \"IdentityView\",\n    props: ['identity'],\n    data() {\n      return {\n        addressCopied: false,\n        modalTitle: this.$t('common.authentication'),\n        passModal: false,\n        password: '',\n        showIdentityKeystore: false,\n        keystore: '',\n        option: ''\n      }\n    },\n    methods: {\n      copyAddress(identity) {\n        this.$copyText(identity.ontid)\n        this.addressCopied = true\n        this.$nextTick(function () {\n          setInterval(this.addressCopiedDisabled, 3000);\n        })\n      },\n      addressCopiedDisabled() {\n        this.addressCopied = false\n      },\n      handleExportIdentity() {\n        this.passModal = true;\n        this.option = 'EXPORT_ONTID'\n      },\n      deleteIdentity() {\n        this.passModal = true;\n        this.option = 'DELETE_ONTID'\n      },\n      handleCancel() {\n        this.passModal = false;\n        this.password = '';\n      },\n      handleValidatePassword() {\n        if(!this.password ) {\n          this.$message.error(this.$t('common.enterIdentityPassword'))\n          return;\n        }\n        this.$store.dispatch('showLoadingModals')\n        const controlData = this.identity.controls[0];\n        const enc = new Crypto.PrivateKey(controlData.key)\n        let pri;\n        const scrypt = this.identity.scrypt ||\n        {\n            n : 4096,\n            p : 8,\n            r : 8,\n            dkLen : 64\n        }\n        const params = formatScryptParams(scrypt);\n        try {\n          pri = enc.decrypt(this.password, new Crypto.Address(controlData.address), controlData.salt, params)\n        } catch (err) {\n          console.log(err);\n          this.$store.dispatch('hideLoadingModals')\n          this.$message.error(this.$t('common.pwdErr'))\n          return;\n        }\n        if(this.option === 'DELETE_ONTID') {\n          this.handleDelete();\n        } else if (this.option === 'EXPORT_ONTID') {\n          this.passModal = false;\n          this.showIdentityKeystore = true;\n          const keystore = {\n            type : 'I',\n            label : this.identity.label,\n            algorithm : 'ECDSA',\n            scrypt,\n            key : this.identity.controls[0].key,\n            salt: this.identity.controls[0].salt,\n            address: this.identity.controls[0].address,\n            parameters : {\n                curve : 'secp256r1'\n            }\n          };\n            this.keystore = JSON.stringify(keystore);\n          this.$store.dispatch('hideLoadingModals')\n        }\n        this.password = '';\n        pri.key = '';\n      },\n      handleDelete() {\n        // remove from db\n        const that = this;\n        const type = 'Identity'\n        const commitType = 'DELETE_IDENTITY';\n        dbService.remove({type:type, address: this.identity.ontid}, {}, function(err, numRemoved) {\n          if(err) {\n            that.$store.dispatch('hideLoadingModals')\n            that.$message.error(that.$t('wallets.deleteIdentityFailed'));\n            return;\n          }\n           // remove from store\n          that.$store.commit(commitType, {ontid: that.identity.ontid})\n          that.$store.dispatch('hideLoadingModals')\n          that.$message.success(that.$t('wallets.deleteIdentitySuccess'))\n          that.passModal = false;\n        })\n      },\n\n      handleShowKeystoreOk() {\n        this.keystore = '';\n        this.showIdentityKeystore = false;\n      }\n\n    }\n  }\n</script>\n\n<style scoped>\n  .common-detail-container {\n\n  }\n  .div-shared-wallet-sign {\n    margin-top: 0.88rem;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #196BD8;\n    cursor: default;\n  }\n\n  .div-wallet-name {\n    margin-top: 1.75rem;\n    font-family: AvenirNext-Medium;\n    font-size: 18px;\n    color: #515457;\n    line-height: 24px;\n    word-wrap: break-word;\n  }\n\n  .img-wallet-edit {\n    position: absolute;\n    top: 4.13rem;\n    right: 1.41rem;\n  }\n\n  .div-wallet-address {\n    font-family: AvenirNext-Regular;\n    font-size: 13px;\n    color: #B2B2B3;\n    position:absolute;\n    bottom:10px;\n    cursor: default;\n  }\n\n  .img-wallet-copy {\n    position: absolute;\n    bottom:15px;\n    right: 1.29rem;\n  }\n\n  .copied-label {\n    position: absolute;\n    top: 9rem;\n    right: 2.69rem;\n    background-color: #8a9098;\n    border-radius: 2px;\n    padding: 3px 4px;\n    font-size: 10px;\n    font-weight: 100;\n    color: white;\n  }\n  .common-export-btn {\n    height: 34px;\n    width:78px;\n    background:#5EA2FF;\n    font-family: AvenirNext-Regular;\n    font-size: 16px;\n    color: #FFFFFF;\n    border: 1px solid #FFFFFF;\n    border-radius: 0;\n    position: absolute;\n    top: 0px;\n    right: 20px;\n  }\n  .common-topRight-btns {\n    position:absolute;\n    top:10px;\n    right:10px;\n  }\n</style>\n"
  },
  {
    "path": "src/components/Identitys/Import/BasicInfo.vue",
    "content": "<template>\n  <div class=\"container json-import-container\">\n    <ul class=\"nav nav-pills import-identity-nav-pills\" id=\"pills-tab\" role=\"tablist\">\n      <li class=\"nav-item active\">\n        <a class=\"nav-link\" id=\"import-identity-keystore-pills-tab\" data-toggle=\"pill\" href=\"#import-identity-keystore-pills\"\n           role=\"tab\"\n           aria-controls=\"import-identity-keystore-pills\" aria-selected=\"false\" @click=\"activeTab('keystore')\">{{ $t('importIdentity.keystoreImport') }}</a>\n      </li>\n    </ul>\n\n    <div class=\"tab-content\" id=\"pills-tabContent\">\n      <div class=\"tab-pane fade show active\" id=\"import-identity-keystore-pills\" role=\"tabpanel\"\n           aria-labelledby=\"import-identity-keystore-pills-tab\">\n\n        <textarea class=\"import-identity-keystore\" id=\"import-identity-keystore\" rows=\"6\"\n                  v-validate=\"{required: true} \" name=\"keystore\"\n                  :placeholder=\"$t('importIdentity.keystore')\" v-model=\"keystore\"></textarea>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('keystore')\">{{ errors.first('keystore') }}</span>\n\n        <a-input type=\"password\" class=\"input input-password\"\n                 v-validate=\"{required: true ,min:6}\" :data-vv-as=\"$t('FormField.password')\" name=\"keystorePassword\"\n                 v-model=\"keystorePassword\" :placeholder=\"$t('importIdentity.ontidPassword')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('keystorePassword')\">{{ errors.first('keystorePassword') }}</span>\n      </div>\n    </div>\n\n    <div class=\"basic-pk-btns\">\n      <div class=\"btn-container\">\n        <a-button type=\"default\" @click=\"cancel\" class=\"btn-cancel\">{{$t('createIdentity.cancel')}}</a-button>\n        <a-button type=\"primary\" @click=\"next\" class=\"btn-next\">{{$t('createIdentity.next')}}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\n  import {mapState} from 'vuex'\n  import {Wallet, Account, Crypto, Identity, OntidContract, RestClient, SDK} from \"ontology-ts-sdk\"\n  import FileHelper from \"../../../core/fileHelper\"\n  import dbService from '../../../core/dbService'\n  import {DEFAULT_SCRYPT, TEST_NET, MAIN_NET} from '../../../core/consts'\n  // import $ from 'jquery'\nimport { getNodeUrl, getRestClient, formatScryptParams } from '../../../core/utils';\n\n  export default {\n    name: 'BasicInfo',\n    data() {\n      const net = localStorage.getItem('net');\n      return {\n        tabName: 'keystore', // keystore\n\n        keystore: '',\n        keystoreLabel: '',\n        keystorePassword: ''\n      }\n    },\n    methods: {\n      activeTab(tabName) {\n        this.tabName = tabName\n      },\n      next() {\n        if (this.tabName === 'keystore') {\n          this.$validator.validateAll({\n            keystore: this.keystore,\n            keystorePassword: this.keystorePassword\n          }).then(result => {\n            if (result) {\n              this.$store.dispatch('showLoadingModals')\n              this.importIdentityForKeystore()\n            }\n          })\n        }\n      },\n      validateKeystore(keystore) {\n        if(!keystore.key || !keystore.address || !keystore.salt) {\n          return false;\n        } else {\n          return true;\n        }\n      },\n      async importIdentityForKeystore() {\n        console.log('keystore:[' + this.keystore + ']; keystorePassword:[' + this.keystorePassword + ']')\n        //import identity\n        let keystore;\n        try {\n          keystore = JSON.parse(this.keystore)\n        } catch(err) {\n          this.$store.dispatch('hideLoadingModals')\n          this.$message.error(this.$t('importIdentity.invalidKeystore'))\n          return;\n        }\n        if(!this.validateKeystore(keystore)) {\n          this.$store.dispatch('hideLoadingModals')\n          this.$message.error(this.$t('importIdentity.invalidKeystore'))\n          return;\n        }\n        let identity = new Identity();\n        try {\n            const encryptedPrivateKeyObj = new Crypto.PrivateKey(keystore.key);\n            const addr = new Crypto.Address(keystore.address);\n            const label = keystore.label || 'Identity'\n            const salt = keystore.salt\n            //must call if use\n            let password = SDK.transformPassword(this.keystorePassword)\n            let params = keystore.scrypt ? formatScryptParams(keystore.scrypt) : null;\n            identity = Identity.importIdentity(label, encryptedPrivateKeyObj, password, addr, salt, params);\n            identity = identity.toJsonObj();\n            //Fix: keystore里需要加上scrypt参数\n            identity.scrypt = keystore.scrypt;\n        } catch (err) {\n            this.$message.error(this.$t('importIdentity.passError'))\n            this.$store.dispatch('hideLoadingModals')\n            return;\n        }\n        const tx = OntidContract.buildGetDDOTx(identity.ontid)\n        const restClient = getRestClient()\n        const res = await restClient.sendRawTransaction(tx.serialize(), true)\n          if(res.Error === 0 && res.Result) {\n            this.saveToDb(identity)\n          } else {\n            const restUrl = getNodeUrl()\n            const doc = await OntidContract.getDocumentJson(identity.ontid, restUrl)\n            const id = doc.publicKey.find(item => item.id.split('#')[0] === identity.ontid)\n            debugger\n            if(id) {\n                this.saveToDb(identity)\n            } else {\n                this.$message.error(this.$t('importIdentity.ontidNotExist'))\n                this.$store.dispatch('hideLoadingModals')\n                return;\n            }\n          }\n      },\n      saveToDb(identity) {\n        const that = this;\n        const wallet = {\n          type: 'Identity',\n          address: identity.ontid,\n          wallet: identity\n        }\n        dbService.insert(wallet, function (err, newDoc) {\n          if (err) {\n            console.log(err)\n            that.$message.warning(that.$t('importIdentity.ontidExist'))\n            that.$store.dispatch('hideLoadingModals')\n            return;\n          }\n\n          that.$message.success(that.$t('importIdentity.importSuccess'))\n          that.$router.push({name: 'Identitys'})\n        })\n      },\n      cancel() {\n        this.$router.push({name: 'Identitys'})\n      }\n    }\n  }\n</script>\n\n<style>\n  .json-import-container {\n    width: 36rem;\n  }\n\n  .import-identity-nav-pills > li.nav-item {\n    width: 100%;\n    text-align: center;\n    height: 2rem;\n    margin-bottom: 30px;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n  }\n\n  .import-identity-nav-pills > li.nav-item > a {\n    color: black;\n  }\n\n  .import-identity-nav-pills .nav-link:hover {\n    color: #196BD8;\n  }\n\n  .import-identity-nav-pills .nav-link.active {\n    color: #196BD8;\n    background-color: transparent;\n    border-radius: 0;\n    border-bottom: #196BD8 solid 1px;\n  }\n\n  .input-password {\n    margin-top: 30px;\n  }\n\n  .import-identity-keystore {\n    width: 100%;\n    resize: none;\n    margin-top: 30px;\n    padding: 12px 20px;\n    border: 1px solid #DFE2E9;\n  }\n\n  textarea::-webkit-input-placeholder {\n    color: #C9CBCF;\n    font-family: AvenirNext-Regular;\n    font-size: 14px;\n  }\n\n  .basic-pk-btns {\n    position: fixed;\n    bottom: 0;\n    width: calc(100% - 4rem);\n    height: 85px;\n    left: 4rem;\n    background: #FFFFFF;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    z-index: 1000;\n  }\n\n  .basic-pk-btns button:first-child {\n    float: left;\n  }\n\n  .basic-pk-btns :nth-child(2) {\n    float: right;\n  }\n\n  .basic-pk-btns :nth-child(3) {\n    float: right;\n    margin-right: 20px;\n  }\n\n  .error-input {\n    border-color: red;\n  }\n</style>\n\n"
  },
  {
    "path": "src/components/Identitys/ImportIdentity.vue",
    "content": "<template>\n  <div>\n    <breadcrumb :current=\"$t('importIdentity.import')\" v-on:backEvent=\"back\"></breadcrumb>\n    <div class=\"shared-container\">\n      <div class=\"steps-content\">\n        <basic-info></basic-info>\n      </div>\n    </div>\n  </div>\n\n</template>\n\n<script>\n  import BasicInfo from './Import/BasicInfo'\n  import Breadcrumb from '../Breadcrumb'\n  import {mapState} from 'vuex';\n\n  export default {\n    name: 'ImportIdentity',\n    data() {\n      return {\n        steps: [{\n          title: this.$t('importIdentity.basicInfo'),\n          content: 'First-content',\n        }]\n      }\n    },\n    components: {\n      BasicInfo,\n      Breadcrumb\n    },\n    methods: {\n      back() {\n        this.$router.push({name: 'Identitys'})\n      }\n    }\n  }\n</script>\n"
  },
  {
    "path": "src/components/Identitys.vue",
    "content": "<template>\n  <div class=\"negative-margin-top\">\n    <ul class=\"nav nav-pills wallets-nav-pills\" id=\"pills-tab\" role=\"tablist\">\n      <li class=\"nav-item\">\n        <a class=\"nav-link active\" id=\"pills-home-tab\" data-toggle=\"pill\" href=\"#pills-home\" role=\"tab\"\n           aria-controls=\"pills-home\" aria-selected=\"true\">{{ $t('identitys.pageTit') }}</a>\n      </li>\n    </ul>\n\n    <div class=\"tab-content\" id=\"pills-tabContent\">\n\n      <div class=\"tab-pane fade show active\" id=\"pills-home\" role=\"tabpanel\" aria-labelledby=\"pills-home-tab\">\n        <div class=\"d-flex flex-wrap align-content-start center\">\n          <div class=\"normalWallet\" v-for=\"w in allIdentitys\" :key=\"w.address\">\n            <identity-view :identity=\"w\"></identity-view>\n          </div>\n\n          <div class=\"div-create-wallet\" :class=\"[viewBtn?'div-create-wallet-bg-color':'']\"\n               v-on:mouseenter=\"viewAllBtn(true)\" v-on:mouseleave=\"viewAllBtn(false)\">\n            <div class=\"div-create\" v-show=\"viewBtn\">\n              <router-link class=\"btn btn-default btn-create\" :to=\"{name: 'CreateIdentity'}\">{{$t('identitys.createIdentity')}}</router-link>\n            </div>\n            <div class=\"div-join\" v-show=\"viewBtn\">\n              <router-link class=\"btn btn-default btn-create\" :to=\"{name: 'ImportIdentity'}\">{{$t('identitys.importIdentity')}}</router-link>\n            </div>\n            <img class=\"img-wallet-create\" v-show=\"!viewBtn\" src=\"./../assets/create-wallet.png\" alt=\"\">\n          </div>\n        </div>\n      </div>\n\n    </div>\n  </div>\n</template>\n\n<script>\nimport {mapState} from 'vuex'\nimport IdentityView from './Identitys/IdentityView'\n\n\texport default {\n    name: \"Identitys\",\n    components:{\n      IdentityView\n    },\n    data() {\n      const net = localStorage.getItem('net')\n      const network = net === 'TEST_NET' ? this.$t('common.testNet') : this.$t('common.mainNet');\n\n      return {\n        network: network,\n        viewBtn: false,\n      }\n    },\n    mounted() {\n      this.$store.dispatch('fetchIdentitiesFromDb')\n    },\n    computed: {\n      ...mapState({\n        allIdentitys : state => state.Identities.Identities\n      })\n    },\n    methods: {\n      copyAddress(wallet) {\n        this.$copyText(wallet.address)\n      },\n      viewAllBtn(bool) {\n        this.viewBtn = bool\n      }\n    }\n\t}\n</script>\n\n<style scoped>\n  .nav-item > a {\n    color: #A5A7A9;\n  }\n\n  .nav-item > a:hover {\n    color: #196BD8;\n  }\n\n  .wallets-nav-pills .nav-link.active {\n    color: #196BD8;\n    background-color: transparent;\n    border-radius: 0;\n  }\n\n  .wallets-nav-pills {\n    line-height: 4rem;\n    font-family: AvenirNext-Medium;\n    font-size: 0.88rem;\n    padding: 0 1.7rem;\n  }\n\n  .nav-link {\n    padding: 0 1.7rem;\n  }\n\n  .nav-pills .show > .nav-link {\n    color: #196BD8;\n    background-color: transparent;\n  }\n\n  .center {\n    padding: 1.88rem 3rem;\n    position: relative;\n  }\n\n  .normalWallet,\n  .div-create-wallet {\n    width: 24.63rem;\n    height: 13.19rem;\n    margin-right: 1.75rem;\n    margin-left:1.75rem;\n    margin-bottom: 2.75rem;\n  }\n\n  .normalWallet {\n    background-color: #F5F7FB;\n    padding: 0 1.25rem;\n    position: relative;\n  }\n\n  .normalWallet:hover {\n    cursor: pointer;\n  }\n\n  .div-create-wallet {\n    background-color: #F5F7FB;\n    font-family: AvenirNext-Medium;\n    position: relative;\n  }\n\n  .div-create-wallet-bg-color {\n    background-color: #498FEF;\n  }\n\n  .img-wallet-create {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    margin-left: -30px;\n    margin-top: -30px;\n  }\n\n  .div-create-wallet > div > a {\n    font-size: 0.88rem;\n  }\n\n  .btn-create {\n    width: 8.25rem;\n    height: 2.13rem;\n    color: white;\n    border: white solid 1px;\n    border-radius: 0;\n  }\n\n  .div-create {\n    padding: 0px;\n    margin: 3.5rem auto 2rem;\n    text-align: center;\n  }\n\n  .div-join {\n    padding: 0px;\n    margin: 2rem auto;\n    text-align: center;\n  }\n</style>\n"
  },
  {
    "path": "src/components/JsonWallet/Create/BasicInfo.vue",
    "content": "<template>\n  <div>\n    <div class=\"basic-label\">\n      <a-input class=\"input\" :placeholder=\"$t('createJsonWallet.label')\" v-model=\"label\"\n          v-validate=\"{required: true}\" name=\"label\"\n      ></a-input>\n      <span class=\"v-validate-span-errors\" v-show=\"errors.has('label')\">{{ errors.first('label') }}</span>\n\n      <a-input type=\"password\" class=\"input input-password\"\n               v-validate=\"{required: true ,min:6}\" name=\"password\"\n               v-model=\"password\" :placeholder=\"$t('createJsonWallet.password')\"></a-input>\n      <span class=\"v-validate-span-errors\" v-show=\"errors.has('password')\">{{ errors.first('password') }}</span>\n\n      <a-input type=\"password\" class=\"input input-repassword\"\n               v-validate=\"{required: true , min:6, 'confirmed':password}\" :data-vv-as=\"$t('FormField.passwordConfirmation')\" name=\"rePassword\"\n               v-model=\"rePassword\" :placeholder=\"$t('createJsonWallet.rePassword')\"></a-input>\n      <span class=\"v-validate-span-errors\" v-show=\"errors.has('rePassword')\">{{ errors.first('rePassword') }}</span>\n    </div>\n\n    <div class=\"basic-pk-btns\">\n      <div class=\"btn-container\">\n        <a-button type=\"default\" @click=\"cancel\" class=\"btn-cancel\">{{$t('createJsonWallet.cancel')}}</a-button>\n        <a-button type=\"primary\" @click=\"next\" class=\"btn-next\">{{$t('createJsonWallet.next')}}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\n  import {mapState} from 'vuex'\n  import {Wallet, Account, Crypto} from \"ontology-ts-sdk\"\n  import FileHelper from \"../../../core/fileHelper\"\n  import dbService from '../../../core/dbService'\n\n  export default {\n    name: 'BasicInfo',\n    data() {\n      return {\n        label: \"\",\n        password: \"\",\n        rePassword: \"\",\n        createSuccess: false\n      }\n    },\n    methods: {\n      next() {\n        this.$validator.validateAll().then(result => {\n          if(result) {\n            let privateKey = Crypto.PrivateKey.random()\n            const wif = privateKey.serializeWIF();\n            let body = {\n              label: this.label,\n              privateKey: privateKey,\n              password: this.password,\n              wif: wif\n            }\n            this.$store.dispatch('createJsonWalletWithPrivateKey', body).then(res => {\n              // console.log(res)\n            })\n\n            this.$store.commit('ADD_CREATE_JSON_STEP')\n          }\n        })\n      },\n      cancel() {\n        this.$router.push({name: 'Wallets'})\n      }\n    }\n  }\n</script>\n\n<style>\n  .basic-label {\n    width: 540px;\n    margin: 2px auto;\n  }\n\n  .input-password {\n    margin-top: 30px;\n  }\n\n  .input-repassword {\n    margin-top: 10px;\n  }\n\n  .copayer-label {\n    margin-left: 172px;\n    margin-top: 40px;\n  }\n\n  .basic-pks {\n    width: 540px;\n    margin: 0px auto;\n  }\n\n  .pk-item {\n    margin-bottom: 15px;\n  }\n\n  .pk-item :first-child {\n    width: 150px;\n    margin-right: 20px;\n    display: inline-block;\n  }\n\n  .pk-item :nth-child(2) {\n    width: 318px;\n  }\n\n  .delete-icon {\n    height: 34px;\n    width: 34px;\n    /* display: inline-block; */\n    background: url('../../../assets/delete.png') center center;\n    background-size: contain;\n    float: right;\n    margin-right: 10px;\n    cursor: pointer;\n  }\n\n  .basic-pk-box {\n    border: 1px solid #dddddd;\n    width: 100%;\n    height: 300px;\n    padding: 10px;\n    position: relative;\n  }\n\n  .basic-pk-add {\n    border-top: 1px solid #dddddd;\n    width: calc(100% - 20px);\n    position: absolute;\n    bottom: 10px;\n    left: 10px;\n    padding-top: 10px;\n  }\n\n  .basic-pk-item {\n    width: 100%;\n    float: left;\n  }\n\n  .basic-pk-item span {\n    margin-right: 10px;\n  }\n\n  .basic-add-item {\n    display: inline-block;\n    width: 40%;\n  }\n\n  .basic-add-item input {\n    width: 80%;\n  }\n\n  .basic-pk-btns {\n    position: fixed;\n    bottom: 0;\n    width: calc(100% - 4rem);\n    height: 85px;\n    left: 4rem;\n    background: #FFFFFF;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    z-index: 1000;\n  }\n\n  .basic-pk-btns button:first-child {\n    float: left;\n  }\n\n  .basic-pk-btns :nth-child(2) {\n    float: right;\n  }\n\n  .basic-pk-btns :nth-child(3) {\n    float: right;\n    margin-right: 20px;\n  }\n\n  .error-input {\n    border-color: red;\n  }\n</style>\n\n"
  },
  {
    "path": "src/components/JsonWallet/Create/ConfirmInfo.vue",
    "content": "<template>\n  <div class=\"container json-confirm-container\">\n    <p><b>{{$t('createJsonWallet.labelN')}}: </b> {{label}}</p>\n    <p><b>{{$t('createJsonWallet.addressN')}}: </b> {{ address }}</p>\n    <p><b>{{$t('createJsonWallet.pubKeyN')}}: </b> {{publicKey}}</p>\n    <p><b>{{$t('createJsonWallet.signatureSchemeN')}}: </b> SHA256withECDSA </p>\n    <p><b>{{$t('createJsonWallet.priavteKeywif')}}: </b> {{wif}}</p>\n\n    <div class=\"backup-text\">\n      <p class=\"font-medium-black\">\n        <span></span>\n         <a-icon type=\"warning\" /> {{$t('createJsonWallet.backupWallet')}}</p>\n         <a-button type=\"primary\" @click=\"downloadWallet\">{{$t('createJsonWallet.download')}}</a-button>\n    </div>\n    <div class=\"confirm-btns\">\n      <div class=\"confirm-btn-container\">\n        <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{ $t('createJsonWallet.back') }}</a-button>\n        <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{ $t('createJsonWallet.next') }}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\n  import {mapState} from 'vuex'\n  import {Crypto, Wallet, Account} from 'ontology-ts-sdk'\n  import FileHelper from \"../../../core/fileHelper\"\n  import dbService from '../../../core/dbService'\n  import {WALLET_TYPE,DEFAULT_SCRYPT} from '../../../core/consts'\n  import en from '../../../lang/en'\n  import zh from '../../../lang/zh'\n\n  export default {\n    name: 'ConfirmInfo',\n    data() {\n      const langType = localStorage.getItem('user_lang') || 'en';\n      const lang = langType === 'en' ? en : zh;\n      return {\n        lang: lang,\n        processing: false\n      }\n    },\n    mounted() {\n      this.downloadWallet()\n    },\n    beforeDestroy() {\n      console.log('clear')\n      this.$store.commit('INIT_JSON_WALLET')\n    },\n    computed: {\n      ...mapState({\n        label: state => state.CreateJsonWallet.label,\n        account: state => state.CreateJsonWallet.account,\n        downloadContent: state => state.CreateJsonWallet.downloadContent,\n        address: state => state.CreateJsonWallet.address,\n        publicKey: state => state.CreateJsonWallet.publicKey,\n        wif: state => state.CreateJsonWallet.wif\n      })\n    },\n    methods: {\n      back() {\n        this.$store.commit('SUB_CREATE_JSON_STEP')\n      },\n      downloadWallet() {\n        const commonWallet = this.account\n        let wallet = Wallet.create(commonWallet.label || \"\")\n        console.log(wallet)\n        wallet.scrypt.n = 16384;\n        const account = Account.parseJsonObj(commonWallet)\n        wallet.addAccount(account)\n        FileHelper.downloadFile(wallet.toJsonObj(), commonWallet.label);\n      },\n      next() {\n        this.$store.dispatch('showLoadingModals')\n        //Download file\n        // FileHelper.downloadFile(this.downloadContent)\n\n        //save to db\n        const wallet = {\n          type : WALLET_TYPE.CommonWallet,\n          address: this.address,\n          wallet: this.account\n        }\n        const that = this;\n        // Add verification to make sure wallet data is right before saving\n        const pri = Crypto.PrivateKey.deserializeWIF(this.wif);\n        const pk = pri.getPublicKey();\n        const addTmp = Crypto.Address.fromPubKey(pk);\n        if (addTmp.toBase58() !== this.account.address) {\n          this.$message.error(this.$t('createJsonWallet.createFail'));\n          this.back();\n          return;\n        }\n        dbService.insert(wallet, function (err, newDoc) {\n          if (err) {\n            console.log(err)\n            that.$store.dispatch('hideLoadingModals')\n            that.$message.error('common.savedbFailed')\n            return;\n          }\n          // console.log(newDoc)\n          that.$store.dispatch('hideLoadingModals')\n          that.$store.commit('INIT_JSON_WALLET')\n          that.$message.success(that.$t('createJsonWallet.createSuccess'))\n          that.$router.push({name: 'Wallets'})\n        })\n      }\n    }\n  }\n</script>\n\n<style lang=\"scss\" scoped>\n  .json-confirm-container {\n    width: 36rem;\n    padding: 15px;\n    border:1px solid #dddddd;\n    p {\n        margin-bottom: 10px;\n        word-break: break-all;\n    }\n  }\n\n\n  .confirm-btns {\n    position: fixed;\n    bottom: 0;\n    width: calc(100% - 4rem);\n    height: 85px;\n    left: 4rem;\n    background: #FFFFFF;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    z-index: 1000;\n  }\n\n  .confirm-btn-container {\n    width: 540px;\n    margin: 20px auto;\n  }\n\n  .confirm-btn-container :last-child {\n    float: right;\n  }\n  .backup-text {\n    text-align: center;\n    p {\n        text-align: left;\n    }\n    /* padding: 20px; */\n    /* border: 1px solid #dddddd; */\n    font-size: 16px;\n  }\n  .backup-text p {\n    margin-bottom: 15px;\n    font-size:16px !important;\n  }\n\n</style>\n"
  },
  {
    "path": "src/components/JsonWallet/CreateJsonWallet.vue",
    "content": "<template>\n  <div>\n    <breadcrumb :current=\"$t('createJsonWallet.create')\" v-on:backEvent=\"back\"></breadcrumb>\n    <div class=\"shared-container\">\n      <a-steps :current=\"current\" class=\"create-steps\">\n        <a-step v-for=\"item in steps\" :key=\"item.title\"/>\n      </a-steps>\n      <div class=\"steps-content\">\n        <basic-info v-if=\"current === 0\"></basic-info>\n        <confirm-info v-if=\"current === 1\"></confirm-info>\n      </div>\n    </div>\n  </div>\n\n</template>\n\n<script>\n  import en from '../../lang/en'\n  import zh from '../../lang/zh'\n  import BasicInfo from './Create/BasicInfo'\n  import ConfirmInfo from './Create/ConfirmInfo'\n  import Breadcrumb from '../Breadcrumb'\n  import {mapState} from 'vuex';\n\n  export default {\n    name: 'CreateJsonWallet',\n    data() {\n      const langType = localStorage.getItem('user_lang') || 'en';\n      const lang = langType === 'en' ? en : zh;\n      return {\n        lang: lang,\n        steps: [{\n          title: lang.createJsonWallet.basicInfo,\n          content: 'First-content',\n        }, {\n          title: lang.createJsonWallet.confirmInfo,\n          content: 'Second-content',\n        }]\n      }\n    },\n    computed: {\n      ...mapState({\n        current: state => state.CreateJsonWallet.currentStep,\n      })\n    },\n    components: {\n      BasicInfo,\n      ConfirmInfo,\n      Breadcrumb\n    },\n    methods: {\n      back() {\n        this.$router.push({name: 'Wallets'})\n      }\n    }\n  }\n</script>\n\n<style scoped>\n  .shared-container {\n  }\n\n  .steps-content {\n  }\n\n  .steps-action {\n    margin-top: 24px;\n  }\n\n  .create-steps {\n    width: 520px;\n    height: 4rem;\n    margin: 2px auto;\n  }\n</style>\n"
  },
  {
    "path": "src/components/JsonWallet/Import/BasicInfo.vue",
    "content": "<style scoped>\n.json-import-container {\n  width: 48rem;\n  padding-bottom: 100px;\n}\n\n.import-json-nav-pills>li.nav-item {\n  width: 25%;\n  text-align: center;\n  height: 2rem;\n  margin-bottom: 30px;\n  font-family: AvenirNext-Medium;\n  font-size: 14px;\n}\n\n.import-json-nav-pills>li.nav-item>a {\n  color: black;\n}\n\n.import-json-nav-pills .nav-link:hover {\n  color: #196BD8;\n}\n\n.import-json-nav-pills .nav-link.active {\n  color: #196BD8;\n  background-color: transparent;\n  border-radius: 0;\n  border-bottom: #196BD8 solid 1px;\n}\n\n.upload-dat-file {\n  margin-top: 25px;\n  position: relative;\n  display: inline-block;\n  background: #FBE45A;\n  border: 1px solid #FBE45A;\n  padding: 4px 12px;\n  overflow: hidden;\n  color: black !important;\n  text-decoration: none;\n  text-indent: 0;\n  line-height: 1.5rem;\n  height: 2.13rem;\n}\n\n.upload-dat-file input {\n  background: #FBE45A;\n  border: 1px solid #FBE45A;\n  color: black !important;\n  ;\n  position: absolute;\n  font-size: 100px;\n  right: 0;\n  top: 0;\n  margin-top: 0;\n  opacity: 0;\n  line-height: 1.5rem;\n  height: 2.13rem;\n}\n\n.upload-dat-file input:hover,\n.upload-dat-file:hover {\n  background: #FBE45A;\n  border-color: black;\n  color: black !important;\n  ;\n  text-decoration: none;\n  cursor: pointer !important;\n  ;\n}\n\n.input-wif {\n  margin-top: 30px;\n}\n\n.input-password {\n  margin-top: 30px;\n}\n\n.input-repassword {\n  margin-top: 6px;\n}\n\n.import-json-mnemonic {\n  width: 100%;\n  resize: none;\n  margin-top: 30px;\n  padding: 12px 20px;\n  border: 1px solid #DFE2E9;\n}\n\ntextarea::-webkit-input-placeholder {\n  color: #C9CBCF;\n  font-family: AvenirNext-Regular;\n  font-size: 14px;\n}\n\n.basic-pk-btns {\n  position: fixed;\n  bottom: 0;\n  width: calc(100% - 4rem);\n  height: 85px;\n  left: 4rem;\n  background: #FFFFFF;\n  box-shadow: 0 -1px 6px 0 #F2F2F2;\n  z-index: 1000;\n}\n\n.basic-pk-btns button:first-child {\n  float: left;\n}\n\n.basic-pk-btns :nth-child(2) {\n  float: right;\n}\n\n.basic-pk-btns :nth-child(3) {\n  float: right;\n  margin-right: 20px;\n}\n\n.error-input {\n  border-color: red;\n}\n\n.nav-item a {\n  font-size: 14px !important;\n}\n\n.tip {\n  font-size: 14px;\n}\n</style>\n<template>\n  <div class=\"container json-import-container\">\n    <ul class=\"nav nav-pills import-json-nav-pills\" id=\"pills-tab\" role=\"tablist\">\n      <li class=\"nav-item\">\n        <a class=\"nav-link active\" id=\"import-json-wif-pills-tab\" data-toggle=\"pill\" href=\"#import-json-wif-pills\"\n          role=\"tab\" aria-controls=\"import-json-wif-pills\" aria-selected=\"true\" @click=\"activeTab('wif')\">{{\n            $t('createJsonWallet.priavteKeywif') }}</a>\n      </li>\n      <li class=\"nav-item\">\n        <a class=\"nav-link\" id=\"import-json-dat-pills-tab\" data-toggle=\"pill\" href=\"#import-json-dat-pills\" role=\"tab\"\n          aria-controls=\"import-json-dat-pills\" aria-selected=\"true\" @click=\"activeTab('dat')\">{{\n            $t('createJsonWallet.keystoreDat') }}</a>\n      </li>\n      <li class=\"nav-item\">\n        <a class=\"nav-link\" id=\"import-json-mnemonic-pills-tab\" data-toggle=\"pill\" href=\"#import-json-mnemonic-pills\"\n          role=\"tab\" aria-controls=\"import-json-mnemonic-pills\" aria-selected=\"false\" @click=\"activeTab('mnemonic')\">{{\n            $t('createJsonWallet.mnemonic') }}</a>\n      </li>\n      <li class=\"nav-item\">\n        <a class=\"nav-link\" id=\"import-json-private-key-pills-tab\" data-toggle=\"pill\"\n          href=\"#import-json-private-key-pills\" role=\"tab\" aria-controls=\"import-json-private-key-pills\"\n          aria-selected=\"true\" @click=\"activeTab('pk')\">{{ $t('createJsonWallet.privateKey64Hex') }}</a>\n      </li>\n    </ul>\n\n    <div class=\"tab-content\" id=\"pills-tabContent\">\n      <div class=\"tab-pane fade show active\" id=\"import-json-wif-pills\" role=\"tabpanel\"\n        aria-labelledby=\"import-json-wif-pills-tab\">\n        <a-input class=\"input\" :placeholder=\"$t('importJsonWallet.label')\" v-validate=\"{ required: true }\"\n          name=\"wifLabel\" :data-vv-as=\"$t('FormField.label')\" v-model=\"wifLabel\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('wifLabel')\">{{ errors.first('wifLabel') }}</span>\n\n        <a-input class=\"input input-wif\" v-validate=\"{ required: true }\" name=\"wif\" v-model=\"wif\"\n          :placeholder=\"$t('importJsonWallet.wifTip')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('wif')\">{{ errors.first('wif') }}</span>\n\n        <a-input type=\"password\" class=\"input input-password\" v-validate=\"{ required: true, min: 6 }\"\n          :data-vv-as=\"$t('FormField.password')\" name=\"wifPassword\" v-model=\"wifPassword\"\n          :placeholder=\"$t('importJsonWallet.setPassword')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('wifPassword')\">{{ errors.first('wifPassword') }}</span>\n        <a-input type=\"password\" class=\"input input-repassword\" v-validate=\"{ required: true, min: 6, is: wifPassword }\"\n          :data-vv-as=\"$t('FormField.passwordConfirmation')\" name=\"wifRePassword\" v-model=\"wifRePassword\"\n          :placeholder=\"$t('importJsonWallet.rePassword')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('wifRePassword')\">{{ errors.first('wifRePassword')\n          }}</span>\n      </div>\n      <div class=\"tab-pane fade\" id=\"import-json-private-key-pills\" role=\"tabpanel\"\n        aria-labelledby=\"import-json-private-key-pills-tab\">\n        <a-input class=\"input\" :placeholder=\"$t('importJsonWallet.label')\" v-model=\"pkLabel\"></a-input>\n        <a-input class=\"input input-wif\" v-validate=\"{ required: true, length: 64 }\"\n          :data-vv-as=\"$t('FormField.privateKey')\" name=\"pk\" v-model=\"pk\"\n          :placeholder=\"$t('importJsonWallet.privateKeyTip')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('pk')\">{{ errors.first('pk') }}</span>\n        <a-input type=\"password\" class=\"input input-password\" v-validate=\"{ required: true, min: 6 }\"\n          :data-vv-as=\"$t('FormField.password')\" name=\"pkPassword\" v-model=\"pkPassword\"\n          :placeholder=\"$t('importJsonWallet.setPassword')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('pkPassword')\">{{ errors.first('pkPassword') }}</span>\n        <a-input type=\"password\" class=\"input input-repassword\" v-validate=\"{ required: true, min: 6, is: pkPassword }\"\n          :data-vv-as=\"$t('FormField.passwordConfirmation')\" name=\"pkRePassword\" v-model=\"pkRePassword\"\n          :placeholder=\"$t('createJsonWallet.rePassword')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('pkRePassword')\">{{ errors.first('pkRePassword')\n          }}</span>\n      </div>\n\n      <div class=\"tab-pane fade\" id=\"import-json-dat-pills\" role=\"tabpanel\" aria-labelledby=\"import-json-dat-pills-tab\">\n\n        <a class=\"upload-dat-file\">{{ datPath }}\n          <input type=\"file\" @change=\"onFileChange\" id=\"datFile\">\n        </a>\n\n        <!-- <p>\n          <a-icon type=\"info-circle-o\" class=\"redeem-info-icon\" />\n          <span class=\"tip\">{{$t('importJsonWallet.importFirstDefault')}}</span>\n        </p> -->\n\n        <div v-show=\"datWallet?.accounts?.length > 0\">\n          <div v-for=\"(account, index) in datWallet.accounts\" :key=\"account.address\" style=\"margin-top: 20px;\">\n            <a-space direction=\"vertical\" style=\"width: 100%\">\n              <span>Address: {{ account.address }}</span>\n              <a-input class=\"input\" :placeholder=\"$t('importJsonWallet.label')\"\n                @change=\"(e) => datLabelChange(e, index)\" name=\"datLabel\"></a-input>\n              <a-input type=\"password\" class=\"input\" name=\"datPassword\" @change=\"(e) => datPasswordChange(e, index)\"\n                :placeholder=\"$t('importJsonWallet.datImportPassword')\"></a-input>\n            </a-space>\n          </div>\n\n        </div>\n\n      </div>\n\n      <div class=\"tab-pane fade\" id=\"import-json-mnemonic-pills\" role=\"tabpanel\"\n        aria-labelledby=\"import-json-mnemonic-pills-tab\">\n        <a-input class=\"input\" :placeholder=\"$t('importJsonWallet.label')\" v-model=\"mnemonicLabel\"></a-input>\n\n        <textarea class=\"import-json-mnemonic\" id=\"import-json-mnemonic\" rows=\"6\" v-validate=\"{ required: true }\"\n          :data-vv-as=\"$t('FormField.mnemonic')\" name=\"mnemonic\" :placeholder=\"$t('importJsonWallet.mnemonic')\"\n          v-model=\"mnemonic\"></textarea>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('mnemonic')\">{{ errors.first('mnemonic') }}</span>\n\n        <a-input type=\"password\" class=\"input input-password\" v-validate=\"{ required: true, min: 6 }\"\n          :data-vv-as=\"$t('FormField.password')\" name=\"mnemonicPassword\" v-model=\"mnemonicPassword\"\n          :placeholder=\"$t('importJsonWallet.setPassword')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('mnemonicPassword')\">{{ errors.first('mnemonicPassword')\n          }}</span>\n        <a-input type=\"password\" class=\"input input-repassword\"\n          v-validate=\"{ required: true, min: 6, is: mnemonicPassword }\"\n          :data-vv-as=\"$t('FormField.passwordConfirmation')\" name=\"mnemonicRePassword\" v-model=\"mnemonicRePassword\"\n          :placeholder=\"$t('importJsonWallet.rePassword')\"></a-input>\n        <span class=\"v-validate-span-errors\" v-show=\"errors.has('mnemonicRePassword')\">{{\n          errors.first('mnemonicRePassword') }}</span>\n      </div>\n    </div>\n    <a-modal :title=\"$t('importJsonWallet.confirmImport')\" :visible=\"confirmModal\" @ok=\"handleConfirmOk\"\n      @cancel=\"handleConfirmCancel\">\n      <div>\n        <p class=\"font-medium\">\n          {{ $t('importJsonWallet.confirmImportExist') }}\n        </p>\n      </div>\n    </a-modal>\n\n    <div class=\"basic-pk-btns\">\n      <div class=\"btn-container\">\n        <a-button type=\"default\" @click=\"cancel\" class=\"btn-cancel\">{{ $t('importJsonWallet.cancel') }}</a-button>\n        <a-button type=\"primary\" @click=\"next\" class=\"btn-next\">{{ $t('importJsonWallet.next') }}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { mapState } from 'vuex'\nimport { Wallet, Account, Crypto } from \"ontology-ts-sdk\"\nimport FileHelper from \"../../../core/fileHelper\"\nimport dbService from '../../../core/dbService'\nimport { DEFAULT_SCRYPT } from '../../../core/consts'\n// import $ from 'jquery'\nimport { isHexString, convertScryptParams } from '../../../core/utils'\n\nexport default {\n  name: 'BasicInfo',\n  data() {\n    return {\n      tabName: 'wif', // dat | pk | wif | mnemonic\n\n      pk: '',\n      pkLabel: '',\n      pkPassword: '',\n      pkRePassword: '',\n\n      datPath: this.$t('importJsonWallet.datFile'),\n      dat: '',\n      datWallet: [],\n      datLabel: [],\n      datPassword: [],\n\n      wif: '',\n      wifLabel: '',\n      wifPassword: '',\n      wifRePassword: '',\n\n      mnemonic: '',\n      mnemonicLabel: '',\n      mnemonicPassword: '',\n      mnemonicRePassword: '',\n      mnemonicAccount: '',\n      confirmModal: false,\n      updatingWallet: ''\n    }\n  },\n\n  beforeDestroy() {\n    console.log('clear')\n  },\n  methods: {\n    activeTab(tabName) {\n      this.tabName = tabName\n    },\n    next() {\n      if (this.tabName === 'pk') {\n        this.$validator.validateAll({\n          pk: this.pk,\n          pkPassword: this.pkPassword,\n          pkRePassword: this.pkRePassword\n        }).then(result => {\n          console.log(result)\n          if (result) {\n            this.$store.dispatch('showLoadingModals')\n            this.importAccountForPK()\n          }\n        })\n      } else if (this.tabName === 'dat') {\n        // this.$validator.validateAll({\n        //   datPassword: this.datPassword,\n        //   datLabel: this.datLabel\n        // }).then(result => {\n        if (!this.dat) {\n          this.$message.error(this.$t('importJsonWallet.invalidDatFile'))\n          return;\n        }\n        // if (result) {\n        this.$store.dispatch('showLoadingModals')\n        this.importAccountForDat()\n        // }\n        // })\n      } else if (this.tabName === 'wif') {\n        this.$validator.validateAll({\n          wifLabel: this.wifLabel,\n          wif: this.wif,\n          wifPassword: this.wifPassword,\n          wifRePassword: this.wifRePassword\n        }).then(result => {\n          if (result) {\n            this.$store.dispatch('showLoadingModals')\n            this.importAccountForWif()\n          }\n        })\n      } else {\n        this.$validator.validateAll({\n          mnemonic: this.mnemonic,\n          mnemonicPassword: this.mnemonicPassword,\n          mnemonicRePassword: this.mnemonicRePassword\n        }).then(result => {\n          if (result) {\n            this.$store.dispatch('showLoadingModals')\n            this.importAccountForMnemonic()\n          }\n        })\n      }\n    },\n    importAccountForPK() {\n      let body = {\n        label: this.pkLabel,\n        privateKey: new Crypto.PrivateKey(this.pk),\n        password: this.pkPassword\n      }\n      if (!isHexString(this.pk)) {\n        this.$message.error(this.$t('importJsonWallet.invalidPrivateKey'))\n        this.$store.dispatch('hideLoadingModals')\n        return;\n      }\n      this.$store.dispatch('createJsonWalletWithPrivateKey', body).then(res => {\n        this.saveToDb(res)\n      })\n    },\n    onFileChange() {\n      // Custom upload button copywriting.\n      // let uploadFile = $(\"#datFile\").val();\n      // $(\".fileerrorTip\").html(\"\").hide();\n      let uploadFile = document.getElementById(\"datFile\").value;\n      let arr = uploadFile.split('\\\\');\n      let fileName = arr[arr.length - 1];\n      let files = document.getElementById(\"datFile\").files\n      this.dat = files[0]\n      console.log('this.dat', this.dat);\n      if (!this.dat) {\n        return\n      }\n      this.datPath = this.$t('importJsonWallet.selectedDatFile') + fileName\n\n      FileHelper.readWalletFile(this.dat).then(res => {\n        console.log('res', res);\n        let wallet;\n        try {\n          wallet = JSON.parse(res)\n          console.log('wallet', wallet);\n          if (!wallet.scrypt || !wallet.accounts || wallet.accounts.length < 1) {\n            throw new Error();\n          }\n\n          let accounts = [];\n          for (const acct of wallet.accounts) {\n            if (acct && acct.key && acct.address && acct.salt) {\n              accounts.push(acct)\n            }\n          }\n          wallet.accounts = accounts\n          if (wallet.accounts.length < 1) {\n            throw new Error();\n          }\n          this.datWallet = wallet\n\n\n        } catch (err) {\n          console.log(err)\n          this.$store.dispatch('hideLoadingModals')\n          this.$message.error(this.$t('importJsonWallet.invalidDatFile'))\n          return;\n        }\n\n\n      })\n\n    },\n\n    datLabelChange(e, index) {\n      this.datLabel[index] = e.target.value\n    },\n    datPasswordChange(e, index) {\n      this.datPassword[index] = e.target.value\n    },\n\n    importAccountForDat() {\n      let successAmount = 0;\n      console.log('this.datWallet', this.datWallet);\n\n      this.datWallet.accounts.forEach((account, index) => {\n        if (!this.datPassword[index]) {\n          return\n        }\n        if (!this.datLabel[index]) {\n          return\n        }\n\n        try {\n          const enc = new Crypto.PrivateKey(account.key);\n          const address = new Crypto.Address(account.address)\n          let scrypt = convertScryptParams(this.datWallet.scrypt)\n          let pri;\n          pri = enc.decrypt(this.datPassword[index], address, account.salt, scrypt)\n          account.label = this.datLabel[index];\n          //Fix: 使导入的wallet的scrypt参数保持一致，都使用 n = 16384\n          if (this.datWallet.scrypt && this.datWallet.scrypt.n !== 16384) {\n            account = Account.create(pri, this.datPassword[index], this.datLabel[index], DEFAULT_SCRYPT)\n            account = account.toJsonObj();\n          }\n          this.saveToDb(account);\n        } catch (err) {\n          console.log(err)\n          return;\n        }\n        successAmount++\n\n\n      });\n      this.$store.dispatch('hideLoadingModals')\n      if(successAmount==0){\n        this.$message.error('Import failed.')\n        return\n      }\n      this.$message.success(`A total of ${ successAmount} addresses succeed to import.`)\n\n    },\n    importAccountForWif() {\n      let privateKey;\n      try {\n        privateKey = Crypto.PrivateKey.deserializeWIF(this.wif);\n      } catch (err) {\n        this.$message.error(this.$t('basicInfo.errWif'))\n        this.$store.dispatch('hideLoadingModals')\n        return;\n      }\n\n      let body = {\n        label: this.wifLabel,\n        privateKey: privateKey,\n        password: this.wifPassword\n      }\n      this.$store.dispatch('createJsonWalletWithPrivateKey', body).then(res => {\n        this.saveToDb(res)\n      })\n    },\n    importAccountForMnemonic() {\n      // 助记词导入\n      let account\n      try {\n        account = Account.importWithMnemonic(this.mnemonicLabel, this.mnemonic, this.mnemonicPassword, DEFAULT_SCRYPT)\n      } catch (err) {\n        this.$store.dispatch('hideLoadingModals')\n        this.$message.error(this.$t('basicInfo.InvalidMnemonic'))\n      }\n      this.mnemonicAccount = account.toJsonObj()\n      this.saveToDb(this.mnemonicAccount)\n    },\n    saveToDb(account) {\n      account.isDefault = true;\n      const that = this;\n      const wallet = {\n        type: 'CommonWallet',\n        address: account.address,\n        wallet: account\n      }\n      dbService.insert(wallet, function (err, newDoc) {\n        if (err) {\n          console.log(err)\n          // that.$message.warning('The wallet already exists in local.')\n          that.$store.dispatch('hideLoadingModals')\n          that.confirmModal = true;\n          that.updatingWallet = wallet;\n          return;\n        }\n        // console.log(newDoc)\n        that.$message.success(that.$t('importJsonWallet.success'))\n        that.$router.push({ name: 'Wallets' })\n      })\n    },\n    cancel() {\n      this.$router.push({ name: 'Wallets' })\n    },\n    handleConfirmOk() {\n      if (this.updatingWallet) {\n        dbService.update({ address: this.updatingWallet.address }, { $set: { wallet: this.updatingWallet.wallet } }, {},\n          (err, numReplaced) => {\n            if (err) {\n              this.$store.dispatch('hideLoadingModals')\n              this.$message.error(this.$t('importJsonWallet.saveDbFailed'))\n              return;\n            }\n            this.$message.success(this.$t('importJsonWallet.success'))\n            this.$router.push({ name: 'Wallets' })\n          })\n      }\n    },\n    handleConfirmCancel() {\n      this.confirmModal = false;\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/JsonWallet/ImportJsonWallet.vue",
    "content": "<template>\n  <div>\n    <breadcrumb :current=\"$t('importJsonWallet.create')\" v-on:backEvent=\"back\"></breadcrumb>\n    <div class=\"shared-container\">\n      <div class=\"steps-content\">\n        <basic-info></basic-info>\n      </div>\n    </div>\n  </div>\n\n</template>\n\n<script>\n  import en from '../../lang/en'\n  import zh from '../../lang/zh'\n  import BasicInfo from './Import/BasicInfo'\n  import Breadcrumb from '../Breadcrumb'\n  import {mapState} from 'vuex';\n\n  export default {\n    name: 'ImportJsonWallet',\n    data() {\n      const langType = localStorage.getItem('user_lang') || 'en';\n      const lang = langType === 'en' ? en : zh;\n      return {\n        lang: lang,\n        steps: [{\n          title: lang.importJsonWallet.basicInfo,\n          content: 'First-content',\n        }]\n      }\n    },\n    components: {\n      BasicInfo,\n      Breadcrumb\n    },\n    methods: {\n      back() {\n        this.$router.push({name: 'Wallets'})\n      }\n    }\n  }\n</script>\n"
  },
  {
    "path": "src/components/JsonWallet/View/Details.vue",
    "content": "<template>\n  <div class=\"common-detail-container\">\n    <div>\n      <div class=\"div-shared-wallet-sign\">\n        <span>{{ isCommonWallet ? $t('common.normalWallet') : $t('common.hardwareWallet') }}</span>\n        <p class=\"neo-compatile\" v-if=\"!isCommonWallet && wallet.neo\">{{$t('common.neoCompatible')}}</p>\n      </div>\n      <div class=\"div-wallet-name\" @click=\"toWalletHome(wallet)\">{{wallet.label}}</div>\n      <!--<img class=\"img-wallet-edit\" src=\"./../assets/edit.png\" alt=\"\">-->\n      <div class=\"div-wallet-address\">\n        <div>{{$t('common.walletAddress')}}:</div>\n        {{wallet.address}}\n      </div>\n    </div>\n    <div v-show=\"addressCopied\" class=\"copied-label\">Copied</div>\n    <img class=\"img-wallet-copy\" src=\"../../../assets/copy.png\" @click=\"copyAddress(wallet)\" alt=\"\">\n    <div class=\"common-topRight-btns\">\n      <span class=\"common-delete-icon\" @click=\"deleteWallet()\" v-if=\"!isCommonWallet\"></span>\n      <a-dropdown v-if=\"isCommonWallet\">\n        <a-menu slot=\"overlay\" >\n          <a-menu-item key=\"1\" @click=\"handleExportWallet()\">\n            <span >{{$t('common.exportDat')}}</span>\n          </a-menu-item>\n          <a-menu-item key=\"2\" @click=\"handleExportWIF()\">\n            <span  >{{$t('common.exportWIF')}}</span>\n          </a-menu-item>\n          <a-menu-item key=\"3\" @click=\"handleChangePassword()\">\n            <span  >{{$t('common.changePassword')}}</span>\n          </a-menu-item>\n          <a-menu-item key=\"4\" @click=\"deleteWallet()\">\n            <span  >{{$t('common.deleteWallet')}}</span>\n          </a-menu-item>\n        </a-menu>\n        <a-button style=\"margin-left: 8px\">\n          {{$t('common.more')}}<a-icon type=\"down\" />\n        </a-button>\n      </a-dropdown>\n    </div>\n\n    <a-modal\n        :title=\"modalTitle\"\n        :visible=\"passModal\"\n        @ok=\"handleValidatePassword\"\n        @cancel=\"handleCancel\">\n          <div>\n              <p class=\"font-medium\">\n                {{option==='TO_DELETE' ? $t('wallets.deleteingWallet') : '' }}\n                {{option === 'TO_EXPORT' ? $t('wallets.exportingWallet') : ''}}\n                {{option === 'EXPORT_WIF' ? $t('wallets.exportingWIF') : ''}}\n                 {{wallet.address}}</p>\n              <div v-if=\"isCommonWallet\">\n                <p>{{$t('common.enterWalletPassword')}}</p>\n                <a-input class=\"input\" v-model=\"password\" :plaecholder=\"$t('common.password')\" type=\"password\"></a-input>\n              </div>\n          </div>\n    </a-modal>\n\n    <a-modal\n        :title=\"$t('common.changePassword')\"\n        :visible=\"changePassModal\"\n        @ok=\"handleChangePassOk\"\n        @cancel=\"handleChangePassCancel\">\n          <div class=\"change-password-input\">\n            <div>\n              <a-input type=\"password\" class=\"input change-password\"\n               v-validate=\"{required: true ,min:6}\" name=\"oldPassword\" :data-vv-as=\"$t('FormField.oldPassword')\"\n               v-model=\"oldPassword\" :placeholder=\"$t('wallets.oldPassword')\"></a-input>\n              <span class=\"v-validate-span-errors\" v-show=\"errors.has('oldPassword')\">{{ errors.first('oldPassword') }}</span>\n            </div>\n\n            <div>\n              <a-input type=\"password\" class=\"input change-password\"\n               v-validate=\"{required: true ,min:6}\" name=\"newPassword\" :data-vv-as=\"$t('FormField.newPassword')\"\n               v-model=\"newPassword\" :placeholder=\"$t('wallets.newPassword')\"></a-input>\n              <span class=\"v-validate-span-errors\" v-show=\"errors.has('newPassword')\">{{ errors.first('newPassword') }}</span>\n            </div>\n\n            <div>\n              <a-input type=\"password\" class=\"input change-password\"\n                      v-validate=\"{required: true , min:6, is:newPassword}\" :data-vv-as=\"$t('FormField.newPasswordConfirmation')\" name=\"reNewPassword\"\n                      v-model=\"reNewPassword\" :placeholder=\"$t('wallets.reNewPassword')\"></a-input>\n              <span class=\"v-validate-span-errors\" v-show=\"errors.has('reNewPassword')\">{{ errors.first('reNewPassword') }}</span>\n            </div>\n\n          </div>\n    </a-modal>\n\n    <a-modal\n        :title=\"$t('common.changePassSuccess')\"\n        v-model=\"showChangePassTip\"\n        @ok=\"handleShowChangePassTipOk\"\n        >\n        <div class=\"change-pass-success\">\n          <p class=\"font-medium\"><a-icon type=\"warning\" /> {{$t('common.changePassSuccessTip')}}</p>\n          <a-button type=\"primary\" @click=\"exportWallet(wallet)\">{{$t('common.download')}}</a-button>\n        </div>\n    </a-modal>\n\n  </div>\n</template>\n\n<script>\n  import {Wallet, Account} from 'ontology-ts-sdk';\n  import FileHelper from \"../../../core/fileHelper\"\n  import {DEFAULT_SCRYPT} from '../../../core/consts'\n  import {Crypto} from 'ontology-ts-sdk'\n  import dbService from '../../../core/dbService'\n\texport default {\n    name: \"JsonWalletDetails\",\n    props: ['wallet'],\n    data() {\n      return {\n        addressCopied: false,\n        isCommonWallet: this.wallet.key ? true: false,\n        passModal: false,\n        password: '',\n        option: '',\n        oldPassword: '',\n        newPassword: '',\n        reNewPassword: '',\n        changePassModal: false,\n        showChangePassTip: false,\n        modalTitle: this.wallet.key ? this.$t('common.authentication') : this.$t('common.confirmation')\n      }\n    },\n    methods: {\n      toWalletHome(wallet) {\n        // if(this.isCommonWallet) {\n          sessionStorage.setItem('currentWallet', JSON.stringify(wallet))\n          this.$router.push({name: 'Dashboard'})\n        // } else {\n        //   sessionStorage.setItem('currentWallet', JSON.stringify(wallet))\n        //   this.$router.push({name: 'LoginLedger'})\n        // }\n\n      },\n      copyAddress(wallet) {\n        this.$copyText(wallet.address)\n        this.addressCopied = true\n        this.$nextTick(function () {\n          setInterval(this.addressCopiedDisabled, 3000);\n        })\n      },\n      addressCopiedDisabled() {\n        this.addressCopied = false\n      },\n\n      exportWallet(commonWallet) {\n        this.$store.dispatch('hideLoadingModals')\n        console.log(commonWallet)\n        let wallet = Wallet.create(commonWallet.label || \"\")\n        console.log(wallet)\n        wallet.scrypt.n = 16384;\n        const account = Account.parseJsonObj(commonWallet)\n        wallet.addAccount(account)\n        FileHelper.downloadFile(wallet.toJsonObj(), commonWallet.label);\n        this.showChangePassTip = false;\n      },\n      handleExportWallet() {\n        this.passModal = true;\n        this.option = 'TO_EXPORT'\n      },\n      deleteWallet() {\n        this.passModal = true;\n        this.option = 'TO_DELETE'\n      },\n      handleValidatePassword() {\n        if(!this.isCommonWallet) {\n          this.handleDelete();\n          return;\n        }\n        if(!this.password && this.isCommonWallet) {\n          this.$message.error(this.$t('common.enterWalletPassword'))\n          return;\n        }\n        this.$store.dispatch('showLoadingModals')\n        const enc = new Crypto.PrivateKey(this.wallet.key)\n        let pri;\n        try {\n          pri = enc.decrypt(this.password, new Crypto.Address(this.wallet.address), this.wallet.salt, DEFAULT_SCRYPT)\n        } catch (err) {\n          console.log(err);\n          this.$store.dispatch('hideLoadingModals')\n          this.$message.error(this.$t('common.pwdErr'))\n          return;\n        }\n        if(this.option === 'TO_DELETE') {\n          this.handleDelete();\n        } else if (this.option === 'TO_EXPORT') {\n          this.passModal = false;\n          this.exportWallet(this.wallet)\n        } else if (this.option === 'EXPORT_WIF') {\n          this.passModal = false;\n          this.$store.dispatch('hideLoadingModals')\n          const wif = pri.serializeWIF();\n          this.$success({\n            title: this.$t('wallets.exportedWIF'),\n            content: wif\n          });\n        }\n        this.password = '';\n        pri.key = '';\n      },\n      handleDelete() {\n        // remove from db\n        const that = this;\n        const type = this.isCommonWallet ? 'CommonWallet' : 'HardwareWallet'\n        const commitType = this.isCommonWallet ? 'DELETE_COMMON_WALLET' : 'DELETE_HARDWARE_WALLET'\n        dbService.remove({type:type, address: this.wallet.address}, {}, function(err, numRemoved) {\n          if(err) {\n            that.$store.dispatch('hideLoadingModals')\n            that.$message.error(that.$t('wallets.deleteFailed'));\n            return;\n          }\n           // remove from store\n          that.$store.commit(commitType, {address: that.wallet.address})\n          that.$store.dispatch('hideLoadingModals')\n          that.$message.success(that.$t('wallets.deleteSucceess'))\n          that.passModal = false;\n        })\n      },\n      handleCancel() {\n        this.passModal = false;\n        this.password = '';\n      },\n      handleExportWIF() {\n        this.passModal = true;\n        this.option = 'EXPORT_WIF'\n      },\n      handleChangePassword() {\n        this.changePassModal = true;\n      },\n      handleChangePassOk() {\n        this.$validator.validateAll().then(result => {\n          if(result) {\n            this.$store.dispatch('showLoadingModals').then( () => {\n            const enc = new Crypto.PrivateKey(this.wallet.key)\n            let pri;\n            try {\n              pri = enc.decrypt(this.oldPassword, new Crypto.Address(this.wallet.address), this.wallet.salt, DEFAULT_SCRYPT)\n            } catch (err) {\n              console.log(err);\n              this.$store.dispatch('hideLoadingModals')\n              this.$message.error(this.$t('common.pwdErr'))\n              return;\n            }\n            //save with new password\n            const saltHex = Buffer.from(this.wallet.salt, 'base64').toString('hex');\n            const address = new Crypto.Address(this.wallet.address)\n            const newEnc = pri.encrypt(this.newPassword, address, saltHex, DEFAULT_SCRYPT);\n            this.wallet.key = newEnc.key;\n            dbService.update(\n              {address: this.wallet.address},\n              {$set: {wallet: this.wallet}}, {},\n              (err, numReplaced) => {\n                if(err) {\n                  this.$store.dispatch('hideLoadingModals')\n                  this.$message.error(this.$t('importJsonWallet.saveDbFailed'))\n                  return;\n                }\n                this.$store.dispatch('hideLoadingModals')\n                this.changePassModal = false;\n                this.$message.success(this.$t('wallets.changePassSuccess'))\n                this.oldPassword = '';\n                this.newPassword = '';\n                this.reNewPassword = ''\n                this.showChangePassTip = true;\n            })\n            })\n\n          }\n        })\n      },\n      handleChangePassCancel() {\n        this.changePassModal = false;\n        this.oldPassword = '';\n        this.newPassword = '';\n        this.reNewPassword = ''\n      },\n      handleShowChangePassTipOk() {\n        this.showChangePassTip = false;\n      }\n    }\n  }\n</script>\n\n<style scoped>\n  .common-detail-container {\n\n  }\n  .div-shared-wallet-sign {\n    margin-top: 0.88rem;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #196BD8;\n    cursor: default;\n  }\n\n  .div-wallet-name {\n    margin-top: 1.75rem;\n    font-family: AvenirNext-Medium;\n    font-size: 18px;\n    color: #515457;\n    line-height: 24px;\n    word-wrap: break-word;\n    height:6rem;\n    cursor: pointer;\n  }\n\n  .img-wallet-edit {\n    position: absolute;\n    top: 4.13rem;\n    right: 1.41rem;\n  }\n\n  .div-wallet-address {\n    font-family: AvenirNext-Regular;\n    font-size: 14px;\n    color: #B2B2B3;\n    position:absolute;\n    bottom:10px;\n    cursor: default;\n  }\n\n  .img-wallet-copy {\n    position: absolute;\n    bottom:15px;\n    right: 1.29rem;\n  }\n\n  .copied-label {\n    position: absolute;\n    top: 9rem;\n    right: 2.69rem;\n    background-color: #8a9098;\n    border-radius: 2px;\n    padding: 3px 4px;\n    font-size: 10px;\n    font-weight: 100;\n    color: white;\n  }\n  .common-export-btn {\n    height: 34px;\n    width:78px;\n    background:#5EA2FF;\n    font-family: AvenirNext-Regular;\n    font-size: 16px;\n    color: #FFFFFF;\n    border: 1px solid #FFFFFF;\n    border-radius: 0;\n    position: absolute;\n    top: 0px;\n    right: 20px;\n  }\n  .common-topRight-btns {\n    position: absolute;\n    top: 10px;\n    right:20px;\n    text-align: right;\n  }\n  .common-delete-icon {\n    width:24px;\n    height: 24px;\n    display: inline-block;\n    cursor: pointer;\n    background:url('../../../assets/delete.png') center center;\n    background-repeat:no-repeat;\n\n  }\n  .common-download-icon {\n    width:24px;\n    height: 24px;\n    display: inline-block;\n    cursor: pointer;\n    background:url('../../../assets/download.png') center center no-repeat;\n  }\n  .change-password-input div{\n    margin-bottom: 15px;\n  }\n  .change-password-input :last-child {\n    margin:0;\n  }\n  .neo-compatile {\n    font-size:12px;\n    margin-top: 5px;\n    margin-bottom:0;\n    position:absolute;\n    color: #515457;\n  }\n  .change-pass-success button {\n    display: block;\n    margin:0 auto;\n  }\n</style>\n"
  },
  {
    "path": "src/components/LedgerWallet/Import/BasicInfo.vue",
    "content": "<template>\n  <div class=\"container ledger-import-container\">\n    <div>\n      <a-input class=\"input\" :placeholder=\"$t('importLedgerWallet.label')\" v-model=\"label\"></a-input>\n\n      <!-- <a-checkbox @change=\"onChangeNeo\" :checked=\"neo\" class=\"check-neo\">{{ $t('importLedgerWallet.neoCompatible')\n        }}</a-checkbox> -->\n    </div>\n    <div class=\"div-ledger-info\">\n      <div class=\"div-ledger-info-tit\">\n        <strong>{{ $t(\"ledgerWallet.info\") }}</strong>\n      </div>\n\n      <div v-show=\"!isAdvancedMode\">\n        <a-spin :spinning=\"isLoading\">\n          <div class=\"font-bold\" style=\"margin-bottom: 15px\">\n            {{ $t(\"ledgerWallet.selectAccount\") }}\n          </div>\n          <!-- <div class=\"ledger-status\">\n            <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n           <span class=\"font-medium\">{{ledgerStatus}} </span>\n          </div> -->\n          <div class=\"address-list\">\n            <a-row v-for=\"pk in publicKeyList\" :key=\"pk.acct\">\n              <!-- <a-col :span=\"24\"> -->\n              <a-checkbox v-if=\"pk\" :value=\"pk\" @change=\"selectAddress\" :checked=\"checkPkSelect(pk)\">\n                {{ `${pk.acct}. ${getAddressFromPubKey(pk.publicKey)}` }}\n              </a-checkbox>\n              <!-- </a-col> -->\n            </a-row>\n          </div>\n\n          <div class=\"paging-line\">\n            <div class=\"prev paging-item\" @click=\"prevPage\" :style=\"{ 'opacity': page === 1 && '0.6' || '1' }\">&lt;\n            </div>\n            <div class=\"page-number paging-item\">{{ page }}</div>\n            <div class=\"next paging-item\" @click=\"nextPage\">&gt;</div>\n          </div>\n        </a-spin>\n      </div>\n      <div v-show=\"isAdvancedMode\">\n        <div class=\"font-bold\" style=\"margin-bottom: 15px\">\n          {{ $t('ledgerWallet.specifyPath') }}\n        </div>\n\n        <a-radio-group v-model=\"neo\">\n          <a-radio :style=\"radioStyle\" :value=\"false\">\n            <span class=\"path\">44'/1024'/0'/0/</span>\n            <a-input-number :disabled=\"neo\" size=\"small\" style=\"width: 60px; margin-left: 10px\" :step=\"1\" :min=\"0\"\n              :precision=\"0\" v-model=\"notNeoPathParam\" placeholder=\"0\" @change=\"advancedModeInputChange\" />\n          </a-radio>\n          <a-radio :style=\"radioStyle\" :value=\"true\">\n            <span class=\"path\">44'/888'/0'/0/</span>\n            <a-input-number :disabled=\"!neo\" size=\"small\" style=\"width: 60px; margin-left: 10px\" :step=\"1\" :min=\"0\"\n              :precision=\"0\" v-model=\"neoPathParam\" placeholder=\"0\" @change=\"advancedModeInputChange\" />\n          </a-radio>\n        </a-radio-group>\n\n        <div><a-spin :spinning=\"advancedModeLoading\" /></div>\n        <div v-if=\"advancedModePublicKey\">{{ getAddressFromPubKey(advancedModePublicKey.publicKey) }}</div>\n      </div>\n    </div>\n\n    <div class=\"mode-line\">\n      <div class=\"mode-select\">\n        <span v-show=\"!isAdvancedMode\" @click=\"isAdvancedMode = !isAdvancedMode\">{{ $t('ledgerWallet.advancedMode')\n          }}</span>\n        <span v-show=\"isAdvancedMode\" @click=\"isAdvancedMode = !isAdvancedMode\">{{ $t('ledgerWallet.normalMode')\n          }}</span>\n      </div>\n    </div>\n\n    <div class=\"basic-pk-btns\">\n      <div class=\"btn-container\">\n        <a-button type=\"default\" @click=\"cancel\" class=\"btn-cancel\">{{\n          $t(\"importJsonWallet.cancel\")\n          }}</a-button>\n        <a-button type=\"primary\" @click=\"addWallet\" class=\"btn-next\" >{{\n          $t(\"importLedgerWallet.next\")\n          }}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { mapState } from \"vuex\";\nimport { Wallet, Account, Crypto } from \"ontology-ts-sdk\";\nimport dbService from \"../../../core/dbService\";\nimport { WALLET_TYPE } from \"../../../core/consts\";\nimport { getDeviceInfo, getPublicKey } from \"../../../core/ontLedger\";\nimport _ from \"lodash\";\n\nfunction toggleElement(array, element) {\n  // console.log('toggleElement', array, element);\n\n\n  const publicKeyArray = array.map(item => item.publicKey)\n  // const index = array.indexOf(element);\n  const index = publicKeyArray.indexOf(element.publicKey);\n  if (index === -1) {\n    array.push(element);\n  } else {\n    array.splice(index, 1);\n  }\n}\n\nexport default {\n  name: \"BasicInfo\",\n  created() {\n    this.debouncedGetPkForAdvancedMode = _.debounce(this.getPkForAdvancedMode, 500);\n  },\n  mounted: async function () {\n    // let that = this;\n    // await that.getDevice()\n    // this.intervalId = setInterval(async() => {\n    //   await that.getDevice()\n    // }, this.interval)\n    await this.getPublicKeyList();\n  },\n  // beforeDestroy() {\n  // clearInterval(this.intervalId)\n  // },\n  data() {\n    return {\n      intervalId: \"\",\n      interval: 3000,\n      label: \"\",\n      ledgerStatus: \"\",\n      neo: false,\n      device: null,\n      page: 1,\n      pageSize: 5,\n      selectPublicKeys: [],\n      publicKeyList: [],\n      isAdvancedMode: false,\n      isLoading: false,\n      radioStyle: {\n        display: \"block\",\n        height: \"30px\",\n        lineHeight: \"30px\",\n      },\n      notNeoPathParam: \"\",\n      neoPathParam: \"\",\n      advancedModeLoading: false,\n      advancedModePublicKey: null,\n    };\n  },\n  computed: {\n    addDisable() {\n      if (!this.label) {\n        return true;\n      }\n      if (this.isAdvancedMode === false) {\n        return this.selectPublicKeys.length === 0 ? true : false;\n      }\n      else {\n        return this.advancedModePublicKey === null ? true : false;\n      }\n    }\n  },\n  watch: {\n    neo: function (val) {\n      this.advancedModePublicKey = null;\n      this.notNeoPathParam = \"\"\n      this.neoPathParam = \"\"\n\n    }\n  },\n  methods: {\n    async addWallet() {\n      if(this.addDisable){\n        this.$message.warn(this.$t('ledgerWallet.pleaseSelectWallet'))\n        return;\n      }\n      // if(!this.label) {\n      //   this.$message.error(this.$t('ledgerWallet.labelEmpty'))\n      //   return;\n      // }\n      // if (!this.publicKey) {\n      //   this.$message.error(this.$t(\"ledgerWallet.deviceError\"));\n      //   return;\n      // }\n      // if (this.publicKey) {\n      //   const body = {\n      //     pk: this.publicKey,\n      //     neo: this.neo,\n      //   };\n      //   this.$store.dispatch(\"createLedgerWalletWithPk\", body).then((res) => {\n      //     if (res) {\n      //       this.saveToDb(res);\n      //     }\n      //   });\n      // }\n\n\n      console.log('this.advancedModePublicKey', this.advancedModePublicKey);\n      // if (!this.isAdvancedMode && this.selectPublicKeys.length === 0) {\n      //   this.$message.error('请选择地址')\n      //   return\n      // }\n      // if (this.isAdvancedMode && (!this.advancedModePublicKey)) {\n      //   this.$message.error('请选择地址')\n      //   return\n      // }\n\n      let list = this.isAdvancedMode ? [this.advancedModePublicKey] : this.selectPublicKeys;\n      list.sort((a, b) => a.acct - b.acct);\n\n      // Check if it has been imported.\n      dbService.find({ 'wallet.publicKey': { $in: list.map(item => item.publicKey) } }, (err, accounts) => {\n        if (err) {\n          console.log(err);\n          return;\n        }\n        if (accounts && accounts.length > 0) {\n          this.$message.warn(this.$t('ledgerWallet.alreadyImported'))\n        }\n      })\n\n      list.forEach(async (pk) => {\n        const body = {\n          pk: pk.publicKey,\n          neo: this.isAdvancedMode && this.neo,\n          acct: pk.acct\n        }\n        const res = await this.$store.dispatch(\"createLedgerWalletWithPk\", body)\n        console.log('createLedgerWalletWithPk', res);\n\n        if (res) {\n          this.saveToDb(res);\n        }\n      })\n      this.$router.push({ name: \"Wallets\" });\n    },\n\n    // getDevice() {\n    //   getDeviceInfo().then(res => {\n    //     console.log('device' ,res)\n    //     this.device = res;\n    //     this.getPublicKey()\n    //   }).catch(err => {\n    //     console.log(err)\n    //     if (err === 'NOT_FOUND') {\n    //       this.ledgerStatus = this.$t('common.ledgerNotOpen')\n    //     } else if (err === 'NOT_SUPPORT') {\n    //       this.ledgerStatus = this.$t('common.ledgerNotSupported')\n    //     } else {\n    //       this.ledgerStatus = this.$t('common.pluginDevice')\n    //     }\n    //   })\n    // },\n    // async getDevice() {\n    //   const res = await getDeviceInfo();\n    //   console.log('device', res)\n    //   this.device = res;\n    //   return res\n    // },\n    async getPublicKeyForLedger(acctNum) {\n      // if(!this.device){\n      //   throw new Error('device not found')\n      // }\n\n      // const acctNum = 0;\n      // getPublicKey(acctNum, this.neo).then(res => {\n      // console.log('pk info: ' + res);\n      // this.publicKey = res\n      // this.ledgerStatus = this.$t('common.readyToImport')\n      // this.next();\n      // }).catch(err => {\n      // this.ledgerStatus = err.message\n      // })\n      console.log(\"acctNum\", acctNum, this.neo);\n      const pk = await getPublicKey(acctNum, this.isAdvancedMode ? this.neo : false);\n      console.log(\"pk\", pk);\n      return pk;\n    },\n    async getPublicKeyList() {\n      this.isLoading = true;\n      const pkArr = [];\n      try {\n        for (let i = 0; i < this.pageSize; i++) {\n          const acctNum = (this.page - 1) * this.pageSize + i;\n          const pk = await this.getPublicKeyForLedger(\n            acctNum\n          );\n          pkArr.push({\n            publicKey: pk,\n            acct: acctNum\n          });\n        }\n        this.publicKeyList = pkArr;\n        console.log(\"this.publicKeyList\", this.publicKeyList);\n        this.isLoading = false;\n      } catch (e) {\n        console.log(e);\n        this.isLoading = false;\n      }\n\n    },\n    checkPkSelect(pk) {\n      // return this.selectPublicKeys.includes(pk);\n      return this.selectPublicKeys.map(item => item.acct).includes(pk.acct)\n    },\n\n    saveToDb(account) {\n      account.label = `${this.label}${account.neo ? '-Compatible NEO' : ''}-${account.acct}`;\n      const that = this;\n      const wallet = {\n        type: WALLET_TYPE.HardwareWallet,\n        address: account.address,\n        wallet: account,\n      };\n\n      dbService.find({ address: account.address }, (err, accounts) => {\n        if (err) {\n          console.log(err);\n          return;\n        }\n        if (accounts && accounts.length > 0) {\n          // this.$message.warn(this.$t('ledgerWallet.alreadyImported'))\n          // dbService.update(\n          //   { address: account.address },\n          //   { $set: { wallet: account } },\n          //   {},\n          //   (err, replaceDoc) => {\n          //     if (err) {\n          //       console.log(err);\n          //       return;\n          //     }\n          //   }\n          // );\n        } else {\n          dbService.insert(wallet, function (err, newDoc) {\n            if (err) {\n              console.log(err);\n            }\n          });\n        }\n      });\n\n      sessionStorage.setItem(\"currentWallet\", JSON.stringify(account));\n      // that.$router.push({ name: \"Dashboard\" });\n    },\n    cancel() {\n      this.$router.push({ name: \"Wallets\" });\n    },\n    // onChangeNeo() {\n    // this.neo = !this.neo;\n    // this.getPublicKey()\n    // },\n    selectAddress(e) {\n      console.log('selectAddress', e);\n      const pk = e.target.value;\n      toggleElement(this.selectPublicKeys, pk);\n      console.log('this.selectPublicKeys', this.selectPublicKeys);\n\n    },\n    getAddressFromPubKey(pk) {\n      if (!pk) return \"\";\n      return Crypto.Address.fromPubKey(new Crypto.PublicKey(pk)).toBase58();\n    },\n    prevPage() {\n      if (this.page === 1) return;\n      this.page--;\n      this.publicKeyList = [];\n      this.getPublicKeyList();\n    },\n    nextPage() {\n      this.page++;\n      this.publicKeyList = [];\n      this.getPublicKeyList();\n    },\n    async getPkForAdvancedMode() {\n      console.log('getPkForAdvancedMode');\n\n      try {\n        this.advancedModeLoading = true;\n        const pk = await this.getPublicKeyForLedger(this.neo ? this.neoPathParam : this.notNeoPathParam)\n        this.advancedModePublicKey = {\n          publicKey: pk,\n          acct: this.neo ? this.neoPathParam : this.notNeoPathParam\n        }\n        this.advancedModeLoading = false;\n      } catch (error) {\n        console.log(error);\n        this.advancedModeLoading = false;\n      }\n\n\n    },\n    advancedModeInputChange() {\n      this.advancedModePublicKey = null;\n      this.debouncedGetPkForAdvancedMode()\n    }\n  },\n};\n</script>\n\n<style scoped>\n.ledger-import-container {\n  width: 36rem;\n}\n\n.div-ledger-info {\n  border: 1px solid #dfe2e9;\n  margin-top: 15px;\n  padding: 10px;\n}\n\n.div-ledger-info-tit {\n  border-bottom: 1px solid #dfe2e9;\n  padding-bottom: 10px;\n  margin-bottom: 10px;\n}\n\n.basic-pk-btns {\n  position: fixed;\n  bottom: 0;\n  width: calc(100% - 4rem);\n  height: 85px;\n  left: 4rem;\n  background: #ffffff;\n  box-shadow: 0 -1px 6px 0 #f2f2f2;\n  z-index: 1000;\n}\n\n.basic-pk-btns button:first-child {\n  float: left;\n}\n\n.basic-pk-btns :nth-child(2) {\n  float: right;\n}\n\n.basic-pk-btns :nth-child(3) {\n  float: right;\n  margin-right: 20px;\n}\n\n.error-input {\n  border-color: red;\n}\n\n.check-neo {\n  margin-top: 10px;\n  font-family: \"AvenirNext-Medium\";\n  color: #000000;\n  font-size: 13px;\n}\n\n.paging-line {\n  margin-top: 10px;\n  display: flex;\n  align-items: center;\n  justify-content: flex-end;\n}\n\n.paging-item {\n  height: 26px;\n  width: 26px;\n  border: 1px solid #555252;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  border-radius: 4px;\n  cursor: pointer;\n}\n\n.paging-item+.paging-item {\n  margin-left: 10px;\n}\n\n.path {\n  display: inline-block;\n  width: 86px;\n}\n\n.mode-line {\n  margin-top: 20px;\n  display: flex;\n  justify-content: flex-end;\n}\n\n.mode-line .mode-select {\n  text-decoration: underline;\n  cursor: pointer;\n  color: #909090;\n  font-size: 14px;\n}\n</style>\n"
  },
  {
    "path": "src/components/LedgerWallet/Import/ConnectLedger.vue",
    "content": "<template>\n  <div class=\"div-ledger-info\">\n    <div class=\"div-ledger-info-tit\">\n      <strong>{{ $t(\"ledgerWallet.info\") }}</strong>\n    </div>\n\n    <div class=\"font-bold\" style=\"margin-bottom: 15px\">\n      {{ $t(\"ledgerWallet.connectApp\") }}\n    </div>\n\n    <div class=\"ledger-status\">\n      <p class=\"font-medium-black\">{{ $t(\"ledgerWallet.status\") }}:</p>\n      <p v-if=\"ledgerStatus\">{{ ledgerStatus }}</p>\n\n    </div>\n\n    <div class=\"basic-pk-btns\">\n      <div class=\"btn-container\">\n        <a-button type=\"default\" @click=\"cancel\" class=\"btn-cancel\">{{\n          $t(\"importJsonWallet.cancel\")\n          }}</a-button>\n        <a-button type=\"primary\" @click=\"connect\" class=\"btn-next\"\n          :disabled=\"!ledgerStatus || !publicKey\">{{ $t(\"importLedgerWallet.next\") }}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { getDeviceInfo, getPublicKey } from \"../../../core/ontLedger\";\nimport { mapState } from \"vuex\";\n\nexport default {\n  data() {\n    return {\n      isLedgerConnected: false,\n      isOpenApp: false,\n    };\n  },\n  computed: {\n    ...mapState({\n      ledgerStatus: (state) => state.LedgerConnector.ledgerStatus,\n      publicKey: (state) => state.LedgerConnector.publicKey,\n    }),\n  },\n  methods: {\n    connect() {\n      this.$emit(\"next\");\n    },\n    cancel() {\n      this.$router.push({ name: \"Wallets\" });\n    },\n  },\n  async mounted() {\n    await this.$store.dispatch(\"getLedgerStatus\");\n  },\n  beforeDestroy() {\n    this.$store.dispatch(\"stopGetLedgerStatus\");\n  },\n  emit: [\"next\"],\n};\n</script>\n\n<style scoped>\n.div-ledger-info {\n  border: 1px solid #dfe2e9;\n  margin-top: 15px;\n  padding: 10px;\n}\n\n.div-ledger-info-tit {\n  border-bottom: 1px solid #dfe2e9;\n  padding-bottom: 10px;\n  margin-bottom: 10px;\n}\n\n.basic-pk-btns {\n  position: fixed;\n  bottom: 0;\n  width: calc(100% - 4rem);\n  height: 85px;\n  left: 4rem;\n  background: #ffffff;\n  box-shadow: 0 -1px 6px 0 #f2f2f2;\n  z-index: 1000;\n}\n</style>\n"
  },
  {
    "path": "src/components/LedgerWallet/ImportLedgerWallet.vue",
    "content": "<template>\n  <div>\n    <breadcrumb\n      :current=\"$t('importLedgerWallet.import')\"\n      v-on:backEvent=\"back\"\n    ></breadcrumb>\n    <div class=\"shared-container\">\n      <div class=\"steps-content\">\n        <ConnectLedger v-if=\"step===1\" @next=\"step=2\"></ConnectLedger>\n        <basic-info v-if=\"step===2\"></basic-info>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport en from \"../../lang/en\";\nimport zh from \"../../lang/zh\";\nimport BasicInfo from \"./Import/BasicInfo\";\nimport Breadcrumb from \"../Breadcrumb\";\nimport { mapState } from \"vuex\";\nimport ConnectLedger from \"./Import/ConnectLedger\";\n\nexport default {\n  name: \"ImportLedgerWallet\",\n  data() {\n    // const langType = localStorage.getItem('user_lang') || 'en';\n    // const lang = langType === 'en' ? en : zh;\n    return {\n      // lang: lang,\n      // steps: [{\n      //   title: lang.importJsonWallet.basicInfo,\n      //   content: 'First-content',\n      // }]\n      step: 1,\n    };\n  },\n  components: {\n    BasicInfo,\n    Breadcrumb,\n    ConnectLedger,\n  },\n  methods: {\n    back() {\n      this.$router.push({ name: \"Wallets\" });\n    },\n  },\n};\n</script>\n"
  },
  {
    "path": "src/components/LedgerWallet/LoginLedger.vue",
    "content": "<template>\n  <div id=\"wrapper\">\n    <main>\n      <div class=\"left-side\">\n        <router-link to=\"Wallets\" class=\"backBtn\">\n          Back\n        </router-link>\n        <div class=\"doc\">\n          <div class=\"title\">Login with Ledger</div>\n          <p class=\"font-medium\" >{{$t('ledgerWallet.connectApp')}}</p>\n            <p>\n                <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                <span class=\"font-medium\">{{ledgerStatus}}</span>\n            </p>\n        </div>\n      </div>\n    </main>\n  </div>\n</template>\n\n<script>\n  import {getDeviceInfo, getPublicKey} from '../../core/ontLedger'\n  const interval = 3000;\n  export default {\n    name: 'LoginLedger',\n    mounted: function () {\n      var that = this;\n      this.getDevice()\n      this.intervalId = setInterval(() => {\n        that.getDevice()\n      }, interval)\n    },\n    beforeDestroy: function () {\n      clearInterval(this.intervalId);\n    },\n    data() {\n      const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'));\n      return {\n        intervalId: 0,\n        ledgerStatus: '',\n        device: null,\n        publicKey: '',\n        currentWallet\n      }\n    },\n    methods: {\n      open(link) {\n        this.$electron.shell.openExternal(link)\n      },\n      goBack() {\n        this.$router.push({name: 'Wallets'})\n      },\n      getDevice() {\n        getDeviceInfo().then(res => {\n          console.log('device: ' + res)\n          this.device = res;\n          this.getPublicKey()\n        }).catch(err => {\n          console.log(err)\n          if (err === 'NOT_FOUND') {\n            this.ledgerStatus = this.$t('common.ledgerNotOpen')\n          } else if (err === 'NOT_SUPPORT') {\n            this.ledgerStatus = this.$t('common.ledgerNotSupported')\n          } else {\n            this.ledgerStatus = this.$t('common.pluginDevice')\n          }\n        })\n      },\n      getPublicKey() {\n        const acctNum = 0;\n        const neo = this.currentWallet.neo;\n        getPublicKey(acctNum, neo).then(res => {\n          console.log('pk info: ' + res);\n          this.publicKey = res;\n          this.ledgerStatus = this.$t('common.readyToLogin')\n          this.login();\n        }).catch(err => {\n          this.ledgerStatus = err.message\n        })\n      },\n      login() {\n        if (!this.device || !this.publicKey) {\n          console.log('no device.')\n          return;\n        }\n        this.$store.dispatch('loginWithLedger', this.publicKey).then(res => {\n          if (res) {\n            this.$router.push({name: 'Dashboard'})\n          } else {\n            this.ledgerStatus = this.$t('common.invalidLedger')\n          }\n        });\n      }\n    }\n  }\n</script>\n\n<style>\n  @import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');\n\n  * {\n    box-sizing: border-box;\n    margin: 0;\n    padding: 0;\n  }\n\n  body {\n    font-family: 'Source Sans Pro', sans-serif;\n  }\n\n  #wrapper {\n    /* background: radial-gradient(\n      ellipse at top left,\n      rgba(255, 255, 255, 1) 40%,\n      rgba(229, 229, 229, .9) 100%\n    ); */\n    height: 100vh;\n    padding: 60px 80px;\n    /* width: 100vw; */\n  }\n\n  #logo {\n    height: auto;\n    margin-bottom: 20px;\n    width: 420px;\n  }\n\n  main {\n    display: flex;\n    justify-content: space-between;\n  }\n\n  main > div {\n  }\n\n  .left-side {\n    display: flex;\n    flex-direction: column;\n    margin-top: 80px;\n  }\n\n  .welcome {\n    color: #555;\n    font-size: 23px;\n    margin-bottom: 10px;\n  }\n\n  .title {\n    color: #2c3e50;\n    font-size: 20px;\n    font-weight: bold;\n    margin-bottom: 15px;\n  }\n\n  .title.alt {\n    font-size: 18px;\n    margin-bottom: 10px;\n  }\n\n  .doc p {\n    color: black;\n    margin-bottom: 10px;\n  }\n\n  .doc button {\n    font-size: 16px;\n    cursor: pointer;\n    outline: none;\n    padding: 8px 20px;\n    border-radius: 0;\n    min-width: 120px;\n    display: inline-block;\n    color: #fff;\n    background-color: #4fc08d;\n    transition: all 0.15s ease;\n    box-sizing: border-box;\n    border: 1px solid #4fc08d;\n  }\n\n  .backBtn {\n    font-size: 16px;\n  }\n</style>\n"
  },
  {
    "path": "src/components/Modals/Loading.vue",
    "content": "<template>\n<div>\n  <transition name=\"fade\">\n    <!-- transition seems not working -->\n  <div v-if=\"showLoading\">\n        <a-spin size=\"large\" tip=\"Loading...\" class=\"modal-dialog\">\n          <div class=\"spin-content\"></div>\n        </a-spin>\n        <div class=\"modal-backdrop\"></div>\n      \n    </div>\n  </transition>\n  </div>\n  <!-- <div class=\"modal fade\" aria-hidden=\"true\" data-backdrop=\"static\" id=\"loadingModal\" v-if=\"showLoading\">\n    <div class=\"modal-dialog\" role=\"document\">\n      <div class=\"div-loading\">\n        <a-spin size=\"large\" tip=\"Loading...\">\n          <div class=\"spin-content\"></div>\n        </a-spin>\n      </div>\n    </div>\n  </div> -->\n</template>\n\n<script>\nimport {mapState} from 'vuex'\n  export default {\n    name: \"loading-modals\",\n    computed: {\n      ...mapState({\n        showLoading: state => state.LoadingModal.showLoading\n      })\n    }\n  }\n  /**\n   * 【 Usage 】\n   *\n   * Start:\n   * this.$store.dispatch('showLoadingModals')\n   *\n   * Automatic end:\n   * Routing changes, automatically hidden.\n   *\n   * End of the manual:\n   * this.$store.dispatch('hideLoadingModals')\n   */\n</script>\n\n<style scoped>\n.fade-enter-active, .fade-leave-active {\n    transition: opacity .5s;\n    opacity: 1;\n}\n.fade-enter, .fade-leave-to /* .fade-leave-active, 2.1.8 版本以下 */ {\n    opacity: 0\n}\n  .modal-dialog {\n    -webkit-transform: translate(0, -50%);\n    -ms-transform: translate(0, -50%);\n    -o-transform: translate(0, -50%);\n    transform: translate(0, -50%);\n  }\n\n  .modal-dialog {\n    position: absolute;\n    width: auto;\n    margin: 0 auto;\n    left: 0;\n    right: 0;\n    top: 40%;\n    z-index: 1050;\n  }\n  .modal-backdrop {\n      position: fixed;\n      top: 0;\n      right: 0;\n      bottom: 0;\n      left: 0;\n      z-index: 1040;\n      background-color: #000;\n      opacity: .5;\n  }\n</style>\n"
  },
  {
    "path": "src/components/Modals/SetPath.vue",
    "content": "<template>\n  <div class=\"modal modal_wapper fade\" id=\"setPathModal\" v-if=\"value\">\n    <div class=\"modal-dialog\" role=\"document\">\n      <div class=\"modal-content\">\n        <div class=\"modal-title text-center\">{{ $t('SetPaths.name') }}</div>\n        <div class=\"modal-header\"></div>\n\n        <div class=\"modal-body\">{{ $t('SetPaths.tips') }}</div>\n\n        <div class=\"modal-footer text-center\">\n          <!--<button class=\"btn btn-skip\" data-dismiss=\"modal\" aria-label=\"Close\">{{ $t('SetPaths.close') }}</button>-->\n          <button class=\"btn btn-save-path\" @click=\"setSavePath\">{{ $t('SetPaths.enter') }}</button>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\n  // import $ from 'jquery'\n  import {mapState} from 'vuex'\n  import { validateKeystorePath } from '../../core/utils'\n\n  const {dialog} = require('@electron/remote');\n\n  export default {\n    name: \"set-path-modal\",\n    data() {\n      return {}\n    },\n    props: ['value'],\n    emits: ['input'],\n    methods: {\n      setSavePath() {\n        dialog.showOpenDialog({properties: ['openDirectory', 'createDirectory']}).then(({filePaths}) => {\n          if (filePaths[0] === undefined) {\n            // alert('You did not set the path')\n            this.$message.warning(this.$t('setting.notSetPath'))\n            return;\n          }\n          if (!validateKeystorePath(filePaths[0])) {\n            this.$message.warning(this.$t('setting.notInstallationPath'))\n            return;\n          }\n          localStorage.setItem('savePath', filePaths[0])\n          localStorage.setItem('isSavePath', 'true')\n          window.location.reload();//reset dbService\n          this.$emit('input', false)\n          // $(\"#setPathModal\").modal(\"hide\")\n        })\n      }\n    }\n  }\n</script>\n\n<style scoped>\n  .modal-dialog {\n    -webkit-transform: translate(0, -50%);\n    -ms-transform: translate(0, -50%);\n    -o-transform: translate(0, -50%);\n    transform: translate(0, -50%);\n  }\n\n  .modal-dialog {\n    position: absolute;\n    width: auto;\n    margin: 0 auto;\n    left: 0;\n    right: 0;\n    top: 30%;\n  }\n\n  .modal-dialog {\n    width: 25rem;\n    /* height: 15rem; */\n    border-radius: 0;\n  }\n\n  .modal-title {\n    margin-top: 30px;\n    font-family: AvenirNext-Bold;\n    font-size: 14px;\n    color: #000000;\n    text-align: center;\n  }\n\n  .modal-header {\n    border-bottom: 0 !important;\n  }\n\n  .modal-content {\n    width: 25rem;\n    height: 18rem;\n    border-radius: 0;\n  }\n\n  .modal-footer {\n    border-top: 0 !important;\n    display: block !important;\n  }\n\n  .modal-footer button {\n    width: 6.4rem;\n    height: 2.13rem;\n    border-radius: 0;\n    border: 0;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n  }\n\n  .btn-skip {\n    color: #5E6369;\n    background: #F5F7FB;\n  }\n\n  .btn-save-path {\n    color: #FFFFFF;\n    background: #196BD8;\n  }\n</style>\n"
  },
  {
    "path": "src/components/Node/Node.vue",
    "content": "<style scoped>\n.node-container {\n    position: relative;\n    width:100%;\n    padding:22px 20px;\n}\n.center-content {\n    display: flex;\n    flex-wrap: wrap;\n}\n.btn-item {\n    width:280px;\n    height:160px;\n    background: #F4F4F6;\n    text-align: left;\n    margin-bottom:32px;\n    margin-right: 32px;\n    padding:16px 24px;\n    position:relative;\n}\n\n.btn-item p:first-child {\n    margin-bottom: 12px;\n}\n.btn-item p:nth-child(2) {\n    font-size:14px;\n    font-family:AvenirNext-Regular,AvenirNext;\n    font-weight:400;\n    color:rgba(0,0,0,1);\n    opacity: 0.4;\n}\n.btn-item button {\n    font-size:18px !important;\n    height: 80px !important;\n    width:300px !important;\n}\n.page-title {\n    font-size:18px;\n    font-family:AvenirNext-Medium,AvenirNext;\n    font-weight:500;\n    color:rgba(0,0,0,1);\n    margin-bottom:24px;\n}\n.icon-bottom {\n    position: absolute;\n    bottom: 0;\n    right: 0;\n    text-align: right;\n    padding-right: 24px;\n    padding-bottom:10px;\n    width:100%;\n    font-weight:400;\n    color:rgba(0,0,0,1);\n    font-size:16px;\n    cursor: pointer;\n}\n.icon-bottom:hover, .icon-policy:hover > i {\n    color: #196BD8;\n}\n\n.icon-policy {\n    position: absolute;\n    top: 10px;\n    right:24px;\n    cursor: pointer;\n}\n\n</style>\n\n<template>\n    <div class=\"negative-margin-top node-container\">\n        <h1 class=\"page-title\">{{$t('vote.node')}}</h1>\n        <div class=\"center-content\">\n            <div class=\"btn-item\" >\n                <p class=\"font-title\">{{$t('nodeMgmt.nodeStakeMgmt')}}</p>\n                <p >{{$t('nodeMgmt.nodeUser')}}</p>\n                <div class=\"icon-bottom\" @click=\"handleNodeStake\">\n                    <i class=\"fa fa-arrow-right fa-s icon-bottom\"></i>\n                </div>\n            </div>\n            <div class=\"btn-item\" >\n                <p class=\"font-title\">{{$t('nodeMgmt.stakeAuthorizaton')}}</p>\n                <p class=\"font-medium\">{{$t('nodeMgmt.normalUser')}}</p>\n                <div class=\"icon-bottom\" @click=\"handleAuthorization\">\n                    <i class=\"fa fa-arrow-right fa-s icon-bottom\"></i>\n                </div>\n            </div>\n            <div class=\"btn-item\" >\n                <p class=\"font-title\">{{$t('vote.vote')}}</p>\n                <p class=\"font-medium\">{{$t('vote.voteTip')}}</p>\n                <div class=\"icon-policy\" @click=\"openPolicyPage\">\n                    <i class=\"fa fa-question-circle-o fa-lg\" aria-hidden=\"true\"></i>\n                </div>\n                <div class=\"icon-bottom\" @click=\"handleVote\">\n                    <i class=\"fa fa-arrow-right fa-s\"></i>\n                </div>\n            </div>\n            <div class=\"btn-item\" >\n                <p class=\"font-title\">{{$t('nodeMgmt.newNodeApply')}}</p>\n                <p class=\"font-medium\">{{$t('nodeMgmt.nodeApplyTip')}}</p>\n                <div class=\"icon-bottom\" @click=\"handleNodeApply\">\n                    <i class=\"fa fa-arrow-right fa-s\"></i>\n                </div>\n            </div>\n        </div>\n    </div>\n\n</template>\n\n<script>\nimport {open} from '../../core/utils'\nexport default {\n    name: 'NodeManagement',\n    data(){\n        return {\n            onlyTestNet: false\n        }\n    },\n    mounted() {\n        this.$store.dispatch('fetchVoteContract')\n    },\n    methods: {\n        handleNodeStake() {\n            // const net = localStorage.getItem('net');\n            // if(net === 'TEST_NET' && this.onlyTestNet) {\n            //     this.$message.warning(this.$t('nodeMgmt.switchMainnet'));\n            //     return;\n            // }\n            // this.$router.push({name: 'NodeStakeIntro'})\n            this.$router.push({name: 'MyNode'})\n        },\n        handleAuthorization() {\n            const net = localStorage.getItem('net');\n            if(net === 'TEST_NET' && this.onlyTestNet) {\n                this.$message.warning(this.$t('nodeMgmt.switchMainnet'));\n                return;\n            }\n            this.$router.push({name: 'NodeList'})\n        },\n        handleVote() {\n            const net = localStorage.getItem('net');\n            if(net === 'TEST_NET' && this.onlyTestNet) {\n                this.$message.warning(this.$t('nodeMgmt.switchMainnet'));\n                return;\n            }\n            this.$router.push('/vote/login')\n        },\n        handleNodeApply() {\n            this.$router.push({name: 'NodeApply'})\n        },\n        openPolicyPage() {\n            const lang = localStorage.getItem('user_lang') || 'en'\n            const url = 'https://node.ont.io/voting-policy/' + lang\n            open(url)\n        }\n    }\n}\n</script>\n\n"
  },
  {
    "path": "src/components/Node/NodeApply/Register.vue",
    "content": "<template>\n<div>\n\t<div v-if=\"!registerSucceed\">\n\t\t<breadcrumb :current=\"$t('nodeApply.newNodeApply')\"\n\t\t\tv-on:backEvent=\"back\"></breadcrumb>\n\t\t<div class=\"app-container\">\n\t\t\t<a-steps :current=\"current\"\n\t\t\t\tclass=\"create-steps\">\n\t\t\t\t<a-step v-for=\"item in steps\"\n\t\t\t\t\t:key=\"item.title\" />\n\t\t\t</a-steps>\n\n\t\t\t<div class=\"steps-content\">\n\t\t\t\t<div class=\"register-form\"\n\t\t\t\t\tv-show=\"current === 0\">\n\t\t\t\t\t<!-- <div class=\"proxy-tip\">\n\t\t\t\t\t\t<span>{{$t('nodeApply.proxyServiceTip')}}</span>\n\t\t\t\t\t\t<span @click=\"onProxyLink\" class=\"proxy-link\">{{$t('nodeApply.proxyServiceLink')}}</span>\n\t\t\t\t\t</div> -->\n\t\t\t\t\t<form>\n\t\t\t\t\t\t<div class=\"form-item\">\n\t\t\t\t\t\t\t<label for=\"stakeWallet\">{{$t('nodeApply.stakeWallet')}}</label>\n\t\t\t\t\t\t\t<select-wallet @walletSelected=\"onWalletSelected\"></select-wallet>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div class=\"form-item\">\n\t\t\t\t\t\t\t<label for=\"stakeWallet\">{{$t('nodeApply.operationWallet')}}</label>\n\t\t\t\t\t\t\t<a-tabs default-active-key=\"1\" type=\"card\" >\n\t\t\t\t\t\t\t\t<a-tab-pane key=\"1\" :tab=\"$t('nodeApply.selectOperationWallet')\">\n\t\t\t\t\t\t\t\t\t<a-select :options=\"normalWalletAndLedgerWallet\"\n\t\t\t\t\t\t\t\t\t\tclass=\"select-ontid\"\n\t\t\t\t\t\t\t\t\t\tv-model=\"operationWallet\"\n\t\t\t\t\t\t\t\t\t\t@change=\"onSelectOperationWallet\"\n\t\t\t\t\t\t\t\t\t\t:placeholder=\"$t('nodeApply.selectOperationWallet')\">\n\t\t\t\t\t\t\t\t\t</a-select>\n\t\t\t\t\t\t\t\t\t<p class=\"ledger-warning\" v-show=\"ledgerList.some((wallet) => wallet.publicKey === operationWallet)\">\n\t\t\t\t\t\t\t\t\t\t<a-icon :style=\"{ color: 'red' }\" type=\"close-circle\" /> {{$t('nodeApply.unsupportedLedger')}}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</a-tab-pane>\n\t\t\t\t\t\t\t\t<a-tab-pane key=\"2\" :tab=\"$t('nodeApply.enterOperationPk')\" >\n\t\t\t\t\t\t\t\t\t<a-input v-model=\"operationPk\"\n\t\t\t\t\t\t\t\t\t@blur=\"onSelectOperationWallet\"\n\t\t\t\t\t\t\t\t\t:placeholder=\"$t('nodeApply.enterOperationPk')\"></a-input>\n\t\t\t\t\t\t\t\t</a-tab-pane>\n\n\t\t\t\t\t\t\t</a-tabs>\n\n\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div class=\"form-item\">\n\t\t\t\t\t\t\t<label for=\"\">{{$t('nodeApply.stakeAmount')}}</label>\n\t\t\t\t\t\t\t<a-input v-model=\"stakeAmount\"\n\t\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\t\t:class=\"validAmount ? '' : 'error-input' \"\n\t\t\t\t\t\t\t\t@change=\"validateAmount\"\n\t\t\t\t\t\t\t\t:placeholder=\"$t('nodeApply.inputStakeAmount')\"></a-input>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"footer-btns\">\n\t\t\t\t\t\t\t<div class=\"btn-known\">\n\t\t\t\t\t\t\t\t<a-button type=\"primary\"\n\t\t\t\t\t\t\t\t\tclass=\"btn-next\"\n\t\t\t\t\t\t\t\t\t@click=\"next\">{{$t('nodeApply.next')}}</a-button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"register-confirm\"\n\t\t\t\t\tv-show=\"current === 1\">\n\n\t\t\t\t\t<div class=\"form-item\">\n\t\t\t\t\t\t<label for=\"\">{{$t('nodeApply.stakeWallet')}}</label>\n\t\t\t\t\t\t<p>{{stakeWallet.address}} {{ this.walletType === 'ledgerWallet' ? '(Ledger)' : '' }}</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"form-item\">\n\t\t\t\t\t\t<label for=\"\">{{$t('nodeApply.operationWalletPublickey')}}</label>\n\t\t\t\t\t\t<p>{{operationWallet || operationPk}}</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"form-item\">\n\t\t\t\t\t\t<label for=\"\">{{$t('nodeApply.stakeAmount')}}</label>\n\t\t\t\t\t\t<p>{{stakeAmount}}</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"footer-btns\">\n                        <div class=\"btn-container\">\n                            <a-button type=\"default\"\n\t\t\t\t\t\t\t@click=\"cancel\"\n\t\t\t\t\t\t\tclass=\"btn-cancel\">{{$t('nodeApply.cancel')}}</a-button>\n\n                            <a-button type=\"primary\"\n                                    class=\"btn-next\"\n                                    @click=\"confirm\">{{$t('nodeApply.ok')}}</a-button>\n                        </div>\n\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n        <sign-send-tx :visible=\"signVisible\" :tx=\"tx\" :wallet=\"stakeWallet\"\n        v-on:signClose=\"handleTxCancel\"\n        v-on:txSent=\"handleTxSent\"\n        ></sign-send-tx>\n\t</div>\n\t<div class=\"success-container\" v-if=\"registerSucceed\">\n        <img :src=\"require('../../../assets/success.svg')\" alt=\"\">\n        <p class=\"success-tip\">{{$t('nodeApply.registerSuccess')}}</p>\n        <a-button class=\"btn-next\" @click=\"onComplete\">{{$t('nodeApply.completeNodeInfo')}}</a-button>\n        <p class=\"later-tip\" @click=\"onLater\">{{$t('nodeApply.later')}}</p>\n    </div>\n</div>\n</template>\n<script>\nimport Breadcrumb from \"../../Breadcrumb\";\nimport SelectWallet from \"../../Common/SelectWallet\";\nimport { Crypto, GovernanceTxBuilder } from \"ontology-ts-sdk\";\nimport SignSendTx from '../../Common/SignSendTx'\nimport { open, varifyPositiveInt } from '../../../core/utils'\nimport { mapState } from 'vuex'\n\nexport default {\n\tname: \"NodeApply\",\n\tcomponents: {\n\t\tBreadcrumb,\n        SelectWallet,\n        SignSendTx\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tcurrent: 0,\n\t\t\tsteps: [{ title: \"first\" }, { title: \"second\" }],\n\t\t\twalletType: \"\",\n\t\t\tstakeWallet: {},\n\t\t\toperationWallet: undefined,\n\t\t\toperationPk: '',\n\t\t\tstakeAmount: \"\",\n            minStakeAmount: 10000,\n            signVisible: false,\n\t\t\ttx: null,\n\t\t\tregisterSucceed: false,\n\t\t\tvalidAmount: true\n\t\t};\n\t},\n\tcreated() {\n\t\tthis.$store.dispatch(\"fetchWalletsFromDb\");\n\t},\n\tcomputed: {\n\t\t...mapState({\n\t\t\tledgerList:state=>state.Wallets.HardwareWallet,\n\t\t}),\n\t\tnormalWallet: {\n\t\t\tget() {\n\t\t\t\tconst list = this.$store.state.Wallets.NormalWallet.slice();\n\t\t\t\treturn list.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address,\n\t\t\t\t\t\tvalue: i.publicKey\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\tnormalWalletAndLedgerWallet: {\n\t\t\tget() {\n\t\t\t\tconst NormalList = this.$store.state.Wallets.NormalWallet.slice();\n\t\t\t\tconst LedgerList = this.$store.state.Wallets.HardwareWallet.slice();\n\n\t\t\t\tconst list1 = NormalList.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address,\n\t\t\t\t\t\tvalue: i.publicKey\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tconst list2 = LedgerList.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address + \" (Ledger)\",\n\t\t\t\t\t\tvalue: i.publicKey\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tlist2.sort((a,b)=>{\n\t\t\t\t\tif (b.timestamp !== a.timestamp) {\n\t\t\t\t\t\treturn b.timestamp - a.timestamp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn b.acct - a.acct;\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\tconst list = [...list1, ...list2]\n\n\t\t\t\treturn list.filter(item => item.address !== this.stakeWallet?.address);\n\t\t\t}\n\t\t}\n\t},\n\tmethods: {\n\t\tback() {\n\t\t\tthis.$router.back();\n\t\t},\n\t\tonWalletSelected({ walletType, wallet }) {\n\t\t\tthis.walletType = walletType;\n\t\t\tthis.stakeWallet = wallet ? wallet : {};\n\t\t\tthis.onSelectOperationWallet();\n\t\t},\n\t\tnext() {\n\t\t\tif (!this.stakeWallet.address) {\n\t\t\t\tthis.$message.error(this.$t(\"nodeApply.stakeWalletRequired\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this.operationWallet && !this.operationPk) {\n\t\t\t\tthis.$message.error(\n\t\t\t\t\tthis.$t(\"nodeApply.operationWalletRequired\")\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this.stakeAmount) {\n\t\t\t\tthis.$message.error(this.$t(\"nodeApply.stakeAmountRequired\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (Number(this.stakeAmount) < this.minStakeAmount) {\n\t\t\t\tthis.$message.error(this.$t(\"nodeApply.minStateAmount\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif(!this.validAmount) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.current += 1;\n\t\t\tthis.$store.dispatch('stopGetLedgerStatus') // 防止过多ledger请求\n\t\t},\n\t\tcancel() {\n\t\t\tthis.current -= 1;\n\t\t},\n\t\tonSelectOperationWallet() {\n            //TODO 同一个公钥智能注册一次节点\n\t\t\tif (this.stakeWallet && (this.operationWallet || this.operationPk )) {\n\t\t\t\tlet address;\n\t\t\t\ttry {\n\t\t\t\t\taddress = Crypto.Address.fromPubKey(\n\t\t\t\t\tthis.operationWallet ? new Crypto.PublicKey(this.operationWallet)\n\t\t\t\t\t\t: new Crypto.PublicKey(this.operationPk)\n\t\t\t\t).toBase58();\n\t\t\t\t} catch(err) {\n\t\t\t\t\tconsole.log(err)\n\t\t\t\t\tthis.$message.warning(this.$t('nodeApply.invalidOperationPk'))\n\t\t\t\t\tthis.operationPk = ''\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (this.stakeWallet.address === address) {\n\t\t\t\t\tthis.$message.warning(\n\t\t\t\t\t\tthis.$t(\"nodeApply.sameWalletNotAllowed\")\n\t\t\t\t\t);\n\t\t\t\t\tthis.operationWallet = null;\n\t\t\t\t\tthis.operationPk = \"\";\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n        },\n        confirm() {\n            const ontid = 'did:ont' + this.stakeWallet.address\n            const publicKey = this.operationWallet ? this.operationWallet : this.operationPk\n            const userAddr = new Crypto.Address(this.stakeWallet.address)\n            const initPos = Number(this.stakeAmount)\n            const tx = GovernanceTxBuilder.makeRegisterCandidateTx(ontid, publicKey, 1, userAddr, initPos, userAddr, '500', '200000')\n            this.tx = tx;\n            this.signVisible = true;\n        },\n        handleTxCancel() {\n            this.signVisible = false;\n            this.tx = null;\n        },\n        async handleTxSent() {\n            // 注册成功后，更新off chain 表。后台同步到off chain表。同步可能有时差。\n\t\t\t// this.$router.push({name: 'NodeApplySuccess'})\n\t\t\tthis.registerSucceed = true\n\t\t\tconst nodePk = this.operationWallet ? this.operationWallet : this.operationPk\n\t\t\tawait this.$store.dispatch('newStakeInfo', {\n\t\t\t\tname: 'Node_' + nodePk.substr(0, 6),\n\t\t\t\taddress: this.stakeWallet.address,\n\t\t\t\tpublic_key: nodePk\n\t\t\t})\n\t\t},\n\n\t\tasync onComplete() { // 进入节点管理页面且打开信息填写的tab\n\t\t\tconst nodePk = this.operationWallet ? this.operationWallet : this.operationPk\n\t\t\tawait this.$store.dispatch('newStakeInfo', {\n\t\t\t\tname: 'Node_' + nodePk.substr(0, 6),\n\t\t\t\taddress: this.stakeWallet.address,\n\t\t\t\tpublic_key: nodePk\n\t\t\t})\n            this.$store.commit('UPDATE_STAKE_WALLET', {stakeWallet: this.stakeWallet})\n            this.$store.commit('UPDATE_NODE_PUBLICKEY', {nodePublicKey: nodePk})\n\t\t\tthis.$store.commit('UPDATE_MENU_TAB_INDEX', 3)\n\t\t\tthis.$router.push({name: 'NodeStakeManagement'})\n        },\n        onLater() {\n            this.$router.push({name: 'MyNode'})\n\t\t},\n\t\t// onProxyLink() {\n\t\t// \tconst url = 'http://triones-node.store.ont.io/'\n\t\t// \topen(url)\n\t\t// },\n\t\tvalidateAmount() {\n\n\t\t\tif(this.stakeAmount && !varifyPositiveInt(this.stakeAmount)) {\n                this.validAmount = false;\n                return;\n\t\t\t}\n\t\t\tthis.validAmount = true\n\t\t}\n\t}\n};\n</script>\n<style lang=\"scss\" scoped>\n.btn-known {\n\tmargin: 20px auto;\n\ttext-align: center;\n}\n.register-form,\n.register-confirm {\n\tmargin-top: 40px;\n\t.form-item {\n\t\tmargin-bottom: 20px;\n\t\tlabel {\n\t\t\tfont-family: AvenirNext-Medium;\n\t\t\tcolor: #000000;\n\t\t}\n\t}\n}\n.btn-container {\n    width: 550px;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n}\n.success-container {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: center;\n    height: 100vh;\n    margin-top: -4rem;\n    img {\n        width: 80px;\n        height: 80px;\n        margin-bottom: 20px;\n    }\n    .success-tip {\n        font-size:24px;\n        font-family:PingFangSC-Medium,PingFang SC;\n        font-weight:500;\n        color:rgba(0,0,0,1);\n        margin-bottom: 40px;\n    }\n    button {\n        margin-bottom: 23px;\n    }\n    .later-tip {\n        font-size:14px;\n        font-family:PingFangSC-Semibold,PingFang SC;\n        font-weight:600;\n        color:rgba(0,0,0,.6);\n        cursor: pointer;\n        text-decoration: underline;\n    }\n}\n.proxy-tip {\n\ttext-align: left;\n    font-size: 12px;\n    font-family: AvenirNext-Regular,AvenirNext;\n    font-weight: 400;\n    margin-top: 4px;\n\tspan:first-child {\n\t\tcolor: #000;\n    opacity: 0.6;\n\t}\n\tspan:last-child {\n\t\topacity: 1 !important;\n\t\tfont-weight: 400;\n\t\tcolor: #196bd8;\n\t\ttext-decoration: underline;\n\t\tcursor: pointer;\n\t}\n}\n.ledger-warning{\n\tmargin-top: 8px;\n\tdisplay: flex;\n\talign-items: center;\n\tcolumn-gap: 6px;\n}\n</style>\n"
  },
  {
    "path": "src/components/Node/NodeApply/RegisterSuccess.vue",
    "content": "<template>\n    <div class=\"success-container\">\n        <img :src=\"require('../../../assets/success.svg')\" alt=\"\">\n        <p class=\"success-tip\">{{$t('nodeApply.registerSuccess')}}</p>\n        <a-button class=\"btn-next\" @click=\"onComplete\">{{$t('nodeApply.completeNodeInfo')}}</a-button>\n        <p class=\"later-tip\" @click=\"onLater\">{{$t('nodeApply.later')}}</p>\n    </div>\n</template>\n<script>\nexport default {\n    name: 'NodeApplySuccess',\n    methods: {\n        onComplete() { // 进入节点管理页面且打开信息填写的tab\n            \n        },\n        onLater() {\n            this.$router.push({name: 'MyNode'})\n        }\n    }\n}\n</script>\n<style lang=\"scss\" scoped>\n.success-container {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: center;\n    height: 100vh;\n    margin-top: -4rem;\n    img {\n        width: 80px;\n        height: 80px;\n        margin-bottom: 20px;\n    }\n    .success-tip {\n        font-size:24px;\n        font-family:PingFangSC-Medium,PingFang SC;\n        font-weight:500;\n        color:rgba(0,0,0,1);\n        margin-bottom: 40px;\n    }\n    button {\n        margin-bottom: 23px;\n    }\n    .later-tip {\n        font-size:14px;\n        font-family:PingFangSC-Semibold,PingFang SC;\n        font-weight:600;\n        color:rgba(0,0,0,.6);\n        cursor: pointer;\n        text-decoration: underline;\n    }\n}\n</style>"
  },
  {
    "path": "src/components/Node/NodeAuthorize/AuthorizationMgmt.vue",
    "content": "<style scoped>\n.content-container {\n    display: flex;\n  }\n\n  .left-half {\n    flex-basis: 55%;\n    padding-right: 20px;\n  }\n\n  .right-half {\n    flex-basis: 50%;\n    padding-left: 40px;\n    border-left: 1px solid #dddddd;\n\n  }\n  .label {\n      font-size:16px;\n  }\n\n  .refresh-icon {\n    color: #000000;\n    font-size: 16px;\n    cursor: pointer;\n    margin-left: 20px;\n  }\n\n  .switch-wallet {\n      margin-left: 20px;\n      cursor: pointer;\n      color: #000000;\n      font-size: 16px;\n  }\n\n  .new-stake {\n      margin:15px 0;\n      border-radius:0;\n  }\n\n  .in-authorization {\n      margin:15px 0 0 0;\n  }\n  .authorize-tip {\n      font-size:16px;\n      margin-bottom: 15px;\n  }\n  .tip-font {\n      font-size: 12px;\n  }\n  .cancel-btn {\n      margin: 15px 0;\n      border-radius: 0;\n  }\n  .redeem-item {\n      width:100%;\n  }\n  .redeem-item span:first-child {\n      width:150px;\n      display: inline-block;\n  }\n  .redeem-item button {\n      margin-left: 20px;\n  }\n  .redeem-ont {\n      margin: 15px 0;\n  }\n  .redeem-btn {\n    width: 100px;\n    height: 36px;\n    border-radius: 0;\n    background: #FBE45A;\n    padding: 0;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #5E6369;\n    border: none;\n    margin-bottom:15px;\n  }\n  .cancel-stake-input {\n      width:200px;\n  }\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('nodeMgmt.stakeAuthorization')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"content-container\">\n            <div class=\"left-half\">\n                <div>\n                    <span class=\"font-medium-black label\">{{$t('nodeMgmt.nodeName')}}: </span>\n                    <span class=\"font-medium\">{{current_node.name}}</span>\n                </div>\n                <div>\n                    <span class=\"label font-medium-black\">{{$t('nodeMgmt.walletAddress')}}: </span>\n                    <span class=\"font-medium\">{{stakeWallet.address}}</span>\n                    <a-tooltip placement=\"top\" :title=\"$t('nodeMgmt.switchWallet')\">\n                        <span class=\"switch-wallet\" @click=\"switchWallet\"><a-icon type=\"sync\" /></span>\n                    </a-tooltip>\n\n                </div>\n                <a-button type=\"primary\" class=\"btn-next new-stake\" @click=\"newStakeAuthorization\">{{$t('nodeMgmt.newStakeAuthorization')}}</a-button>\n                <div class=\"in-authorization\">\n                    <span class=\"label font-medium-black\">{{$t('nodeMgmt.inAuthorization')}}: </span>\n                    <span class=\"font-medium\">{{authorizationInfo.inAuthorization}} ONT</span>\n                    <a-tooltip placement=\"top\" :title=\"$t('nodeMgmt.refresh')\">\n                        <span class=\"common-icon refresh-icon\" @click=\"handleRefresh\"></span>\n                    </a-tooltip>\n                </div>\n                <div>\n                    <span>{{$t('nodeMgmt.getProfitPart')}}:</span>\n                    <span>{{authorizationInfo.receiveProfitPortion}} ONT</span>\n                </div>\n                <div>\n                    <span>{{$t('nodeMgmt.newStakePart')}}:</span>\n                    <span>{{authorizationInfo.newStakePortion}} ONT</span>\n                </div>\n                <div class=\"authorize-tip\">\n                    <a-icon type=\"info-circle\" />\n                    <span class=\"font-regular tip-font\">{{$t('nodeMgmt.authorizeTip')}}</span>\n                </div>\n                <a-button type=\"default\" class=\"cancel-btn\" @click=\"cancelAuthorization\">{{$t('nodeMgmt.cancelAuthorization')}}</a-button>\n                <div class=\"redeem-ont\">\n                    <p class=\"redeem-item\">\n                        <span class=\"font-medium-black label\">\n                            <a-tooltip placement=\"right\" :title=\"$t('nodeMgmt.lockedONT')\">\n                                <a-icon type=\"info-circle-o\" />\n                            </a-tooltip>\n                            {{$t('nodeMgmt.locked')}}:\n                        </span>\n                        <span class=\"font-medium\">{{authorizationInfo.locked}} ONT</span>\n                    </p>\n                    <p class=\"redeem-item\">\n                        <span class=\"font-medium-black label\">\n                            {{$t('nodeMgmt.claimable')}}:\n                        </span>\n                        <span class=\"font-medium\">{{authorizationInfo.claimable}} ONT</span>\n                        <a-button type=\"primary\" class=\"redeem-btn\" @click=\"redeemOnt\">{{$t('nodeMgmt.redeem')}}</a-button>\n                    </p>\n                    <p class=\"redeem-item\">\n                        <span class=\"font-medium-black label\">\n                            <a-tooltip placement=\"right\" :title=\"$t('nodeMgmt.unboundONG')\">\n                                <a-icon type=\"info-circle-o\" />\n                            </a-tooltip>\n                            {{$t('nodeMgmt.unboundOng')}}:\n                        </span>\n                        <span class=\"font-medium\">{{unboundOng}} ONG</span>\n                        <!-- <a-button type=\"primary\" class=\"redeem-btn\" @click=\"redeemOng\">{{$t('nodeMgmt.redeem')}}</a-button> -->\n                    </p>\n                </div>\n            </div>\n            <div class=\"right-half\">\n                <p class=\"font-medium-black label\">{{$t('nodeMgmt.rewards')}}</p>\n                <p>\n                    <span class=\"font-medium-black label\">\n                        <a-tooltip placement=\"right\" :title=\"$t('nodeMgmt.profitONG')\">\n                                <a-icon type=\"info-circle-o\" />\n                            </a-tooltip>\n                        {{$t('nodeMgmt.profit')}}:\n                    </span>\n                    <span class=\"font-medium\">{{splitFee.amount}} ONG</span>\n                </p>\n                <a-button type=\"primary\" class=\"redeem-btn\" @click=\"redeemRewards\">{{$t('nodeMgmt.redeem')}}</a-button>\n\n                <p class=\"authorize-tip\">\n                   <a-icon type=\"info-circle\" />\n                   <span class=\"font-regular tip-font\">{{$t('nodeMgmt.rewardTip')}}</span>\n                </p>\n            </div>\n        </div>\n        <a-modal\n            :title=\"$t('nodeMgmt.cancelAuthorization')\"\n            :visible=\"cancelVisible\"\n            @ok=\"handleCancelAuthorizationOk\"\n            @cancel=\"handleCancelAuthorizationCancel\">\n            <div>\n                <div>\n                    <span class=\"font-medium-black label\">{{$t('nodeMgmt.nodeName')}}: </span>\n                    <span class=\"font-medium\">{{current_node.name}}</span>\n                </div>\n                <div class=\"in-authorization\">\n                    <span class=\"label font-medium-black\">{{$t('nodeMgmt.inAuthorization')}}: </span>\n                    <span class=\"font-medium\">{{authorizationInfo.inAuthorization}} ONT</span>\n                </div>\n                <div>\n                    <span class=\"label font-medium-black\">{{$t('nodeMgmt.unitToCancel')}}: </span>\n                    <a-input class=\"input cancel-stake-input\" :class=\"validCancelAmount? '': 'error-input'\"\n                    v-model=\"cancelAmount\" @change=\"validateCancelAmount\"></a-input> {{$t('nodeMgmt.cancelUnits')}}\n                </div>\n                <div>\n                    <span class=\"label font-medium-black\">{{$t('nodeMgmt.amountToCancel')}}: </span>\n                    <span class=\"font-medium\">{{cancelAmount}} ONT</span>\n                </div>\n            </div>\n        </a-modal>\n        <sign-send-tx :visible=\"signVisible\" :tx=\"tx\" :wallet=\"stakeWallet\"\n        v-on:signClose=\"handleCancel\"\n        v-on:txSent=\"handleTxSent\"\n        ></sign-send-tx>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport {mapState} from 'vuex'\nimport SignSendTx from '../../Common/SignSendTx'\nimport {GAS_PRICE, GAS_LIMIT} from '../../../core/consts'\nimport {Crypto, GovernanceTxBuilder, utils} from 'ontology-ts-sdk'\nimport numeral from 'numeral'\nimport {varifyPositiveInt} from '../../../core/utils.js'\n\nexport default {\n    name:'AuthorizationMgmt',\n    components: {\n        Breadcrumb,\n        SignSendTx\n    },\n    data() {\n        return {\n            intervalId:'',\n            signVisible: false,\n            // inAuthorization: 0,\n            // locked: 0,\n            // claimable:0,\n            tx: '',\n            cancelVisible: false,\n            cancelAmount: 0,\n            validCancelAmount: true\n        }\n    },\n    mounted() {\n        //fetch stake info\n        // const pk = this.stakeDetail.publicKey\n\n        this.refresh();\n        this.intervalId = setInterval(()=>{\n            this.refresh();\n        }, 10000)\n    },\n    beforeDestroy(){\n        clearInterval(this.intervalId)\n    },\n\n    computed:{\n        ...mapState({\n            current_node: state => state.NodeAuthorization.current_node,\n            stakeWallet: state => state.NodeStake.stakeWallet,\n            splitFee: state => state.NodeAuthorization.splitFee,\n            authorizationInfo: state => state.NodeAuthorization.authorizationInfo,\n            peer_attrs: state => state.NodeAuthorization.peer_attrs,\n            unboundOng: state => state.NodeAuthorization.peerUnboundOng\n        }),\n    },\n    methods: {\n        refresh(){\n            const address = this.stakeWallet.address;\n            const pk = this.current_node.pk;\n            this.$store.dispatch('fetchAuthorizationInfo', {pk, address})\n            this.$store.dispatch('fetchSplitFee', address)\n            this.$store.dispatch('fetchPeerAttributes', pk)\n            this.$store.dispatch('fetchPeerUnboundOng', address)\n        },\n        handleRouteBack() {\n            this.$router.go(-1);\n        },\n        newStakeAuthorization() {\n            if(this.peer_attrs.maxAuthorize === 0) {\n                this.$message.warning(this.$t('nodeMgmt.peerNotAllowAuthorize'))\n                return;\n            }\n            this.$router.push({name: 'NewAuthorization'})\n        },\n        switchWallet() {\n            this.$router.push({name: 'AuthorizeLogin'})\n        },\n        handleRefresh() {\n            this.$store.dispatch('showLoadingModals')\n            setTimeout(() => {\n                this.$store.dispatch('hideLoadingModals')\n            }, 100)\n            const address = this.stakeWallet.address;\n            const pk = this.current_node.pk;\n            this.$store.dispatch('fetchAuthorizationInfo', {pk, address})\n            this.$store.dispatch('fetchSplitFee', address)\n            this.$store.dispatch('fetchPeerAttributes', pk)\n        },\n        handleCancel() {\n            this.signVisible = false;\n            this.tx = ''\n            this.cancelAmount = 0;\n        },\n        handleTxSent() {\n            this.signVisible = false;\n            // this.tx = ''\n            this.cancelAmount = 0;\n            this.refresh();\n            const address = this.stakeWallet.address;\n            const pk = this.current_node.pk;\n            const record = {\n                indexKey : address + '-' + pk,\n                stakeWalletAddress: address,\n                nodePk: pk,\n                nodeName: this.current_node.name,\n            }\n            const txHash = utils.reverseHex(this.tx.getHash());\n            this.tx = '';\n            // this.$store.dispatch('recordStakeHistory', {txHash, record})\n        },\n        validateCancelAmount() {\n            if(!this.cancelAmount || !varifyPositiveInt(this.cancelAmount)) {\n                this.validCancelAmount = false;\n                return;\n            }\n            const inAuthorization = this.authorizationInfo.consensusPos + this.authorizationInfo.freezePos\n                                    + this.authorizationInfo.newPos;\n            if(Number(this.cancelAmount) > inAuthorization) {\n                this.validCancelAmount = false;\n                return;\n            }\n            this.validCancelAmount = true;\n        },\n        handleCancelAuthorizationOk() {\n            if(!this.cancelAmount || !this.validCancelAmount) {\n                this.$message.error(this.$t('nodeMgmt.invalidInput'))\n                return;\n            }\n            this.cancelVisible = false;\n            this.signVisible = true;\n            const userAddr = new Crypto.Address(this.stakeWallet.address);\n            const amount = Number(this.cancelAmount);\n            const tx = GovernanceTxBuilder.makeUnauthorizeForPeerTx(\n                userAddr,\n                [this.current_node.pk],\n                [parseInt(amount)],\n                userAddr,\n                GAS_PRICE,\n                GAS_LIMIT\n            )\n            this.tx = tx;\n            this.cancelAmount = 0;\n        },\n        handleCancelAuthorizationCancel() {\n            this.cancelVisible = false;\n        },\n        redeemRewards() {\n            if(!this.splitFee.amount) {\n                this.$message.warning(this.$t('nodeMgmt.noRewards'))\n                return;\n            }\n            const tx = GovernanceTxBuilder.makeWithdrawFeeTx(\n                new Crypto.Address(this.stakeWallet.address),\n                new Crypto.Address(this.stakeWallet.address),\n                GAS_PRICE,\n                GAS_LIMIT\n            )\n            this.signVisible = true;\n            this.tx = tx;\n        },\n        cancelAuthorization() {\n            this.cancelVisible = true\n            this.tx = '';\n        },\n        redeemOnt() {\n            if(!this.authorizationInfo.withdrawUnfreezePos) {\n                this.$message.warning(this.$t('nodeMgmt.noClaimableOnt'))\n                return;\n            }\n            const claimable = this.authorizationInfo.claimableVal\n            const tx = GovernanceTxBuilder.makeWithdrawTx(\n                new Crypto.Address(this.stakeWallet.address),\n                [this.current_node.pk],\n                [claimable],\n                new Crypto.Address(this.stakeWallet.address),\n                GAS_PRICE,\n                GAS_LIMIT\n            )\n            this.signVisible = true;\n            this.tx = tx;\n        },\n        redeemOng() {\n            if(!this.unboundOng) {\n                this.$message.warning(this.$t('nodeMgmt.noUnboundOng'));\n                return;\n            }\n            const tx = GovernanceTxBuilder.makeWithdrawPeerUnboundOngTx(\n                new Crypto.Address(this.stakeWallet.address),\n                new Crypto.Address(this.stakeWallet.address),\n                GAS_PRICE,\n                GAS_LIMIT\n            )\n            this.signVisible = true;\n            this.tx = tx;\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeAuthorize/AuthorizeLogin.vue",
    "content": "<style scoped>\n.auth-login {\n    width:540px;\n    margin:20px auto;\n}\n.select-wallet {\n    width:100%;\n}\n.change-payer-radio {\n    width:100%;\n}\n.payer-radio-item {\n    margin-bottom:20px;\n}\n.btn-container {\n    text-align: center;\n    margin:5px auto;\n    padding-top:15px;\n}\n.btn-container p {\n    margin-bottom:5px;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('nodeMgmt.stakeAuthorization')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"auth-login\">\n            <div class=\"intro-item\">\n                <p class=\"font-medium-black\" style=\"margin-bottom: 10px\">{{$t('nodeStake.selectStakeWallet')}}</p>\n\n                <div>\n                    <a-select :options=\"normalWalletAndLedgerWallet\" class=\"select-wallet\" v-model=\"payerWalletValue\"\n                    :placeholder=\"$t('createIdentity.selectCommonWallet')\"\n                        @change=\"handleChangePayer\">\n                    </a-select>\n                </div>\n            </div>\n        </div>\n        <div class=\"footer-btns\">\n            <div class=\"btn-container\">\n                <!-- <p class=\"font-medium\"><a-icon type=\"exclamation-circle\" /> {{$t('nodeMgmt.userParticipate')}}</p> -->\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{$t('nodeStake.next')}}</a-button>\n            </div>\n        </div>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport {mapState} from 'vuex'\nexport default {\n    name: 'AuthorizeLogin',\n    components: {\n        Breadcrumb\n    },\n    data(){\n        return {\n            payerWalletValue: undefined\n        }\n    },\n    mounted() {\n        this.$store.dispatch(\"fetchWalletsFromDb\").then(() => {\n            //set payer wallet \n        });\n        const stakeAuthorizationWalletAddress = this.$store.state.NodeAuthorization.stake_authorization_wallet;\n        if(stakeAuthorizationWalletAddress) {\n            const index = this.$store.state.Wallets.NormalWallet.findIndex((w)=> w.address === stakeAuthorizationWalletAddress.address)\n            if(index > -1) {\n                this.payerWalletValue = stakeAuthorizationWalletAddress\n                this.payerWallet = this.$store.state.Wallets.NormalWallet[index]\n            }\n        }\n\n    },\n    beforeDestroy(){\n        this.$store.dispatch('stopGetLedgerStatus')\n    },\n    computed: {\n        ...mapState({\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n            ledgerWallet: state => state.LedgerConnector.ledgerWallet\n        }),\n\n\t\tnormalWalletAndLedgerWallet: {\n\t\t\tget() {\n\t\t\t\tconst NormalList = this.$store.state.Wallets.NormalWallet.slice();\n\t\t\t\tconst LedgerList = this.$store.state.Wallets.HardwareWallet.slice();\n\n\t\t\t\tconst list1 = NormalList.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address,\n\t\t\t\t\t\tvalue: i.address\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tconst list2 = LedgerList.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address + \" (Ledger)\",\n\t\t\t\t\t\tvalue: i.address\n\t\t\t\t\t});\n\t\t\t\t});\n                list2.sort((a,b)=>{\n\t\t\t\t\tif (b.timestamp !== a.timestamp) {\n\t\t\t\t\t\treturn b.timestamp - a.timestamp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn b.acct - a.acct;\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\treturn [...list1, ...list2];\n\t\t\t}\n\t\t}\n    },\n    methods: {\n        handleRouteBack() {\n            this.$router.go(-1);\n        },\n        handleChangePayer(value) {\n            this.payerWallet = this.normalWalletAndLedgerWallet.find((v)=>{return v.address === value})\n            this.payerWalletValue = this.payerWallet.address\n        },\n        next() {\n            if(!this.payerWallet) {\n                this.$message.error(this.$t('nodeStake.selectIndividualWallet'))\n                return;\n            }\n\n            let stakeWallet = this.payerWallet\n            this.$store.commit('UPDATE_STAKE_WALLET', {stakeWallet: stakeWallet})             \n            this.$router.push({name: 'AuthorizationMgmt'})\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeAuthorize/NewAuthorization.vue",
    "content": "<style scoped>\n.content-container {\n    width:540px;\n    margin:20px auto;\n}\n.content-container div {\n    margin-bottom: 15px;\n}\n.label {\n    font-size: 16px;\n}\n.authorize-tip {\n    font-size: 16px;\n    padding-left: 15px;\n}\n.error-input {\n    border-color: red !important;\n}\n.unit-input {\n    width:100px;\n}\n.btn-container {\n    text-align: center;\n}\n</style>\n\n<template>\n    <div>\n        <breadcrumb :current=\"$t('nodeMgmt.stakeAuthorization')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"content-container\">\n            <div>\n                <span class=\"font-medium-black label\">{{$t('nodeMgmt.nodeName')}}: </span>\n                <span class=\"font-medium\">{{current_node.name}}</span>\n            </div>\n            <div>\n                <span class=\"font-medium-black label\">{{$t('nodeMgmt.allowedStakeAmount')}}: </span>\n                <span class=\"font-medium\">{{current_node.maxAuthorizeStr}} ONT</span>\n            </div>\n            <div>\n                <span class=\"font-medium-black label\">{{$t('nodeMgmt.totalStakeAmount')}}: </span>\n                <span class=\"font-medium\">{{current_node.totalPosStr}} ONT</span>\n            </div>\n            <div>\n                <span class=\"label font-medium-black\">{{$t('nodeMgmt.walletAddress')}}: </span>\n                <span class=\"font-medium\">{{stakeWallet.address}}</span>\n            </div>\n            <div>\n                <span class=\"font-medium-black label\">{{$t('nodeMgmt.units')}}: </span>\n                <a-input type=\"text\" class=\"input unit-input\" v-model=\"units\" @change=\"handleChange\"\n                :class=\"validInput? '' : 'error-input'\"></a-input>\n            </div>\n            <p class=\"authorize-tip\">\n                <a-icon type=\"info-circle\" />\n                <span class=\"font-regular\">{{$t('nodeMgmt.stakeAmountTip')}}</span>\n            </p>\n            <div>\n                <span class=\"font-medium-black label\">{{$t('nodeMgmt.stakeAmount')}}: </span>\n                <span class=\"font-medium\">{{amount}} ONT</span>\n            </div>\n        </div>\n        <div class=\"footer-btns\">\n            <div class=\"btn-container\">\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"submit\">{{$t('nodeMgmt.submit')}}</a-button>\n            </div>\n        </div>\n\n        <sign-send-tx :visible=\"signVisible\" :tx=\"tx\" :wallet=\"stakeWallet\"\n        v-on:signClose=\"handleCancel\"\n        v-on:txSent=\"handleTxSent\"\n        ></sign-send-tx>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport {varifyPositiveInt} from '../../../core/utils.js'\nimport SignSendTx from '../../Common/SignSendTx'\nimport {mapState} from 'vuex'\nimport {GAS_LIMIT, GAS_PRICE} from '../../../core/consts'\nimport {Crypto, GovernanceTxBuilder, utils} from 'ontology-ts-sdk'\n\nexport default {\n    name: 'NewAuthorization',\n    components: {\n        Breadcrumb,\n        SignSendTx\n    },\n    data(){\n        return {\n            units:1,\n            amount:1,\n            validInput: true,\n            signVisible: false,\n            tx: ''\n        }\n    },\n    computed:{\n        ...mapState({\n            current_node: state => state.NodeAuthorization.current_node,\n            stakeWallet: state => state.NodeStake.stakeWallet,\n            peer_attrs: state => state.NodeAuthorization.peer_attrs,\n        })\n    },\n    methods: {\n        handleRouteBack() {\n            this.$router.go(-1);\n        },\n        handleChange() {\n            if(!this.units || !varifyPositiveInt(this.units)) {\n                this.validInput = false;\n                return;\n            }\n            this.amount = parseInt(this.units) * 1;\n            if(this.units && this.amount > (this.current_node.maxAuthorize - this.current_node.totalPos)) {\n                this.validInput = false;\n                return;\n            }\n\n            this.validInput = true;\n        },\n        handleCancel() {\n            this.signVisible = false;\n            this.tx = ''\n        },\n        handleTxSent() {\n            this.signVisible = false;\n            // this.tx = ''\n            this.$router.go(-1);\n            //record stake history\n            const address = this.stakeWallet.address;\n            const pk = this.current_node.pk;\n            const record = {\n                indexKey : address + '-' + pk,\n                stakeWalletAddress: address,\n                nodePk: pk,\n                nodeName: this.current_node.name,\n            }\n            const txHash = utils.reverseHex(this.tx.getHash());\n            this.tx = '';\n            // this.$store.dispatch('recordStakeHistory', {txHash, record})\n        },\n        submit() {\n            if(!this.validInput) {\n                this.$message.error(this.$t('nodeMgmt.invalidInput'))\n                return;\n            }\n            const userAddr = new Crypto.Address(this.stakeWallet.address)\n            const tx = GovernanceTxBuilder.makeAuthorizeForPeerTx(\n                userAddr,\n                [this.current_node.pk],\n                [this.amount],\n                userAddr,\n                GAS_PRICE,\n                GAS_LIMIT\n            )\n            this.tx = tx;\n            this.signVisible = true;\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeAuthorize/NodeList.vue",
    "content": "<style scoped>\n.block-clock {\n    width:540px;\n    height: 80px;\n    margin:15px auto;\n    border:1px solid #dddddd;\n}\n.countdown-img {\n    float: left;\n    height:80px;\n    line-height: 80px;\n}\n.countdown-img img {\n    width:60px;\n    height: 60px;\n}\n.countdown-text {\n    padding-right: 60px;\n    text-align: center;\n}\n.countdown-text p {\n    margin-bottom:10px;\n    font-family: 'AvenirNext-Medium';\n    color: #5E6369;\n    font-size: 16px;\n}\n.label {\n    font-size: 18px;\n    margin-left: 15px;\n}\n.detail-link {\n    text-align: center;\n    cursor: pointer;\n}\n.detail-link i {\n    font-size:20px;\n}\n\n.proportion-title p {\n    margin:0\n}\n.proportion-info-icon {\n    cursor: pointer;\n}\n\n.btn-history {\n    float: right;\n}\n.question-icon {\n    position:absolute;\n    top:10px;\n    right:10px;\n    font-size:18px;\n    cursor: pointer;\n}\n.node-name {\n    /* color: #227EEC !important; */\n}\n.node-name:hover {\n    color: #227EEC !important;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('nodeMgmt.stakeAuthorization')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n            <a-button type=\"primary\" class=\"btn-next btn-history\" @click=\"toStakeHistory\">{{$t('nodeMgmt.stakeHistory')}}</a-button>\n        <div class=\"block-clock\">\n            <div style=\"position:relative;\">\n                <div class=\"countdown-img\">\n                    <img src=\"../../../assets/countdown.svg\" alt=\"\">\n                </div>\n                <div class=\"countdown-text\">\n                    <p>{{$t('nodeMgmt.toNextRound')}}</p>\n                    <span class=\"font-medium-black\" style=\"font-size:20px;\">{{countdown}}</span>\n                    <span class=\"font-medium label\">{{$t('nodeMgmt.blocks')}}</span>\n                </div>\n                <span class=\"question-icon\" @click=\"toQuestion\"><a-icon type=\"question-circle-o\" /></span>\n            </div>\n        </div>\n        <a-table :columns=\"columns\"\n            :dataSource=\"node_list\"\n            :loading= \"requesting\"\n            :pagination=\"pagination\"\n            @change=\"handleTableChange\"\n        >\n            <div slot=\"nodeProportionTitle\"  class=\"proportion-title\">\n                <p>{{$t('nodeMgmt.proportionNextRound')}}\n                    <a-icon type=\"info-circle-o\" class=\"proportion-info-icon\" @click=\"showProportionTip\"/>\n                </p>\n                </div>\n            <span slot=\"nodeProportion\" slot-scope=\"text, record\">{{record.nodeProportion}} / {{record.userProportion}}</span>\n            <a slot=\"name\" slot-scope=\"text, record\" class=\"node-name\" :class=\"record.status ===2 ? 'node-consensus' : 'node-candidate' \"\n                @click=\"handleNodeDetail(record)\">\n\n                <a-tooltip placement=\"top\" :title=\"$t('nodeMgmt.consensusNode')\">\n                    <a-icon type=\"star\" v-if=\"record.status === 2\" />\n                </a-tooltip>\n                <a-tooltip placement=\"top\" :title=\"$t('nodeMgmt.candidateNode')\">\n                    <a-icon type=\"star-o\" v-if=\"record.status === 1\" />\n                </a-tooltip>\n                {{text}}\n            </a>\n            <div slot=\"action\" slot-scope=\"text, record\" class=\"detail-link\" v-if=\"record.maxAuthorize>0 && record.process !== '100.00%'\">\n                <a-icon type=\"arrow-right\" @click=\"handleAuthorizeLogin(record)\" v-if=\"record.maxAuthorize>0\"/>\n            </div>\n\n        </a-table>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport {mapState} from 'vuex'\nimport { open } from '../../../core/utils'\nexport default {\n    name: 'NodeList',\n    components: {\n        Breadcrumb\n    },\n    data() {\n        const columns = [\n            {\n                title: this.$t('nodeMgmt.rank'),\n                dataIndex: 'rank',\n                key:'rank'\n            },\n            {\n                title: this.$t('nodeMgmt.name'),\n                dataIndex: 'name',\n                key: 'name',\n                scopedSlots: {customRender: 'name'}\n            },\n            {\n                dataIndex: 'nodeProportion',\n                key: 'nodeProportion',\n                slots: {title: 'nodeProportionTitle'},\n                scopedSlots: {customRender: 'nodeProportion'}\n            },\n            {\n                title: this.$t('nodeMgmt.currentStake'),\n                dataIndex: 'currentStake',\n                key: 'currentStake'\n            },\n            {\n                title: this.$t('nodeMgmt.process'),\n                dataIndex: 'process',\n                key: 'process'\n            },\n            {\n                title: '',\n                key: 'action',\n                scopedSlots: {customRender:'action'}\n            }\n        ]\n        return {\n            columns,\n            intervalId:'',\n            pagination: {\n                current:1,\n                pageSize:10,\n                total:30\n            },\n            requesting: false\n        }\n    },\n    mounted(){\n        this.requesting = true;\n        const net = localStorage.getItem('net')\n        this.fetchList()\n        // if(net === 'TEST_NET') {\n        //     this.$store.dispatch('fetchAllSortedNodeList').then(res => {\n        //         this.pagination.total = res.length;\n        //         this.fetchList()\n        //     })\n        // } else {\n        //     this.fetchList()\n        // }\n\n        this.$store.dispatch('fetchBlockCountdown')\n        this.intervalId = setInterval(()=>{\n            // this.$store.dispatch('fetchNodeList')\n            this.$store.dispatch('fetchBlockCountdown')\n        }, 6000)\n    },\n    beforeDestroy(){\n        clearInterval(this.intervalId);\n    },\n    computed:{\n        ...mapState({\n            node_list: state => state.NodeAuthorization.node_list,\n            countdown: state => state.NodeAuthorization.countdown\n        })\n    },\n    methods: {\n        handleRouteBack() {\n            this.$router.go(-1);\n        },\n        handleAuthorizeLogin(record, item){\n            console.log(record)\n            this.$store.commit('UPDATE_STAKE_AUTHORIZATION_WALLET', {stakeWallet:''})\n            this.$store.commit('UPDATE_CURRENT_NODE', {current_node: record})\n            this.$router.push({name: 'AuthorizeLogin'})\n        },\n        handleNodeDetail(record, item) {\n            console.log(record);\n            open(record.detailUrl)\n        },\n        handleTableChange(pagination) {\n            console.log(pagination)\n            this.pagination = pagination;\n            this.fetchList()\n        },\n        fetchList() {\n            this.requesting = true;\n            this.$store.dispatch('fetchNodeListNew', {\n                pageSize: this.pagination.pageSize,\n                pageNum: this.pagination.current - 1\n            }).then(res => {\n                this.requesting = false;\n                this.pagination.total = res;\n            })\n        },\n        showProportionTip() {\n            const h = this.$createElement\n            const title = this.$t('nodeMgmt.proportionNextRound')\n            const content = this.$t('nodeMgmt.proportionNextRoundTip')\n            const faqLink = this.$t('nodeMgmt.authorizationFAQ')\n            this.$info({\n                title: title,\n                content: h('div',{}, [\n                h('p', {\n                    style: {\n                        margin:0,\n                        whiteSpace: 'pre-line'\n                    }\n                },content),\n                h('a', {\n                    attrs: {\n                        name: 'FAQ'\n                    },\n                    style: {\n                        color: '#40a9ff',\n                        textDecoration: 'underline'\n                    },\n                    on: {\n                        click: () => {\n                            const url = 'https://medium.com/ontologynetwork/owallet-stake-authorization-faq-4a4bce224122'\n                            open(url);\n                        }\n                    }\n                }, faqLink),\n                ]),\n                onOk() {},\n            });\n        },\n        handleFAQLink(e) {\n            e = e || window.event;\n            var target = e.target || e.srcElement;\n            console.log(target)\n            alert('helo')\n        },\n        toStakeHistory() {\n            this.$router.push({name: 'StakeHistory'})\n        },\n        toQuestion() {\n            let url = \"https://medium.com/ontologynetwork/owallet-stake-authorization-faq-4a4bce224122\";\n\n            open(url)\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeAuthorize/Sesameseed/AuthorizationMgmtSesameseed.vue",
    "content": "<style scoped>\n.content-container {\n  display: flex;\n}\n\n.left-half {\n  flex-basis: 55%;\n  padding-right: 20px;\n}\n\n.right-half {\n  flex-basis: 50%;\n  padding-left: 40px;\n  border-left: 1px solid #dddddd;\n}\n.label {\n  font-size: 16px;\n}\n\n.refresh-icon {\n  color: #000000;\n  font-size: 16px;\n  cursor: pointer;\n  margin-left: 20px;\n}\n\n.switch-wallet {\n  margin-left: 20px;\n  cursor: pointer;\n  color: #000000;\n  font-size: 16px;\n}\n\n.new-stake {\n  margin: 15px 0;\n  border-radius: 0;\n}\n\n.in-authorization {\n  margin: 15px 0 0 0;\n}\n.authorize-tip {\n  font-size: 16px;\n  margin-bottom: 15px;\n}\n.tip-font {\n  font-size: 12px;\n}\n.cancel-btn {\n  margin: 15px 0;\n  border-radius: 0;\n}\n.redeem-item {\n  width: 100%;\n}\n.redeem-item span:first-child {\n  width: 150px;\n  display: inline-block;\n}\n.redeem-item button {\n  margin-left: 20px;\n}\n.redeem-ont {\n  margin: 15px 0;\n}\n.redeem-btn {\n  width: 100px;\n  height: 36px;\n  border-radius: 0;\n  background: #fbe45a;\n  padding: 0;\n  font-family: AvenirNext-Medium;\n  font-size: 14px;\n  color: #5e6369;\n  border: none;\n  margin-bottom: 15px;\n}\n.cancel-stake-input {\n  width: 200px;\n}\n</style>\n<template>\n  <div>\n    <breadcrumb :current=\"$t('nodeMgmt.stakeAuthorization')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n    <div class=\"content-container\">\n      <div class=\"left-half\">\n        <div>\n          <span class=\"font-medium-black label\">{{$t('nodeMgmt.nodeName')}}:</span>\n          <span class=\"font-medium\">Sesameseed</span>\n        </div>\n        <div>\n          <span class=\"label font-medium-black\">{{$t('nodeMgmt.walletAddress')}}:</span>\n          <span class=\"font-medium\">{{stakeWallet.address}}</span>\n          <a-tooltip placement=\"top\" :title=\"$t('nodeMgmt.switchWallet')\">\n            <span class=\"switch-wallet\" @click=\"switchWallet\">\n              <a-icon type=\"sync\" />\n            </span>\n          </a-tooltip>\n        </div>\n        <a-button\n          type=\"primary\"\n          class=\"btn-next new-stake\"\n          @click=\"newStakeAuthorization\"\n        >{{$t('nodeMgmt.newStakeAuthorization')}}</a-button>\n        <div class=\"in-authorization\">\n          <span class=\"label font-medium-black\">{{$t('nodeMgmt.inAuthorization')}}:</span>\n          <span class=\"font-medium\">{{ssInfo.votes}} ONT</span>\n        </div>\n        <div class=\"authorize-tip\">\n          <a-icon type=\"info-circle\" />\n          <span class=\"font-regular tip-font\">{{$t('sesameseed.authorizeTip')}}</span>\n        </div>\n        <a-button\n          type=\"default\"\n          class=\"cancel-btn\"\n          @click=\"cancelAuthorization\"\n        >{{$t('nodeMgmt.cancelAuthorization')}}</a-button>\n        <div class=\"redeem-ont\">\n          <p>\n            <span class=\"font-medium-black label\">\n              <a-tooltip placement=\"right\" :title=\"$t('sesameseed.pendingWithdrawals')\">\n                <a-icon type=\"info-circle-o\" />\n              </a-tooltip>\n              {{$t('sesameseed.pendingWithdrawals')}}:\n            </span>\n            <span class=\"font-medium\">{{ssInfo.pendingWithdrawals}} ONT</span>\n          </p>\n        </div>\n      </div>\n      <!-- <div class=\"right-half\">\n\n      </div>-->\n    </div>\n    <a-modal\n      :title=\"$t('nodeMgmt.cancelAuthorization')\"\n      :visible=\"cancelVisible\"\n      @ok=\"handleCancelAuthorizationOk\"\n      @cancel=\"handleCancelAuthorizationCancel\"\n    >\n      <div>\n        <div>\n          <span class=\"font-medium-black label\">{{$t('nodeMgmt.nodeName')}}:</span>\n          <span class=\"font-medium\">{{current_node.name}}</span>\n        </div>\n        <div class=\"in-authorization\">\n          <span class=\"label font-medium-black\">{{$t('nodeMgmt.inAuthorization')}}:</span>\n          <span class=\"font-medium\">{{ssInfo.votes}} ONT</span>\n        </div>\n        <div>\n          <span class=\"label font-medium-black\">{{$t('nodeMgmt.unitToCancel')}}:</span>\n          <a-input\n            class=\"input cancel-stake-input\"\n            :class=\"validCancelAmount? '': 'error-input'\"\n            v-model=\"cancelAmount\"\n            @change=\"validateCancelAmount\"\n          ></a-input>\n          {{$t('nodeMgmt.cancelUnits')}}\n        </div>\n        <div>\n          <span class=\"label font-medium-black\">{{$t('nodeMgmt.amountToCancel')}}:</span>\n          <span class=\"font-medium\">{{cancelAmount}} ONT</span>\n        </div>\n      </div>\n    </a-modal>\n    <sign-send-tx\n      :visible=\"signVisible\"\n      :tx=\"tx\"\n      :wallet=\"stakeWallet\"\n      v-on:signClose=\"handleCancel\"\n      v-on:txSent=\"handleTxSent\"\n    ></sign-send-tx>\n  </div>\n</template>\n<script>\nimport Breadcrumb from \"../../../Breadcrumb\";\nimport { mapState } from \"vuex\";\nimport SignSendTx from \"../../../Common/SignSendTx\";\nimport { GAS_PRICE, GAS_LIMIT } from \"../../../../core/consts\";\nimport { Crypto, TransactionBuilder, utils } from \"ontology-ts-sdk\";\nimport numeral from \"numeral\";\nimport { varifyPositiveInt } from \"../../../../core/utils.js\";\nimport { CONTRACT_HASH } from \"./SesameseedVars\";\n\nexport default {\n  name: \"AuthorizationMgmtSesameseed\",\n  components: {\n    Breadcrumb,\n    SignSendTx\n  },\n  data() {\n    return {\n      intervalId: \"\",\n      signVisible: false,\n      // inAuthorization: 0,\n      // locked: 0,\n      // claimable:0,\n      tx: \"\",\n      cancelVisible: false,\n      cancelAmount: 0,\n      validCancelAmount: true\n    };\n  },\n  mounted() {\n    //fetch stake info\n    // const pk = this.stakeDetail.publicKey\n    this.refresh();\n    this.intervalId = setInterval(() => {\n      this.refresh();\n    }, 10000);\n  },\n  beforeDestroy() {\n    clearInterval(this.intervalId);\n  },\n\n  computed: {\n    ...mapState({\n      current_node: state => state.NodeAuthorization.current_node,\n      stakeWallet: state => state.NodeStake.stakeWallet,\n      splitFee: state => state.NodeAuthorization.splitFee,\n      authorizationInfo: state => state.NodeAuthorization.authorizationInfo,\n      peer_attrs: state => state.NodeAuthorization.peer_attrs,\n      unboundOng: state => state.NodeAuthorization.peerUnboundOng,\n      ssInfo: state => state.NodeAuthorizationSesameseed.sesameseed\n    }),\n  },\n  methods: {\n    refresh() {\n      const address = this.stakeWallet.address;\n      const pk = this.current_node.pk;\n      this.$store.dispatch(\"fetchAuthorizationInfo\", { pk, address });\n      this.$store.dispatch(\"fetchSplitFee\", address);\n      this.$store.dispatch(\"fetchPeerAttributes\", pk);\n      this.$store.dispatch(\"fetchPeerUnboundOng\", address);\n      this.$store.dispatch(\"fetchSSPerInfo\", address);\n    },\n    handleRouteBack() {\n      this.$router.go(-1);\n    },\n    newStakeAuthorization() {\n      this.$router.push({ name: \"NewAuthorizationSesameseed\" });\n    },\n    switchWallet() {\n      this.$router.push({ name: \"AuthorizeLoginSesameseed\" });\n    },\n    handleRefresh() {\n      this.$store.dispatch(\"showLoadingModals\");\n      setTimeout(() => {\n        this.$store.dispatch(\"hideLoadingModals\");\n      }, 100);\n      const address = this.stakeWallet.address;\n      const pk = this.current_node.pk;\n      this.$store.dispatch(\"fetchAuthorizationInfo\", { pk, address });\n      this.$store.dispatch(\"fetchSplitFee\", address);\n      this.$store.dispatch(\"fetchPeerAttributes\", pk);\n      this.$store.dispatch(\"fetchSSPerInfo\", address);\n    },\n    handleCancel() {\n      this.signVisible = false;\n      this.tx = \"\";\n      this.cancelAmount = 0;\n    },\n    handleTxSent() {\n      this.signVisible = false;\n      // this.tx = ''\n      this.cancelAmount = 0;\n      this.refresh();\n      const address = this.stakeWallet.address;\n      const pk = this.current_node.pk;\n      const record = {\n        indexKey: address + \"-\" + pk,\n        stakeWalletAddress: address,\n        nodePk: pk,\n        nodeName: this.current_node.name\n      };\n      const txHash = utils.reverseHex(this.tx.getHash());\n      this.tx = \"\";\n      // this.$store.dispatch('recordStakeHistory', {txHash, record})\n    },\n    validateCancelAmount() {\n      if (!this.cancelAmount || !varifyPositiveInt(this.cancelAmount)) {\n        this.validCancelAmount = false;\n        return;\n      }\n      if (Number(this.cancelAmount) > this.ssInfo.votes) {\n        this.validCancelAmount = false;\n        return;\n      }\n      this.validCancelAmount = true;\n    },\n    handleCancelAuthorizationOk() {\n      if (!this.cancelAmount || !this.validCancelAmount) {\n        this.$message.error(this.$t(\"nodeMgmt.invalidInput\"));\n        return;\n      }\n      this.cancelVisible = false;\n      this.signVisible = true;\n      const userAddr = new Crypto.Address(this.stakeWallet.address);\n      const amount = Number(this.cancelAmount);\n      const tx = TransactionBuilder.makeTransactionsByJson({\n        action: \"invoke\",\n        params: {\n          login: true,\n          invokeConfig: {\n            contractHash: CONTRACT_HASH,\n            functions: [\n              {\n                operation: \"Unvote\",\n                args: [\n                  {\n                    name: \"from_acct\",\n                    value: \"Address:\" + this.stakeWallet.address\n                  },\n                  {\n                    name: \"amount\",\n                    value: amount\n                  }\n                ]\n              }\n            ],\n            gasLimit: GAS_LIMIT,\n            gasPrice: GAS_PRICE,\n            payer: this.stakeWallet.address\n          }\n        }\n      });\n      this.tx = tx[0];\n      this.cancelAmount = 0;\n    },\n    handleCancelAuthorizationCancel() {\n      this.cancelVisible = false;\n    },\n    cancelAuthorization() {\n      this.cancelVisible = true;\n      this.tx = \"\";\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeAuthorize/Sesameseed/AuthorizeLoginSesameseed.vue",
    "content": "<style scoped>\n.auth-login {\n    width:540px;\n    margin:20px auto;\n}\n.select-wallet {\n    width:100%;\n}\n.change-payer-radio {\n    width:100%;\n}\n.payer-radio-item {\n    margin-bottom:20px;\n}\n.btn-container {\n    text-align: center;\n    margin:5px auto;\n    padding-top:15px;\n}\n.btn-container p {\n    margin-bottom:5px;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('nodeMgmt.stakeAuthorization')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"auth-login\">\n            <div class=\"intro-item\">\n                <p class=\"font-medium-black\">{{$t('nodeStake.selectStakeWallet')}}</p>\n                <a-radio-group @change=\"changePayerWallet\" v-model=\"payerWalletType\" class=\"change-payer-radio\">\n                <a-radio value=\"commonWallet\" class=\"payer-radio-item\">{{$t('createIdentity.commonWallet')}}</a-radio>\n                <a-radio value=\"ledgerWallet\" class=\"payer-radio-item\">{{$t('createIdentity.ledgerWallet')}}</a-radio>\n\n                <div v-if=\"payerWalletType === 'commonWallet'\">\n                    <a-select :options=\"normalWallet\" class=\"select-wallet\" v-model=\"payerWalletValue\"\n                    :placeholder=\"$t('createIdentity.selectCommonWallet')\"\n                        @change=\"handleChangePayer\">\n                    </a-select>\n                </div>\n\n                <div v-if=\"payerWalletType === 'ledgerWallet'\">\n\n                    <div class=\"payer-ledger-status\">\n                    <div class=\"font-bold\" style=\"margin-bottom: 10px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                    <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}} </span>\n                    </div>\n                    \n                </div>\n                </a-radio-group>\n            </div>\n        </div>\n        <div class=\"footer-btns\">\n            <div class=\"btn-container\">\n                <!-- <p class=\"font-medium\"><a-icon type=\"exclamation-circle\" /> {{$t('nodeMgmt.userParticipate')}}</p> -->\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{$t('nodeStake.next')}}</a-button>\n            </div>\n        </div>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../../Breadcrumb'\nimport {mapState} from 'vuex'\nexport default {\n    name: 'AuthorizeLoginSesameseed',\n    components: {\n        Breadcrumb\n    },\n    data(){\n        return {\n            payerWalletType: 'commonWallet',\n            payerWalletValue: undefined\n        }\n    },\n    mounted() {\n        this.$store.dispatch(\"fetchWalletsFromDb\").then(() => {\n            //set payer wallet \n        });\n        const stakeAuthorizationWalletAddress = this.$store.state.NodeAuthorization.stake_authorization_wallet;\n        if(stakeAuthorizationWalletAddress) {\n            const index = this.$store.state.Wallets.NormalWallet.findIndex((w)=> w.address === stakeAuthorizationWalletAddress.address)\n            if(index > -1) {\n                this.payerWalletType = 'commonWallet'\n                this.payerWalletValue = stakeAuthorizationWalletAddress\n                this.payerWallet = this.$store.state.Wallets.NormalWallet[index]\n            } else {    \n                this.payerWalletType = 'ledgerWallet'\n                this.$store.dispatch('getLedgerStatus')\n            } \n        }\n\n    },\n    beforeDestroy(){\n        this.$store.dispatch('stopGetLedgerStatus')\n    },\n    computed: {\n        ...mapState({\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n            ledgerWallet: state => state.LedgerConnector.ledgerWallet\n        }),\n        normalWallet: {\n            get() {\n                const list = this.$store.state.Wallets.NormalWallet.slice();\n                return list.map(i => {\n                    return Object.assign({}, i, {\n                        label: i.label + \" \" + i.address,\n                        value: i.address\n                    });\n                });\n            }\n        },\n    },\n    methods: {\n        handleRouteBack() {\n            this.$router.go(-1);\n        },\n        changePayerWallet(e) {\n            this.payerWalletType = e.target.value\n            if(e.target.value === 'ledgerWallet') {\n                this.$store.dispatch('getLedgerStatus')\n            } else {\n                this.$store.dispatch('stopGetLedgerStatus')\n            }\n        },\n        handleChangePayer(value) {\n            this.payerWallet = this.normalWallet.find((v)=>{return v.address === value})\n            this.payerWalletValue = this.payerWallet.address\n        },\n        next() {\n            if(this.payerWalletType === 'commonWallet' && !this.payerWallet) {\n                this.$message.error(this.$t('nodeStake.selectIndividualWallet'))\n                return;\n            }\n            if(this.payerWalletType === 'ledgerWallet' && !this.ledgerWallet.address) {\n                this.$message.error(this.$t('nodeStake.selectLedgerWallet'))\n                return;\n            }\n            let stakeWallet = ''\n            if(this.payerWalletType === 'commonWallet' && this.payerWallet){\n                stakeWallet = this.payerWallet\n            } else {\n                stakeWallet = this.ledgerWallet\n            }\n            this.$store.commit('UPDATE_STAKE_WALLET', {stakeWallet: stakeWallet})             \n            this.$router.push({name: 'AuthorizationMgmtSesameseed'})\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeAuthorize/Sesameseed/NewAuthorizationSesameseed.vue",
    "content": "<style scoped>\n.content-container {\n  width: 540px;\n  margin: 20px auto;\n}\n.content-container div {\n  margin-bottom: 15px;\n}\n.label {\n  font-size: 16px;\n}\n.authorize-tip {\n  font-size: 16px;\n  padding-left: 15px;\n}\n.error-input {\n  border-color: red !important;\n}\n.unit-input {\n  width: 100px;\n}\n.btn-container {\n  text-align: center;\n}\n</style>\n\n<template>\n  <div>\n    <breadcrumb :current=\"$t('nodeMgmt.stakeAuthorization')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n    <div class=\"content-container\">\n      <div>\n        <span class=\"font-medium-black label\">{{$t('nodeMgmt.nodeName')}}:</span>\n        <span class=\"font-medium\">{{current_node.name}}</span>\n      </div>\n      <div>\n        <span class=\"font-medium-black label\">{{$t('nodeMgmt.allowedStakeAmount')}}:</span>\n        <span class=\"font-medium\">{{current_node.maxAuthorizeStr}} ONT</span>\n      </div>\n      <div>\n        <span class=\"font-medium-black label\">{{$t('nodeMgmt.totalStakeAmount')}}:</span>\n        <span class=\"font-medium\">{{current_node.totalPosStr}} ONT</span>\n      </div>\n      <div>\n        <span class=\"label font-medium-black\">{{$t('nodeMgmt.walletAddress')}}:</span>\n        <span class=\"font-medium\">{{stakeWallet.address}}</span>\n      </div>\n      <div>\n        <span class=\"font-medium-black label\">{{$t('nodeMgmt.units')}}:</span>\n        <a-input\n          type=\"text\"\n          class=\"input unit-input\"\n          v-model=\"units\"\n          @change=\"handleChange\"\n          :class=\"validInput? '' : 'error-input'\"\n        ></a-input>\n      </div>\n      <p class=\"authorize-tip\">\n        <a-icon type=\"info-circle\" />\n        <span class=\"font-regular\">{{$t('sesameseed.stakeAmountTip')}}</span>\n      </p>\n      <div>\n        <span class=\"font-medium-black label\">{{$t('nodeMgmt.stakeAmount')}}:</span>\n        <span class=\"font-medium\">{{amount}} ONT</span>\n      </div>\n    </div>\n    <div class=\"footer-btns\">\n      <div class=\"btn-container\">\n        <a-button type=\"primary\" class=\"btn-next\" @click=\"submit\">{{$t('nodeMgmt.submit')}}</a-button>\n      </div>\n    </div>\n\n    <sign-send-tx\n      :visible=\"signVisible\"\n      :tx=\"tx\"\n      :wallet=\"stakeWallet\"\n      v-on:signClose=\"handleCancel\"\n      v-on:txSent=\"handleTxSent\"\n    ></sign-send-tx>\n  </div>\n</template>\n<script>\nimport Breadcrumb from \"../../../Breadcrumb\";\nimport { varifyPositiveInt } from \"../../../../core/utils.js\";\nimport SignSendTx from \"../../../Common/SignSendTx\";\nimport { mapState } from \"vuex\";\nimport { GAS_LIMIT, GAS_PRICE } from \"../../../../core/consts\";\nimport { Crypto, TransactionBuilder, utils } from \"ontology-ts-sdk\";\nimport { CONTRACT_HASH } from \"./SesameseedVars\";\n\nexport default {\n  name: \"NewAuthorizationSesameseed\",\n  components: {\n    Breadcrumb,\n    SignSendTx\n  },\n  data() {\n    return {\n      units: 1,\n      amount: 1,\n      validInput: true,\n      signVisible: false,\n      tx: \"\"\n    };\n  },\n  computed: {\n    ...mapState({\n      current_node: state => state.NodeAuthorization.current_node,\n      stakeWallet: state => state.NodeStake.stakeWallet,\n      peer_attrs: state => state.NodeAuthorization.peer_attrs\n    })\n  },\n  methods: {\n    handleRouteBack() {\n      this.$router.go(-1);\n    },\n    handleChange() {\n      if (!this.units || !varifyPositiveInt(this.units)) {\n        this.validInput = false;\n        return;\n      }\n      this.amount = parseInt(this.units);\n      if (\n        this.units &&\n        this.amount >\n          this.current_node.maxAuthorize - this.current_node.totalPos\n      ) {\n        this.validInput = false;\n        return;\n      }\n\n      this.validInput = true;\n    },\n    handleCancel() {\n      this.signVisible = false;\n      this.tx = \"\";\n    },\n    handleTxSent() {\n      this.signVisible = false;\n      // this.tx = ''\n      this.$router.go(-1);\n      //record stake history\n      const address = this.stakeWallet.address;\n      const pk = this.current_node.pk;\n      const record = {\n        indexKey: address + \"-\" + pk,\n        stakeWalletAddress: address,\n        nodePk: pk,\n        nodeName: this.current_node.name\n      };\n      const txHash = utils.reverseHex(this.tx.getHash());\n      this.tx = \"\";\n      // this.$store.dispatch('recordStakeHistory', {txHash, record})\n    },\n    submit() {\n      if (!this.validInput) {\n        this.$message.error(this.$t(\"nodeMgmt.invalidInput\"));\n        return;\n      }\n      const userAddr = new Crypto.Address(this.stakeWallet.address);\n      const tx = TransactionBuilder.makeTransactionsByJson({\n        action: \"invoke\",\n        params: {\n          login: true,\n          message: \"Sesameseed Vote\",\n          invokeConfig: {\n            contractHash: CONTRACT_HASH,\n            functions: [\n              {\n                operation: \"Vote\",\n                args: [\n                  {\n                    name: \"from_acct\",\n                    value: \"Address:\" + this.stakeWallet.address\n                  },\n                  {\n                    name: \"amount\",\n                    value: this.amount\n                  }\n                ]\n              }\n            ],\n            gasLimit: GAS_LIMIT,\n            gasPrice: GAS_PRICE,\n            payer: this.stakeWallet.address\n          }\n        }\n      });\n      this.tx = tx[0];\n      this.signVisible = true;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeAuthorize/Sesameseed/SesameseedVars.js",
    "content": "export const CONTRACT_HASH = 'a63c33d2209854feafbf40685a33d4846ee82556'\nexport const SESAMESEED_NODE_ADDRESS = 'ANRRE8xKwKzuaCeAjP6eZYDnVi7n2x6byE'\n"
  },
  {
    "path": "src/components/Node/NodeAuthorize/StakeHistory.vue",
    "content": "<style scoped>\n.detail-link {\n    text-align: center;\n    cursor: pointer;\n}\n.detail-link i {\n    font-size:20px;\n}\n\n.auth-login {\n    width:540px;\n    margin:20px auto;\n}\n.select-wallet {\n    width:100%;\n}\n.change-payer-radio {\n    width:100%;\n}\n.payer-radio-item {\n    margin-bottom:20px;\n}\n.stake-btn-container {\n    width: 540px;\n    margin: 25px auto;\n    text-align: center;\n}\n</style>\n\n<template>\n    <div>\n        <breadcrumb :current=\"$t('nodeMgmt.stakeHistory')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"auth-login\">\n            <div class=\"intro-item\">\n                <p class=\"font-medium-black\" style=\"margin-bottom: 10px\">{{$t('nodeStake.selectStakeWallet')}}</p>\n\n                <div>\n                    <a-select :options=\"normalWalletAndLedgerWallet\" class=\"select-wallet\" v-model=\"payerWalletValue\"\n                    :placeholder=\"$t('createIdentity.selectCommonWallet')\"\n                        @change=\"handleChangePayer\">\n                    </a-select>\n                </div>\n            </div>\n            <div class=\"stake-btn-container\">\n                <!-- <p class=\"font-medium\"><a-icon type=\"exclamation-circle\" /> {{$t('nodeMgmt.userParticipate')}}</p> -->\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"handleSearch\" :disabled=\"requesting\">{{$t('nodeStake.search')}}</a-button>\n            </div>\n        </div>\n        <a-table :columns=\"columns\"\n        :dataSource=\"stakeHistory\"\n        :loading=\"requesting\"\n        >\n        <div slot=\"action\" slot-scope=\"text, record\" class=\"detail-link\">\n            <a-icon type=\"arrow-right\" @click=\"handleAuthorizeLogin(record)\"/>\n        </div>\n\n        </a-table>\n    </div>\n</template>\n\n<script>\nimport {mapState} from 'vuex'\nimport Breadcrumb from '../../Breadcrumb'\n\nexport default {\n    name: 'StakeHistory',\n    data() {\n        const columns = [\n            {\n                title: this.$t('nodeMgmt.name'),\n                dataIndex: 'name',\n                key:'name'\n            },\n            // {\n            //     title: this.$t('nodeMgmt.stakeWalletAddress'),\n            //     dataIndex: 'stakeWalletAddress',\n            //     key: 'stakeWalletAddress'\n            // },\n\n            {\n                title: this.$t('nodeMgmt.inAuthorization'),\n                dataIndex: 'inAuthorization',\n                key: 'inAuthorization'\n            },\n            {\n                title: this.$t('nodeMgmt.locked'),\n                dataIndex: 'locked',\n                key: 'locked'\n            },\n            {\n                title: this.$t('nodeMgmt.claimableONT'),\n                dataIndex: 'claimable',\n                key: 'claimable'\n            },\n            \n            {\n                title: '',\n                key: 'action',\n                scopedSlots: {customRender:'action'}\n            }\n        ]\n        return {\n            columns,\n            payerWalletType: 'commonWallet',\n            payerWalletValue: undefined,\n            stakeWallet:'',\n            payerWallet: '',\n            requesting: false\n        }\n    },\n    components:{\n        Breadcrumb\n    },\n    mounted() {\n        // this.$store.commit('CLEAR_STAKE_HISTORY')\n        this.$store.dispatch(\"fetchWalletsFromDb\").then(() => {\n            //set payer wallet \n        });\n        // const stakeAuthorizationWalletAddress = this.$store.state.NodeAuthorization.stake_authorization_wallet;\n        // if(stakeAuthorizationWalletAddress) {\n        //     const index = this.$store.state.Wallets.NormalWallet.findIndex((w)=> w.address === stakeAuthorizationWalletAddress.address)\n        //     if(index > -1) {\n        //         this.payerWalletType = 'commonWallet'\n        //         this.payerWalletValue = stakeAuthorizationWalletAddress\n        //         this.payerWallet = this.$store.state.Wallets.NormalWallet[index]\n        //     } else {    \n        //         this.payerWalletType = 'ledgerWallet'\n        //         this.$store.dispatch('getLedgerStatus')\n        //     } \n        // }\n\n    },\n    beforeDestroy(){\n        this.$store.dispatch('stopGetLedgerStatus')\n    },\n    computed: {\n        ...mapState({\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n            ledgerWallet: state => state.LedgerConnector.ledgerWallet,\n            stakeHistory: state => state.NodeAuthorization.stakeHistory,\n        }),\n\n\t\tnormalWalletAndLedgerWallet: {\n\t\t\tget() {\n\t\t\t\tconst NormalList = this.$store.state.Wallets.NormalWallet.slice();\n\t\t\t\tconst LedgerList = this.$store.state.Wallets.HardwareWallet.slice();\n\n\t\t\t\tconst list1 = NormalList.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address,\n\t\t\t\t\t\tvalue: i.address\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tconst list2 = LedgerList.map(i => {\n\t\t\t\t\treturn Object.assign({}, i, {\n\t\t\t\t\t\tlabel: i.label + \" \" + i.address + \" (Ledger)\",\n\t\t\t\t\t\tvalue: i.address\n\t\t\t\t\t});\n\t\t\t\t});\n                list2.sort((a,b)=>{\n\t\t\t\t\tif (b.timestamp !== a.timestamp) {\n\t\t\t\t\t\treturn b.timestamp - a.timestamp;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn b.acct - a.acct;\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\treturn [...list1, ...list2];\n\t\t\t}\n\t\t}\n    },\n    methods: {\n        handleRouteBack() {\n            this.$router.go(-1);\n        },\n        handleAuthorizeLogin(record, item){\n            // this.$store.commit('UPDATE_STAKE_AUTHORIZATION_WALLET', {stakeWallet: this.stakeWallet})\n            // this.$router.push({name: 'AuthorizeLogin'})\n            this.$store.commit('UPDATE_CURRENT_NODE', {current_node : record})\n            this.$store.commit('UPDATE_STAKE_AUTHORIZATION_WALLET', {stakeWallet: record.stakeWallet})          \n            this.$router.push({name: 'AuthorizationMgmt'})\n        },\n        changePayerWallet(e) {\n            this.payerWalletType = e.target.value\n            if(e.target.value === 'ledgerWallet') {\n                this.$store.dispatch('getLedgerStatus')\n            }\n        },\n        handleChangePayer(value) {\n            this.payerWallet = this.normalWalletAndLedgerWallet.find((v)=>{return v.address === value})\n            this.payerWalletValue = this.payerWallet.address\n        },\n        handleSearch() {\n            if(this.payerWalletType === 'commonWallet' && !this.payerWallet) {\n                this.$message.error(this.$t('nodeStake.selectIndividualWallet'))\n                return;\n            }\n            if(this.payerWalletType === 'ledgerWallet' && !this.ledgerWallet.address) {\n                this.$message.error(this.$t('nodeStake.selectLedgerWallet'))\n                return;\n            }\n            if(this.payerWalletType === 'commonWallet' && this.payerWallet){\n                this.stakeWallet = this.payerWallet\n            } else {\n                this.stakeWallet = this.ledgerWallet\n            }\n            this.$store.commit('UPDATE_STAKE_WALLET', {stakeWallet: this.stakeWallet})  \n            this.requesting = true;\n            this.$store.dispatch('searchStakeHistory', {address: this.stakeWallet.address}).then(res => {\n                this.requesting = false;\n            })      \n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeManagement/MyNode.vue",
    "content": "<template>\n\t<div class=\"nodes-container\">\n\t\t<breadcrumb :current=\"$t('myNode.myNode')\"\n\t\t\tv-on:backEvent=\"back\"></breadcrumb>\n\t\t<ul class=\"nodes-list\">\n\t\t\t<li v-for=\"(item, index) of myNodes\"\n\t\t\t\t:key=\"index\">\n\t\t\t\t<div class=\"node-item\">\n\t\t\t\t\t<p class=\"node-name\">{{item.name}}</p>\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<label for=\"\">{{$t('myNode.stakeWalletAddress')}}</label>\n\t\t\t\t\t\t<p>{{item.stakeAddress}}</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<label for=\"\">{{$t('myNode.operationWalletPk')}}</label>\n\t\t\t\t\t\t<p>{{item.publicKey}}</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"btn-footer\">\n\t\t\t\t\t\t<a-button class=\"btn-next\" @click=\"onManage(item)\">{{$t('myNode.manage')}}</a-button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<div class=\"node-item node-item-create\"\n\t\t\t\t\t:class=\"[showCreate?'show-create-btn':'']\"\n\t\t\t\t\t@mouseenter=\"()=>{this.showCreate = true;}\"\n\t\t\t\t\t@mouseleave=\"()=>{this.showCreate = false;}\">\n\t\t\t\t\t<div class=\"node-create\"\n\t\t\t\t\t\tv-show=\"showCreate\">\n\t\t\t\t\t\t<router-link class=\"btn btn-default btn-create\"\n\t\t\t\t\t\t\t:to=\"{name: 'NodeApply'}\">{{$t('myNode.applyNode')}}</router-link>\n\t\t\t\t\t</div>\n\t\t\t\t\t<img class=\"img-wallet-create\"\n\t\t\t\t\t\tv-show=\"!showCreate\"\n\t\t\t\t\t\tsrc=\"../../../assets/create-wallet.png\"\n\t\t\t\t\t\talt=\"\">\n\t\t\t\t</div>\n\t\t\t</li>\n\t\t</ul>\n\t</div>\n</template>\n<script>\nimport { mapState } from \"vuex\";\nimport { GovernanceTxBuilder } from \"ontology-ts-sdk\";\nimport { getNodeUrl } from \"../../../core/utils\";\nimport { OFF_CHAIN_NODES, GovernanceStatus } from \"../../../core/consts\";\nimport axios from \"axios\";\nimport Breadcrumb from \"../../Breadcrumb\";\n\nexport default {\n\tname: \"MyNode\",\n\tdata() {\n\t\treturn {\n\t\t\tmyNodes: [],\n\t\t\tshowCreate: true\n\t\t};\n\t},\n\tcomponents: {\n\t\tBreadcrumb\n\t},\n\tcreated() {\n\t\tthis.$store.dispatch(\"fetchWalletsFromDb\");\n\t},\n\tcomputed: {\n        localWallets: {\n            get() {\n                const list1 = this.$store.state.Wallets.NormalWallet.slice();\n                const list2 = this.$store.state.Wallets.HardwareWallet.slice();\n                return [...list1, ...list2]\n            }\n        }\n\t},\n\twatch: {\n\t\tlocalWallets(newV, oldV) {\n\t\t\tif (newV && newV.length > 0) {\n\t\t\t\tthis.fetchMyNodes();\n\t\t\t}\n\t\t},\n\t},\n\tmethods: {\n\t\tback() {\n\t\t\tthis.$router.back();\n        },\n        // 先从off_chain 接口查询所有节点，用节点的stake address跟本地钱包（普通钱包和ledger钱包）的地址比对，\n        // 找出用户的节点，同时找出stake wallet，节点的运营公钥也能从接口获取到。\n        // 再将用户的节点跟链上的peerPoolMap进行比对，获取节点的状态。如果节点不在peerPoolMap中，表示节点已经退出\n\t\tasync fetchMyNodes() {\n            this.$store.dispatch('showLoadingModals')\n            const url = getNodeUrl();\n\t\t\tconst peers = await GovernanceTxBuilder.getPeerPoolMap(url);\n\t\t\tconst mynodes = [];\n            const net = localStorage.getItem(\"net\");\n\t\t\tconst off_chain_nodes_url = OFF_CHAIN_NODES[net];\n\t\t\tconst res = await axios.get(off_chain_nodes_url);\n            const result = res.data.result;\n\n            for(const wallet of this.localWallets) {\n                for(const resItem of result) {\n                    if(wallet.address === resItem.address) {\n                        const node ={\n                            publicKey: resItem.public_key,\n                            stakeAddress: wallet.address,\n                            stakeWallet: wallet,\n                            name: resItem.name || \"Node_\" + resItem.public_key.substr(0, 6)\n                        }\n                        const peerOnchain = peers[resItem.public_key]\n                        if(peerOnchain) {\n                            node.stakeAmount = peerOnchain.initPos + peerOnchain.totalPos\n                            node.status = peerOnchain.status\n                        } else {\n                            node.stakeAmount = 0 // 已退出节点\n                            node.status = GovernanceStatus.EXIXTED\n                        }\n                        mynodes.push(node)\n                    }\n                }\n            }\n\n            this.myNodes = mynodes;\n            this.$store.dispatch('hideLoadingModals')\n        },\n        onManage(node) {\n            this.$store.commit('UPDATE_STAKE_WALLET', {stakeWallet: node.stakeWallet})\n            this.$store.commit('UPDATE_NODE_PUBLICKEY', {nodePublicKey: node.publicKey})\n            this.$store.commit('UPDATE_NODE_STATUS', {status: node.status})\n\t\t\tthis.$store.commit('UPDATE_MENU_TAB_INDEX', 1)\n            this.$router.push({name: 'NodeStakeManagement'})\n        }\n\t}\n};\n</script>\n<style lang=\"scss\" scoped>\n.nodes-list {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tlist-style: none;\n}\n.node-item {\n\t.node-name {\n\t\tfont-family: AvenirNext-Medium;\n\t\tfont-size: 18px;\n\t\tcolor: #515457;\n\t\tmargin-bottom: 15px;\n\t}\n\tbackground-color: #f5f7fb;\n\tpadding: 1.25rem;\n\tposition: relative;\n\twidth: 440px;\n\n\tmargin-right: 40px;\n\tmargin-bottom: 40px;\n\theight: 250px;\n\t.info-item {\n\t\tmargin-bottom: 15px;\n\t\tfont-family: AvenirNext-Regular;\n\t\tfont-size: 14px;\n\t\tcolor: #b2b2b3;\n\t\tp {\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\t\t}\n\t}\n\t.btn-footer {\n\t\ttext-align: right;\n\t}\n}\n.show-create-btn {\n\tbackground-color: #498fef;\n}\n.node-item-create {\n\tdisplay: flex;\n\tjustify-content: center;\n\talign-items: center;\n}\n.btn-create {\n  width: unset;\n  color: white;\n  border: white solid 1px;\n  border-radius: 0;\n}\n</style>\n"
  },
  {
    "path": "src/components/Node/NodeManagement/NodeStakeAuthorization.vue",
    "content": "<style scoped>\n.content-container {\n    padding: 10px 10px;\n}\n.header-text {\n    font-size:16px;\n}\n\n.stake-content {\n    padding:10px;\n    border:1px solid #dddddd;\n    margin-top: 10px;\n}\n.change-ifAuthorize-radio {\n    margin-bottom:15px;\n}\n.change-ifAuthorize-radio label {\n    margin-right: 30px;\n}\n.status-radio-item {\n    /* font-size:14px; */\n    /* font-family: 'AvenirNext-Medium'; */\n    color: #000000;\n}\n.content-row {\n    display: flex;\n    flex-direction: row;\n    width:100%;\n    margin-bottom:10px;\n    padding-bottom:5px;\n    border-bottom:1px solid #dddddd;\n}\n.content-row div:first-child {\n    border-right: 1px solid #dddddd;\n}\n.content-column {\n    flex-basis: 50%;\n    padding: 5px 10px;\n}\n.content-column :first-child {\n    font-size:14px;\n    font-family: 'AvenirNext-Medium';\n    color: #5E6369;\n}\n.content-column :last-child {\n    float: right;\n    font-family: 'AvenirNext-Medium';\n    color: #000000;\n    font-size: 0.88rem;\n}\n.rewardsTip {\n\n}\n.reward-slider {\n    width:40%;\n    float: left;\n    margin-right: 16px;\n}\n.reward-input {\n    margin-top:5px;\n    width:50px\n}\n.current-proportion {\n    margin-left: 20px;\n}\n.rewardProportionTip {\n    float: left;\n    height: 40px;\n    line-height: 40px;\n    margin-right: 10px;\n    font-size: 16px;\n}\n.btn-confirm {\n    margin:5px auto;\n    text-align: center;\n}\n.btn-confirm p {\n    margin-bottom: 5px;\n}\n.error-input {\n    border-color:red !important;\n}\n.unit-input {\n    width:100px;\n    height:30px !important;\n    margin-right: 20px;\n}\n.allowed-stake {\n    margin:10px 15px;\n}\n.redeem-btn {\n    width: 100px;\n    height: 36px;\n    border-radius: 0;\n    background: #FBE45A;\n    padding: 0;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #5E6369;\n    border: none;\n    margin-bottom:15px;\n  }\n  .redeem-profit {\n      margin-top: 20px;\n  }\n  .redeem-profit p {\n      margin-bottom: 5px;\n  }\n  .label {\n      font-size: 16px;\n  }\n\n.redeem-item span:first-child {\n    display: inline-block;\n    width:130px;\n}\n.redeem-item button {\n    margin-left: 20px;\n}\n.node-reward-proportion {\n    margin-top:10px;\n    margin-right: 10px;\n    float:left;\n}\n.node-reward-proportion p {\n    margin:0;\n}\n.edit-proportion-btn {\n    margin-top: 10px;\n}\n.h-spacer {\n  display: inline-block;\n  width: 10px;\n}\n</style>\n<template>\n    <div class=\"content-container\">\n        <div class=\"font-medium-black header-text\">{{$t('nodeMgmt.allowStakes')}}</div>\n        <div class=\"allowed-stake\">\n            <span class=\"font-medium\">{{$t('nodeMgmt.allowedStakeUnits')}}: </span>\n            <a-input class=\"input unit-input\" :class=\"validUnit?'':'error-input' \" v-model=\"unit\"\n            @change=\"validateUnit\"\n            ></a-input>\n            <span class=\"font-medium\">{{$t('nodeMgmt.allowedStakeAmount')}}: </span>\n            <span>{{unit*unitVal}} ONT</span>\n            <span class=\"font-medium\" style=\"margin-left:20px;\">({{$t('nodeMgmt.current')}} {{peer_attrs.maxAuthorizeStr}} ONT)</span>\n            <p class=\"authorize-tip\">\n                <a-icon type=\"info-circle\" />\n                <span class=\"font-regular\">{{$t('nodeMgmt.stakeAmountTip')}}</span>\n            </p>\n            <a-button type=\"primary\" class=\"btn-next\" @click=\"confirmChangeAuthorization\">{{$t('nodeMgmt.confirm')}}</a-button>\n        </div>\n        <div class=\"stake-content\">\n            <div class=\"content-row\">\n                <div class=\"content-column\">\n                    <span>{{$t('nodeMgmt.yourStakeAmount')}}</span>\n                    <span>{{initPosStr}} ONT</span>\n                </div>\n                <div class=\"content-column\">\n                    <span>{{$t('nodeMgmt.stakeLimit')}}</span>\n                    <span>{{maxStakeLimit}} ONT</span>\n                </div>\n            </div>\n            <div class=\"content-row\">\n                <div class=\"content-column\">\n                    <span>{{$t('nodeMgmt.userStakeAmount')}}</span>\n                    <span>{{current_peer.totalPosStr}} ONT</span>\n                </div>\n            </div>\n\n            <div class=\"rewardsTip\">\n                <a-icon type=\"exclamation-circle-o\" />\n                <span class=\"font-regular\">{{$t('nodeMgmt.rewardsTip')}}</span>\n            </div>\n        </div>\n        <div class=\"clearfix\">\n            <div class=\"font-medium-black rewardProportionTip\">{{$t('nodeMgmt.rewardProportion')}}</div>\n            <div class=\"node-reward-proportion\">\n                <p class=\"font-medium\">{{$t('nodeMgmt.nodeRewardProportion')}}</p>\n                <p class=\"font-medium\">{{peer_attrs.tPeerCost}}%  ({{$t('nodeMgmt.activeT')}})</p>\n                <p class=\"font-medium\">{{peer_attrs.t1PeerCost}}%  ({{$t('nodeMgmt.activeT1')}})</p>\n                <p class=\"font-medium\">{{peer_attrs.t2PeerCost}}%  ({{$t('nodeMgmt.activeT2')}})</p>\n            </div>\n            <div class=\"node-reward-proportion\">\n                <p class=\"font-medium\">{{$t('nodeMgmt.userRewardProportion')}}</p>\n                <p class=\"font-medium\">{{peer_attrs.tStakeCost}}%  ({{$t('nodeMgmt.activeT')}})</p>\n                <p class=\"font-medium\">{{peer_attrs.t1StakeCost}}%  ({{$t('nodeMgmt.activeT1')}})</p>\n                <p class=\"font-medium\">{{peer_attrs.t2StakeCost}}%  ({{$t('nodeMgmt.activeT2')}})</p>\n            </div>\n            <a-button type=\"primary\" class=\"btn-next edit-proportion-btn\" @click=\"editProportion\">{{$t('nodeMgmt.edit')}}</a-button>\n        </div>\n\n\n\n        <div class=\"redeem-profit\">\n            <div class=\"redeem-item\">\n                <span class=\"font-medium-black label\">{{$t('nodeMgmt.profit')}}: </span>\n                <span class=\"font-medium\">{{splitFee.amount}} ONG</span>\n                <a-button type=\"primary\" class=\"redeem-btn\" @click=\"redeemRewards\">{{$t('nodeMgmt.redeem')}}</a-button>\n            </div>\n            <div class=\"redeem-item\">\n                <span class=\"font-medium-black label\">{{$t('nodeMgmt.unboundOng')}}: </span>\n                <span class=\"font-medium\">{{peerUnboundOng}} ONG</span>\n                <a-button type=\"primary\" class=\"redeem-btn\" @click=\"redeemPeerUnboundOng\">{{$t('nodeMgmt.redeem')}}</a-button>\n            </div>\n        </div>\n\n        <sign-send-tx :visible=\"signVisible\" :tx=\"tx\"  :wallet=\"stakeWallet\"\n        v-on:signClose=\"handleCancel\"\n        v-on:txSent=\"handleTxSent\"\n        ></sign-send-tx>\n\n        <a-modal\n            :title=\"$t('nodeMgmt.changeRewardProportion')\"\n            :visible=\"showEditProportion\"\n            @ok=\"confirmChangeCost\"\n            @cancel=\"handleCancelChangeCost\"\n            >\n            <div class=\"clearfix\">\n              {{$t('nodeMgmt.nodeRewardProportion')}}:\n              <a-input-number\n                  :min=\"0\"\n                  :max=\"100\"\n                  class=\"reward-input\"\n                  v-model=\"peerCost\"\n                  style=\"width:60px;\"\n              /> %\n              <span class=\"h-spacer\" />\n              {{$t('nodeMgmt.userRewardProportion')}}:\n              <a-input-number\n                  :min=\"0\"\n                  :max=\"100\"\n                  class=\"reward-input\"\n                  v-model=\"stakeCost\"\n                  style=\"width:60px;\"\n              /> %\n            </div>\n            <div style=\"margin-top:5px;\">\n                <a-icon type=\"exclamation-circle-o\" />\n                <span>{{$t('nodeMgmt.nodeRewardProportionTip')}}</span>\n            </div>\n            <div style=\"margin-top:5px;\">\n                <a-icon type=\"exclamation-circle-o\" />\n                <span>{{$t('nodeMgmt.userRewardProportionTip')}}</span>\n            </div>\n            <div style=\"margin-top:5px;\">\n                <a-icon type=\"exclamation-circle-o\" />\n                <span>{{$t('nodeMgmt.changesTakeEffect')}}</span>\n            </div>\n\n        </a-modal>\n    </div>\n</template>\n<script>\nimport {mapState} from 'vuex'\nimport {varifyPositiveInt} from '../../../core/utils.js'\nimport {GAS_PRICE, GAS_LIMIT} from '../../../core/consts'\nimport numeral from 'numeral'\nimport SignSendTx from '../../Common/SignSendTx'\nimport {Crypto, GovernanceTxBuilder} from 'ontology-ts-sdk'\nexport default {\n    name: 'NodeStakeAuthorization',\n    components: {\n        SignSendTx\n    },\n    data(){\n        return {\n            peerCost: 0,\n            stakeCost: 0,\n            validUnit:true,\n            unit:0,\n            intervalId:0,\n            signVisible: false,\n            tx: '',\n            showEditProportion: false,\n            unitVal: 1\n        }\n    },\n    mounted() {\n        //fetch stake info\n        this.refresh()\n        this.intervalId = setInterval(()=>{\n            this.refresh()\n        }, 10000)\n    },\n    beforeDestroy(){\n        clearInterval(this.intervalId)\n    },\n    computed: {\n        ...mapState({\n            current_peer: state => state.NodeAuthorization.current_peer,\n            peer_attrs: state => state.NodeAuthorization.peer_attrs,\n            stakeIdentity: state => state.NodeStake.stakeIdentity,\n            stakeWallet: state => state.NodeStake.stakeWallet,\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n            ledgerWallet: state => state.LedgerConnector.ledgerWallet,\n            stakeDetail: state => state.NodeStake.detail,\n            splitFee: state => state.NodeAuthorization.splitFee,\n            posLimit: state => state.NodeAuthorization.posLimit,\n            peerUnboundOng: state => state.NodeAuthorization.peerUnboundOng\n        }),\n        maxStakeLimit: {\n            get(){\n                const initPos = this.$store.state.NodeAuthorization.current_peer.initPos;\n                return numeral(this.posLimit * initPos).format('0,0');\n            }\n        },\n        initPosStr (){\n            return this.current_peer.initPosStr\n        }\n    },\n    methods:{\n        editProportion() {\n            this.showEditProportion = true;\n        },\n        handleCancelChangeCost() {\n            this.showEditProportion = false;\n        },\n        confirmChangeAuthorization() {\n            if(!this.validUnit) {\n                this.$message.error(this.$t('nodeMgmt.invalidInput'))\n                return;\n            }\n            if(parseInt(this.unit)*this.unitVal != this.peer_attrs.maxAuthorize) {\n                const tx = GovernanceTxBuilder.makeChangeAuthorizationTx(\n                    this.stakeDetail.publickey,\n                    new Crypto.Address(this.stakeWallet.address),\n                    parseInt(this.unit)*this.unitVal,\n                    new Crypto.Address(this.stakeWallet.address),\n                    GAS_PRICE,\n                    GAS_LIMIT\n                )\n                this.tx = tx;\n                this.signVisible = true;\n            } else {\n                this.$message.warning(this.$t('nodeMgmt.noChange'))\n            }\n        },\n        confirmChangeCost() {\n            const tx = GovernanceTxBuilder.makeSetFeePercentageTx(\n                    this.stakeDetail.publickey,\n                    new Crypto.Address(this.stakeWallet.address),\n                    parseInt(this.peerCost),\n                    parseInt(this.stakeCost),\n                    new Crypto.Address(this.stakeWallet.address),\n                    GAS_PRICE,\n                    GAS_LIMIT\n                )\n                this.tx = tx;\n                this.signVisible = true;\n                this.showEditProportion = false;\n                this.peerCost = 0;\n        },\n        validateUnit(){\n            if(this.unit && !varifyPositiveInt(this.unit)) {\n                this.validUnit = false;\n                return;\n            }\n            if(this.unit && parseInt(this.unit)*this.unitVal > this.current_peer.initPos * this.posLimit) {\n                this.validUnit = false;\n                this.$message.error(this.$t('nodeMgmt.notThanMax'))\n                return;\n            }\n            this.validUnit = true;\n        },\n        handleCancel() {\n            this.signVisible = false;\n            this.tx = ''\n            this.unit = 0;\n        },\n        handleTxSent() {\n            this.signVisible = false;\n            this.tx = ''\n            this.unit = 0;\n            this.refresh();\n        },\n        refresh(){\n            const pk = this.stakeDetail.publickey\n            const address = this.stakeWallet.address;\n            this.$store.dispatch('fetchPeerItem', pk)\n            this.$store.dispatch('fetchPeerAttributes', pk)\n            this.$store.dispatch('fetchSplitFee', address)\n            this.$store.dispatch('fetchPosLimit')\n            this.$store.dispatch('fetchPeerUnboundOng', address)\n        },\n        redeemRewards() {\n            if(!this.splitFee.amount) {\n                this.$message.warning(this.$t('nodeMgmt.noRewards'))\n                return;\n            }\n            const tx = GovernanceTxBuilder.makeWithdrawFeeTx(\n                new Crypto.Address(this.stakeWallet.address),\n                new Crypto.Address(this.stakeWallet.address),\n                GAS_PRICE,\n                GAS_LIMIT\n            )\n            this.signVisible = true;\n            this.tx = tx;\n        },\n        redeemPeerUnboundOng() {\n            if(!this.peerUnboundOng) {\n                this.$message.warning(this.$t('nodeMgmt.noUnboundOng'))\n                return;\n            }\n            const tx = GovernanceTxBuilder.makeWithdrawPeerUnboundOngTx(\n                new Crypto.Address(this.stakeWallet.address),\n                new Crypto.Address(this.stakeWallet.address),\n                GAS_PRICE,\n                GAS_LIMIT\n            )\n            this.signVisible = true;\n            this.tx = tx;\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeManagement/NodeStakeManagement.vue",
    "content": "<style scoped>\n.btn-new-stake {\n    width:200px !important;\n    float: right;\n    margin-right: 10px;\n    top: -50px;\n}\n.node-stake-info {\n    padding-bottom: 5rem;\n    overflow-y:auto;\n}\n\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('nodeMgmt.nodeStakeMgmt')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n\n        <a-tabs :default-active-key=\"currentIndex\" :animated=\"false\">\n            <a-tab-pane :key=\"1\" :tab=\"$t('nodeMgmt.nodeStake')\">\n                <node-stake-info :showPosBtn=\"true\" :breadcrumb=\"true\"></node-stake-info>\n            </a-tab-pane>\n            <a-tab-pane :key=\"2\" :tab=\"$t('nodeMgmt.userStakeAuthorization')\">\n                <node-stake-authorization ></node-stake-authorization>\n            </a-tab-pane>\n            <a-tab-pane :key=\"3\" :tab=\"$t('nodeInfo.nodeInfo')\">\n                <node-info></node-info>\n            </a-tab-pane>\n        </a-tabs>\n\n\n        <!-- <a-menu  mode=\"horizontal\" @click=\"handleSelect\">\n            <a-menu-item key=\"1\">{{$t('nodeMgmt.nodeStake')}}</a-menu-item>\n            <a-menu-item key=\"2\">{{$t('nodeMgmt.userStakeAuthorization')}}</a-menu-item>\n            <a-menu-item key=\"3\">{{$t('nodeInfo.nodeInfo')}}</a-menu-item>\n        </a-menu>\n        <div>\n            <div v-show=\"currentIndex === 1 \" class=\"node-stake-info\">\n                <node-stake-info :showPosBtn=\"true\" :breadcrumb=\"true\"></node-stake-info>\n            </div>\n            <node-stake-authorization v-show=\"currentIndex === 2\"></node-stake-authorization>\n            <node-info v-show=\"currentIndex === 3\"></node-info>\n        </div> -->\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport NodeStakeInfo from '../NodeStake/NodeStakeInfo'\nimport NodeStakeAuthorization from './NodeStakeAuthorization'\nimport NodeInfo from '../NodeStake/NodeInfo'\nimport {mapState} from  'vuex'\nexport default {\n    name: 'NodeStakeManagement',\n    components: {\n        Breadcrumb,\n        NodeStakeInfo,\n        NodeStakeAuthorization,\n        NodeInfo\n    },\n    data(){\n        return {\n            current: [1]\n        }\n    },\n    computed: {\n        ...mapState({\n            currentIndex: state => state.NodeStake.menuTabIndex\n        })\n    },\n    methods: {\n        handleRouteBack(){\n            this.$router.go(-1);\n\n        },\n        handleSelect({item, key, keyPath}){\n            this.current[0] = key\n        },\n        newStake() {\n            this.$router.push({name: 'NodeStakeIntro'})\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeStake/NodeInfo.vue",
    "content": "<template>\n<div>\n    <!-- <div v-if=\"!stakeWallet.key\" class=\"ledger-not-support\">\n        <p>{{$t('nodeInfo.ledgerWalletNotSupportForNow')}}\n             <a href=mailto:contact@ont.io>contact@ont.io</a>\n        </p>\n       \n    </div> -->\n    <div class=\"container\"  >\n        <div class=\"info-container\">\n        <div class=\"left-half\">\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.name')}}</label>\n                <a-input v-model=\"info.name\" :placeholder=\"$t('nodeInfo.enterName')\"></a-input>\n            </div>\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.logo')}}</label>\n                <a-input v-model=\"info.logo_url\" :placeholder=\"$t('nodeInfo.enterLogo')\"></a-input>\n            </div>\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.location')}}</label>\n                <a-input v-model=\"info.region\" :placeholder=\"$t('nodeInfo.enterLocation')\"></a-input>\n            </div>\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.ip')}}</label>\n                <a-input v-model=\"info.ip\" :placeholder=\"$t('nodeInfo.enterIp')\"></a-input>\n            </div>\n           \n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.description')}}</label>\n                <a-textarea rows=\"4\" v-model=\"info.introduction\" :placeholder=\"$t('nodeInfo.enterDesc')\"></a-textarea>\n            </div>\n        </div>\n        <div class=\"right-half\">\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.website')}}</label>\n                <a-input v-model=\"info.website\" :placeholder=\"$t('nodeInfo.enterWebsite')\"></a-input>\n            </div>\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.telegram')}}</label>\n                <a-input v-model=\"info.telegram\" :placeholder=\"$t('nodeInfo.enterTelegram')\"></a-input>\n            </div>\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.twitter')}}</label>\n                <a-input v-model=\"info.twitter\" :placeholder=\"$t('nodeInfo.enterTwitter')\"></a-input>\n            </div>\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.facebook')}}</label>\n                <a-input v-model=\"info.facebook\" :placeholder=\"$t('nodeInfo.enterFacebook')\"></a-input>\n            </div>\n            <div class=\"form-item-column\">\n                <label for=\"\">{{$t('nodeInfo.contactOntologyEmail')}}</label>\n                <div>\n                    <a-input v-model=\"info.contact_mail\" :placeholder=\"$t('nodeInfo.enterContactEmail')\"></a-input>\n                </div>\n            </div>\n            <div class=\"form-item\">\n                <label for=\"\">{{$t('nodeInfo.openEmail')}}</label>\n                <a-input v-model=\"info.open_mail\" :placeholder=\"$t('nodeInfo.enterOpenEmail')\"></a-input>\n            </div>\n        </div>\n        </div>\n        <div class=\"form-bottom\">\n            <label for=\"\">{{$t('nodeInfo.ifOpenInfo')}}</label>\n            <a-switch v-model=\"info.open_flag\"></a-switch>\n        </div>\n        <div class=\"footer-btns\">\n            <div class=\"btn-container\">\n            <a-button class=\"btn-next\" @click=\"onSubmit\" >{{$t('nodeInfo.submit')}}</a-button>\n            </div>\n        </div>\n        <sign-send-tx :visible=\"signVisible\" :tx=\"tx\" :wallet=\"stakeWallet\"\n        v-on:signClose=\"handleTxCancel\"\n        v-on:afterSign=\"handleAfterSign\"\n        ></sign-send-tx>\n    </div>\n</div>\n</template>\n<script>\nimport {mapState} from 'vuex'\nimport SignSendTx from '../../../components/Common/SignSendTx'\nimport { utils, Crypto } from 'ontology-ts-sdk'\nexport default {\n    name: 'NodeInfo',\n    data() {\n        return {\n            info: {\n                open_flag: false\n            },\n            tx: '',\n            signVisible: false,\n            node_info: ''\n        }\n    },\n    components: {\n        SignSendTx\n    },\n    mounted() {\n        this.fetchNodeInfo(this.nodePublicKey)\n    },\n    computed: {\n        ...mapState({\n            nodePublicKey: state => state.NodeStake.nodePublicKey,\n            stakeWallet: state => state.NodeStake.stakeWallet\n        })\n    },\n    \n    methods: {\n        async fetchNodeInfo() {\n            const info = await this.$store.dispatch('fetchNodeInfo', this.nodePublicKey)\n            this.info = Object.assign({},this.info, info);\n        },\n        async onSubmit() {\n            const data = Object.assign({}, this.info)\n            data.public_key = this.nodePublicKey\n            data.address = this.stakeWallet.address\n            const node_info = JSON.stringify(data)\n            this.node_info = utils.str2hexstr(node_info)\n            this.tx = this.node_info\n            this.signVisible = true;\n        },\n        handleTxCancel() {\n            this.signVisible = false;\n            this.tx = null;\n        },\n        handleAfterSign(signed) {\n            if(this.stakeWallet.key) { // 普通钱包\n                    const data =  {\n                    node_info: this.node_info,\n                    public_key: this.stakeWallet.publicKey,\n                    address: this.stakeWallet.address,\n                    signature: typeof signed === 'string' ? signed : signed.serializeHex()\n                }\n                this.$store.dispatch('updateNodeInfo', data).then(res => {\n                    this.signVisible = false;\n                    this.tx = null;\n                    if(res.code === 0){\n                        this.$message.success(this.$t('nodeInfo.updateSuccess'))\n                    } else {\n                        this.$message.error(this.$t('nodeInfo.updateFailed'))\n                    }\n                    \n                })\n            } else { // ledger 钱包\n                const data = {\n                    node_info: signed,\n                    public_key: this.stakeWallet.publicKey\n                }\n                this.$store.dispatch('updateLedgerNodeInfo', data).then(res => {\n                    this.signVisible = false;\n                    this.tx = null;\n                    if(res.code === 0){\n                        this.$message.success(this.$t('nodeInfo.updateSuccess'))\n                    } else {\n                        this.$message.error(this.$t('nodeInfo.updateFailed'))\n                    }\n                    \n                })\n            }\n           \n        }\n\n    }\n}\n</script>\n<style lang=\"scss\" scoped>\n.info-container {\n    margin: 30px 0;\n    display: flex;\n    flex-direction: row;\n    align-items: flex-start;\n    .left-half {\n        margin-right: 40px;\n    }\n    .left-half, .right-half {\n        flex: 1;\n    }\n    \n}\n.form-bottom {\n        width: 100%;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        label {\n            margin: 0;\n            margin-right: 20px;\n        }\n}\n.form-item {\n    display: flex;\n    label {\n        width: 100px;\n        // margin-right: 10px;\n    }\n    input {\n        flex: 1;\n    }\n    textarea {\n        flex: 1;\n    }\n    margin-bottom: 20px;\n}\n.form-item-column {\n    margin-bottom: 20px;\n    div {\n        padding-left: 100px;\n        input {\n        }\n    }\n    \n}\n.btn-container {\n    text-align: center;\n}\n</style>"
  },
  {
    "path": "src/components/Node/NodeStake/NodeStakeInfo.vue",
    "content": "<style scoped>\n.nodeStake-container {\n  width: 540px;\n  margin: 0px auto;\n  padding-top:20px;\n}\n.detail-item {\n  margin-bottom: 10px;\n}\n.detail-item p {\n  margin-bottom: 5px;\n}\n.select-ontid {\n  width: 100%;\n}\n\n.step-item-container {\n  display: flex;\n  flex-direction: row;\n  justify-content: space-between;\n  align-items: flex-start;\n  margin-bottom:15px;\n  /* padding-left: 50px;\n    padding-right: 50px; */\n}\n\n.step-item-container div {\n  width: 30%;\n  text-align: center;\n  font-size:14px;\n\n}\n.stake-status-tip {\n    text-align: center;\n    font-size:12px;\n    height:20px;\n    margin:0;\n}\n.btn-stake {\n    width:540px;\n    margin-left: auto;\n    margin-right: auto;\n    display: flex;\n    flex-direction: row;\n    justify-content: space-between;\n}\n.initPos-btns {\n    margin:10px auto;\n    width:640px;\n}\n.initPos-btns button {\n    margin-right: 20px;\n}\n.add-initPos-btn {\n    width: 180px;\n    height: 36px;\n    border-radius: 0;\n    background: #FBE45A;\n    padding: 0;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #5E6369;\n    border: none;\n    margin-bottom:15px;\n  }\n  .add-pos-input {\n    width:200px;\n  }\n</style>\n<template>\n    <div >\n        <breadcrumb  v-if=\"!breadcrumb\" :current=\"$t('nodeStake.nodeStake')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"nodeStake-container\">\n            <div>\n                <a-steps progressDot :current=\"current\">\n                    <a-step ></a-step>\n                    <a-step ></a-step>\n                    <a-step ></a-step>\n                </a-steps>\n                <div class=\"step-item-container\">\n                    <div>\n                        {{status1}}\n                    </div>\n                    <div>\n                        {{status2}}\n                    </div>\n                    <div>\n                        {{status3}}\n                    </div>\n                </div>\n            </div>\n\n            <!-- <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.ontid')}}</p>\n                <p>{{detail.ontid}}</p>\n            </div> -->\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.stakeWalletAddress')}}</p>\n                <p>{{detail.stakewalletaddress}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.nodePk')}}</p>\n                <p>{{nodePublicKey}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.contract')}}</p>\n                <p>{{detail.contract}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.commitmentQuantity')}}</p>\n                <p>{{detail.commitmentquantity}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.stakeQuantity')}}</p>\n                <p>{{current_peer.initPos}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.claimableQuantity')}}</p>\n                <p>{{authorizationInfo.claimable}}</p>\n            </div>\n            <!-- 只有成为节点后可以操作初始质押部分 -->\n            <div class=\"initPos-btns\" v-if=\"detail.status === 8\">\n                    <a-button class=\"add-initPos-btn\" @click=\"handleAddInitPos\">{{$t('nodeMgmt.addInitPos')}}</a-button>\n                    <a-button class=\"add-initPos-btn\" @click=\"handleReduceInitPos\"\n                    v-if=\"current_peer.initPos> detail.commitmentquantity\"\n                    >{{$t('nodeMgmt.reduceInitPos')}}</a-button>\n                    <a-button class=\"add-initPos-btn\" @click=\"()=>{this.redeemPosVisible = true;}\">{{$t('nodeMgmt.redeemInitPos')}}</a-button>\n            </div>\n        </div>\n        <div class=\"footer-btns\">\n            <p class=\"font-medium stake-status-tip\" >\n              <span v-if=\"statusTip\"><a-icon type=\"info-circle-o\"/> {{statusTip}}</span>\n              </p>\n            <div class=\"btn-stake\">\n                <a-button @click=\"handleBack\" type=\"default\" class=\"btn-cancel\">{{$t('nodeStake.back')}}</a-button>\n                <a-button @click=\"handleRecall\" class=\"btn-next\" v-if=\"detail.status ===2\">{{$t('nodeStake.recall')}}</a-button>\n                <a-button @click=\"handleRefund\" class=\"btn-next\" v-if=\"detail.status ===4 || detail.status ===3 || detail.status ===7 \"\n                :disabled=\"refundClicked\">{{$t('nodeStake.refund')}}</a-button>\n                <a-button @click=\"handleQuitNode\" class=\"btn-next\" v-if=\"detail.status ===8\">{{$t('nodeStake.quitNode')}}</a-button>\n                <a-button @click=\"handleNewStake\" class=\"btn-next\" v-if=\"detail.status ===6 || detail.status ===1\">{{$t('nodeStake.newStake')}}</a-button>\n\n            </div>\n        </div>\n\n        <a-modal\n            :title=\"$t('nodeMgmt.addInitPos')\"\n            :visible=\"addPosVisible\"\n            @ok=\"handleAddPosOk\"\n            @cancel=\"handleAddPosCancel\">\n            <div>\n                <div>\n                    <span class=\"label font-medium-black\">{{$t('nodeMgmt.amountToAdd')}}: </span>\n                    <a-input class=\"input add-pos-input\" :class=\"validAddPos? '': 'error-input'\"\n                    v-model=\"addPos\" @change=\"validateAddPos\"></a-input> ONT\n                </div>\n            </div>\n        </a-modal>\n\n        <a-modal\n            :title=\"$t('nodeMgmt.reduceInitPos')\"\n            :visible=\"reducePosVisible\"\n            @ok=\"handleReducePosOk\"\n            @cancel=\"handleReducePosCancel\">\n            <div>\n                <div>\n                    <span class=\"label font-medium-black\">{{$t('nodeMgmt.amountToReduce')}}: </span>\n                    <a-input class=\"input add-pos-input\" :class=\"validReducePos? '': 'error-input'\"\n                    v-model=\"reducePos\" @change=\"validateReducePos\"></a-input> ONT\n                </div>\n            </div>\n        </a-modal>\n\n        <a-modal\n          :title=\"$t('nodeMgmt.redeemInitPos')\"\n          :visible=\"redeemPosVisible\"\n          :okText=\"$t('nodeMgmt.redeemInitPosOk')\"\n          @ok=\"handleRedeemPosOk\"\n          @cancel=\"handleRedeemPosCancel\">\n            <div>\n              <p class=\"font-medium-black\">{{$t('nodeMgmt.initPosInLock')}}: {{authorizationInfo.locked}} ONT</p>\n              <p class=\"font-medium-black\">{{$t('nodeMgmt.initPosRedeemable')}}: {{authorizationInfo.claimable}} ONT</p>\n            </div>\n        </a-modal>\n\n        <a-modal\n        :title=\"$t('nodeStake.signWithWallet')\"\n        :visible=\"walletPassModal\"\n        @ok=\"handleWalletSignOK\"\n        @cancel=\"handleWalletSignCancel\">\n          <div v-if=\"stakeWallet.key\">\n              <p v-if=\"isQuit\">{{$t('nodeStake.quitWarmMsg')}}</p><br>\n              <p>{{$t('nodeStake.enterWalletPass')}}</p>\n              <a-input class=\"input\" v-model=\"walletPassword\" :plaecholder=\"$t('nodeStake.password')\" type=\"password\"></a-input>\n          </div>\n          <div v-if=\"!stakeWallet.key\">\n            <div class=\"font-bold\" style=\"margin-bottom: 10px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                    <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}} </span>\n          </div>\n        </a-modal>\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from \"../../Breadcrumb\";\nimport { mapState } from \"vuex\";\nimport { Crypto, TransactionBuilder, utils, TxSignature, GovernanceTxBuilder, RestClient } from \"ontology-ts-sdk\";\nimport {legacySignWithLedger, checkPublicKeyIsInTheConnectedLedger} from '../../../core/ontLedger'\nimport {varifyPositiveInt, getNodeUrl} from '../../../core/utils.js'\nimport axios from \"axios\";\nimport {\n  ONT_PASS_NODE,\n  ONT_PASS_NODE_PRD,\n  ONT_PASS_URL,\n  GAS_PRICE,\n  GAS_LIMIT,\n  DEFAULT_SCRYPT\n} from \"../../../core/consts\";\n\nexport default {\n  name: \"NodeStakeInfo\",\n  props: ['showPosBtn','breadcrumb'],\n  components: {\n    Breadcrumb\n  },\n  data() {\n    return {\n      localOntid: [],\n      intervalId: \"\",\n      interval: 10000,\n      refundClicked: false,\n      walletPassModal: false,\n      walletPassword: \"\",\n      tx: \"\",\n\n      addPosVisible: false,\n      addPos: 0,\n      validAddPos: true,\n      reducePosVisible: false,\n      reducePos: 0,\n      validReducePos: true,\n      isDelegateSendTx:true,\n\n      redeemPosVisible: false,\n\n      isQuit: false,\n\n    };\n  },\n  mounted() {\n    //fetch node stake details\n    if(!this.stakeWallet.key) {//common wallet\n      this.$store.dispatch('getLedgerStatus')\n    }\n    const data = {\n      address: this.stakeWallet.address,\n      public_key: this.nodePublicKey\n    }\n    this.$store.dispatch(\"fetchStakeDetail\", data);\n    this.$store.dispatch('fetchPeerItem', this.nodePublicKey);\n    this.$store.dispatch('fetchPosLimit')\n    this.$store.dispatch('fetchAuthorizationInfo',\n      {pk: this.nodePublicKey, address: this.stakeWallet.address}\n      )\n    const intervalId = setInterval(() => {\n      this.$store.dispatch(\"fetchStakeDetail\", data);\n      this.$store.dispatch('fetchPeerItem', this.nodePublicKey);\n      this.$store.dispatch('fetchPosLimit')\n      this.$store.dispatch('fetchAuthorizationInfo',\n      {pk: this.nodePublicKey, address: this.stakeWallet.address}\n      )\n    }, this.interval);\n    this.intervalId = intervalId\n  },\n  beforeDestroy() {\n    clearInterval(this.intervalId);\n    this.$store.dispatch('stopGetLedgerStatus')\n  },\n  computed: {\n    ...mapState({\n      stakeIdentity: state => state.NodeStake.stakeIdentity,\n      stakeWallet: state => state.NodeStake.stakeWallet,\n      nodePublicKey: state => state.NodeStake.nodePublicKey,\n      ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n      ledgerPk : state => state.LedgerConnector.publicKey,\n      ledgerWallet: state => state.LedgerConnector.ledgerWallet,\n      detail: state => state.NodeStake.detail,\n      current_peer: state => state.NodeAuthorization.current_peer,\n      posLimit: state => state.NodeAuthorization.posLimit,\n      // detail: state => state.NodeStake.detail\n      status1: state => state.NodeStake.status1,\n      status2: state => state.NodeStake.status2,\n      status3: state => state.NodeStake.status3,\n      current: state => state.NodeStake.current,\n      statusTip: state => state.NodeStake.statusTip,\n      btnText: state => state.NodeStake.btnText,\n      authorizationInfo: state => state.NodeAuthorization.authorizationInfo\n    })\n  },\n  methods: {\n    handleRouteBack() {\n      this.$router.go(-1);\n    },\n    handleBack() {\n      this.$router.go(-1);\n    },\n    handleWalletSignCancel() {\n      this.tx = \"\";\n      this.walletPassModal = false;\n      this.isQuit = false;\n      this.walletPassword = '';\n    },\n    async handleWalletSignOK() {\n      const tx = this.tx;\n      if (this.stakeWallet.key && !this.walletPassword) {\n        //common wallet\n        this.$message.error(this.$t(\"nodeStake.passwordEmpty\"));\n        return;\n      }\n      this.refundClicked = true;\n      if (this.stakeWallet.key) {\n        this.$store.dispatch(\"showLoadingModals\");\n        const enc = new Crypto.PrivateKey(this.stakeWallet.key);\n        let pri;\n        try {\n          pri = enc.decrypt(\n            this.walletPassword,\n            new Crypto.Address(this.stakeWallet.address),\n            this.stakeWallet.salt,\n            DEFAULT_SCRYPT\n          );\n        } catch (err) {\n          console.log(err);\n          this.refundClicked = false;\n          this.$store.dispatch(\"hideLoadingModals\");\n          this.$message.error(this.$t(\"common.pwdErr\"));\n          return;\n        }\n        TransactionBuilder.signTransaction(tx, pri);\n        if(this.isDelegateSendTx) {\n          this.delegateSendTx(tx);\n        } else {\n          this.sendTx(tx);\n        }\n      } else {\n        //ledger sign\n        if (this.ledgerWallet.address) {\n          console.log(\"stakeWallet: \", this.stakeWallet);\n          // 当前连接的Ledger需要和之前导入钱包的Ledger是同一个\n          await checkPublicKeyIsInTheConnectedLedger(this.stakeWallet.acct || 0, this.stakeWallet.neo, this.stakeWallet.publicKey);\n          this.$store.dispatch(\"showLoadingModals\");\n          const pk = new Crypto.PublicKey(this.stakeWallet.publicKey);\n          const txSig = new TxSignature();\n          txSig.M = 1;\n          txSig.pubKeys = [pk];\n          tx.payer = new Crypto.Address(this.stakeWallet.address);\n          const txData = tx.serializeUnsignedData();\n          legacySignWithLedger(txData, this.stakeWallet.neo, this.stakeWallet.acct).then(res => {\n              // console.log('txSigned: ' + res);\n              const sign = \"01\" + res; //ECDSAwithSHA256\n              txSig.sigData = [sign];\n              tx.sigs = [txSig];\n              if(this.isDelegateSendTx) {\n                this.delegateSendTx(tx);\n              } else {\n                this.sendTx(tx);\n              }\n            },\n            err => {\n              this.sending = false;\n              this.ledgerStatus = \"\";\n              this.$store.dispatch('hideLoadingModals')\n              alert(err.message);\n            }\n          );\n        } else {\n          this.refundClicked = false;\n          this.$store.dispatch(\"hideLoadingModals\");\n          this.$message.warning(this.$t(\"ledgerWallet.connectApp\"));\n        }\n      }\n    },\n    delegateSendTx(tx) {\n      const body = {\n        ontid: this.stakeIdentity.ontid,\n        publickey: this.nodePublicKey,\n        stakewalletaddress: this.stakeWallet.address,\n        transactionhash: utils.reverseHex(tx.getHash()),\n        transactionbodyhash: tx.serialize()\n      };\n      const net = localStorage.getItem(\"net\");\n      const ontPassNode =\n        net === \"TEST_NET\" ? ONT_PASS_NODE : ONT_PASS_NODE_PRD;\n      axios.post(ontPassNode + ONT_PASS_URL.DelegateSendTx, body).then(res => {\n        this.walletPassModal = false;\n        this.isQuit = false;\n        this.walletPassword = ''\n        this.tx = ''\n        this.$store.dispatch(\"hideLoadingModals\");\n        this.$store.dispatch(\"fetchStakeDetail\",\n        {\n          address: this.stakeWallet.address,\n          public_key: this.nodePublicKey\n        });\n      }).catch(err=>{\n        this.$store.dispatch(\"hideLoadingModals\");\n        this.$message.error(this.$t('common.networkErr'))\n      });\n      setTimeout(() => {\n        this.refundClicked = false;\n      }, 5000)\n    },\n    sendTx(tx){\n        const url = getNodeUrl();\n        const restClient = new RestClient(url);\n        restClient.sendRawTransaction(tx.serialize()).then(res => {\n        console.log(res)\n        this.isDelegateSendTx = true;\n        this.isQuit = false;\n        this.walletPassModal = false;\n        this.walletPassword = '';\n        this.$store.dispatch(\"hideLoadingModals\");\n        if (res.Error === 0) {\n            this.$message.success(this.$t('common.transSentSuccess'))\n        } else if (res.Error === -1) {\n          if(res.Result.indexOf('balance insufficient') > -1 ) {\n              this.$message.error(this.$t('common.balanceInsufficient'))\n          } else if(res.Result.indexOf('cover gas cost') > -1) {\n              this.$message.error(this.$t('common.ongNoEnough'))\n          } else {\n              this.$message.error(res.Result)\n          }\n          return;\n        } else {\n            this.$message.error(res.Result)\n            return;\n        }\n        this.$emit('txSent')\n        const title = this.$t('common.transSentSuccess')\n        setTimeout(() => {\n            this.$success({\n                title: title,\n                content: 'Transaction hash: ' + utils.reverseHex(tx.getHash())\n            })\n        }, 100)\n        }).catch(err => {\n                    console.log(err)\n                    this.$message.error(this.$t('common.networkError'))\n                })\n    },\n    handleRecall() {\n      const userAddr = new Crypto.Address(this.stakeWallet.address);\n      const peerPubkey = this.nodePublicKey;\n      const payer = userAddr;\n      const tx = GovernanceTxBuilder.makeUnregisterCandidateTx(\n        userAddr,\n        peerPubkey,\n        payer,\n        GAS_PRICE,\n        GAS_LIMIT\n      );\n      this.tx = tx;\n      this.walletPassModal = true;\n    },\n\n    handleRefund() {\n        if(this.authorizationInfo && this.authorizationInfo.claimableVal === 0) {\n          this.$message.warning(this.$t('nodeMgmt.noClaimbleToRefund'))\n          return;\n        }\n        const userAddr = new Crypto.Address(this.stakeWallet.address);\n        const peerPubkeys = [this.nodePublicKey]\n        // const withdrawList = [this.detail.stakequantity]\n        // Fix:节点质押部分可能会增加或减少，退款应该用initPos；\n        // Fix2: 退款都可以用可提取部分\n        const withdrawList = [this.authorizationInfo.claimableVal]\n        const payer = userAddr\n        const tx = GovernanceTxBuilder.makeWithdrawTx(userAddr, peerPubkeys, withdrawList, payer, GAS_PRICE, GAS_LIMIT)\n        this.tx = tx;\n        this.walletPassModal = true;\n    },\n    handleQuitNode() {\n        //Fixme:退出节点前先把可提取初始质押提取出来。\n        if(this.authorizationInfo && this.authorizationInfo.claimableVal > 0) {\n          this.$message.warning(this.$t('nodeMgmt.hasClaimableInitPos'))\n          return;\n        }\n        const userAddr = new Crypto.Address(this.stakeWallet.address);\n        const peerPubkey = this.nodePublicKey;\n        const payer = userAddr;\n        const tx = GovernanceTxBuilder.makeQuitNodeTx(userAddr, peerPubkey, payer, GAS_PRICE, GAS_LIMIT)\n        this.tx = tx;\n        this.isQuit = true;\n        this.walletPassModal = true;\n    },\n    handleNewStake() {\n      // this.$router.push({ name: \"NodeStakeRegister\" });\n      this.$router.push({name: 'NodeApply'})\n    },\n    handleAddInitPos() {\n      this.addPosVisible = true;\n    },\n    handleReduceInitPos() {\n      this.reducePosVisible = true;\n    },\n    validateAddPos() {\n      if(this.addPos && !varifyPositiveInt(this.addPos)) {\n        this.validAddPos = false;\n        return;\n      }\n      this.validAddPos = true;\n    },\n    validateReducePos() {\n      if(this.reducePos && !varifyPositiveInt(this.reducePos)) {\n        this.validReducePos = false;\n        return;\n      }\n      if(this.current_peer.totalPos === 0 && (this.current_peer.initPos - this.reducePos) <  this.detail.commitmentquantity) {\n        this.validReducePos = false;\n        this.$message.error(this.$t('nodeMgmt.notThanCommitment'))\n        return;\n      }\n      if(this.current_peer.totalPos && (this.current_peer.initPos - this.reducePos)* this.posLimit < this.current_peer.totalPos ) {\n        this.validaReducePos = false;\n        this.$message.error(this.$t('nodeMgmt.notLessTotalPos'))\n        return;\n      }\n      this.validReducePos = true;\n    },\n    handleAddPosOk() {\n      if(!this.validAddPos) {\n        this.$message.error(this.$t('nodeMgmt.invalidInput'))\n        return;\n      }\n      this.addPosVisible = false;\n      const userAddr = new Crypto.Address(this.stakeWallet.address);\n      const tx = GovernanceTxBuilder.makeAddInitPosTx(\n        this.nodePublicKey,\n        userAddr,\n        parseInt(this.addPos),\n        userAddr,\n        GAS_PRICE,\n        GAS_LIMIT\n      )\n      this.tx = tx;\n      this.walletPassModal = true;\n      this.isDelegateSendTx = false;\n    },\n    handleAddPosCancel() {\n      this.addPosVisible = false;\n    },\n    handleReducePosOk() {\n      if(!this.validReducePos) {\n        this.$message.error(this.$t('nodeMgmt.invalidInput'))\n        return;\n      }\n      this.reducePosVisible = false;\n      const userAddr = new Crypto.Address(this.stakeWallet.address);\n      const tx = GovernanceTxBuilder.makeReduceInitPosTx(\n        this.nodePublicKey,\n        userAddr,\n        parseInt(this.reducePos),\n        userAddr,\n        GAS_PRICE,\n        GAS_LIMIT\n      )\n      this.tx = tx;\n      this.walletPassModal = true;\n      this.isDelegateSendTx = false;\n    },\n    handleReducePosCancel() {\n      this.reducePosVisible = false;\n    },\n    handleRedeemPosOk() {\n      if(this.authorizationInfo && this.authorizationInfo.claimableVal === 0) {\n        this.$message.warning(this.$t('nodeMgmt.noClaimbleInitPos'))\n        return;\n      }\n      this.redeemPosVisible = false;\n      const userAddr = new Crypto.Address(this.stakeWallet.address);\n      const peerPubkeys = [this.nodePublicKey]\n      const withdrawList = [this.authorizationInfo.claimableVal]\n      const payer = userAddr\n      const tx = GovernanceTxBuilder.makeWithdrawTx(userAddr, peerPubkeys, withdrawList, payer, GAS_PRICE, GAS_LIMIT)\n      this.tx = tx;\n      this.walletPassModal = true;\n      this.isDelegateSendTx = false;\n    },\n    handleRedeemPosCancel() {\n      this.redeemPosVisible = false;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeStake/NodeStakeIntro.vue",
    "content": "<style scoped>\n.intro-content {\n  width: 540px;\n  margin: 0rem auto;\n}\n.btn-known {\n  margin: 20px auto;\n  text-align: center;\n}\n.btn-known button {\n  width: 150px !important;\n}\n.select-ontid {\n  width: 100%;\n}\n.intro-item {\n  margin-bottom: 15px;\n}\n.intro-content p {\n  margin-bottom: 5px;\n}\n.change-payer-radio {\n    width:100%;\n}\n.payer-radio-item {\n    margin-bottom:15px;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb  :current=\"$t('nodeStake.nodeStake')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"intro-content\">\n            <div class=\"intro-item\">\n                <p class=\"font-medium-black\">{{$t('nodeStake.selectOntid')}}</p>\n                <a-select :options=\"identities\" class=\"select-ontid\" @change=\"changeIdentity\"></a-select>\n\n            </div>\n            <div class=\"intro-item\">\n                <p class=\"font-medium-black\">{{$t('nodeStake.selectStakeWallet')}}</p>\n                <a-radio-group @change=\"changePayerWallet\" v-model=\"payerWalletType\" class=\"change-payer-radio\">\n                <a-radio value=\"commonWallet\" class=\"payer-radio-item\">{{$t('createIdentity.commonWallet')}}</a-radio>\n                <a-radio value=\"ledgerWallet\" class=\"payer-radio-item\">{{$t('createIdentity.ledgerWallet')}}</a-radio>\n\n                <div v-if=\"payerWalletType === 'commonWallet'\">\n                    <a-select :options=\"normalWallet\" class=\"select-ontid\"\n                    :placeholder=\"$t('createIdentity.selectCommonWallet')\"\n                        @change=\"handleChangePayer\">\n                    </a-select>\n                </div>\n\n                <div v-if=\"payerWalletType === 'ledgerWallet'\">\n\n                    <div class=\"payer-ledger-status\">\n                    <div class=\"font-bold\" style=\"margin-bottom: 10px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                    <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}} </span>\n                    </div>\n\n                </div>\n\n                </a-radio-group>\n            </div>\n        </div>\n        <div class=\"footer-btns\">\n            <div class=\"btn-known\">\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{$t('nodeStake.next')}}</a-button>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from \"../../Breadcrumb\";\nimport { mapState } from \"vuex\";\nimport axios from 'axios'\nimport {ONT_PASS_NODE, ONT_PASS_NODE_PRD, ONT_PASS_URL} from '../../../core/consts'\nexport default {\n  name: \"NodeStakeIntro\",\n  data() {\n    return {\n        payerWalletType: 'commonWallet',\n        payerWallet: '',\n        stakeIdentity: '',\n        payerWalletAddress:''\n    };\n  },\n  components: {\n    Breadcrumb\n  },\n  mounted() {\n    this.$store.dispatch(\"fetchWalletsFromDb\");\n    this.$store.dispatch(\"fetchIdentitiesFromDb\");\n  },\n  beforeDestroy(){\n      this.$store.dispatch('stopGetLedgerStatus')\n   },\n  computed: {\n      ...mapState({\n        ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n        ledgerPk : state => state.LedgerConnector.publicKey,\n        ledgerWallet: state => state.LedgerConnector.ledgerWallet\n      }),\n    normalWallet: {\n      get() {\n        const list = this.$store.state.Wallets.NormalWallet.slice();\n        return list.map(i => {\n          return Object.assign({}, i, {\n            label: i.label + \" \" + i.address,\n            value: i.address\n          });\n        });\n      }\n    },\n    hardwareWallet: {\n      get() {\n        const list = this.$store.state.Wallets.HardwareWallet.slice();\n        return list.map(i => {\n          return Object.assign({}, i, {\n            label: i.label + \" \" + i.address,\n            value: i.address\n          });\n        });\n      }\n    },\n    identities: {\n      get() {\n        const list = this.$store.state.Identities.Identities.slice();\n        return list.map(i => {\n          return Object.assign({}, i, {\n            label: i.label + \" \" + i.ontid,\n            value: i.ontid\n          });\n        });\n      }\n    }\n  },\n  methods: {\n    handleRouteBack() {\n      this.$router.go(-1);\n    },\n    next() {\n        if(!this.stakeIdentity) {\n            this.$message.error(this.$t('nodeStake.selectIdentity'))\n            return;\n        }\n        if(this.payerWalletType === 'commonWallet' && !this.payerWallet) {\n            this.$message.error(this.$t('nodeStake.selectIndividualWallet'))\n            return;\n        }\n        if(this.payerWalletType === 'ledgerWallet' && !this.ledgerWallet.address) {\n            this.$message.error(this.$t('nodeStake.selectLedgerWallet'))\n            return;\n        }\n     //get qualified state\n     let address = '',\n        stakeWallet = ''\n     if(this.payerWalletType === 'commonWallet' && this.payerWallet){\n        address = this.payerWallet.address\n        stakeWallet = this.payerWallet\n     } else {\n         address = this.ledgerWallet.address\n         stakeWallet = this.ledgerWallet\n     }\n     this.$store.dispatch('showLoadingModals')\n     const net = localStorage.getItem('net')\n     const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD\n     axios.get(ontPassNode + ONT_PASS_URL.GetQualifiedState, {\n         params: {\n             ontid: this.stakeIdentity.ontid,\n             address: address\n         }\n     }).then(res => {\n         if(res.data.QualifiedState === 0) {\n             this.$store.commit('UPDATE_STAKE_IDENTITY', {stakeIdentity: this.stakeIdentity})\n             this.$store.commit('UPDATE_STAKE_WALLET', {stakeWallet: stakeWallet})\n         } else if(res.data.QualifiedState === 1) {\n             this.$store.dispatch('hideLoadingModals')\n             this.$message.error(this.$t('nodeStake.invalidOntid'))\n             return;\n         } else if(res.data.QualifiedState === 2) {\n             this.$store.dispatch('hideLoadingModals')\n             this.$message.error(this.$t('nodeStake.invalidAddress'))\n             return;\n         }\n         axios.get(ontPassNode + ONT_PASS_URL.GetStakeInfo, {\n             params: {\n                 ontid: this.stakeIdentity.ontid\n             }\n         }).then(res => {\n             this.$store.commit('UPDATE_STAKE_DETAIL', { detail:res.data})\n             if(res.data.status) {\n                 this.$router.push({name: 'NodeStakeManagement'})\n             } else {\n                 this.$router.push({name: 'NodeStakeRegister'})\n             }\n         })\n     }).catch(err => {\n         console.log(err)\n         this.$store.dispatch('hideLoadingModals')\n         this.$message.error(this.$t('common.networkErr'))\n     })\n\n\n    },\n    changePayerWallet(e) {\n        this.payerWalletType = e.target.value\n        if(e.target.value === 'ledgerWallet') {\n            this.$store.dispatch('getLedgerStatus')\n        }\n      },\n    handleChangePayer(value) {\n        this.payerWallet = this.normalWallet.find((v)=>{return v.address === value})\n    },\n    changeIdentity(value) {\n        this.stakeIdentity = this.identities.find(v => v.ontid === value)\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/components/Node/NodeStake/NodeStakeRegister.vue",
    "content": "<style scoped>\n.nodeStake-container {\n  width: 540px;\n  margin: 20px auto;\n}\n.detail-item {\n  margin-bottom: 15px;\n}\n.detail-item p {\n  margin-bottom: 5px;\n}\n.select-ontid {\n  width: 100%;\n}\n\n.step-item-container {\n  display: flex;\n  flex-direction: row;\n  justify-content: space-between;\n  align-items: flex-start;\n  /* padding-left: 50px;\n    padding-right: 50px; */\n}\n.step-item-container div {\n  width: 30%;\n  text-align: center;\n}\n.btn-stake {\n  text-align: center;\n  margin: 0 auto;\n}\n.btn-stake p {\n  font-size: 12px;\n  margin-bottom: 10px;\n  margin-top: 5px;\n}\n</style>\n<template>\n    <div >\n        <breadcrumb  :current=\"$t('nodeStake.nodeStake')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"nodeStake-container\">\n\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.ontid')}}</p>\n                <p>{{detail.ontid}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.stakeWalletAddress')}}</p>\n                <p>{{detail.stakewalletaddress}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.nodePk')}}</p>\n                <p>{{detail.publickey}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.contract')}}</p>\n                <p>{{detail.contract}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.commitmentQuantity')}}</p>\n                <p>{{detail.commitmentquantity}}</p>\n            </div>\n            <div class=\"detail-item\">\n                <p class=\"font-medium-black\" for=\"\">{{$t('nodeStake.stakeQuantity')}}</p>\n                <a-input class=\"input\" v-model=\"stakeQuantity\"></a-input>\n            </div>\n        </div>\n        <div class=\"footer-btns\">\n            <div class=\"btn-stake\">\n                <p class=\"font-medium\"><a-icon type=\"info-circle-o\" /> {{$t('nodeStake.feeTip')}}</p>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"handleStake\">{{$t('nodeStake.stake')}}</a-button>\n            </div>\n\n        </div>\n        <a-modal\n        :title=\"$t('nodeStake.signWithOntid')\"\n        :visible=\"ontidPassModal\"\n        @ok=\"handleOntidSignOK\"\n        @cancel=\"handleOntidSignCancel\">\n          <div>\n              <p>{{$t('nodeStake.enterOntidPass')}}</p>\n              <a-input class=\"input\" v-model=\"ontidPassword\" :plaecholder=\"$t('nodeStake.password')\" type=\"password\"></a-input>\n          </div>\n        </a-modal>\n\n        <a-modal\n        :title=\"$t('nodeStake.signWithWallet')\"\n        :visible=\"walletPassModal\"\n        @ok=\"handleWalletSignOK\"\n        @cancel=\"handleWalletSignCancel\">\n          <div v-if=\"stakeWallet.key\">\n              <p>{{$t('nodeStake.enterWalletPass')}}</p>\n              <a-input class=\"input\" v-model=\"walletPassword\" :plaecholder=\"$t('nodeStake.password')\" type=\"password\"></a-input>\n          </div>\n          <div v-if=\"!stakeWallet.key\">\n            <div class=\"font-bold\" style=\"margin-bottom: 10px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                    <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}} </span>\n          </div>\n        </a-modal>\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from \"../../Breadcrumb\";\nimport { mapState } from \"vuex\";\nimport { GAS_PRICE, GAS_LIMIT, TEST_NET, MAIN_NET, ONT_PASS_NODE, ONT_PASS_NODE_PRD, ONT_PASS_URL, DEFAULT_SCRYPT } from \"../../../core/consts\";\nimport { Crypto, TransactionBuilder, RestClient, utils, GovernanceTxBuilder, TxSignature } from \"ontology-ts-sdk\";\nimport axios from 'axios'\nimport {legacySignWithLedger} from '../../../core/ontLedger'\n\nexport default {\n  name: \"NodeStakeRegister\",\n  components: {\n    Breadcrumb\n  },\n  beforeDestroy(){\n    this.$store.dispatch('stopGetLedgerStatus')\n  },\n  data() {\n    const net = localStorage.getItem('net');\n    return {\n      localOntid: [],\n      stakeQuantity: 0,\n      ontidPassModal: false,\n      walletPassModal: false,\n      walletModalHandled: false,\n      ontidPassword: \"\",\n      walletPassword: \"\",\n      tx: \"\"\n    };\n  },\n  mounted() {\n    //fetch node stake details\n    if(!this.stakeWallet.key) {//common wallet\n      this.$store.dispatch('getLedgerStatus')\n    }\n    this.$store.dispatch(\"fetchStakeDetail\", this.stakeIdentity.ontid);\n  },\n  computed: {\n    ...mapState({\n      stakeIdentity: state => state.NodeStake.stakeIdentity,\n      stakeWallet: state => state.NodeStake.stakeWallet,\n      detail: state => state.NodeStake.detail,\n      ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n        ledgerPk : state => state.LedgerConnector.publicKey,\n        ledgerWallet: state => state.LedgerConnector.ledgerWallet\n    })\n  },\n  methods: {\n    handleRouteBack() {\n      this.$router.go(-1);\n    },\n    handleStake() {\n      if (!this.stakeQuantity) {\n        this.$message.error(this.$t(\"nodeStake.stakeQuantityEmpty\"));\n        return;\n      }\n      const ontid = this.detail.ontid;\n      const peerPubkey = this.detail.publickey;\n      const keyNo = 1;\n      const userAddr = new Crypto.Address(this.detail.stakewalletaddress);\n      const initPos = parseInt(this.stakeQuantity);\n      const payer = userAddr;\n      const tx = GovernanceTxBuilder.makeRegisterCandidateTx(\n        ontid,\n        peerPubkey,\n        keyNo,\n        userAddr,\n        initPos,\n        payer,\n        GAS_PRICE,\n        GAS_LIMIT\n      );\n      this.tx = tx;\n      this.ontidPassModal = true;\n    },\n    handleOntidSignOK() {\n      if(!this.ontidPassword) {\n        this.$message.error(this.$t('nodeStake.passwordEmpty'))\n        return;\n      }\n      if (this.ontidPassword) {\n        const enc = new Crypto.PrivateKey(this.stakeIdentity.controls[0].key);\n        let pri;\n        try {\n          pri = enc.decrypt(\n            this.ontidPassword,\n            new Crypto.Address(this.stakeIdentity.controls[0].address),\n            this.stakeIdentity.controls[0].salt\n          );// ontid use 4096 as n\n        } catch (err) {\n          console.log(err);\n          this.$message.error(this.$t(\"common.pwdErr\"));\n          return;\n        }\n        TransactionBuilder.signTransaction(this.tx, pri);\n        this.ontidPassModal = false;\n        this.walletPassModal = true;\n      }\n    },\n    handleOntidSignCancel() {\n      this.ontidPassModal = false;\n    },\n    handleWalletSignOK(){\n      if(this.walletModalHandled) {\n        return;\n      }\n      this.walletModalHandled = true;\n      if(this.stakeWallet.key && !this.walletPassword) { //common wallet\n        this.$message.error(this.$t('nodeStake.passwordEmpty'))\n        return;\n      }\n      if(this.stakeWallet.key) {\n        const enc = new Crypto.PrivateKey(this.stakeWallet.key);\n        let pri;\n        try {\n          pri = enc.decrypt(\n            this.walletPassword,\n            new Crypto.Address(this.stakeWallet.address),\n            this.stakeWallet.salt,\n            DEFAULT_SCRYPT\n          );\n        } catch (err) {\n          console.log(err);\n          this.$message.error(this.$t(\"common.pwdErr\"));\n          this.walletModalHandled = false;\n          return;\n        }\n        TransactionBuilder.addSign(this.tx, pri);\n        this.delegateSendTx(this.tx);\n      } else { //ledger sign\n        if(this.ledgerWallet.address) {\n            this.$store.dispatch('showLoadingModals')\n            const tx = this.tx;\n            const pk = new Crypto.PublicKey(this.ledgerWallet.publicKey);\n            const txSig = new TxSignature();\n            txSig.M = 1;\n            txSig.pubKeys = [pk];\n            tx.payer = new Crypto.Address(this.ledgerWallet.address);\n            const txData = tx.serializeUnsignedData();\n            legacySignWithLedger(txData).then(res => {\n            // console.log('txSigned: ' + res);\n            const sign = '01' + res; //ECDSAwithSHA256\n            txSig.sigData = [sign]\n            tx.sigs.push(txSig);\n            this.delegateSendTx(tx);\n            }, err => {\n                this.walletModalHandled = false;\n                this.$store.dispatch('hideLoadingModals')\n                alert(err.message)\n            })\n        } else {\n            this.$message.warning(this.$t('ledgerWallet.connectApp'))\n        }\n\n      }\n    },\n    handleWalletSignCancel() {\n      this.walletPassModal = false;\n    },\n    delegateSendTx(tx){\n      const body = {\n        ontid: this.stakeIdentity.ontid,\n        publickey: this.detail.publickey,\n        stakewalletaddress: this.stakeWallet.address,\n        transactionhash: utils.reverseHex(tx.getHash()),\n        transactionbodyhash: tx.serialize()\n      }\n      const net = localStorage.getItem('net')\n      const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD\n      this.$store.dispatch('showLoadingModals')\n      axios.post(ontPassNode + ONT_PASS_URL.DelegateSendTx, body).then(res => {\n        this.$store.dispatch('hideLoadingModals')\n        this.walletModalHandled = false;\n        const params = {\n          ontid: this.stakeIdentity.ontid,\n          stakewalletaddress: this.stakeWallet.address,\n          stakequantity: this.stakeQuantity\n        }\n        axios.post(ontPassNode + ONT_PASS_URL.SetStakeInfo, params).then(res => {\n          this.$router.push({name: 'NodeStakeInfo'})\n        })\n      }).catch(err => {\n        this.$store.dispatch('hideLoadingModals')\n        this.walletModalHandled = false;\n        console.log(err)\n        this.$message.error(this.$t('nodeStake.txFailed'))\n        this.walletPassModal = false;\n      })\n    }\n\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/Node/Vote/Create.vue",
    "content": "<template>\n\t<div>\n\t\t<breadcrumb :routes=\"routes\"\n\t\t\t:current=\"$t('vote.new')\"\n\t\t\tv-on:backEvent=\"back\"></breadcrumb>\n\t\t<div class=\"create-container\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<p class=\"title\">{{$t('vote.title')}}</p>\n\t\t\t\t<a-textarea v-model=\"title\"\n\t\t\t\t\tplaceholder=\"Title of the voted issue\"\n\t\t\t\t\t:autosize=\"{ minRows: 2, maxRows: 6 }\"\n                    @keyup=\"onTitleInput\"\n\t\t\t\t\tclass=\"common-input title-input\">\n\t\t\t\t</a-textarea>\n\t\t\t\t<span class=\"title-length\">{{title.length}}/{{title_limit}}</span>\n\t\t\t</div>\n            <div class=\"date-container\">\n                <div class=\"date-start\">\n                    <p class=\"title\">{{$t('vote.votingStarts')}}</p>\n                    <div>\n                        <a-date-picker placeholder=\"Date\" v-model=\"startDate\" class=\"input-date\"/>\n                        <a-time-picker placeholder=\"Time\" v-model=\"startTime\" class=\"input-time\"/>\n                    </div>\n                </div>\n                <div class=\"date-end\">\n                    <p class=\"title\">{{$t('vote.votingEnds')}}</p>\n                    <div>\n                        <a-date-picker placeholder=\"Date\" v-model=\"endDate\" class=\"input-date\"/>\n                        <a-time-picker placeholder=\"Time\" v-model=\"endTime\" class=\"input-time\"/>\n                    </div>\n                </div>\n            </div>\n\n            <div class=\"form-group\">\n                <p class=\"title\">{{$t('vote.detail')}}</p>\n                <a-textarea v-model=\"content\"\n\t\t\t\t\tplaceholder=\"Detailed information of the voting\"\n\t\t\t\t\t:rows=\"6\"\n                    @keyup=\"onDetailInput\"\n\t\t\t\t\tclass=\"common-input title-input\">\n\t\t\t\t</a-textarea>\n\t\t\t\t<span class=\"title-length\">{{content.length}}/{{detail_limit}}</span>\n            </div>\n\n            <div class=\"btns-container\">\n                <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{ $t('vote.back') }}</a-button>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"submit\">{{ $t('vote.submit') }}</a-button>\n            </div>\n            <!-- <p class=\"create-tip\">{{$t('vote.nodeCanVoteOnly')}}</p> -->\n\n\t\t</div>\n        <sign-send-tx :visible=\"signVisible\" :tx=\"tx\" :wallet=\"vote_wallet\"\n        v-on:signClose=\"handleCancel\"\n        v-on:txSent=\"handleTxSent\"\n        ></sign-send-tx>\n\t</div>\n</template>\n\n<script>\nimport Breadcrumb from \"@/components/Breadcrumb\";\nimport SignSendTx from '../../Common/SignSendTx'\n\nimport { mapState } from \"vuex\";\nvar dateFormat = require('dateformat');\n\nexport default {\n\tname: \"VoteCreate\",\n\tcomponents: {\n        Breadcrumb,\n        SignSendTx\n\t},\n\tdata() {\n\t\tconst routes = [\n\t\t\t{ name: this.$t(\"vote.node\"), path: \"/node\" },\n\t\t\t{ name: this.$t(\"vote.votingTopics\"), path: \"/vote/votes\" }\n\t\t];\n\t\treturn {\n            title_limit: 150,\n            detail_limit: 2000,\n\t\t\troutes,\n            title: \"\",\n            content: '',\n            startDate:null,\n            startTime: null,\n            endDate: null,\n            endTime: null,\n            tx: '',\n            signVisible: false\n\t\t};\n    },\n    computed: {\n        ...mapState({\n            vote_wallet: state => state.Vote.voteWallet,\n        })\n    },\n\tmethods: {\n\t\tback() {\n\t\t\tthis.$router.back();\n        },\n        onTitleInput(e) {\n            const value = e.target.value;\n            if(this.title.length > this.title_limit) {\n                this.title = this.title.substr(0, this.title_limit)\n            }\n            if (/[\\u4E00-\\u9FA5]/g.test(value)) { // 中文字符\n                this.$message.warning(this.$t('vote.onlySupportEnglish'))\n                this.title = this.title.substring(0, value.length-1)\n            }\n        },\n        onDetailInput(e) {\n            const value = e.target.value;\n            if(this.content.length > this.detail_limit) {\n                this.content = this.content.substr(0, this.detail_limit)\n            }\n            if (/[\\u4E00-\\u9FA5]/g.test(value)) { // 中文字符\n                this.$message.warning(this.$t('vote.onlySupportEnglish'))\n                this.content = this.content.substring(0, value.length-1)\n            }\n        },\n        validateInput(str) {\n            str = str.trim();\n            if(!str) {\n                this.$message.warning(this.$t('vote.fillBlanks'))\n                return false;\n            }\n            if(/[\\u4E00-\\u9FA5]/g.test(str)) {\n                this.$message.warning(this.$t('vote.onlySupportEnglish'))\n                return false\n            }\n            return true;\n        },\n        submit() {\n            if(!this.validateInput(this.title) || !this.validateInput(this.content)) {\n                return;\n            }\n            if(!this.title || !this.content || !this.startDate || !this.startTime || !this.endDate || !this.endTime) {\n                this.$message.warning(this.$t('vote.fillBlanks'))\n                return\n            }\n            const start_time_str = dateFormat(this.startDate, 'isoDate') + ' ' + dateFormat(this.startTime, 'isoTime')\n            const end_time_str = dateFormat(this.endDate, 'isoDate') + ' ' + dateFormat(this.endTime, 'isoTime')\n            const startTime = Math.floor((new Date(start_time_str).getTime()) / 1000)\n            const endTime = Math.floor((new Date(end_time_str).getTime()) / 1000)\n            if(startTime >= endTime) {\n                this.$message.warning(this.$t('vote.startTimeError'))\n                return\n            }\n            if(Date.now() >= new Date(end_time_str).getTime()) {\n                this.$message.warning(this.$t('vote.endTimeError'))\n                return \n            }\n            const voters = []\n            const vote = {\n                title: this.title,\n                content: this.content,\n                startTime ,\n                endTime,\n                voters\n            }\n            this.$store.dispatch('createVote', {vote}).then(tx => {\n                this.tx = tx;\n                this.signVisible = true;\n            } )\n        },\n        handleCancel() {\n            this.signVisible = false;\n            this.tx = ''\n        },\n        handleTxSent() {\n            this.signVisible = false;\n            this.$router.back();\n        }\n\t}\n};\n</script>\n<style lang=\"scss\" scoped>\n.create-container {\n\twidth: 550px;\n\tmargin: 0 auto;\n\tmargin-top: 20px;\n}\n.title {\n\tfont-size: 14px;\n\tfont-family: AvenirNext-Medium, AvenirNext;\n\tfont-weight: 500;\n\tcolor: rgba(0, 0, 0, 1);\n\tmargin-bottom: 6px;\n}\n.common-input {\n\tborder: 1px solid rgba(208, 210, 217, 1);\n\tborder-radius: 0;\n}\n.common-input:focus {\n\tbox-shadow: 0 0 0 2px rgba(208, 210, 217, 0.6);\n}\n.form-group {\n\tposition: relative;\n    margin-bottom:36px;\n}\n.title-length {\n\tposition: absolute;\n\tright: 0;\n\tbottom: -20px;\n\tfont-size: 12px;\n\tfont-family: AvenirNext-Regular, AvenirNext;\n\tfont-weight: 400;\n\tcolor: rgba(0, 0, 0, 1);\n    opacity: 0.6;\n}\n.input-date {\n    width:140px;\n    margin-right:5px;\n\tborder-radius: 0;\n}\n.input-time {\n    width:110px;\n    input {\n\tborder-radius: 0 !important;\n    }\n\n}\n.date-container {\n    width: 100%;\n    display: flex;\n    flex-direction: row;\n    justify-content: space-between;\n    margin-bottom: 36px;\n}\n.btns-container {\n    display: flex;\n    flex-direction: row;\n    justify-content: center;\n    align-items: center;\n    margin:0 auto;\n    margin-top: 27px;\n    margin-bottom: 16px;\n    button:first-child {\n        margin-right:40px;\n    }\n}\n.create-tip {\n    font-size:14px;\n    font-family:AvenirNext-Regular,AvenirNext;\n    font-weight:400;\n    color:rgba(0,0,0,1);\n    opacity: 0.4;\n    text-align: center;\n}\n</style>"
  },
  {
    "path": "src/components/Node/Vote/Detail.vue",
    "content": "<template>\n\t<div>\n\t\t<breadcrumb :routes=\"routes\"\n\t\t\t:current=\"$t('vote.votingDetail')\"\n\t\t\tv-on:backEvent=\"back\"></breadcrumb>\n\t\t<div class=\"detail-container\">\n\t\t\t<div class=\"left-part\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t{{vote.title}}\n\t\t\t\t</div>\n\t\t\t\t<div class=\"voted-container\">\n\n\t\t\t\t\t<div class=\"visiter-approve\"\n\t\t\t\t\t\tv-if=\"!isVoter\">\n\t\t\t\t\t\t<a-icon type=\"caret-up\"\n\t\t\t\t\t\t\tclass=\"icon-approve\" />\n\t\t\t\t\t\t<span class=\"total-voted\">{{vote.approves}}</span>\n\t\t\t\t\t\t<span class=\"text-smal\">votes</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"short-line\"\n\t\t\t\t\t\tv-if=\"!isVoter\"></div>\n\t\t\t\t\t<div class=\"visiter-reject\"\n\t\t\t\t\t\tv-if=\"!isVoter\">\n\t\t\t\t\t\t<a-icon type=\"caret-down\"\n\t\t\t\t\t\t\tclass=\"icon-reject\" />\n\t\t\t\t\t\t<span class=\"total-voted\">{{vote.rejects}}</span>\n\t\t\t\t\t\t<span class=\"text-smal\">votes</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"not-voted\"\n\t\t\t\t\t\tv-if=\"isVoter\"\n\t\t\t\t\t\t@click=\"onApprove\"\n\t\t\t\t\t\t:class=\"{'voted-approve': myVoted === MY_VOTED.APPROVED}\">\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t<a-icon type=\"caret-up\"\n\t\t\t\t\t\t\t\tclass=\"icon-approve\" />\n\t\t\t\t\t\t\t<span :class=\"{'my-voted-text': myVoted === MY_VOTED.APPROVED}\"\n\t\t\t\t\t\t\t\tclass=\"total-voted\">{{vote.approves}}</span>\n\t\t\t\t\t\t\t<span :class=\"{'my-voted-text': myVoted === MY_VOTED.APPROVED}\"\n\t\t\t\t\t\t\t\tclass=\"text-smal\">votes</span>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p class=\"vote-option\"\n\t\t\t\t\t\t\tv-if=\"myVoted !== MY_VOTED.APPROVED \">Vote Up</p>\n\t\t\t\t\t\t<p class=\"my-voted my-voted-approve\"\n\t\t\t\t\t\t\tv-if=\"myVoted === MY_VOTED.APPROVED \">\n\t\t\t\t\t\t\t<span>Voted</span> <span class=\"added-votes\"> +{{my_weight}}</span>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"not-voted\"\n\t\t\t\t\t\tv-if=\"isVoter\"\n\t\t\t\t\t\t@click=\"onReject\"\n\t\t\t\t\t\t:class=\"{'voted-reject': myVoted === MY_VOTED.REJECTED}\">\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t<a-icon type=\"caret-down\"\n\t\t\t\t\t\t\t\tclass=\"icon-reject\" />\n\t\t\t\t\t\t\t<span :class=\"{'my-voted-text': myVoted === MY_VOTED.REJECTED}\"\n\t\t\t\t\t\t\t\tclass=\"total-voted\">{{vote.rejects}}</span>\n\t\t\t\t\t\t\t<span :class=\"{'my-voted-text': myVoted === MY_VOTED.REJECTED}\"\n\t\t\t\t\t\t\t\tclass=\"text-smal\">votes</span>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p class=\"my-voted my-voted-reject\"\n\t\t\t\t\t\t\tv-if=\"myVoted === MY_VOTED.REJECTED \">\n\t\t\t\t\t\t\t<span>Voted</span> <span class=\"added-votes\"> +{{my_weight}}</span>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p class=\"vote-option\"\n\t\t\t\t\t\t\tv-if=\"myVoted !== MY_VOTED.REJECTED \">Vote Down</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"stop-btn\"\n\t\t\t\t\t@click=\"onStop\"\n\t\t\t\t\tv-if=\"vote.admin === voteWallet.address\">\n\t\t\t\t\t{{$t('vote.stopVote')}}\n\t\t\t\t</div>\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\t{{vote.content}}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"right-part\">\n\t\t\t\t<div class=\"info-container\">\n\t\t\t\t\t<p class=\"title\">{{$t('vote.info')}}</p>\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<span>{{$t('vote.startTime')}}</span>\n\t\t\t\t\t\t<span>{{formatTime(vote.startTime)}}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<span>{{$t('vote.endTime')}}</span>\n\t\t\t\t\t\t<span>{{formatTime(vote.endTime)}}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<span>{{$t('vote.hash')}}</span>\n\t\t\t\t\t\t<span class=\"hash-link\" @click=\"openVoteInExplorer\">{{reverseHash(vote.hash)}}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<span>{{$t('vote.creatorAddress')}}</span>\n\t\t\t\t\t\t<span>{{vote.admin}}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<span>{{$t('vote.votingStatus')}}</span>\n\t\t\t\t\t\t<span>{{formatStatus(vote)}}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<span>{{$t('vote.myVotes')}}</span>\n\t\t\t\t\t\t<span>{{my_weight}}</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"records-container\">\n\t\t\t\t\t<a-tabs defaultActiveKey=\"1\">\n\t\t\t\t\t\t<a-tab-pane :tab=\"$t('vote.approval')\"\n\t\t\t\t\t\t\tkey=\"1\">\n\t\t\t\t\t\t\t<a-table :columns=\"columns\"\n\t\t\t\t\t\t\t\t:dataSource=\"approve_data\"\n\t\t\t\t\t\t\t\t:pagination=\"false\"\n                                :bordered=\"false\"\n\t\t\t\t\t\t\t\tsize=\"small\">\n\t\t\t\t\t\t\t</a-table>\n\t\t\t\t\t\t</a-tab-pane>\n\t\t\t\t\t\t<a-tab-pane :tab=\"$t('vote.opposition')\"\n\t\t\t\t\t\t\tkey=\"2\">\n\t\t\t\t\t\t\t<a-table :columns=\"columns\"\n\t\t\t\t\t\t\t\t:dataSource=\"reject_data\"\n\t\t\t\t\t\t\t\t:pagination=\"false\"\n                                :bordered=\"false\"\n\t\t\t\t\t\t\t\tsize=\"small\">\n\t\t\t\t\t\t\t</a-table>\n\t\t\t\t\t\t</a-tab-pane>\n\t\t\t\t\t</a-tabs>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<sign-send-tx :visible=\"signVisible\"\n\t\t\t:tx=\"tx\"\n\t\t\t:wallet=\"voteWallet\"\n\t\t\tv-on:signClose=\"handleCancel\"\n\t\t\tv-on:txSent=\"handleTxSent\"></sign-send-tx>\n\t</div>\n</template>\n\n<script>\nimport Breadcrumb from \"@/components/Breadcrumb\";\nimport SignSendTx from \"../../Common/SignSendTx\";\nimport { VOTE_STATUS_TEXT, MY_VOTED } from \"../../../store/modules/Vote\";\nimport { open, getExplorerUrl } from \"../../../core/utils\";\n\nimport { mapState } from \"vuex\";\nvar dateFormat = require(\"dateformat\");\n\nexport default {\n\tname: \"VoteCreate\",\n\tcomponents: {\n\t\tBreadcrumb,\n\t\tSignSendTx\n\t},\n\tdata() {\n\t\tconst routes = [\n\t\t\t{ name: this.$t(\"vote.node\"), path: \"/node\" },\n\t\t\t{ name: this.$t(\"vote.votingTopics\"), path: \"/vote/votes\" }\n\t\t];\n\t\tconst columns = [\n\t\t\t{\n\t\t\t\tdataIndex: \"name\",\n\t\t\t\tkey: \"name\",\n\t\t\t\ttitle: this.$t(\"vote.name\")\n\t\t\t},\n\t\t\t{\n\t\t\t\tdataIndex: \"address\",\n\t\t\t\tkey: \"address\",\n\t\t\t\ttitle: this.$t(\"vote.address\"),\n\t\t\t\twidth: \"100px\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tdataIndex: \"weight\",\n\t\t\t\tkey: \"weight\",\n\t\t\t\ttitle: this.$t(\"vote.votes\")\n\t\t\t}\n\t\t];\n\t\treturn {\n\t\t\troutes,\n\t\t\tcolumns,\n\t\t\tapprove_data: [],\n\t\t\treject_data: [],\n\t\t\tmyVoted: \"\",\n\t\t\tMY_VOTED,\n\t\t\tisVoter: false,\n\t\t\tsignVisible: false,\n\t\t\ttx: \"\"\n\t\t};\n\t},\n\tcomputed: {\n\t\t...mapState({\n\t\t\tvote: state => state.Vote.currentVote,\n\t\t\trole: state => state.Vote.role,\n\t\t\tmy_weight: state => state.Vote.my_weight,\n\t\t\tvoteWallet: state => state.Vote.voteWallet,\n\t\t\tvotedRecords: state => state.Vote.current_vote_records\n\t\t})\n\t},\n\tmounted() {\n\t\twindow.scroll(0, 0);\n\t\tthis.refresh();\n\t\tthis.intervalId = setInterval(() => {\n\t\t\tthis.refresh();\n\t\t}, 10 * 1000);\n\t},\n\tbeforeDestroy() {\n\t\tclearInterval(this.intervalId);\n\t},\n\twatch: {\n\t\tvotedRecords: function(newVal, oldVal) {\n\t\t\tthis.approve_data = newVal.filter(item => item.isApproval);\n\t\t\tthis.reject_data = newVal.filter(item => !item.isApproval);\n\t\t}\n\t},\n\tmethods: {\n\t\tback() {\n\t\t\tthis.$router.back();\n\t\t},\n\t\tformatTime(dateTime) {\n\t\t\tconst time = dateFormat(dateTime, \"yyyy-mm-dd HH:MM:ss\");\n\t\t\treturn time;\n\t\t},\n\t\tformatStatus(vote) {\n\t\t\tconst statusMap = {\n\t\t\t\t[VOTE_STATUS_TEXT.NOT_START]: this.$t(\"vote.notStart\"),\n\t\t\t\t[VOTE_STATUS_TEXT.IN_PROGRESS]: this.$t(\"vote.inProgress\"),\n\t\t\t\t[VOTE_STATUS_TEXT.FINISHED]: this.$t(\"vote.finished\"),\n\t\t\t\t[VOTE_STATUS_TEXT.CANCELED]: this.$t(\"vote.canceled\")\n\t\t\t};\n\t\t\treturn statusMap[vote.statusText];\n\t\t},\n\t\treverseHash(hash) {\n\t\t\treturn Buffer.from(hash, 'hex').reverse().toString('hex');\n\t\t},\n\t\topenVoteInExplorer() {\n\t\t\tconst url = `${getExplorerUrl()}/transaction/${this.reverseHash(this.vote.hash)}`;\n\t\t\topen(url);\n\t\t},\n\t\trefresh() {\n\t\t\tconst hash = this.vote.hash;\n\t\t\tconst address = this.voteWallet.address;\n\t\t\tthis.$store\n\t\t\t\t.dispatch(\"getVotedInfo\", { hash, address })\n\t\t\t\t.then(res => {\n\t\t\t\t\tthis.myVoted = res;\n\t\t\t\t});\n\t\t\tthis.$store.dispatch(\"isVoter\", { hash }).then(res => {\n\t\t\t\tthis.isVoter = res;\n\t\t\t});\n\t\t\tthis.$store.dispatch(\"getVotedRecords\", { hash });\n\t\t\tthis.$store.dispatch(\"updateCurrentVote\", { hash });\n\t\t},\n\t\thandleCancel() {\n\t\t\tthis.signVisible = false;\n\t\t\tthis.tx = \"\";\n\t\t},\n\t\thandleTxSent() {\n\t\t\tthis.signVisible = false;\n\t\t\t// 更新页面数据\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.refresh();\n\t\t\t}, 3000);\n\t\t},\n\t\tonApprove() {\n\t\t\tif (this.myVoted === this.MY_VOTED.APPROVED) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this.vote.statusText !== VOTE_STATUS_TEXT.IN_PROGRESS) {\n\t\t\t\tthis.$message.warning(\n\t\t\t\t\tthis.$t(\"vote.notAllowVote\") + this.formatStatus(this.vote)\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.$store\n\t\t\t\t.dispatch(\"submitVote\", {\n\t\t\t\t\ttype: true,\n\t\t\t\t\thash: this.vote.hash\n\t\t\t\t})\n\t\t\t\t.then(tx => {\n\t\t\t\t\tthis.tx = tx;\n\t\t\t\t\tthis.signVisible = true;\n\t\t\t\t});\n\t\t},\n\t\tonReject() {\n\t\t\tif (this.myVoted === this.MY_VOTED.REJECTED) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this.vote.statusText !== VOTE_STATUS_TEXT.IN_PROGRESS) {\n\t\t\t\tthis.$message.warning(\n\t\t\t\t\tthis.$t(\"vote.notAllowVote\") + this.formatStatus(this.vote)\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.$store\n\t\t\t\t.dispatch(\"submitVote\", {\n\t\t\t\t\ttype: false,\n\t\t\t\t\thash: this.vote.hash\n\t\t\t\t})\n\t\t\t\t.then(tx => {\n\t\t\t\t\tthis.tx = tx;\n\t\t\t\t\tthis.signVisible = true;\n\t\t\t\t});\n\t\t},\n\t\tonStop() {\n\t\t\tif (\n\t\t\t\tthis.vote.statusText === VOTE_STATUS_TEXT.CANCELED ||\n\t\t\t\tthis.vote.statusText === VOTE_STATUS_TEXT.FINISHED\n\t\t\t) {\n\t\t\t\tthis.$message.warning(\n\t\t\t\t\tthis.$t(\"vote.notAllowStop\") + this.formatStatus(this.vote)\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.$store\n\t\t\t\t.dispatch(\"stopVote\", {\n\t\t\t\t\thash: this.vote.hash\n\t\t\t\t})\n\t\t\t\t.then(tx => {\n\t\t\t\t\tthis.tx = tx;\n\t\t\t\t\tthis.signVisible = true;\n\t\t\t\t});\n\t\t}\n\t}\n};\n</script>\n<style lang=\"scss\" scoped>\n.icon-approve {\n\tcolor: #4eb926;\n}\n.icon-reject {\n\tcolor: #ea4545;\n}\n.text-smal {\n\tfont-size: 14px;\n\tfont-family: AvenirNext-Regular, AvenirNext;\n\tfont-weight: 400;\n\tcolor: rgba(0, 0, 0, 1);\n}\n\n.detail-container {\n\twidth: 100%;\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: space-between;\n\t.left-part {\n\t\twidth: 50%;\n\t\tmargin-right: 50px;\n\t\t.title {\n\t\t\tfont-size: 18px;\n\t\t\tfont-family: AvenirNext-DemiBold, AvenirNext;\n\t\t\tfont-weight: 600;\n\t\t\tcolor: rgba(0, 0, 0, 1);\n\t\t\tmargin-bottom: 24px;\n\t\t}\n\t}\n\t.right-part {\n\t\twidth: 50%;\n\t}\n}\n.visiter-approve {\n\tmin-width: 120px;\n\tmargin-right: 24px;\n}\n.visiter-reject {\n\tmin-width: 120px;\n\tmargin-left: 24px;\n}\n.short-line {\n\twidth: 1px;\n\theight: 22px;\n\tbackground: rgba(244, 244, 246, 1);\n}\n.voted-container {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: flex-start;\n\talign-items: center;\n\tmargin-bottom: 23px;\n\t.voted-approve {\n\t\tmargin-right: 32px;\n\t\twidth: 200px;\n\t\theight: 86px;\n\t\tborder-radius: 6px;\n\t\tbackground: rgba(78, 185, 38, 0.1);\n\t\tpadding: 16px;\n\t\tborder-bottom: 3px solid #4eb926;\n\t\tcursor: pointer;\n\t}\n\t.my-voted {\n\t\tmargin-top: 5px;\n\t\tspan {\n\t\t\tfont-size: 14px;\n\t\t\tfont-family: AvenirNext-Regular, AvenirNext;\n\t\t\tfont-weight: 400;\n\t\t}\n\t\tspan:last-child {\n\t\t\tcolor: rgba(0, 0, 0, 1);\n\t\t\topacity: 0.4;\n\t\t}\n\t}\n\t.my-voted-approve {\n\t\tspan:first-child {\n\t\t\tcolor: rgba(78, 185, 38, 1);\n\t\t}\n    }\n\t.my-voted-reject {\n\t\tspan:first-child {\n\t\t\tcolor: rgba(234, 69, 69, 1);\n\t\t}\n\t}\n\t.not-voted {\n\t\twidth: 200px;\n\t\theight: 86px;\n\t\tborder-radius: 6px;\n\t\tbackground: rgba(245, 247, 251, 1);\n\t\tpadding-top: 16px;\n\t\tpadding: 16px;\n\t\tcursor: pointer;\n\t\tmargin-right: 32px;\n\t}\n\t.not-voted:hover {\n\t\tbackground: #e4e6ea;\n\t}\n\t.voted-reject {\n\t\tbackground: rgba(234, 69, 69, 0.1);\n\t\tborder-bottom: 3px solid #ea4545;\n\t\tcursor: default;\n\t}\n\t.voted-approve {\n\t\tbackground: rgba(78, 185, 38, 0.1);\n\t\tborder-bottom: 3px solid #4eb926;\n\t\tcursor: default;\n    }\n    .voted-reject:hover {\n        background: rgba(234, 69, 69, 0.1);\n    }\n    .voted-approve:hover {\n        background: rgba(78, 185, 38, 0.1);\n    }\n\t.total-voted {\n\t\tfont-size: 18px;\n\t\tfont-family: AvenirNext-Regular, AvenirNext;\n\t\tfont-weight: 400;\n\t\tcolor: rgba(0, 0, 0, 1);\n\t\topacity: 0.4;\n\t}\n\t.text-smal {\n\t\topacity: 0.4;\n\t}\n\t.vote-option {\n\t\tfont-size: 14px;\n\t\tfont-family: AvenirNext-Regular, AvenirNext;\n\t\tfont-weight: 400;\n\t\tcolor: rgba(0, 0, 0, 1);\n\t\topacity: 0.4;\n\t\tmargin-top: 5px;\n\t}\n}\n.stop-btn {\n\twidth: 432px;\n\theight: 32px;\n\tbackground: rgba(244, 244, 246, 1);\n\tborder-radius: 3px;\n\tfont-size: 14px;\n\tfont-family: AvenirNext-Medium, AvenirNext;\n\tfont-weight: 500;\n\tcolor: rgba(234, 69, 69, 1);\n\ttext-align: center;\n\tline-height: 32px;\n\tcursor: pointer;\n\tmargin-bottom: 16px;\n}\n\n.stop-btn:hover {\n    background: #e4e6ea;\n}\n\n.content {\n\tfont-size: 16px;\n\tfont-family: AvenirNext-Regular, AvenirNext;\n\tfont-weight: 400;\n\tcolor: rgba(0, 0, 0, 1);\n\topacity: 0.6;\n}\n.info-container {\n\tmargin-bottom: 22px;\n\t.title {\n\t\tfont-size: 16px;\n\t\tfont-family: AvenirNext-Bold, AvenirNext;\n\t\tfont-weight: bold;\n\t\tcolor: rgba(0, 0, 0, 1);\n\t\topacity: 0.6;\n\t\tborder-bottom: 1px solid #f4f4f6;\n\t}\n\t.info-item {\n\t\tpadding: 10px 0;\n\t\tborder-bottom: 1px solid #f4f4f6;\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\ttext-align: left;\n\t\twidth: 100%;\n\t\tword-break: break-all;\n\t\tspan:first-child {\n\t\t\twidth: 200px;\n\t\t\tfont-size: 12px;\n\t\t\tfont-family: AvenirNext-Medium, AvenirNext;\n\t\t\tfont-weight: 500;\n\t\t\tcolor: rgba(81, 84, 87, 1);\n\t\t}\n\t\tspan:last-child {\n\t\t\tflex: 1;\n\t\t\tfont-size: 14px;\n\t\t\tfont-family: AvenirNext-Regular, AvenirNext;\n\t\t\tfont-weight: 400;\n\t\t\tcolor: rgba(0, 0, 0, 1);\n\t\t}\n\t}\n}\n.my-voted-text {\n\topacity: 1 !important;\n}\n\n.hash-link {\n\tcolor: #1890ff;\n\tcursor: pointer;\n\ttext-decoration: none;\n\ttransition: color 0.3s ease;\n\tword-break: break-all;\n}\n\n.hash-link:hover {\n\tcolor: #40a9ff;\n\ttext-decoration: underline;\n}\n</style>"
  },
  {
    "path": "src/components/Node/Vote/List.vue",
    "content": "<template>\n\t<div>\n        <breadcrumb :routes=\"routes\" :current=\"$t('vote.votingTopics')\" v-on:backEvent=\"back\"></breadcrumb>\n        <div class=\"top-menu-container\" v-if=\"role.indexOf(VOTE_ROLE.ADMIN) > -1\">\n            <a-menu v-model=\"current\" mode=\"horizontal\" @click=\"handleSelectMenu\">\n                <a-menu-item v-for=\"menu in menus\" :key=\"menu.key\">{{menu.name}}</a-menu-item>\n            </a-menu>\n            <div class=\"btn-new\" @click=\"handleAddVote\" v-if=\"role.indexOf(VOTE_ROLE.ADMIN) > -1\"></div>\n            \n        </div>\n        <div class=\"list-container\" v-show=\"current[0] === 'all' \">\n            <div class=\"no-data\" v-if=\"all_votes.length === 0\"><p>No data</p> </div>\n            <div class=\"list-item\" v-for=\"item in all_votes\" :key=\"item.hash\">\n                <div class=\"title\">\n                    {{item.title}}\n                </div>\n                <div class=\"duration\">\n                    <p>{{$t('vote.duration')}}</p>\n                    <p>{{formatDuration(item)}}</p>\n                </div>\n                <div class=\"status\">\n                    <p>{{formatStatus(item)}}</p>\n                    <div class=\"status-detail\">\n                        <div class=\"status-item\">\n                            <a-icon type=\"caret-up\" class=\"icon-approve\" /> <span>{{item.approves}}</span>\n                        </div>\n                        <div class=\"status-item\">\n                            <a-icon type=\"caret-down\" class=\"icon-reject\" /> <span>{{item.rejects}}</span>\n                        </div>\n                    </div>\n                    \n                </div>\n                <div class=\"actions\">\n                    <a-button type=\"link\" @click=\"toDetail(item)\">Detail</a-button>\n                </div>\n            </div>\n        </div>\n        <div class=\"list-container\" v-show=\"current[0] === 'created' \">\n            <div class=\"no-data\" v-if=\"admin_votes.length === 0\"><p>No data</p> </div>\n            <div class=\"list-item\" v-for=\"item in admin_votes\" :key=\"item.hash\">\n                <div class=\"title\">\n                    {{item.title}}\n                </div>\n                <div class=\"duration\">\n                    <p>{{$t('vote.duration')}}</p>\n                    <p>{{formatDuration(item)}}</p>\n                </div>\n                <div class=\"status\">\n                    <p>{{formatStatus(item)}}</p>\n                    <div class=\"status-detail\">\n                        <div class=\"status-item\">\n                            <a-icon type=\"caret-up\" class=\"icon-approve\" /> <span>{{item.approves}}</span>\n                        </div>\n                        <div class=\"status-item\">\n                            <a-icon type=\"caret-down\" class=\"icon-reject\" /> <span>{{item.rejects}}</span>\n                        </div>\n                    </div>\n                    \n                </div>\n                <div class=\"actions\">\n                    <a-button type=\"link\" @click=\"toDetail(item)\">Detail</a-button>\n                    <span>|</span>\n                    <a-button type=\"link\" style=\"color: #EA4545\" @click=\"onStopVote(item)\"\n                    v-if=\"item.statusText === VOTE_STATUS_TEXT.NOT_START ||\n                          item.statusText === VOTE_STATUS_TEXT.IN_PROGRESS\">Stop Vote</a-button>\n                </div>\n            </div>\n        </div>\n        <sign-send-tx :visible=\"signVisible\" :tx=\"tx\" :wallet=\"voteWallet\"\n        v-on:signClose=\"handleCancel\"\n        v-on:txSent=\"handleTxSent\"\n        ></sign-send-tx>\n\t</div>\n</template>\n<script>\nimport Breadcrumb from '@/components/Breadcrumb'\nimport SignSendTx from \"../../Common/SignSendTx\";\nimport {mapState} from 'vuex'\nimport { VOTE_STATUS_TEXT } from '../../../store/modules/Vote'\nvar dateFormat = require('dateformat');\n\nexport default {\n    name: \"VoteList\",\n    components: {\n        Breadcrumb,\n        SignSendTx\n    },\n    data() {\n        const routes = [{name: this.$t('vote.node'), path:'/node'}]\n        return {\n            routes,\n            current: ['all'],\n            menus: [\n                {key: 'all', name: this.$t('vote.allVotes')}\n            ],\n            signVisible: false,\n            tx: '',\n            VOTE_STATUS_TEXT\n        }\n    },\n    computed: {\n        ...mapState({\n            role: state => state.Vote.role,\n            all_votes: state =>{\n               return  state.Vote.all_votes.sort((a, b)=>b.startTime - a.startTime)\n            },\n            admin_votes: state => state.Vote.admin_votes,\n            voteWallet : state => state.Vote.voteWallet,\n            \n        })\n    },\n    created() {\n        this.$store.dispatch('getVoteRole', {address: this.voteWallet.address})\n    },\n\tmounted() {\n        this.refresh()\n        this.intervalId = setInterval(() => {\n            this.refresh(false)\n        }, 10*1000)\n    },\n    beforeDestroy() {\n        clearInterval(this.intervalId)\n    },\n    watch: {\n        role: function(newVal, oldVal) {\n            if(newVal.indexOf(this.VOTE_ROLE.ADMIN) > -1) {\n                this.$store.dispatch('getAdminVotes')\n                this.menus.push({key: 'created', name: this.$t('vote.created')})\n            }\n        }\n    },\n    methods: {\n        back() {\n            this.$router.back()\n        },\n        refresh(showLoading = true) {\n            this.$store.dispatch('getAllVotes', {showLoading})\n            if(this.role.indexOf(this.VOTE_ROLE.ADMIN) > -1) {\n                    this.$store.dispatch('getAdminVotes')\n            }\n        },\n        handleSelectMenu({item, key, keyPath}){\n            this.current[0] = key\n        },\n        handleAddVote() {\n            this.$router.push('/vote/create')\n        },\n        formatDuration(vote) {\n            const start = dateFormat(vote.startTime, 'yyyy-mm-dd HH:MM')\n            const end = dateFormat(vote.endTime, 'yyyy-mm-dd HH:MM')\n            return start + ' ~ ' + end\n        },\n        formatStatus(vote) {\n            const statusMap = {\n                [VOTE_STATUS_TEXT.NOT_START]: this.$t('vote.notStart'),\n                [VOTE_STATUS_TEXT.IN_PROGRESS]: this.$t('vote.inProgress'),\n                [VOTE_STATUS_TEXT.FINISHED]: this.$t('vote.finished'),\n                [VOTE_STATUS_TEXT.CANCELED]: this.$t('vote.canceled')\n            }\n            return statusMap[vote.statusText]\n        },\n        toDetail(vote) {\n            this.$store.dispatch('setCurrentVote', {vote})\n            this.$router.push('/vote/detail')\n        },\n        handleCancel() {\n            this.signVisible = false;\n            this.tx = ''\n        },\n        handleTxSent() {\n            this.signVisible = false;\n            // 更新页面数据\n            this.refresh()\n        },\n        onStopVote(vote) {\n            if(vote.statusText === VOTE_STATUS_TEXT.CANCELED \n                || vote.statusText === VOTE_STATUS_TEXT.FINISHED) {\n                this.$message.warning(this.$t('vote.notAllowStop') + this.formatStatus(this.vote))\n                return;\n            }\n            this.$store.dispatch('stopVote', {\n                hash: vote.hash}).then(tx => {\n                    this.tx = tx;\n                    this.signVisible = true;\n                })\n        }\n    }\n};\n</script>\n<style lang=\"scss\" scoped>\n.icon-approve {\n    color:#4EB926\n}\n.icon-reject {\n    color:#EA4545\n}\n.top-menu-container {\n    position: fixed;\n    top:23px;\n    right:49px;\n    z-index: 101; \n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    .btn-new {\n        background: url('../../../assets/icon-add.svg') no-repeat center center;\n        width:20px;\n        height:20px;\n        border-radius: 50%;\n        background-color:#F4F4F6;\n        cursor: pointer;\n        margin-left: 50px;   \n    }\n    .btn-new:hover {\n        opacity: .8;\n    }\n    .ant-menu-horizontal {\n        line-height: 36px;\n    }\n    .ant-menu-item {\n        height: 36px;\n        font-size:16px;\n        font-family:AvenirNext-Regular,AvenirNext;\n        font-weight:400;\n        color:rgba(0,0,0,1);\n        opacity: 0.4;\n    }\n    .ant-menu-item-selected {\n        opacity: 1;\n    }\n}\n\n.no-data {\n    width: 100%;\n    height:500px;\n    text-align: center;\n    line-height: 50px;\n    background: #F4F4F6;\n    position: relative;\n    p {\n        margin: 200px auto;\n        font-size:16px;\n        font-family:AvenirNext-Regular,AvenirNext;\n        font-weight:400;\n        color:rgba(0,0,0,1);\n        opacity: 0.6;\n        position: absolute;\n        left:0;\n        right:0;\n    }\n}\n\n.list-container {\n    margin-left:15px;\n    margin-top:15px;\n    .list-item {\n        display: flex;\n        flex-direction: row;\n        padding: 16px 0;\n        border-bottom: 1px solid #F4F4F6;\n        align-items: center;\n\n        .title {\n            width:30%;\n            margin-right:50px;\n            font-size:14px;\n            font-family:PingFangSC-Medium,PingFang SC;\n            font-weight:500;\n            color:rgba(0,0,0,0.65);\n            display: -webkit-box;\n            -webkit-box-orient: vertical;\n            -webkit-line-clamp: 2;\n            overflow: hidden;\n        }\n        .duration {\n            margin-right:50px;\n            p {\n                opacity: 0.4;\n                font-size:12px;\n                font-family:AvenirNext-Regular,AvenirNext;\n                font-weight:400;\n                color:rgba(0,0,0,1);\n            }\n            \n            p:last-child {\n                margin-top:4px;\n                font-size: 14px;\n                opacity: 0.6;\n            }\n        }\n        .status {\n            font-size:12px;\n            font-family:AvenirNext-Regular,AvenirNext;\n            font-weight:400;\n            color:rgba(0,0,0,1);\n            .status-detail {\n                margin-top:4px;\n                display: flex;\n                flex-direction: row;\n                align-items:center;\n                div:first-child {\n                    margin-right: 20px;\n                }\n                .status-item {\n                    display: flex;\n                    flex-direction: row;\n                    justify-content: flex-start;\n                    align-items:center;\n                    span {\n                        margin-left:4px;\n                        font-size: 14px;\n                        opacity: 0.6;\n                    }\n                }\n\n            }\n        }\n        .actions {\n            position:absolute;\n            right:22px;\n            span {\n                color: #E8E8E8;\n            }\n            button {\n                padding:0;\n            }\n        }\n    }\n}\n</style>"
  },
  {
    "path": "src/components/Node/Vote/Login.vue",
    "content": "<template>\n    <div>\n        <breadcrumb :routes=\"routes\" :current=\"$t('vote.login')\" v-on:backEvent=\"back\"></breadcrumb>\n        <div class=\"auth-login\">\n            <div class=\"intro-item\">\n                <p class=\"font-medium-black\">{{$t('vote.selectWallet')}}</p>\n                <a-radio-group @change=\"changeVoteWallet\" v-model=\"voteWalletType\" class=\"change-payer-radio\">\n                <a-radio value=\"commonWallet\" class=\"payer-radio-item\">{{$t('createIdentity.commonWallet')}}</a-radio>\n                <a-radio value=\"ledgerWallet\" class=\"payer-radio-item\">{{$t('createIdentity.ledgerWallet')}}</a-radio>\n\n                <div v-if=\"voteWalletType === 'commonWallet'\">\n                    <a-select :options=\"normalWallet\" class=\"select-wallet\" v-model=\"voteWalletValue\"\n                    :placeholder=\"$t('createIdentity.selectCommonWallet')\"\n                        @change=\"handleChangePayer\">\n                    </a-select>\n                </div>\n\n                <div v-if=\"voteWalletType === 'ledgerWallet'\">\n\n                    <div class=\"payer-ledger-status\">\n                    <div class=\"font-bold\" style=\"margin-bottom: 10px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                    <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}} </span>\n                    </div>\n                    \n                </div>\n                </a-radio-group>\n                <div class=\"import-tip\">\n                    <span>{{$t('vote.notSeeWallet')}} </span>\n                    <span @click=\"hereImport\">{{$t('vote.importHere')}}</span>\n                </div>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{$t('nodeStake.next')}}</a-button>\n            </div>\n        </div>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '@/components/Breadcrumb'\nimport {mapState} from 'vuex'\n\nexport default {\n    name: 'VoteLogin',\n    components: {\n        Breadcrumb\n    },\n    data() {\n        const routes = [{name: this.$t('vote.node'), path:'/node'}]\n        return {\n            routes,\n            voteWalletType: 'commonWallet',\n            voteWallet: '',\n            voteWalletValue: ''\n        }\n    },\n    mounted() {\n        this.$store.dispatch(\"fetchWalletsFromDb\").then(() => {\n            //set payer wallet \n        });\n    },\n    beforeDestroy(){\n        this.$store.dispatch('stopGetLedgerStatus')\n    },\n    computed: {\n        ...mapState({\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n            ledgerWallet: state => state.LedgerConnector.ledgerWallet\n        }),\n        normalWallet: {\n            get() {\n                const list = this.$store.state.Wallets.NormalWallet.slice();\n                return list.map(i => {\n                    return Object.assign({}, i, {\n                        label: i.label + \" \" + i.address,\n                        value: i.address\n                    });\n                });\n            }\n        },\n    },\n    methods: {\n        back() {\n            this.$router.back()\n        },\n        hereImport() {\n            this.$router.push('/Wallets/importJsonWallet')\n        },\n        changeVoteWallet(e) {\n            this.voteWalletType = e.target.value\n            if(e.target.value === 'ledgerWallet') {\n                this.$store.dispatch('getLedgerStatus')\n            } else {\n                this.$store.dispatch('stopGetLedgerStatus')\n            }\n        },\n        handleChangePayer(value) {\n            this.voteWallet = this.normalWallet.find((v)=>{return v.address === value})\n            this.voteWalletValue = this.voteWallet.address\n        },\n        next() {\n            if(this.voteWalletType === 'commonWallet' && !this.voteWallet) {\n                this.$message.error(this.$t('nodeStake.selectIndividualWallet'))\n                return;\n            }\n            if(this.voteWalletType === 'ledgerWallet' && !this.ledgerWallet.address) {\n                this.$message.error(this.$t('nodeStake.selectLedgerWallet'))\n                return;\n            }\n            let wallet = ''\n            if(this.voteWalletType === 'commonWallet' && this.voteWallet){\n                wallet = this.voteWallet\n            } else {\n                wallet = this.ledgerWallet\n            }\n            this.$store.commit('UPDATE_VOTE_WALLET', {voteWallet: wallet})    \n            this.$store.commit('UPDATE_VOTE_WALLET_TYPE', {type: this.voteWalletType})         \n            this.$router.push({name: 'VoteList'})\n        }\n    }\n}\n</script>\n<style lang=\"scss\" scoped>\n.auth-login {\n    width:540px;\n    margin:20px auto;\n}\n.select-wallet {\n    width:100%;\n}\n.change-payer-radio {\n    width:100%;\n}\n.payer-radio-item {\n    margin-bottom:20px;\n}\n.btn-container {\n    text-align: center;\n    margin:5px auto;\n    padding-top:15px;\n}\n.btn-container p {\n    margin-bottom:5px;\n}\n.import-tip {\n    text-align: right;\n    font-size:12px;\n    font-family:AvenirNext-Regular,AvenirNext;\n    font-weight:400;\n    \n    margin-top: 4px;\n    \n    span:first-child {\n        color:rgba(0,0,0,1);\n        opacity: 0.6;\n    }\n    span:last-child {\n        opacity: 1 !important;\n        font-weight:400;\n        color:rgba(25,107,216,1);\n        text-decoration: underline;\n        cursor: pointer;\n    }\n\n}\n</style>"
  },
  {
    "path": "src/components/Node/Vote/index.vue",
    "content": "<template>\n    <div>\n        <router-view></router-view>\n    </div>\n</template>\n<script>\nexport default {\n    name: 'NodeVote'\n}\n</script>\n<style>\n\n</style>"
  },
  {
    "path": "src/components/RedeemInfoIcon.vue",
    "content": "<style scoped>\n.redeem-info-icon {\n    margin-left: 10px;\n  font-size: 16px;\n  cursor: pointer;\n  color:#D0D2D9;\n}\n.redeem-info-icon:hover {\n    color:#6F7781;\n}\n\n</style>\n<template>\n    <div>\n        <!-- <a-icon type=\"info-circle-o\" class=\"redeem-info-icon\" @click=\"show\"/> -->\n        <i class=\"fa fa-info-circle redeem-info-icon\" @click=\"show\"></i>\n        <a-modal\n            title=\"Redeem Info\"\n            v-model=\"visible\"\n            @ok=\"handleOk\"\n            >\n            <p class=\"font-regular\"><span class=\"font-medium\">{{$t('redeemInfo.claimableOngName')}}</span> {{$t('redeemInfo.claimableOng')}}</p>\n            <p class=\"font-regular\"><span class=\"font-medium\">{{$t('redeemInfo.unboundOngName')}}</span> {{$t('redeemInfo.unboundOng')}}</p>\n        </a-modal>\n    </div>\n</template>\n<script>\nexport default {\n    name: 'RedeemInfoIcon',\n    data(){\n        return {\n            visible:false\n        }\n    },\n    methods:{\n        show() {\n            this.visible = true;\n        },\n        handleOk() {\n            this.visible = false;\n        }\n    }\n}\n</script>\n\n"
  },
  {
    "path": "src/components/Setting.vue",
    "content": "<template>\n  <div class=\"setting-container\">\n    <breadcrumb :current=\"$t('setting.name')\" v-on:backEvent=\"handleBack\"></breadcrumb>\n\n    <div class=\"form-container\">\n      <form>\n        <div class=\"form-group\">\n          <label for=\"network-selection\">{{ $t('setting.net') }}</label>\n          <select name=\"network-selection\" id=\"network-selection\" class=\"form-control\" v-model=\"net\"\n                  @change=\"changeNet\">\n            <option value=\"TEST_NET\">{{ $t('setting.testNet') }}</option>\n            <option value=\"MAIN_NET\">{{ $t('setting.mainNet') }}</option>\n          </select>\n        </div>\n\n        <div class=\"form-group\">\n          <label for=\"network-selection\">{{ $t('setting.nodeAddress') }}</label>\n          <select name=\"network-selection\" id=\"network-selection\" class=\"form-control\" v-model=\"nodeAddress\"\n                  @change=\"changeNode\">\n            <option v-for=\"item of nodeList\" :key=\"item\"  :value=\"item\" >{{item}}</option>\n          </select>\n        </div>\n\n        <!-- <div class=\"form-group form-group-top\">\n          <label for=\"lang-selection\">{{ $t('setting.lang') }}</label>\n          <select name=\"lang-selection\" id=\"lang-selection\" class=\"form-control\" v-model=\"lang\"\n                  @change=\"changeLanguage\">\n            <option value=\"en\">{{ $t('setting.en') }}</option>\n            <option value=\"zh\">{{ $t('setting.zh') }}</option>\n          </select>\n        </div> -->\n\n        <div class=\"form-group form-group-top\">\n          <label>{{ $t('setting.path') }}</label>\n          <p>\n            <span class=\"span-path-title\">{{ $t('setting.pathTit') }}</span>{{savePath}}\n          </p>\n          <div>\n            <a-button type=\"primary\" class=\"btn-next\" @click=\"setSavePath\">{{ $t('setting.change') }}</a-button>\n          </div>\n        </div>\n      </form>\n    </div>\n  </div>\n</template>\n\n<script>\n  import Breadcrumb from './Breadcrumb'\n  import LangStorage from './../core/lang'\n  import { TEST_NET_LIST, MAIN_NET_LIST, TEST_NET} from '../core/consts'\n  import { validateKeystorePath, validateAddress } from '../core/utils'\n  const {dialog} = require('@electron/remote')\n\n\n  export default {\n    name: 'Setting',\n    data() {\n      return {\n        net: localStorage.getItem('net') || 'MAIN_NET',\n        nodeAddress: localStorage.getItem('nodeAddress') || MAIN_NET_LIST[0],\n        nodeList: localStorage.getItem('net') === 'TEST_NET' ? TEST_NET_LIST : MAIN_NET_LIST,\n        lang: this.$i18n.locale,\n        savePath: localStorage.getItem('savePath')\n      }\n    },\n    methods: {\n      handleBack() {\n        this.$router.push({name: 'Wallets'})\n      },\n      changeNet() {\n        localStorage.setItem('net', this.net);\n        this.$store.commit('UPDATE_SETTING_NETWORK', {network: this.net})\n        if(this.net === 'TEST_NET') {\n          this.nodeList = TEST_NET_LIST;\n          this.nodeAddress = TEST_NET_LIST[0]\n          localStorage.setItem('nodeAddress', this.nodeAddress)\n        } else {\n          this.nodeList = MAIN_NET_LIST;\n          this.nodeAddress = MAIN_NET_LIST[0]\n          localStorage.setItem('nodeAddress', this.nodeAddress)\n        }\n        setTimeout(() => {\n          const net = this.net === 'TEST_NET' ? this.$t('common.testNet') : this.$t('common.mainNet');\n          this.$message.success(this.$t('setting.setNetworkSuccess') + net);\n        }, 100)\n      },\n      changeNode() {\n        localStorage.setItem('nodeAddress', this.nodeAddress)\n        setTimeout(() => {\n          this.$message.success(this.$t('setting.setNodeSuccess') + this.nodeAddress);\n        }, 100)\n      },\n      changeLanguage() {\n        this.$i18n.locale = this.lang\n        LangStorage.setLang(this.$i18n.locale)\n      },\n      setSavePath() {\n        dialog.showOpenDialog({properties: ['openDirectory','createDirectory']}).then(({filePaths}) => {\n          if (filePaths[0] === undefined) {\n            // alert('You did not set the path')\n            this.$message.warning(this.$t('setting.notSetPath'))\n            return;\n          }\n          if (!validateKeystorePath(filePaths[0])) {\n            this.$message.warning(this.$t('setting.notInstallationPath'))\n            return;\n          }\n          localStorage.setItem('savePath', filePaths[0])\n          localStorage.setItem('isSavePath', 'true')\n          window.location.reload();\n          this.savePath = filePaths[0]\n        })\n      }\n    },\n    components: {\n      Breadcrumb\n    }\n  }\n</script>\n\n<style>\n  .setting-container {\n    padding: 0 20px;\n    height: 100%;\n  }\n\n  .form-container {\n    padding: 0 20px;\n    width: 800px;\n  }\n\n  .form-container label {\n    color: #000000;\n    font-size: 16px;\n    font-family: AvenirNext-Bold;\n  }\n\n  .form-container select {\n    border-radius: 0;\n  }\n\n  .form-group-top {\n    margin-top: 45px;\n  }\n\n  .span-path-title {\n    color: #000000;\n    font-size: 16px;\n    font-family: AvenirNext;\n  }\n</style>\n"
  },
  {
    "path": "src/components/SharedWallet/Create/BasicInfo.vue",
    "content": "<template>\n    <div class=\"basic-container\">\n        <div class=\"basic-label\">\n            <a-input class=\"input\" :class=\"validLabel?'':'error-input'\" :placeholder=\"$t('createSharedWallet.label')\"\n            v-model=\"label\" @change=\"validateLabel\"></a-input>\n        </div>\n        <p class=\"copayer-label font-bold\">{{$t('createSharedWallet.copayers2_12')}}</p>\n        <div class=\"basic-pks\">\n            <div class=\"pk-item\" v-for=\"(item,index) in pks\" :key=\"index\">\n                <a-input class=\"input\" :class=\"item.nameValid?'':'error-input' \" :placeholder=\"$t('createSharedWallet.name')\"\n                v-model=\"item.name\" ></a-input>\n                <a-input class=\"input\" :class=\"item.pkValid?'':'error-input' \" :placeholder=\"$t('createSharedWallet.publicKey')\" v-model=\"item.publickey\"\n                @change=\"validatePublickey(index,item.publickey)\"></a-input>\n                <span class=\"delete-icon\" @click=\"removePk(index)\"></span>\n                <p class=\"error-pk\" v-if=\"!item.pkValid\">{{$t('createSharedWallet.invalidPk')}}</p>\n            </div>\n            <a-button class=\"btn-add\" style=\"margin-top:30px;\" @click=\"addNewPk\" v-if=\"pks.length<12\">\n                {{$t('createSharedWallet.add')}}\n            </a-button>\n        </div>\n        <div class=\"basic-pk-btns\">\n            <div class=\"btn-container\">\n                <a-button type=\"default\"  @click=\"cancel\" class=\"btn-cancel\">\n                    {{$t('createSharedWallet.cancel')}}</a-button>\n                <a-button type=\"primary\" @click=\"next\" class=\"btn-next\">\n                    {{$t('createSharedWallet.next')}}</a-button>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\nimport {mapState} from 'vuex'\nimport {Crypto} from 'ontology-ts-sdk'\nexport default {\n    name: 'BasicInfo',\n    data() {\n        return {\n            label: '',\n            validLabel:true,\n            pks:[\n                {name:'',publickey:'', nameValid:true, pkValid: true},\n                {name:'',publickey:'', nameValid:true, pkValid: true},\n            ]\n        }\n    },\n    mounted(){\n        this.label = this.$store.state.CreateSharedWallet.label;\n        const copayers = this.$store.state.CreateSharedWallet.copayers;\n        this.pks = copayers.map(p => {\n            return {\n                name: p.name,\n                publickey: p.publickey,\n                nameValid: true,\n                pkValid: true\n            }\n        })\n    },\n    computed:{\n        ...mapState({\n\n        }),\n    },\n    methods: {\n        addNewPk() {\n            this.pks.push({\n                name:'', publickey:'', nameValid:true, pkValid: true\n            })\n        },\n        removePk(index) {\n            if(this.pks.length <= 2) {\n                this.$message.error(this.$t('createSharedWallet.pksLte2'))\n                return;\n            }\n            const pks = this.pks.slice()\n            pks.splice(index, 1)\n            this.pks = pks;\n        },\n        validateLabel() {\n            if(!this.label) {\n                this.validLabel = false;\n                return;\n            }\n            const length = this.label.split('').length;\n            if(length > 12) {\n                this.$message.error(this.$t('createSharedWallet.walletNameErr'))\n                this.validLabel = false;\n            } else {\n                this.validLabel = true;\n            }\n        },\n        validatePublickey(index,value) {\n            console.log(index, value)\n            if(value && value.length !== 66) {\n                this.pks[index].pkValid = false;\n            } else {\n                this.pks[index].pkValid = true;\n            }\n        },\n        validInput() {\n            if(!this.label) {\n                return false;\n            }\n            for(let i = 0; i < this.pks.length; i++) {\n                const p = this.pks[i];\n                if(!p.name || !p.publickey || !p.nameValid || !p.pkValid) {\n                    return false;\n                }\n                for (let j = 0; j < this.pks.length; j++) {\n                    const pp = this.pks[j]\n                    if(i !== j && p.publickey === pp.publickey) {\n                        this.$message.error(this.$t('createSharedWallet.duplicatePks'))\n                        return false;\n                    }\n                    if(i !== j &&  p.name === pp.name) {\n                        this.$message.error(this.$t('createSharedWallet.duplicateNames'))\n                        return false;\n                    }\n                }\n            }\n\n            return true;\n        },\n        next() {\n            if(!this.label) {\n                this.$message.error(this.$t('createSharedWallet.emptyLabel'))\n                return;\n            }\n            if(this.validInput()) {\n                const copayers = this.pks.map(p => {\n                    return {\n                        name: p.name,\n                        publickey: p.publickey,\n                        address: Crypto.Address.fromPubKey(new Crypto.PublicKey(p.publickey)).toBase58()\n                    }\n                })\n                this.$store.commit('UPDATE_CREATE_SHARED_LABEL', {label: this.label})\n                this.$store.commit('UPDATE_CREATE_SHARED_COPAYERS', {copayers})\n                this.$store.commit('ADD_CREATE_SHARED_STEP')\n            }\n        },\n        cancel() {\n            this.$router.push({name: 'Wallets'})\n        },\n        importSharedWallet() {\n            this.$router.push({name:'ImportSharedWallet'})\n        }\n    }\n}\n</script>\n\n<style>\n\n.basic-container {\n    padding-bottom:90px;\n    overflow:auto;\n}\n.basic-label {\n    width:540px;\n    margin:2px auto;\n}\n\n.copayer-label {\n    margin-left: 172px;\n    margin-top: 40px;\n}\n\n.basic-pks {\n    width:540px;\n    margin:0px auto;\n}\n.pk-item {\n    margin-bottom:15px;\n}\n.pk-item :first-child {\n    width: 150px;\n    margin-right: 20px;\n    display: inline-block;\n}\n.pk-item :nth-child(2) {\n    width:318px;\n}\n.delete-icon {\n    height: 24px;\n    width:24px;\n    /* display: inline-block; */\n    background:url('../../../assets/delete.png') center center;\n    background-size:contain;\n    float: right;\n    margin-right: 10px;\n    cursor: pointer;\n    margin-top:3px;\n}\n.basic-pk-box {\n    border:1px solid #dddddd;\n    width:100%;\n    height:300px;\n    padding:10px;\n    position: relative;\n}\n.basic-pk-add {\n    border-top: 1px solid #dddddd;\n    width: calc(100% - 20px);\n    position: absolute;\n    bottom: 10px;\n    left: 10px;\n    padding-top: 10px;\n}\n.basic-pk-item {\n    width:100%;\n    float:left;\n}\n.basic-pk-item span {\n    margin-right:10px;\n}\n.basic-add-item {\n    display: inline-block;\n    width:40%;\n}\n.basic-add-item input {\n    width:80%;\n}\n\n.basic-pk-btns {\n    position: fixed;\n    bottom:0;\n    width:calc(100% - 4rem);\n    height:85px;\n    left:4rem;\n    background: #FFFFFF;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    z-index: 1000;\n}\n.basic-pk-btns button:first-child {\n    float:left;\n}\n.basic-pk-btns :nth-child(2) {\n    float:right;\n}\n.basic-pk-btns :nth-child(3) {\n    float:right;\n    margin-right:20px;\n}\n\n.error-input {\n    border-color: red;\n}\n.error-pk {\n    padding-left: 175px;\n    font-size: 13px;\n    color: red;\n}\n</style>\n\n"
  },
  {
    "path": "src/components/SharedWallet/Create/ConfirmSigNum.vue",
    "content": "<template>\n  <div class=\"basic-container\">\n    <p class=\"confirm-label wallet-label\" style=\"margin-bottom:40px;\">{{label}}</p>\n\n    <p class=\"confirm-label font-bold\">{{$t('createSharedWallet.copayers')}}({{copayers.length}})</p>\n    <div class=\"confirm-pk-box\">\n      <div class=\"confirm-pk-item clearfix\" v-for=\"(pk,index) in copayers\" :key=\"pk.index\">\n        <span class=\"circle\">{{index+1}}</span>\n        <span class=\"copayer-name\">{{pk.name}}</span>\n        <span class=\"copayer-address\">{{pk.address}}</span>\n        <span class=\"copayer-publicKey\">{{pk.publickey}}</span>\n        \n      </div>\n    </div>\n    <p class=\"confirm-label wallet-label\">{{$t('createSharedWallet.requiredSigNum')}}</p>\n    <div class=\"confirm-requireNum\">\n      <a-select v-model=\"requiredSigNum\" :options=\"options\" class=\"confirm-select\">\n      </a-select>\n    </div>\n    <div class=\"confirm-btns\">\n      <div class=\"confirm-btn-container\">\n        <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{$t('createSharedWallet.back')}}</a-button>\n        <a-button type=\"primary\" class=\"btn-next\" @click=\"next\" :disabled=\"processing\">{{$t('createSharedWallet.next')}}</a-button>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\n  import {mapState} from 'vuex'\n  import {Crypto} from 'ontology-ts-sdk'\n\n  export default {\n    name: 'ConfirmSigNum',\n    data() {\n      return {\n        processing: false\n      }\n    },\n    computed: {\n      ...mapState({\n        label: state => state.CreateSharedWallet.label,\n        copayers: state => state.CreateSharedWallet.copayers\n      }),\n      options: {\n        get() {\n          let options = []\n          const length = this.$store.state.CreateSharedWallet.copayers.length;\n          for (let i = 2; i <= length; i++) {\n            options.push({value: i, label: i})\n          }\n          return options\n        }\n      },\n      requiredSigNum: {\n        get() {\n          return this.$store.state.CreateSharedWallet.requiredSigNum\n        },\n        set(val) {\n          this.$store.commit('UPDATE_REQUIRED_SIG_NUMBER', {requiredSigNum: val})\n        }\n      }\n    },\n    methods: {\n      cancel() {\n        this.$router.push({name: 'Wallets'})\n      },\n      back() {\n        this.$store.commit('SUB_CREATE_SHARED_STEP')\n      },\n      next() {\n        if (this.processing) {\n          return;\n        }\n        this.processing = true;\n        const pks = this.copayers.map((p) => new Crypto.PublicKey(p.publickey));\n        const multiAddr = Crypto.Address.fromMultiPubKeys(this.requiredSigNum, pks);\n        const sharedAddress = multiAddr.toBase58();\n        const body = {\n          \"sharedWalletAddress\": sharedAddress,\n          \"sharedWalletName\": this.label,\n          \"totalNumber\": pks.length,\n          \"requiredNumber\": this.requiredSigNum,\n          \"coPayers\": this.copayers\n        }\n        this.$store.dispatch('createSharedWallet', body).then(res => {\n          this.processing = false;\n          if (res === 0) {\n            this.$message.success(this.$t('createSharedWallet.createSuccess'));\n            this.$store.commit('CLEAR_CREATE_SHARED_STATE')\n            this.$router.push({name: 'Wallets'})\n          } else if (res === 61002) { //重复创建\n            this.$message.error(this.$t('createSharedWallet.duplicateCreate'));\n            this.$store.commit('CLEAR_CREATE_SHARED_STATE')\n            this.$router.push({name: 'Wallets'})\n          }\n        }, err => {\n          this.$message.success(this.$t('createSharedWallet.createFailed'))\n          console.log(err)\n        })\n        // this.$store.commit('ADD_CURRENT_STEP')\n      }\n    }\n  }\n</script>\n\n<style scoped>\n  .confirm-label {\n    margin-left: 172px;\n    margin-bottom: 0;\n  }\n\n  .wallet-label {\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size: 14px;\n  }\n\n  .confirm-pk-box {\n    width: 540px;\n    margin: 20px auto;\n    margin-bottom: 40px;\n  }\n\n  .confirm-pk-item {\n    margin-bottom: 20px;\n  }\n\n  .confirm-requireNum {\n    width: 540px;\n    margin: 12px auto;\n  }\n\n  .confirm-select {\n    width: 100%;\n  }\n\n  .circle {\n    display: inline-block;\n    text-align: center;\n    border-radius: 50%;\n    width: 1.5rem;\n    height: 1.5rem;\n    line-height: 1.5rem;\n    background: #FBE45A;\n    font-family: 'AvenirNext-Medium';\n    font-size: 14px;\n    color: #000000;\n    vertical-align: middle;\n    float: left;\n  }\n\n  .copayer-name {\n    margin-left: 20px;\n    font-family: 'AvenirNext-Medium';\n    font-size: 14px;\n    color: #000000;\n    float: left;\n    display: block;\n    width: 150px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n  }\n\n  .copayer-address {\n    font-family: 'AvenirNext-Medium';\n    font-size: 14px;\n    color: #5E6369;\n    float: right;\n  }\n  .copayer-publicKey {\n    float: right;\n  }\n\n  .confirm-btns {\n    position: fixed;\n    bottom: 0;\n    width: calc(100% - 4rem);\n    height: 85px;\n    left: 4rem;\n    background: #FFFFFF;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    z-index: 1000;\n  }\n\n  .confirm-btn-container {\n    width: 540px;\n    margin: 20px auto;\n  }\n\n  .confirm-btn-container :last-child {\n    float: right;\n  }\n</style>\n"
  },
  {
    "path": "src/components/SharedWallet/Create/CreateSuccess.vue",
    "content": "<template>\n<div>\n    <div class=\"content\">\n        <a-alert :message=\"$t('createSharedWallet.success')\" type=\"success\" showIcon />\n        <p>{{$t('createSharedWallet.label')}}: {{label}}</p>\n        <p>{{$t('createSharedWallet.address')}}: {{address}}</p>        \n    </div>\n    <div class=\"btns\">\n        <a-button type=\"primary\"  @click=\"next\">{{$t('createSharedWallet.next')}}</a-button>            \n    </div>\n</div>\n    \n</template>\n\n<script>\nimport {mapState} from 'vuex'\nexport default {\n    name:'CreateSuccess',\n    computed: {\n        ...mapState({\n            label: state => state.CreateSharedWallet.label,\n            address: state => state.CreateSharedWallet.address\n        })\n    },\n    methods:{\n        next() {\n            this.$router.push({name:'Dashboard'})\n        }\n    }\n}\n</script>\n\n<style scoped>\n.content {\n    border: 1px solid #dddddd;\n    padding: 10px;\n}\n.content p {\n    margin-top:10px;\n}\n\n.btns {\n    float: right;\n    margin-top:20px;\n}\n</style>\n\n"
  },
  {
    "path": "src/components/SharedWallet/CreateSharedWallet.vue",
    "content": "<style scoped>\n.shared-container {\n}\n  .steps-content {\n  }\n\n  .steps-action {\n    margin-top: 24px;\n  }\n\n  .create-steps {\n    width:520px;\n    height:4rem;\n    margin:2px auto;\n  }\n\n</style>\n<template>\n  <div>\n    <breadcrumb :current=\"$t('createSharedWallet.create')\" v-on:backEvent=\"back\"></breadcrumb>\n    <div class=\"shared-container\">\n      <a-steps :current=\"current\" class=\"create-steps\">\n        <a-step v-for=\"item in steps\" :key=\"item.title\" />\n      </a-steps>\n      <div class=\"steps-content\">\n          <basic-info v-if=\"current === 0\"></basic-info>\n          <confirm-sig-num v-if=\"current === 1\"></confirm-sig-num>\n      </div>\n    </div>\n  </div>\n\n</template>\n<script>\nimport en from '../../lang/en'\nimport zh from '../../lang/zh'\nimport BasicInfo from './Create/BasicInfo'\nimport ConfirmSigNum from './Create/ConfirmSigNum'\nimport CreateSuccess from './Create/CreateSuccess'\nimport Breadcrumb from '../Breadcrumb'\nimport { mapState } from 'vuex';\n\n  export default {\n    name: 'CreateSharedWallet',\n    data() {\n        const langType = localStorage.getItem('user_lang') || 'en';\n        const lang = langType === 'en' ? en : zh;\n      return {\n        lang: lang,\n        steps: [{\n          title: lang.createSharedWallet.basicInfo,\n          content: 'First-content',\n        }, {\n          title: lang.createSharedWallet.copayers,\n          content: 'Second-content',\n        }]\n      }\n    },\n    computed : {\n        ...mapState({\n            current: state => state.CreateSharedWallet.currentStep,\n        })\n    },\n    components: {\n        BasicInfo,\n        ConfirmSigNum,\n        Breadcrumb\n    },\n    methods: {\n      back(){\n        this.$router.push({name:'Wallets'})\n      }\n    }\n  }\n</script>\n\n"
  },
  {
    "path": "src/components/SharedWallet/Import/InputPass.vue",
    "content": "<style scoped>\n\n\n.wallet-info {\n    margin-bottom: 20px;\n}\n.wallet-info-item label {\n    font-weight: bold;\n}\n\n.choose-local-wallet {\n    margin-bottom:15px;\n}\n.choose-local-wallet label {\n    font-weight: bold;\n}\n.input-select {\n    width:100%;\n}\n\n.local-wallet-info {\n    padding: 10px;\n    background:#52a2bb;\n    color: #ffffff;\n    margin-bottom:20px;\n}\n\n.input-btns {\n    position: absolute;\n    right: 100px;\n    bottom:100px;\n}\n\n.input-btns button {\n    margin-left:30px;\n}\n.label {\n    font-family: 'PingFangSC-Semibold';\n    font-size: 20px;\n    color: #5E6369;\n    margin-left: 172px;\n}\n.wallet-address {\n    margin-bottom: 40px;\n    margin-top: 14px;\n}\n.wallet-num {\n    width:540px;\n    margin:0 auto;\n    margin-bottom:30px;\n    padding-left: 38px;\n}\n.wallet-num-item {\n    padding:6px 3px;\n    border-bottom: 1px solid #DFE2E9;\n}\n\n.wallet-num-item :last-child {\n float: right;\n}\n.confirm-pk-box {\n    width:540px;\n    margin:20px auto;\n    margin-bottom:40px;\n}\n.confirm-pk-item {\n    margin-bottom:20px;\n}\n.confirm-requireNum {\n    width:540px;\n    margin:12px auto;\n}\n\n.confirm-select {\n    width:100%;\n}\n\n.circle {\n    text-align: center;\n    border-radius:50%;\n    width:1.5rem;\n    height:1.5rem;\n    line-height: 1.5rem;\n    background:#FBE45A;\n    font-family: 'AvenirNext-Medium';\n    font-size:14px;\n    color:#000000;\n    vertical-align: middle;\n    float: left;\n}\n\n.copayer-name {\n    margin-left: 20px;\n    font-family: 'AvenirNext-Medium';\n    font-size:14px;\n    color:#000000;\n    float: left;\n    display: block;\n    width:150px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n.copayer-address {\n    font-family: 'AvenirNext-Medium';\n    font-size:14px;\n    color:#5E6369;\n    float:right;\n}\n.input-container {\n    padding-bottom:5.3rem;\n    overflow:scroll;\n}\n.notfound {\n    width:280px;\n    height:228px;\n    margin:5px auto;\n    margin-bottom:15px;\n    background:url('../../../assets/notfound.png') center center;\n    background-size:cover;\n}\n.notfound-text {\n    width:540px;\n    margin: 0 auto;\n}\n.notfound-p {\n    margin:0;\n    font-family: PingFangSC-Semibold;\n    font-size: 14px;\n    color: #5E6369;\n    text-align: center;\n}\n</style>\n<template>\n    <div class=\"input-container\">\n        <div class=\"wallet-info\" v-if=\"sharedWallet\">\n            <div class=\"label wallet-label\">{{sharedWallet.sharedWalletName}}</div>\n            <div class=\"label wallet-address\">\n                {{sharedWallet.sharedWalletAddress}}\n            </div>\n\n            <div class=\"wallet-num\">\n                <div class=\"wallet-num-item\">\n                    <span class=\"font-medium\">{{$t('importSharedWallet.totalCopayerNumber')}}</span>\n                    <span class=\"font-medium-black\">{{sharedWallet.totalNumber}}</span>\n                </div>\n                <div class=\"wallet-num-item\">\n                    <span class=\"font-medium\">{{$t('importSharedWallet.requiredCopayerNumber')}}</span>\n                    <span class=\"font-medium-black\">{{sharedWallet.requiredNumber}}</span>\n                </div>\n            </div>\n            <div class=\"confirm-pk-box\">\n                <div class=\"confirm-pk-item clearfix\" v-for=\"(pk,index) in sharedWallet.coPayers\" :key=\"pk.publickey\">\n                    <span class=\"circle\">{{index+1}}</span>\n                    <span class=\"copayer-name\">{{pk.name}}</span>\n                    <span class=\"copayer-address\">{{pk.address}}</span>\n                </div>\n            </div>\n        </div>\n\n        <div v-if=\"!sharedWallet\">\n            <div class=\"notfound\"></div>\n            <div class=\"notfound-text\">\n                <p class=\"notfound-p\">{{$t('importSharedWallet.sorry')}}</p>\n                <p class=\"notfound-p\">{{$t('importSharedWallet.notFound')}}</p>\n            </div>\n        </div>\n\n\n        <div class=\"footer-btns\">\n            <div class=\"footer-btn-container\">\n                <a-button class=\"btn-cancel\" type=\"default\" @click=\"back\">{{$t('importSharedWallet.back')}}</a-button>\n                <a-button class=\"btn-next\" type=\"primary\" @click=\"next\" :disabled=\"!sharedWallet\">{{$t('importSharedWallet.join')}}</a-button>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\nimport {mapState} from 'vuex'\nimport {Crypto} from 'ontology-ts-sdk'\nimport {DEFAULT_SCRYPT} from '../../../core/consts'\nimport dbService from '../../../core/dbService'\nimport en from '../../../lang/en'\nimport zh from '../../../lang/zh'\nexport default {\n    name: 'InputPass',\n    data() {\n        const langType = localStorage.getItem('user_lang') || 'en';\n        const lang = langType === 'en' ? en : zh;\n        return {\n            lang: lang,\n        }\n    },\n    computed:{\n        ...mapState({\n            sharedWallet: state => state.ImportSharedWallet.sharedWallet\n        }),\n    },\n    methods: {\n        back() {\n            this.$store.commit('SUB_IMPORT_SHARED_STEP')\n        },\n\n        next() {\n            //save to db\n            const that = this\n            const wallet = {\n                type : 'SharedWallet',\n                address: this.sharedWallet.sharedWalletAddress,\n                wallet: this.sharedWallet\n            }\n            dbService.insert(wallet, function (err,newDoc) {\n                if(err) {\n                    that.$message.warning(that.lang.importSharedWallet.joinBefore);\n                    that.$store.commit('CLEAR_IMPORT_SHARED_STATE')\n                    that.$router.push({name:'Wallets'})\n                    return;\n                }\n                that.$message.success(that.lang.importSharedWallet.success);\n                that.$store.commit('CLEAR_IMPORT_SHARED_STATE')\n                that.$router.push({name:'Wallets'})\n            })\n\n\n        }\n    }\n}\n</script>\n\n\n\n\n"
  },
  {
    "path": "src/components/SharedWallet/Import/QuerySharedWallet.vue",
    "content": "<style scoped>\n.query-input {\n    width:540px;\n    margin:20px auto;\n}\n.result-item {\n    float:left;\n    width:100%;\n}\n\n.result-item label {\n    width:30%;\n    text-align: right;\n    float: left;\n    font-weight: bold;\n}\n.result-item span {\n    float:left;\n    margin-left:10px;\n}\n\n.no-result {\n    padding: 15px;\n}\n\n.result-item-container {\n    display: inline-block;\n    margin-left:10px;\n}\n\n.copayer-item {\n    margin-bottom:10px;\n}\n.copayer-item p {\n    margin:0\n}\n.copayer-name {\n    width:10px;\n    height:10px;\n    border-radius:50%;\n    background:#52a2bb;\n    display: inline-block;\n}\n\n</style>\n<template>\n    <div class=\"query-container\">\n        <div class=\"query-input\">\n            <a-input\n            class=\"input\"\n            v-model=\"searchText\"\n            :placeholder=\"$t('importSharedWallet.inputAddress')\"  />\n        </div>\n\n        <div class=\"footer-btns\">\n            <div class=\"footer-btn-container\">\n                <a-button class=\"btn-cancel\" type=\"default\" @click=\"cancel\">{{$t('importSharedWallet.cancel')}}</a-button>\n                <a-button class=\"btn-next\" type=\"primary\" @click=\"next\" :disabled=\"!searchText\">{{$t('importSharedWallet.search')}}</a-button>\n            </div>\n\n        </div>\n\n    </div>\n</template>\n\n<script>\nimport axios from 'axios';\nimport {ONT_PASS_NODE, ONT_PASS_NODE_PRD,ONT_PASS_URL} from '../../../core/consts'\nimport dbService from '../../../core/dbService'\nimport en from '../../../lang/en'\nimport zh from '../../../lang/zh'\n\nexport default {\n    name: 'QuerySharedWallet',\n    data() {\n        const langType = localStorage.getItem('user_lang') || 'en';\n        const lang = langType === 'en' ? en : zh;\n        return {\n            lang:lang,\n            noSuchWallet: false,\n            searchText: '',\n            sharedWallet:{\n            },\n            coPayers: [],\n            showJoinBtn: false,\n            accountToJoin: {\n                address: ''\n            },\n        }\n    },\n    methods: {\n        cancel() {\n            this.$router.push({name:'Wallets'})\n        },\n        next() {\n            const net = localStorage.getItem('net')\n            const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD\n            this.$store.dispatch('showLoadingModals')\n            axios.get(ontPassNode+ONT_PASS_URL.QuerySharedWallet, {\n                params: {\n                    sharedWalletAddress: this.searchText\n                }\n            }).then(res => {\n                this.$store.dispatch('hideLoadingModals')\n                if(res.status === 200 && res.data.sharedWalletAddress) {\n                    this.sharedWallet = res.data\n                    this.$store.commit('UPDATE_SHARED_WALLET', {sharedWallet: res.data})\n                    this.$store.commit('ADD_IMPORT_SHARED_STEP');\n                } else {\n                    this.$store.commit('UPDATE_SHARED_WALLET', {sharedWallet: null} )\n                    this.$message.error(this.$t('importSharedWallet.notFound'))\n                }\n                // this.$store.commit('ADD_IMPORT_SHARED_STEP');\n            }).catch(err => {\n                this.$store.dispatch('hideLoadingModals')\n                this.$store.commit('UPDATE_SHARED_WALLET', {sharedWallet: null} )\n                this.$message.error(this.$t('commonWalletHome.networkError'))\n                // this.$store.commit('ADD_IMPORT_SHARED_STEP');\n            })\n        },\n    }\n}\n</script>\n\n\n"
  },
  {
    "path": "src/components/SharedWallet/ImportSharedWallet.vue",
    "content": "<style scoped>\n\n.import-steps {\n    width:540px;\n    margin:0 auto;\n    height: 4rem;\n}\n</style>\n<template>\n<div>\n    <breadcrumb :current=\"$t('importSharedWallet.import')\" v-on:backEvent=\"back\"></breadcrumb>\n    <div class=\"import-container\">\n        <a-steps :current=\"current\" class=\"import-steps\">\n            <a-step />\n            <a-step  />\n        </a-steps>\n        <query-shared-wallet v-if=\"current ===0\"></query-shared-wallet>\n        <input-pass v-if=\"current === 1\"></input-pass>\n    </div>\n</div>\n    \n</template>\n<script>\nimport QuerySharedWallet from './Import/QuerySharedWallet'\nimport InputPass from './Import/InputPass'\nimport {mapState} from 'vuex'\nimport Breadcrumb from '../Breadcrumb'\nexport default {\n    name: 'ImportSharedWallet',\n    data() {\n        return {\n\n        }\n    },\n    computed:{\n        ...mapState({\n            current: state => state.ImportSharedWallet.currentStep\n        })\n    },\n    components: {\n        QuerySharedWallet,\n        InputPass,\n        Breadcrumb\n    },\n    methods:{\n        back(){\n            this.$router.push({name:'Wallets'})\n        }\n    }\n}\n</script>\n\n\n\n"
  },
  {
    "path": "src/components/SharedWallet/PAX/PaxMgmt.vue",
    "content": "<style scoped>\n.pax-container {\n    text-align: center;\n    position: relative;\n}\n.btn-ethScan {\n    position: absolute;\n    right:0;\n    top:-40px;\n}\n.status-group {\n    margin:10px auto;\n}\n.table-container {\n    position: relative;;\n}\n\n.table-btns {\n    text-align: right;\n    margin-bottom:5px;\n}\n.table-btns button {\n    margin-left: 15px;\n}\n.pax-header {\n    position: relative;\n}\n.select-current {\n    width:300px;\n}\n.pax-selectPayer {\n    margin-bottom: 10px;\n    text-align: left;\n}\n.text-small {\n    font-size: 14px;\n    margin-top: 20px;\n}\n.detail-link {\n    text-align: center;\n    cursor: pointer;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :routes=\"routes\" :current=\"$t('sharedWalletHome.paxMgmt')\" @backEvent=\"handleBack\"></breadcrumb>\n        <div class=\"pax-container\">\n            <div class=\"pax-header\">\n\n                <!-- <a-button class=\"btn-ethScan\" @click=\"toEthScan\">{{$t('pax.toEthScan')}}</a-button> -->\n                <a-radio-group :value=\"status\" @change=\"handleStatusChange\" class=\"status-group\">\n                    <a-radio-button value=\"0\">{{$t('sharedWalletHome.unprocessed')}}</a-radio-button>\n                    <a-radio-button value=\"1\">{{$t('sharedWalletHome.processing')}}</a-radio-button>\n                    <a-radio-button value=\"2\">{{$t('sharedWalletHome.completed')}}</a-radio-button>\n                    <a-radio-button value=\"3\">{{$t('pax.txCompleted')}}</a-radio-button>\n                </a-radio-group>\n                <div v-if=\"status === '1' \" class=\"pax-selectPayer\">\n                    <label for=\"\">{{$t('pax.selectCurrentSigner')}}</label>\n                    <a-select :options=\"localCopayers\" class=\"select-current\"  @change=\"handleChangeCurrentSigner\"></a-select>\n                </div>\n            </div>\n            <div class=\"table-btns\">\n                    <a-button type=\"primary\" :disabled=\"selectedRowKeys.length < 1\" @click=\"handleVarify\">\n                    {{$t('pax.toVarify')}}</a-button>\n                    <a-button type=\"primary\" :disabled=\"selectedRowKeys.length < 1 || status === '1' && !currentSigner\"\n                    v-if=\"status === '0' || status === '1' \" @click=\"handleProcess\">{{$t('pax.toProcess')}}</a-button>\n                </div>\n\n                <a-table :rowSelection=\"(status === '2' || status === '3') ? null : {selectedRowKeys: selectedRowKeys, onChange: onSelectChange}\"\n                rowKey=\"Txhash\"\n                :columns=\"currentColumns\"\n                :dataSource=\"data\"\n                :pagination=\"pagination\"\n                @change=\"handleTableChange\"\n                >\n                <div slot=\"action\" slot-scope=\"text, record\" class=\"detail-link\" >\n                    <a-icon type=\"arrow-right\" @click=\"handleOpenTxDetail(record)\" />\n                </div>\n                </a-table>\n\n\n        </div>\n\n        <a-modal\n            :title=\"$t('pax.toProcess')\"\n            :visible=\"visible\"\n            @cancel=\"handleProcessCancel\"\n            @ok=\"handleProcessOk\"\n            >\n            <p>{{$t('pax.selectedNum')}} {{selectedNum}}</p>\n            <p>{{$t('pax.totalAmount')}} {{totalAmount}}</p>\n        </a-modal>\n\n        <a-modal\n            :title=\"$t('pax.varifyResult')\"\n            :visible=\"varifyFailedList.length > 0\"\n            @cancel=\"handleShowVarifyResultCancel\"\n            :footer=\"null\"\n            >\n            <p>{{$t('pax.failedTxhashes')}}</p>\n            <p v-for=\"item of varifyFailedList\" :key=\"item.txhash\">\n                <a :href=\"item.url\">{{item.txhash}}</a>\n            </p>\n        </a-modal>\n\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport {PAX_API} from '../../../core/consts'\nimport {convertNumber2Str, open} from '../../../core/utils'\nimport dbService from '../../../core/dbService'\nimport { BigNumber } from 'bignumber.js'\n\nexport default {\n    name: 'PaxMgmt',\n    components: {\n        Breadcrumb\n    },\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        const routes = [\n            {name: sharedWallet.sharedWalletName, path:'/sharedWallet/home'}\n        ]\n        const columns = [\n            {\n                title: this.$t('pax.ethAddress'),\n                dataIndex: 'EthAddress'\n            },\n            {\n                title: this.$t('pax.ontAddress'),\n                dataIndex: 'OntAddress'\n            },\n            {\n                title: this.$t('pax.amount'),\n                dataIndex: 'AmountStr'\n            },\n            {\n                title: this.$t('pax.date'),\n                dataIndex: 'Updated'\n            },\n            {\n                title: this.$t('pax.txDetail'),\n                key: 'action',\n                scopedSlots: {customRender:'action'}\n            }\n        ]\n        return {\n            sharedWallet,\n            status: '0',\n            routes,\n            data:[],\n            columns,\n            currentColumns: columns,\n            selectedRowKeys: [],\n            selectedRowsPerPage: {},\n            pagination: {\n                current:1,\n                pageSize:10,\n                total:30\n            },\n            localCopayers: [],\n            processing_list: [],\n            currentSigner: '',\n            selectedNum:0,\n            totalAmount: 0,\n            ethTotal: 0,\n            visible: false,\n            varifyFailedList: []\n        }\n    },\n    mounted() {\n        this.updateLocalCopayers()\n        this.fetchList();\n    },\n    methods: {\n        toEthScan() {\n            const net = localStorage.getItem('net');\n            let url = net === 'TEST_NET' ? PAX_API.EthScanTest : PAX_API.EthScanMain;\n            open(url)\n        },\n        handleBack() {\n            this.$router.push({path: '/Wallets'});\n        },\n        async handleVarify() {\n            let list = []\n            for(let key in this.selectedRowsPerPage) {\n                list = list.concat(this.selectedRowsPerPage[key])\n            }\n            const data = {\n                txhashs: [],\n                ercaddresses: [],\n                oep4addresses: [],\n                amounts: []\n            }\n            list.forEach(item => {\n                data.txhashs.push(item.Txhash),\n                data.ercaddresses.push(item.EthAddress),\n                data.oep4addresses.push(item.OntAddress),\n                data.amounts.push(item.Amount)\n            })\n            this.$store.dispatch('showLoadingModals')\n            const net = localStorage.getItem('net');\n            const result = await this.httpService({\n                method:'post',\n                data,\n                url: (net === 'TEST_NET' ? PAX_API.TestHost : PAX_API.Host) + PAX_API.validateTx\n            })\n            const varifyFailedList = []\n            const ethScanHost = net === 'TEST_NET' ? PAX_API.EthScanTest : PAX_API.EthScanMain\n            for(let i = 0; i < result.Result.length; i++) {\n                if(result.Result[i] !== '0') { // 0: pass;\n                    varifyFailedList.push(\n                        {\n                           txhash: data.txhashs[i],\n                           url: ethScanHost + data.txhashs[i]\n                        })\n                }\n            }\n            this.varifyFailedList = varifyFailedList;\n            if(varifyFailedList.length === 0) {\n                this.$message.success(this.$t('pax.varifySuccess'))\n            } else {\n                this.$message.error(this.$t('pax.varifyFailed'))\n            }\n            console.log(result)\n\n        },\n        handleShowVarifyResultCancel() {\n            this.varifyFailedList = [];\n        },\n        handleStatusChange(e) {\n            this.status = e.target.value\n            // if(this.status === '3') {\n            //     this.currentColumns = [...this.columns,\n            //     {\n            //         title: this.$t('pax.txDetail'),\n            //         key: 'action',\n            //         scopedSlots: {customRender:'action'}\n            //     }]\n            // }\n            // else {\n            //     this.currentColumns = [...this.columns]\n            // }\n            this.fetchList()\n        },\n        handleOpenTxDetail(record) {\n            const net = localStorage.getItem('net');\n            let url = '';\n            if(this.status === '3') {\n                let url = `https://explorer.ont.io/transaction/${record.Senthash}`\n                const net = localStorage.getItem('net')\n                if(net === 'TEST_NET') {\n                    url = url+ '/testnet'\n                }\n            } else {\n                url = (net === 'TEST_NET' ? PAX_API.EthScanTest : PAX_API.EthScanMain) + record.Txhash\n            }\n            open(url)\n        },\n        onSelectChange (selectedRowKeys,  selectedRows) {\n            console.log('selectedRowKeys changed: ', selectedRowKeys);\n            console.log('selectedRow changed: ', selectedRows);\n            // 更新选择的条目\n            const list = []\n            for(let key of selectedRowKeys) {\n                for(let item of this.data) {\n                    if(key === item.Txhash) {\n                        list.push(item)\n                    }\n                }\n            }\n            this.selectedRowsPerPage[this.pagination.current] = list;\n            this.selectedRowKeys = selectedRowKeys;\n        },\n        handleProcessCancel() {\n            this.visible = false;\n        },\n        handleProcess() {\n\n            let list = []\n            for(let key in this.selectedRowsPerPage) {\n                list = list.concat(this.selectedRowsPerPage[key])\n            }\n            this.selectedNum = list.length;\n            this.totalAmount = list.reduce((item1, item2) => {\n                return (item1.AmountStr ? new BigNumber(item1.AmountStr) : new BigNumber(item1) ).plus(new BigNumber(item2.AmountStr))\n            }, 0).toFixed(8)\n            this.visible = true;\n        },\n\n        handleProcessOk() {\n            let list = []\n                for(let key in this.selectedRowsPerPage) {\n                    list = list.concat(this.selectedRowsPerPage[key])\n                }\n            if(this.status === '0') {\n                this.$store.commit('UPDATE_UNPROCESS_LIST', {list})\n                this.$router.push({path:'/sharedWallet/startProcess'})\n            } else if(this.status === '1') {\n                this.$store.commit('UPDATE_PROCESSING_LIST', {list})\n                this.$store.commit('UDPATE_CURRENT_SIGNER', {signer: this.currentSigner})\n                this.$router.push({path: '/sharedWallet/signProcess'})\n            }\n        },\n        handleTableChange(pagination) {\n            console.log(pagination)\n            this.pagination = pagination;\n            this.fetchList()\n        },\n        async fetchList(page,pageSize) {\n            const net = localStorage.getItem('net');\n            if(this.status) {\n                const res = await this.httpService({\n                    method: 'get',\n                    params: {\n                        status: this.status,\n                        limit: this.pagination.pageSize,\n                        offset: (this.pagination.current - 1)*this.pagination.pageSize,\n                        order: 0 // 时间倒序\n                    },\n                    url: (net === 'TEST_NET' ? PAX_API.TestHost : PAX_API.Host) + PAX_API.fetchApprovalList\n                })\n                if(res.ErrorCode === 0) {\n                    this.data = res.Result.map((item) => {\n                        item.AmountStr = convertNumber2Str(item.Amount, 18, 8)\n                        if(this.status === '1') {\n                            item.cosigners = JSON.parse(item.CoSigners)\n                        }\n                        return item;\n                    });\n\n                    if(this.status === '1') {\n                        this.processing_list = this.data;\n                    }\n                    if(this.currentSigner) {\n                        this.handleChangeCurrentSigner(this.currentSigner.address)\n                    }\n\n                    const total = res.TotalCount || res.Result.length;\n                    this.pagination.total = total;\n                }\n            }\n\n        },\n        updateLocalCopayers() {\n            var that = this;\n                const coPayers = this.sharedWallet.coPayers;\n                const localCopayers = []\n                dbService.find({type: {$in:['CommonWallet', 'HardwareWallet']}}, function (err, accounts) {\n                    if (err) {\n                        console.log(err)\n                        return;\n                    }\n                    for (let cp of coPayers) {\n                        for (let ac of accounts) {\n                            if (cp.address === ac.address) {\n                                localCopayers.push(Object.assign({}, cp, {value:ac.address, label:ac.wallet.label, type: ac.type, wallet: ac.wallet}))\n                            }\n                        }\n                    }\n                    if (localCopayers.length > 0) {\n                        that.localCopayers = localCopayers;\n                    }\n                })\n        },\n        handleChangeCurrentSigner(value) {\n            console.log(value)\n            this.currentSigner = this.localCopayers.find((item) => (item.address === value));\n            //filter data\n            this.data = this.processing_list.filter((item) => {\n                return this.isCurrentSigner(value, item.cosigners)\n            })\n        },\n        isCurrentSigner(address, cosigners) {\n            for(let i = cosigners.length -1; i > -1; i--) {\n                if(cosigners[i].isSign && !cosigners[i+1].isSign) {\n                    if(address === cosigners[i+1].address) {\n                        return true;\n                    } else {\n                        return false;\n                    }\n                }\n            }\n            return false;\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/PAX/SignProcess.vue",
    "content": "<style scoped>\n.sign-container {\n    width:700px;\n    margin:20px auto;\n}\n.label-container {\n    position: relative;\n}\n.label {\n    font-weight: bold;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size:1.25rem;\n    margin:0;\n}\n\n.asset-table {\n    padding: 5px 50px;\n}\n.asset-item {\n    border-bottom: 1px solid #dddddd;\n    padding:10px 20px;\n}\n.asset-item span {\n    width: 30%;\n    display: inline-block;\n    text-align: left;\n}\n.asset-item :nth-child(2) {\n    width:69%;\n    display: inline-block;\n    text-align: right\n}\n.select-sponsor {\n    margin-left: 20px;\n    width:80%;\n    margin-bottom:15px;\n}\n.circle {\n    display: inline-block;\n    text-align: center;\n    border-radius:50%;\n    width:1.5rem;\n    height:1.5rem;\n    line-height: 1.5rem;\n}\n\n.circle-signed {\n    background:#FBE45A;\n}\n.circle-unsigned {\n    background:#F5F7FB;\n}\n.confirm-btns {\n    position: fixed;\n    bottom: 0;\n    left: 4rem;\n    height:5.3rem;\n    width:calc(100% - 4rem);\n    z-index: 1000;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    background:#ffffff;\n}\n.fee {\n    padding-left: 20px;\n    padding-top:10px;\n    margin-bottom:50px;\n}\n.sponsor-item {\n    padding-left: 4rem;\n    margin-bottom:12px;\n}\n.sponsor-item :nth-child(2) {\n    margin-left: 14px;\n}\n.sponsor-item :nth-child(3) {\n    float: right;\n    margin-right: 14px;\n}\n.sponsor-label {\n    margin-bottom:20px;\n}\n.sponsor-label :last-child {\n    float: right;\n}\n\n.payer-item {\n    height: 20px;\n    margin-top: 20px;\n    padding-left: 4rem;\n}\n\n.payer-item :nth-child(2) {\n    margin-left: 14px;\n}\n.payer-item :nth-child(3) {\n    float: right;\n    margin-right: 14px;\n}\n\n.btns-container {\n    width:500px;\n    margin:20px auto;\n}\n.btns-container :last-child {\n    float: right;\n}\n.sign-content {\n    margin-top: 20px;\n    padding-left: 4rem;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :routes=\"routes\" :current=\"$t('pax.paxSign')\"></breadcrumb>\n        <div class=\"sign-container\">\n            <div >\n                <div class=\"sponsor-label\">\n                    <span class=\"label\">{{$t('sharedWalletHome.sponsor')}}</span>\n                    <span class=\"label\">[{{sharedWallet.requiredNumber}} - OF - {{sharedWallet.totalNumber}} ]</span>\n                </div>\n                <div class=\"sponsor-item\">\n                    <span class=\"circle font-medium-black\" :class=\"processing_list[0].cosigners[0] && processing_list[0].cosigners[0].isSign? 'circle-signed': 'circle-unsigned'\">1</span>\n                    <span class=\"font-medium-black\">{{processing_list[0].cosigners[0] && processing_list[0].cosigners[0].name}}</span>\n                    <span class=\"font-medium\">{{processing_list[0].cosigners[0] && processing_list[0].cosigners[0].address}}</span>\n                </div>\n\n                <p class=\"label\">{{$t('sharedWalletHome.signSequence')}}\n                </p>\n                <div class=\"drag-item\" v-for=\"(payer,index) in processing_list[0].cosigners\" :key=\"payer.address\">\n                    <div class=\"payer-item\" v-if=\"index!==0\">\n                        <span class=\"circle font-medium-black\" :class=\"payer.isSign? 'circle-signed': 'circle-unsigned'\">{{index+1}}</span>\n                        <span class=\"font-medium-black\">{{payer.name}}</span>\n                        <span class=\"font-medium\">{{payer.address}}</span>\n                    </div>\n                </div>\n            </div>\n            <div class=\"sign-container\" v-if=\"showSign\">\n                    <p class=\"label\">{{$t('pax.currentSign')}}</p>\n                    <div class=\"sign-content\">\n                        <div v-if=\"currentSigner.type === 'CommonWallet'\">\n                            <a-input type=\"password\" class=\"input-pass\" :placeholder=\"$t('pax.inputPassword')\" v-model=\"password\"></a-input>\n                        </div>\n\n                        <div class=\"ledger-status\" v-if=\"currentSigner.type === 'HardwareWallet'\">\n                            <div class=\"font-bold\" style=\"margin-bottom: 15px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                            <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                            <span class=\"font-medium\">{{ledgerStatus}} </span>\n                            <p>{{$t('pax.ledgerSignMultiTimes')}}</p>\n                        </div>\n                    </div>\n\n            </div>\n        </div>\n        <div class=\"confirm-btns\">\n            <div class=\"btns-container\">\n                <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{$t('pax.back')}}</a-button>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"confirm\"\n                :disabled=\"sending || !currentSigner\n                || currentSigner.type === 'CommonWallet' && !password\n                || currentSigner.type === 'HardwareWallet' && !ledgerPk\">\n                {{$t('pax.confirm')}}</a-button>\n            </div>\n        </div>\n\n         <a-modal\n            :title=\"$t('pax.sendingTx')\"\n            :visible=\"visible\"\n            :footer=\"null\"\n            >\n            <p>{{$t('pax.txToSend')}} {{txToSend}}</p>\n            <p>{{$t('pax.txSent')}} {{txSent}}</p>\n        </a-modal>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport {mapState} from 'vuex'\nimport { getRestClient } from '../../../core/utils'\nimport {Transaction, Crypto, TransactionBuilder, TxSignature, utils, RestClient} from 'ontology-ts-sdk'\nimport {legacySignWithLedger} from '../../../core/ontLedger'\nimport {PAX_API} from '../../../core/consts'\nimport {decryptWallet} from '../../../core/utils'\n\nexport default {\n    name: 'SignProcess',\n    components: {\n        Breadcrumb\n    },\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        const routes = [\n            {name: sharedWallet.sharedWalletName, path:'/sharedWallet/home'},\n            {name: this.$t('sharedWalletHome.paxMgmt'), path: '/sharedWallet/paxMgmt'}\n        ]\n        const payers = sharedWallet.coPayers\n        return {\n            routes,\n            sharedWallet,\n            payers,\n            password: '',\n            sending: false,\n            showSign: true,\n            visible: false,\n            txToSend:0,\n            txSent: 0\n        }\n    },\n    computed:{\n        ...mapState({\n            processing_list: state => state.PaxMgmt.processing_list,\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n            currentSigner: state => state.PaxMgmt.currentSigner\n        })\n    },\n    mounted() {\n        if(this.currentSigner.type === 'HardwareWallet') {\n            this.$store.dispatch('getLedgerStatus')\n        }\n    },\n    beforeDestroy(){\n        if(this.currentSigner.type === 'HardwareWallet') {\n            this.$store.dispatch('stopGetLedgerStatus')\n        }\n    },\n    methods: {\n        back() {\n            this.$router.back();\n        },\n        async confirm() {\n            //sign tx\n            if(this.processing_list.length === 0) {\n                return;\n            }\n\n            this.$store.dispatch('showLoadingModals')\n            const M = this.sharedWallet.requiredNumber;\n            //避免已发交易被再签\n            const txBefore = Transaction.deserialize(this.processing_list[0].Txbodyhash)\n            const sigNumBefore = txBefore.sigs[0].sigData.length;\n            if(sigNumBefore >= M) {\n                this.$message.error(this.$t('pax.hasSignedSent'), 10)\n                return;\n            }\n            this.sending = true;\n\n            const pks = this.sharedWallet.coPayers.map(p => new Crypto.PublicKey(p.publickey))\n            const txbodyhashes = [];\n            const txhashes = [];\n            const cosignerList = [];\n\n            const cosignerUpdate = this.processing_list[0].cosigners.map((item) => {\n                if(item.address === this.currentSigner.address) {\n                    return {...item, isSign: true}\n                }\n                return {...item};\n            })\n\n            if (this.currentSigner.type === 'CommonWallet') {\n                const enc = new Crypto.PrivateKey(this.currentSigner.wallet.key)\n                const pri = decryptWallet({\n                    key: this.currentSigner.wallet.key,\n                    address: this.currentSigner.address,\n                    salt: this.currentSigner.wallet.salt\n                    }, this.password);\n                if (!pri) {\n                    return;\n                }\n\n                for(let item of this.processing_list) {\n                    const tx = Transaction.deserialize(item.Txbodyhash)\n                    console.log(tx)\n                    TransactionBuilder.signTx(tx, M, pks, pri)\n                    console.log(tx)\n                    txbodyhashes.push(tx.serialize())\n                    txhashes.push(item.Txhash)\n                    cosignerList.push(JSON.stringify(cosignerUpdate))\n                }\n            } else {\n                for(let item of this.processing_list) {\n                    const tx = Transaction.deserialize(item.Txbodyhash)\n                    let res;\n                    try {\n                        res = await legacySignWithLedger(tx.serializeUnsignedData())\n                    } catch(err) {\n                        this.ledgerStatus = '';\n                        this.$store.dispatch('hideLoadingModals')\n                        alert(err.message)\n                        return;\n                    }\n                   const sig = new TxSignature();\n                    sig.M = M;\n                    sig.pubKeys = pks;\n                    const sigVal = '01' + res;\n                    tx.sigs[0].sigData.push(sigVal);\n                    txbodyhashes.push(tx.serialize())\n                    txhashes.push(item.Txhash)\n                    cosignerList.push(JSON.stringify(cosignerUpdate))\n                }\n            }\n\n            //decide to send to chain\n                const tx = Transaction.deserialize(txbodyhashes[0])\n                const sigNum = tx.sigs[0].sigData.length;\n                const data = {\n                    txhashs: txhashes,\n                    cosigners: cosignerList,\n                    txbodyhashs: txbodyhashes,\n                    status:1\n                }\n                if(M <= sigNum) {\n                    data.status = 2;\n                }\n                if(M <= sigNum) {\n                    const senthashs = [];\n                    this.$store.dispatch('hideLoadingModals')\n                    this.visible = true;\n                    this.txToSend = txbodyhashes.length;\n                    for(let txData of txbodyhashes) {\n                        const txRes = await this.sendTx(txData)\n                        if(txRes) {\n                            this.txSent ++;\n                            senthashs.push(txRes)\n                        } else {\n                            // send tx failed\n                            this.visible = false;\n                            return;\n                        }\n                    }\n                    data.senthashs =  senthashs;\n                    setTimeout(()=> {\n                        this.visible = false;\n                        if(this.txToSend === this.txSent && this.txSent > 0) {\n                            this.updateApprovalList(data)\n                        }\n                    }, 2000)\n                } else {\n                    this.updateApprovalList(data)\n                }\n\n        },\n        async updateApprovalList(data) {\n            this.$store.dispatch('showLoadingModals')\n            const net = localStorage.getItem('net');\n            const result = await this.httpService({\n                method:'post',\n                data,\n                url: (net === 'TEST_NET' ? PAX_API.TestHost : PAX_API.Host) + PAX_API.updateApprovals\n            })\n            console.log(result)\n            this.sending = false;\n            if(result && result.ErrorCode === 0) {\n                this.$message.success(this.$t('pax.signSuccess'))\n                this.$router.push({path: '/sharedWallet/paxMgmt'})\n            } else {\n                this.$store.dispatch('hideLoadingModals')\n                this.$message.error(result.Error)\n            }\n        },\n        async sendTx(txData) {\n             //send tx\n            const restClient = getRestClient();\n            try {\n                const res = await restClient.sendRawTransaction(txData)\n                console.log(res)\n                if(res.Error === 0) {\n                    return res.Result;\n                } else {\n                    if(res.Result.indexOf('balance insufficient') > -1 ) {\n                        this.$message.error(this.$t('common.balanceInsufficient'), 5)\n                    } else if(res.Result.indexOf('cover gas cost') > -1){\n                        this.$message.error(this.$t('common.ongNoEnough'), 5)\n                    } else {\n                        this.$message.error(res.Result, 5)\n                    }\n                    this.$store.dispatch('hideLoadingModals')\n                    return '';\n                }\n            }catch(err) {\n                console.log(err)\n                return '';\n            }\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/PAX/StartProcess.vue",
    "content": "<style scoped>\n.start-container {\n    width: 700px;\n    margin:20px auto;\n}\n.drag-item {\n    cursor: pointer;\n}\n.label-container {\n    position: relative;\n}\n.label {\n    font-weight: bold;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size:1.25rem;\n    margin:0;\n}\n\n.asset-table {\n    padding: 5px 50px;\n}\n.asset-item {\n    border-bottom: 1px solid #dddddd;\n    padding:10px 20px;\n}\n.asset-item span {\n    width: 30%;\n    display: inline-block;\n    text-align: left;\n}\n.asset-item :nth-child(2) {\n    width:69%;\n    display: inline-block;\n    text-align: right\n}\n.select-sponsor {\n    margin-left: 20px;\n    width:80%;\n    margin-bottom:15px;\n}\n.circle {\n    display: inline-block;\n    text-align: center;\n    border:1px solid #dddddd;\n    border-radius:50%;\n    width:1.5rem;\n    height:1.5rem;\n    line-height: 1.5rem;\n    background:#FBE45A;\n}\n.confirm-btns {\n    position: fixed;\n    bottom: 0;\n    left: 4rem;\n    height:5.3rem;\n    width:calc(100% - 4rem);\n    z-index: 1000;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    background:#ffffff;\n}\n.fee {\n    padding-left: 20px;\n    padding-top:10px;\n    margin-bottom:50px;\n    text-align: left !important;\n}\n.sponsor-select {\n    padding-left: 4rem;\n}\n.sponsor-label {\n    margin-bottom:20px;\n}\n.sponsor-label :last-child {\n    float: right;\n}\n.drag-container {\n    margin-top: 20px;\n    padding-left: 4rem;\n}\n.payer-item {\n    height: 30px;\n}\n.payer-item:hover {\n    background: #F5F7FB;\n}\n.payer-item:hover span {\n    color: #196BD8 !important;\n}\n.payer-item :nth-child(2) {\n    margin-left: 14px;\n}\n.payer-item :nth-child(3) {\n    float: right;\n    margin-right: 14px;\n}\n\n.btns-container {\n    width:500px;\n    margin:20px auto;\n}\n.btns-container :last-child {\n    float: right;\n}\n\n.sign-container {\n    margin-top: 30px;\n    position: relative;\n}\n.sign-container > button {\n    position: absolute;\n    right:0;\n    top: -5px;\n}\n\n.sign-content {\n    margin-top: 20px;\n    padding-left:4rem;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :routes=\"routes\" :current=\"$t('pax.paxStart')\"></breadcrumb>\n        <div class=\"start-container\">\n            <div class=\"sponsor-label\">\n                <span class=\"label\">{{$t('sharedWalletHome.sponsor')}}</span>\n                <span class=\"label\">[{{sharedWallet.requiredNumber}} - OF - {{sharedWallet.totalNumber}} ]</span>\n            </div>\n            <div class=\"sponsor-select\">\n                <span class=\"circle font-medium-black\">1</span>\n                <a-select :options=\"localCopayers\" class=\"select-sponsor\"  @change=\"handleChangeSponsor\"></a-select>\n            </div>\n\n            <p class=\"label\">{{$t('sharedWalletHome.dragDecide')}}\n            </p>\n            <draggable v-model=\"payers\" @start=\"drag=true\" @end=\"drag=false\" class=\"drag-container\">\n                <div class=\"drag-item\" v-for=\"(payer,index) in payers\" :key=\"payer.address\">\n                    <div class=\"payer-item\">\n                        <span class=\"circle font-medium-black\">{{index+2}}</span>\n                        <span class=\"font-medium-black\">{{payer.name}}</span>\n                        <span class=\"font-medium\">{{payer.address}}</span>\n                    </div>\n                </div>\n            </draggable>\n\n            <div class=\"sign-container\" v-if=\"sponsorPayer\">\n                <p class=\"label\">{{$t('pax.sponsorSign')}}</p>\n\n                <div class=\"sign-content\">\n                    <div v-if=\"sponsorPayer.type === 'CommonWallet'\">\n                        <a-input type=\"password\" class=\"input-pass\" :placeholder=\"$t('pax.inputPassword')\" v-model=\"password\"></a-input>\n                    </div>\n\n                    <div class=\"ledger-status\" v-if=\"sponsorPayer.type === 'HardwareWallet'\">\n                        <div class=\"font-bold\" style=\"margin-bottom: 15px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                        <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                        <span class=\"font-medium\">{{ledgerStatus}} </span>\n                        <p>{{$t('pax.ledgerSignMultiTimes')}}</p>\n                    </div>\n                </div>\n            </div>\n        </div>\n\n        <div class=\"confirm-btns\">\n            <div class=\"btns-container\">\n                <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{$t('pax.back')}}</a-button>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"confirm\"\n                :disabled=\"sending || !sponsorPayer\n                || sponsorPayer.type === 'CommonWallet' && !password\n                || sponsorPayer.type === 'HardwareWallet' && !ledgerPk\">\n                {{$t('pax.confirm')}}</a-button>\n            </div>\n        </div>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport draggable from 'vuedraggable'\nimport dbService from '../../../core/dbService'\nimport {mapState} from 'vuex'\nimport {legacySignWithLedger} from '../../../core/ontLedger'\nimport {Transaction, Crypto, TransactionBuilder, TxSignature, utils} from 'ontology-ts-sdk'\nimport {PAX_API} from '../../../core/consts'\nimport {decryptWallet} from '../../../core/utils'\n\nexport default {\n    name: 'StartProcess',\n    components: {\n        Breadcrumb,\n        draggable\n    },\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        const routes = [\n            {name: sharedWallet.sharedWalletName, path:'/sharedWallet/home'},\n            {name: this.$t('sharedWalletHome.paxMgmt'), path: '/sharedWallet/paxMgmt'}\n        ]\n        const payers = sharedWallet.coPayers\n        return {\n            routes,\n            sharedWallet,\n            payers,\n            sponsorPayer:'',\n            localCopayers: [],\n            password: '',\n            sending: false\n        }\n    },\n    computed:{\n        ...mapState({\n            unprocess_list: state => state.PaxMgmt.unprocess_list,\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n        })\n    },\n    mounted() {\n        this.updateLocalCopayers()\n        if(this.sponsorPayer.type === 'HardwareWallet') {\n            this.$store.dispatch('getLedgerStatus')\n        }\n    },\n    beforeDestroy(){\n        if(this.sponsorPayer.type === 'HardwareWallet') {\n            this.$store.dispatch('stopGetLedgerStatus')\n        }\n    },\n    methods: {\n        updateLocalCopayers() {\n            var that = this;\n                const coPayers = this.sharedWallet.coPayers;\n                const localCopayers = []\n                dbService.find({type: {$in:['CommonWallet', 'HardwareWallet']}}, function (err, accounts) {\n                    if (err) {\n                        console.log(err)\n                        return;\n                    }\n                    for (let cp of coPayers) {\n                        for (let ac of accounts) {\n                            if (cp.address === ac.address) {\n                                localCopayers.push(Object.assign({}, cp, {value:ac.address, label:ac.wallet.label, type: ac.type, wallet: ac.wallet}))\n                            }\n                        }\n                    }\n                    if (localCopayers.length > 0) {\n                        that.localCopayers = localCopayers;\n                    }\n                })\n        },\n        handleChangeSponsor(value,option) {\n            const payers = []\n            for(let p of this.sharedWallet.coPayers) {\n                if(p.address !== value) {\n                    payers.push(p)\n                } else {\n                    this.sponsorPayer = this.localCopayers.find(item=> item.address === value)\n                    if(this.sponsorPayer.type === 'HardwareWallet') {\n                        this.$store.dispatch('getLedgerStatus')\n                    }\n                }\n            }\n            this.payers = payers;\n        },\n        back() {\n            this.$router.back();\n        },\n        async confirm() {\n            //sign tx\n            if(this.unprocess_list.length === 0) {\n                return;\n            }\n            this.$store.dispatch('showLoadingModals')\n            const M = this.sharedWallet.requiredNumber;\n            const pks = this.sharedWallet.coPayers.map(p => new Crypto.PublicKey(p.publickey))\n            const txbodyhashes = [];\n            const txhashes = [];\n            const cosignerList = [];\n            const cosigner = this.payers.map((item)=>{\n                item.isSign = false;\n                return item;\n            })\n            cosigner.unshift({\n                address: this.sponsorPayer.address,\n                name: this.sponsorPayer.name,\n                publickey: this.sponsorPayer.publickey,\n                isSign: true\n            })\n            //sponsorPayer\n            if (this.sponsorPayer.type === 'CommonWallet') {\n                const enc = new Crypto.PrivateKey(this.sponsorPayer.wallet.key)\n                const pri = decryptWallet({\n                    key: this.sponsorPayer.wallet.key,\n                    address: this.sponsorPayer.address,\n                    salt: this.sponsorPayer.wallet.salt\n                    }, this.password);\n                if (!pri) {\n                    return;\n                }\n\n                for(let item of this.unprocess_list) {\n                    const tx = Transaction.deserialize(item.Rawtxdata)\n                    tx.payer = new Crypto.Address(this.sharedWallet.sharedWalletAddress);\n                    TransactionBuilder.signTx(tx, M, pks, pri)\n                    txbodyhashes.push(tx.serialize())\n                    txhashes.push(item.Txhash)\n                    cosignerList.push(JSON.stringify(cosigner))\n                }\n            } else {\n                for(let item of this.unprocess_list) {\n                    const tx = Transaction.deserialize(item.Rawtxdata)\n                    tx.payer = new Crypto.Address(this.sharedWallet.sharedWalletAddress);\n                    let res;\n                    try {\n                        res = await legacySignWithLedger(tx.serializeUnsignedData())\n                    } catch(err) {\n                        this.ledgerStatus = '';\n                        this.$store.dispatch('hideLoadingModals')\n                        alert(err.message)\n                        return;\n                    }\n                    const sig = new TxSignature();\n                    sig.M = M;\n                    sig.pubKeys = pks;\n                    sig.sigData = ['01' + res];\n                    tx.sigs.push(sig);\n                    txbodyhashes.push(tx.serialize())\n                    txhashes.push(item.Txhash)\n                    cosignerList.push(JSON.stringify(cosigner))\n                }\n            }\n\n            const data = {\n                txhashs: txhashes,\n                cosigners: cosignerList,\n                txbodyhashs: txbodyhashes,\n                status:1\n            }\n            const net = localStorage.getItem('net');\n            const result = await this.httpService({\n                method:'post',\n                data,\n                url: (net === 'TEST_NET' ? PAX_API.TestHost : PAX_API.Host) + PAX_API.updateApprovals\n            })\n            console.log(result)\n            if(result && result.ErrorCode === 0) {\n                this.$message.success(this.$t('pax.startProcessSuccess'))\n                this.$router.push({path: '/sharedWallet/paxMgmt'})\n            } else {\n                this.$store.dispatch('hideLoadingModals')\n                this.$message.error(result.Error)\n            }\n        },\n\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/PendingTxHome.vue",
    "content": "<style scoped>\n.pending-container {\n    width:600px;\n    margin:4rem auto;\n}\n</style>\n\n<template>\n    <div>\n        <breadcrumb :routes=\"routes\" :current=\"$t('sharedWalletHome.pendingTx')\" v-on:backEvent=\"backToWallets\"></breadcrumb>\n        <div class=\"pending-container\">\n            <pending-confirm \n            v-on:signEvent=\"handleSignEvent\"\n            v-if=\"!showInputPass\"></pending-confirm>\n            <pending-tx-sign \n            v-on:backEvent=\"handleBackEvent\"\n            v-on:submitEvent=\"handleSubmitEvent\"\n            v-if=\"showInputPass\"></pending-tx-sign>\n        </div>\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from '../Breadcrumb'\nimport PendingConfirm from './Transfer/PendingConfirm'\nimport PendingTxSign from './Transfer/PendingTxSign'\n\nexport default {\n    name:'PendingTxHome',\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        const routes = [{name: sharedWallet.sharedWalletName, path:'/sharedWallet/home'}]\n        return {\n            routes,\n            showInputPass:false\n        }\n    },\n    components: {\n        Breadcrumb,\n        PendingConfirm,\n        PendingTxSign\n    },\n    methods: {\n        backToWallets() {\n            this.$router.push({name:'Wallets'})\n        },\n        handleSignEvent() {\n            this.showInputPass = true;\n        },\n        handleBackEvent() {\n            this.showInputPass = false;\n        },\n        handleSubmitEvent(){\n            this.$router.push({path:'/sharedWallet/home'})\n            //this.$store.dispatch('fetchPendingTx')\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/SharedWalletDetail.vue",
    "content": "\n\n\n<template>\n    <div>\n        <router-view></router-view>\n    </div>\n</template>\n<script>\nexport default {\n    name: 'SharedWalletDetail'\n}\n</script>\n<style>\n\n</style>"
  },
  {
    "path": "src/components/SharedWallet/SharedWalletHome.vue",
    "content": "<style scoped>\n.header-header {\n  height: 4rem;\n  padding: 1.1rem 0;\n  width: 100%;\n}\n.home-container {\n  padding: 0 20px;\n  height: 100%;\n}\n\n.content-container {\n  display: flex;\n}\n\n.left-half {\n  flex: 1;\n}\n\n.right-half {\n  flex: 1;\n  padding-left: 67px;\n}\n\n.asset {\n  margin: 20px auto;\n  display: flex;\n  flex-direction: row;\n  justify-content: space-around;\n}\n.claim-btn {\n  text-align: center;\n}\n\n.rule {\n  text-align: center;\n}\n\n.owners-table {\n}\n\n.table-item {\n  margin: 10px 0;\n}\n.table-item :first-child {\n  width: 72px;\n  overflow: hidden;\n  display: inline-block;\n  text-overflow: ellipsis;\n}\n.table-item :last-child {\n  float: right;\n}\n.wallet-info {\n  position: relative;\n  padding-top: 12px;\n  font-family: AvenirNext-Regular;\n  font-size: 0.88rem;\n  /* height: 4rem; */\n}\n.wallet-info p {\n  margin-bottom: 4px;\n}\n\n.wallet-type {\n  position: absolute;\n  width: 3rem;\n  height: 3rem;\n  background: url(\"../../assets/sharedWallet.png\") center center;\n  background-size: cover;\n  right: 0;\n  top: -12px;\n}\n\n.copayer-header {\n  padding-bottom: 5px;\n  border-bottom: 1px solid #dfe2e9;\n}\n.copayer-header :last-child {\n  float: right;\n  font-family: AvenirNext-Bold;\n  font-size: 14px;\n  color: #6f7781;\n}\n.copayer-header :first-child {\n  font-family: AvenirNext-Bold;\n  font-size: 14px;\n  color: #000000;\n}\n.check-more {\n  font-family: AvenirNext-Medium;\n  font-size: 12px;\n  color: #227eec;\n  text-align: center;\n  cursor: pointer;\n}\n.txList-header {\n  padding-bottom: 5px;\n  border-bottom: 1px solid #dfe2e9;\n  position: relative;\n  margin-bottom: 10px;\n}\n.txList-header :first-child {\n  font-family: AvenirNext-Bold;\n  font-size: 14px;\n  color: #000000;\n  text-align: center;\n}\n\n/* .txList-header :last-child {\n  width: 64px;\n  height: 64px;\n  display: block;\n  float: right;\n  background: url(\"../../assets/transaction.png\");\n  background-size: contain;\n  top: -20px;\n  right: 0;\n  position: absolute;\n} */\n.pending-tx {\n  margin-bottom: 50px;\n}\n\n.pending-tx-container {\n  height: 150px;\n  overflow-y: auto;\n}\n.pending-tx-container::-webkit-scrollbar {\n  /*滚动条整体样式*/\n  width: 4px; /*高宽分别对应横竖滚动条的尺寸*/\n  height: 4px;\n}\n.pending-tx-container::-webkit-scrollbar-thumb {\n  /*滚动条里面小方块*/\n  border-radius: 5px;\n  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);\n  background: rgba(0, 0, 0, 0.2);\n}\n.pending-tx-container::-webkit-scrollbar-track {\n  /*滚动条里面轨道*/\n  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);\n  border-radius: 0;\n  background: rgba(0, 0, 0, 0.1);\n}\n\n\n.commonWallet-btn {\n  width: 70px;\n  height: 28px;\n  border-radius: 0;\n  background: #fbe45a;\n  padding: 0;\n  font-family: AvenirNext-Medium;\n  font-size: 14px;\n  color: #5e6369;\n  border: none;\n}\n.commonWallet-btn {\n  width: 70px;\n  height: 28px;\n  border-radius: 0;\n  background: #fbe45a;\n  padding: 0;\n  font-family: AvenirNext-Medium;\n  font-size: 14px;\n  color: #5e6369;\n  border: none;\n}\n.btn-swap {\n  margin-left: 30px;\n}\n.btn-redeem {\n  float: left;\n  margin-left: 30px;\n}\n.btn-dropdown {\n  width: 120px;\n  height: 34px;\n  background: #f4f4f6;\n  font-size: 14px;\n  font-family: AvenirNext-Medium;\n  font-weight: 500;\n  color: rgba(25, 107, 216, 1);\n  border-radius: 0;\n  border: none;\n}\n.dropdown-item:hover {\n  color: #196bd8;\n}\n.left-btn-container {\n  display: flex;\n  justify-content: space-between;\n}\n.left-btn-more {\n    display:flex;\n}\n.vertical-line {\n    width:2px;\n    height:34px;\n    background:#F4F4F6;\n    margin-right:29px;\n}\n.icon-arow {\n    font-size: 10px;\n    margin-left:4px;\n}\n\n</style>\n<template>\n  <div class=\"home-container\">\n    <breadcrumb :current=\"sharedWallet.sharedWalletName\" v-on:backEvent=\"handleBack\"></breadcrumb>\n    <div class=\"wallet-info\">\n      <p class=\"font-regular\">\n        {{$t('sharedWalletHome.walletAddress')}}: <span class=\"font-gray\">{{this.sharedWallet.sharedWalletAddress}}</span>\n        <span class=\"common-icon copy-icon\" @click=\"copy()\"></span>\n      </p>\n    </div>\n    <div class=\"content-container\">\n      <div class=\"left-half\">\n        <div class=\"wallet-balance\">\n          <div>\n            <span>{{$t('sharedWalletHome.balance')}}</span>\n            <span class=\"common-icon  refresh-icon\" @click=\"refresh(true)\"></span>\n          </div>\n          <span class=\"common-icon add-icon\" @click=\"addOep4\"></span>\n        </div>\n        <div class=\"asset-container\">\n          <div class=\"asset-item\">\n            <span class=\"asset-label\">ONT</span>\n            <span class=\"asset-amount\">{{balance.ont}}</span>\n          </div>\n          <!-- <div class=\"asset-value\">${{balance.ontValue}}</div> -->\n\n          <div class=\"asset-item\">\n            <span class=\"asset-label\">ONG</span>\n            <span class=\"asset-amount\">{{balance.ong}}</span>\n          </div>\n          <!-- <div class=\"asset-value\">{{'$900'}}</div> -->\n\n          <div class=\"asset-item\" v-for=\"item of oep4s\" :key=\"item.contract_hash\">\n            <span class=\"asset-label\">{{item.symbol}}</span>\n            <span class=\"asset-amount\">{{item.balance}}</span>\n          </div>\n        </div>\n\n        <div class=\"left-footer\">\n          <div class=\"claim-ong-container\">\n            <div class=\"claim-ong\">\n              <div class=\"claim-ong-item\">\n                <span>{{$t('commonWalletHome.claimableOng')}}:</span>\n                <span>{{balance.unboundOng}}</span>\n              </div>\n              <div class=\"claim-ong-item\">\n                <span>{{$t('commonWalletHome.unboundOng')}}:</span>\n                <span>{{balance.waitBoundOng}}</span>\n              </div>\n            </div>\n            <div class=\"redeem-container\">\n              <a-button\n                type=\"default\"\n                class=\"btn-redeem\"\n                @click=\"redeemOng\"\n              >{{$t('commonWalletHome.redeem')}}</a-button>\n              <redeem-info-icon></redeem-info-icon>\n            </div>\n          </div>\n\n          <div v-if=\"hasLocalCopayer\" class=\"left-btn-container\">\n            <div>\n              <a-button class=\"asset-btn\" type=\"primary\" @click=\"showTransferBox\">\n                <i class=\"fa fa-paper-plane\"></i>\n                {{$t('sharedWalletHome.send')}}\n              </a-button>\n              <a-button class=\"asset-btn\" type=\"primary\" @click=\"showReceive\">\n                <i class=\"fa fa-qrcode\"></i>\n                {{$t('sharedWalletHome.receive')}}\n              </a-button>\n            </div>\n\n            <div class=\"left-btn-more\">\n              <div class=\"vertical-line\"></div>\n              <a-dropdown placement=\"topCenter\">\n                <a-menu slot=\"overlay\">\n                  <a-menu-item key=\"1\" v-if=\"showPax\">\n                    <span @click=\"showPaxMgmt()\">{{$t('sharedWalletHome.paxMgmt')}}</span>\n                  </a-menu-item>\n                  <a-menu-item key=\"2\" @click=\"showTxMgmt()\">\n                    <span>{{$t('sharedWalletHome.txMgmt')}}</span>\n                  </a-menu-item>\n                  <a-menu-item key=\"3\" @click=\"toCopayerDetail()\">\n                    <span>{{$t('sharedWalletHome.copayers')}}</span>\n                  </a-menu-item>\n                </a-menu>\n                <a-button class=\"btn-dropdown\">\n                  {{$t('common.more')}}\n                  <!-- <a-icon type=\"down\" /> -->\n                  <i class=\"fa fa-chevron-down icon-arrow\"></i>\n                </a-button>\n              </a-dropdown>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"right-half\">\n        <div class=\"pending-tx\">\n          <div class=\"txList-header\">\n            <span>{{$t('sharedWalletHome.pendingTx')}}</span>\n            <!-- <span class=\"transfer-icon\"></span> -->\n          </div>\n          <div class=\"pending-tx-container\">\n            <div\n              v-for=\"tx in pendingTx\"\n              :key=\"tx.transactionidhash\"\n              class=\"tx-item pendingTx-item\"\n              @click=\"pendingTxDetail(tx)\"\n            >\n              <span>{{tx.transactionidhash}}</span>\n              <span>\n                {{tx.receiveaddress === sharedWallet.sharedWalletAddress ? '+' : '-'}}\n                {{tx.amount}} {{tx.assetName}}\n              </span>\n            </div>\n          </div>\n        </div>\n        <div class=\"completed-tx\">\n          <div class=\"txList-header\">\n            <span>{{$t('sharedWalletHome.completedTx')}}</span>\n            <span class=\"transfer-icon\"></span>\n          </div>\n\n          <div\n            v-for=\"(tx) in completedTx\"\n            :key=\"tx.txHash\"\n            class=\"tx-item\"\n            @click=\"showTxDetail(tx.txHash)\"\n          >\n            <span>{{tx.txHash.substring(0,40)+'...'}}</span>\n            <span>{{tx.amount}} {{tx.asset}}</span>\n          </div>\n          <div\n            class=\"check-more\"\n            v-if=\"completedTx.length > 5\"\n            @click=\"checkMoreTx\"\n          >{{$t('sharedWalletHome.checkMore')}}\n            <i class=\"fa fa-chevron-right icon-arrow\"></i>\n          </div>\n        </div>\n      </div>\n    </div>\n    <a-modal :title=\"$t('redeemInfo.info')\" v-model=\"redeemInfoVisible\" @ok=\"handleModalOk\">\n      <p class=\"font-regular\">\n        <span class=\"font-medium\"></span>\n        {{$t('redeemInfo.noClaimableOng')}}\n      </p>\n    </a-modal>\n\n    <oep4-selection :visible=\"showOep4Selection\" @closeOep4Selection=\"closeOep4Selection\"></oep4-selection>\n  </div>\n</template>\n\n<script>\nimport { mapState } from \"vuex\";\nimport {\n  TEST_NET,\n  MAIN_NET,\n  ONT_PASS_NODE,\n  ONT_PASS_NODE_PRD,\n  ONT_PASS_URL,\n  PAX_SC_HASH\n} from \"../../core/consts\";\nimport dbService from \"../../core/dbService\";\nimport axios from \"axios\";\nimport Breadcrumb from \"../Breadcrumb\";\nimport { BigNumber } from \"bignumber.js\";\nimport RedeemInfoIcon from \"../RedeemInfoIcon\";\nimport Oep4Selection from \"./../Common/Oep4Selection\";\nimport {\n  open,\n  getRestClient,\n  getTransactionListUrl,\n  getBalanceUrl\n} from \"../../core/utils\";\nimport { TransactionBuilder, Crypto, utils } from \"ontology-ts-sdk\";\nconst ONG_GOVERNANCE_CONTRACT = \"AFmseVrdL9f9oyCzZefL9tG6UbviEH9ugK\";\nexport default {\n  name: \"SharedWalletHome\",\n  data() {\n    const net = localStorage.getItem(\"net\");\n    const network =\n      net && net === \"TEST_NET\"\n        ? this.$t(\"common.testNet\")\n        : this.$t(\"common.mainNet\");\n    const sharedWallet = JSON.parse(sessionStorage.getItem(\"sharedWallet\"));\n    return {\n      amount: 0,\n      toAddress: \"\",\n      transactions: \"\",\n      sharedWallet,\n      pendingTx: [],\n      completedTx: [],\n      showTransfer: false,\n      transferStep: 0,\n      network,\n      hasLocalCopayer: true,\n      interval: 15000,\n      intervalId: \"\",\n      redeemInfoVisible: false,\n      requestStart: false,\n      showPax: false,\n      showOep4Selection: false\n    };\n  },\n  components: {\n    Breadcrumb,\n    RedeemInfoIcon,\n    Oep4Selection\n  },\n  created() {\n    const net = localStorage.getItem(\"net\");\n    const scriptHash = net === \"TEST_NET\" ? PAX_SC_HASH.TEST : PAX_SC_HASH.MAIN;\n    const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));\n    const method = \"getManualSupplyController\";\n    const tx = TransactionBuilder.makeInvokeTransaction(\n      method,\n      [],\n      contractAddr,\n      \"500\",\n      \"20000\"\n    );\n    const restClient = getRestClient();\n    restClient.sendRawTransaction(tx.serialize(), true).then(res => {\n      console.log(res);\n      if (res.Error === 0) {\n        const controller = new Crypto.Address(res.Result.Result).toBase58();\n        if (controller === this.sharedWallet.sharedWalletAddress) {\n          this.showPax = true;\n        }\n      }\n    });\n  },\n  mounted() {\n    // UPDATE CURRENT WALLET\n    const wallet = {\n      address: this.sharedWallet.sharedWalletAddress,\n      name: this.sharedWallet.sharedWalletName\n    };\n    this.$store.commit(\"UPDATE_CURRENT_WALLET\", { wallet });\n\n    this.refresh(true);\n    this.ifHasLocalCopayer();\n    let that = this;\n    this.intervalId = setInterval(() => {\n      this.refresh(false);\n    }, this.interval);\n  },\n  beforeDestroy() {\n    clearInterval(this.intervalId);\n  },\n  computed: {\n    ...mapState({\n      balance: state => state.CurrentWallet.balance,\n      oep4s: state => state.Tokens.oep4WithBalances\n    })\n  },\n  methods: {\n    handleBack() {\n      this.$router.push({ name: \"Wallets\" });\n    },\n    async getTransactions() {\n      const url = getTransactionListUrl(this.sharedWallet.sharedWalletAddress);\n      try {\n        const res = await this.httpService(url);\n        const txlist = res.result;\n        const completed = [];\n        for (const t of txlist) {\n          for (const tx of t.transfers) {\n            const asset = tx.asset_name.toUpperCase();\n            if (\n              tx.to_address === ONG_GOVERNANCE_CONTRACT &&\n              asset === \"ONG\"\n            ) {\n              continue;\n            }\n            let amount = asset === \"ONT\" ? parseInt(tx.amount) : tx.amount;\n            if (tx.from_address === this.sharedWallet.sharedWalletAddress) {\n              amount = \"-\" + amount;\n            } else {\n              amount = \"+\" + amount;\n            }\n            completed.push({\n              txHash: t.tx_hash,\n              asset,\n              amount: amount\n            });\n          }\n        }\n        this.completedTx = completed.slice(0, 6);\n        return completed; // fetch tx history succeed\n      } catch (err) {\n        console.log(err);\n        this.$message.error(this.$t(\"dashboard.getTransErr\"));\n        return false; // fetch tx history failed\n      }\n    },\n    getBalance() {\n      return this.$store\n        .dispatch(\"getNativeBalance\", {\n          address: this.sharedWallet.sharedWalletAddress\n        })\n        .then(res => {\n          if (!res) {\n            this.$message.error(this.$t(\"dashboard.getBalanceErr\"));\n          }\n          return res;\n        });\n    },\n    getOep4Balances() {\n      this.$store\n        .dispatch(\"fetchTokenBalances\", {\n          address: this.sharedWallet.sharedWalletAddress\n        })\n        .then(res => {\n          if (!res) {\n            this.$message.error(this.$t(\"dashboard.getBalanceErr\"));\n          }\n          return res;\n        });\n    },\n    getExchangeCurrency() {\n      const currency = \"ont\";\n      const goaltype = \"USD\";\n      const amount = this.balance.ont;\n      const url = `https://service.onto.app/S3/api/v1/onto/exchangerate/reckon/${currency}/${goaltype}/${amount}`;\n      axios.get(url).then(res => {\n        console.log(res);\n        if (res.data.Result) {\n          this.balance.ontValue = res.data.Result.Money;\n        }\n      });\n    },\n    getPendingTx() {\n      const sharedAddress = this.sharedWallet.sharedWalletAddress;\n      // const assetName = 'ONT'\n      const timeStamp = new Date().getTime();\n      const net = localStorage.getItem(\"net\");\n      const ontPassNode =\n        net === \"TEST_NET\" ? ONT_PASS_NODE : ONT_PASS_NODE_PRD;\n      const url = ontPassNode + ONT_PASS_URL.QueryPendingTransfer;\n      this.axios\n        .get(url, {\n          params: {\n            sharedAddress,\n            // assetName,\n            beforeTimeStamp: timeStamp\n          }\n        })\n        .then(res => {\n          console.log(res);\n          this.pendingTx = res.data.SigningSharedTransfers.map(p => {\n            if (p.assetName.toLowerCase() === \"ong\") {\n              p.amount = new BigNumber(p.amount).div(1e9).toFixed(9);\n            }\n            return p;\n          });\n        })\n        .catch(err => {\n          console.log(err);\n          this.$message.error(this.$t(\"common.networkErr\"));\n        });\n    },\n    toCopayerDetail() {\n      this.$router.push({ path: \"/sharedWallet/copayers\" });\n    },\n    refresh(showLoading) {\n      if (showLoading) {\n        this.$store.dispatch(\"showLoadingModals\");\n      }\n      if (this.requestStart) {\n        return;\n      }\n      this.requestStart = true;\n      Promise.all([\n        this.getTransactions(),\n        this.getBalance(),\n        this.getOep4Balances(),\n        this.getPendingTx()\n      ]).then(res => {\n        this.requestStart = false;\n        this.$store.dispatch(\"hideLoadingModals\");\n      });\n    },\n    back() {\n      this.$router.push({ name: \"Dashboard\" });\n    },\n    showTransferBox() {\n      if (Number(this.balance.ong) < 0.01) {\n        this.$message.warning(this.$t(\"common.ongNoEnough\"));\n        return;\n      }\n      this.$store.commit(\"CLEAR_CURRENT_TRANSFER\");\n\n      this.$store.commit(\"UPDATE_TRANSFER_REDEEM_TYPE\", { type: false });\n      this.$router.push({ path: \"/sharedWallet/sendTransfer\" });\n    },\n    showReceive() {\n      this.$router.push({ path: \"/commonWalletReceive/sharedWallet\" });\n    },\n    pendingTxDetail(tx) {\n      //判断当前是否在上链中状态\n      const requiredNumber = this.sharedWallet.requiredNumber;\n      let signed = 0;\n      for (let c of tx.coPayerSignDtos) {\n        if (c.isSign) {\n          signed++;\n        }\n      }\n      if (requiredNumber <= signed) {\n        this.$message.warning(this.$t(\"sharedWalletHome.txSendingTochain\"));\n        return;\n      }\n      this.$store.commit(\"UPDATE_PENDINGTX\", { pendingTx: tx });\n      if (tx.receiveaddress === tx.sendaddress && tx.assetName === \"ONG\") {\n        this.$store.commit(\"UPDATE_TRANSFER_REDEEM_TYPE\", { type: true });\n      }\n      this.$router.push(\"/sharedWallet/pendingTxHome\");\n    },\n    ifHasLocalCopayer() {\n      var that = this;\n      const coPayers = this.sharedWallet.coPayers;\n      const localCopayers = [];\n      dbService.find(\n        { $or: [{ type: \"CommonWallet\" }, { type: \"HardwareWallet\" }] },\n        function(err, accounts) {\n          if (err) {\n            console.log(err);\n            that.$message.error(err);\n            return;\n          }\n          for (let cp of coPayers) {\n            for (let ac of accounts) {\n              if (cp.address === ac.address) {\n                localCopayers.push(ac.wallet);\n              }\n            }\n          }\n          if (localCopayers.length > 0) {\n            that.hasLocalCopayer = true;\n          } else {\n            that.hasLocalCopayer = false;\n          }\n        }\n      );\n    },\n    checkMoreTx() {\n      let url = `https://explorer.ont.io/address/${this.sharedWallet.sharedWalletAddress}/10/1`;\n      if (this.network === \"TestNet\") {\n        url += \"/testnet\";\n      }\n      open(url);\n    },\n    showTxDetail(txHash) {\n      let url = `https://explorer.ont.io/transaction/${txHash}`;\n      if (this.network === \"TestNet\") {\n        url += \"/testnet\";\n      }\n      open(url);\n    },\n    copy() {\n      this.$copyText(this.sharedWallet.sharedWalletAddress);\n      this.$message.success(this.$t(\"common.copied\"));\n    },\n    redeemOng() {\n      if (this.balance.unboundOng == 0) {\n        this.redeemInfoVisible = true;\n        return;\n      }\n      if (Number(this.balance.ong) < 0.01) {\n        this.$message.warning(this.$t(\"common.ongNoEnough\"));\n        return;\n      }\n      this.$store.commit(\"CLEAR_CURRENT_TRANSFER\");\n      this.$store.commit(\"UPDATE_TRANSFER_REDEEM_TYPE\", { type: true });\n\n      const redeem = {\n        claimableOng: this.balance.unboundOng,\n        balance: this.balance.ong\n      };\n      this.$store.commit(\"UPDATE_CURRENT_REDEEM\", { redeem: redeem });\n      this.$router.push({ path: \"/sharedWallet/sendTransfer\" });\n    },\n    handleModalOk() {\n      this.redeemInfoVisible = false;\n    },\n    showPaxMgmt() {\n      this.$router.push({ path: \"/sharedWallet/paxMgmt\" });\n    },\n    showTxMgmt() {\n      this.$router.push({ path: \"/sharedWallet/txMgmt\" });\n    },\n    checkMoreOep4() {\n      this.$router.push({ name: \"Oep4Home\" });\n    },\n    addOep4() {\n      this.showOep4Selection = true;\n    },\n    closeOep4Selection() {\n      this.showOep4Selection = false;\n      this.$store.dispatch(\"showLoadingModals\");\n      this.$store.dispatch(\"fetchTokenBalances\", {\n        address: this.sharedWallet.sharedWalletAddress\n      });\n    }\n  }\n};\n</script>\n\n\n"
  },
  {
    "path": "src/components/SharedWallet/SharedWalletSend.vue",
    "content": "<style scoped>\n    .send-container {\n        width:600px;\n        margin:0 auto;\n        padding-bottom:5.3rem;\n        overflow: auto;\n    }\n    .steps {\n        height:68px;\n        padding:0 4rem;\n\n    }\n</style>\n\n<template>\n    <div>\n        <breadcrumb :routes=\"routes\" :current=\"$t('sharedWalletHome.send')\" v-on:backEvent=\"handleRouteBack\"></breadcrumb>\n        <div class=\"send-container\">\n            <div class=\"steps\">\n                <a-steps :current=\"current\">\n                    <a-step  v-if=\"!isRedeem\"/>\n                    <a-step  />\n                    <a-step  />\n                </a-steps>\n            </div>\n            \n            <send-asset\n            v-on:cancelEvent=\"handleCancel\"\n            v-on:sendAssetNext=\"handleSendAssetNext\" \n            v-if=\"current ===0 && !isRedeem\">\n            </send-asset>\n            <send-confirm\n            v-if=\"current === 1\"\n            v-on:cancelEvent=\"handleCancel\"\n            v-on:sendConfirmNext=\"handleSendConfirmNext\"\n            v-on:sendConfirmBack=\"handleSendConfirmBack\"\n            ></send-confirm>\n            <input-password\n            v-if=\"current === 2\"\n            v-on:inputPassBack=\"handleInputPassBack\"\n            v-on:inputPassNext=\"handleInputPassNext\"\n            ></input-password>            \n        </div>\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from '../Breadcrumb'\nimport SendAsset from './Transfer/SendAsset'\nimport SendConfirm from './Transfer/SendConfirm'\nimport InputPassword from './Transfer/InputPassword'\nimport {mapState} from 'vuex'\nexport default {\n    name: 'SharedWalletSend',\n    components: {\n        Breadcrumb,\n        SendAsset,\n        SendConfirm,\n        InputPassword\n    },\n    computed: {\n        ...mapState({\n            isRedeem: state => state.CurrentWallet.transfer.isRedeem,\n        })\n    },\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        const routes = [{name: sharedWallet.sharedWalletName, path:'/sharedWallet/home'}]\n        return {\n            sharedWallet,\n            routes,\n            current: 0\n        }\n    },\n    mounted(){\n        this.current = this.isRedeem ? 1 : 0;\n    },\n    methods: {\n        handleRouteBack() {\n            this.$router.push({name: 'Wallets'})\n        },\n        handleCancel() {\n            this.$router.go(-1);\n        },\n        handleSendAssetNext() {\n            this.current = 1;\n        },\n        handleSendConfirmNext() {\n            this.current = 2;\n        },\n        handleSendConfirmBack() {\n            this.current = 0;\n        },\n        handleInputPassBack() {\n            this.current = 1;\n        },\n        handleInputPassNext(){\n            this.$router.push({path:'/sharedWallet/home'})\n        },\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/Transfer/InputPassword.vue",
    "content": "<style scoped>\n.label {\n    font-weight: bold;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size:1.25rem;\n    margin:0;\n}\n\n.asset-table {\n    padding: 10px 20px;\n}\n.asset-item {\n    border-bottom: 1px solid #dddddd;\n    padding:10px 10px;\n}\n.asset-item span {\n    width: 30%;\n    display: inline-block;\n    text-align: center;\n}\n.asset-item :nth-child(2) {\n    width:69%;\n    display: inline-block;\n}\n.select-sponsor {\n    margin-left: 20px;\n    width:80%;\n    margin-bottom:15px;\n}\n.circle {\n    display: inline-block;\n    text-align: center;\n    border:1px solid #dddddd;\n    border-radius:50%;\n    width:20px;\n    height:20px;\n    line-height: 20px;\n}\n.input-btns :last-child {\n    float: right;\n}\n.input-content {\n    padding-left: 4rem;\n}\n.input-check {\n    margin-top:12px;\n    margin-bottom: 40px;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #000000;\n}\n.input-pass {\n    margin-bottom:50px;\n}\n\n.ledger-status {\n    margin-bottom:40px;\n}\n</style>\n<template>\n    <div class=\"clearfix\">\n        <p class=\"label\">{{$t('sharedWalletHome.confirmation')}}</p>\n        <div class=\"input-content\">\n            <div >\n                <a-checkbox @change=\"onChange\" :checked=\"checked\" class=\"input-check\">{{$t('sharedWalletHome.agreeToSend')}}</a-checkbox>\n\n                <div v-if=\"sponsorWallet.type === 'CommonWallet'\">\n                    <a-input type=\"password\" class=\"input-pass\" :placeholder=\"$t('sharedWalletHome.inputPassToTransfer')\" v-model=\"password\"></a-input>\n                </div>\n\n                <div class=\"ledger-status\" v-if=\"sponsorWallet.type === 'HardwareWallet'\">\n                    <div class=\"font-bold\" style=\"margin-bottom: 15px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                    <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}} </span>\n                </div>\n            </div>\n\n\n            <div class=\"input-btns\" >\n                <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{$t('sharedWalletHome.back')}}</a-button>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"submit\"\n                :disabled=\"sending || !checked\n                || sponsorWallet.type === 'CommonWallet' && !password\n                || sponsorWallet.type === 'HardwareWallet' && !ledgerPk\">\n                    {{$t('sharedWalletHome.submit')}}\n                    </a-button>\n            </div>\n\n        </div>\n\n    </div>\n</template>\n\n<script>\nimport {mapState} from 'vuex'\nimport draggable from 'vuedraggable'\nimport {OntAssetTxBuilder, Crypto, TransactionBuilder, TxSignature, utils, Oep4} from 'ontology-ts-sdk'\nimport {ONT_PASS_NODE, ONT_PASS_NODE_PRD, ONT_PASS_URL, DEFAULT_SCRYPT} from '../../../core/consts'\nimport axios from 'axios'\nimport dbService from '../../../core/dbService'\nimport { BigNumber } from 'bignumber.js';\nimport {legacySignWithLedger, checkPublicKeyIsInTheConnectedLedger} from '../../../core/ontLedger'\n\nexport default {\n    name:'InputPassword',\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        return {\n            sharedWallet,\n            payers: [],\n            password:'',\n            sponsorWallet:{},\n            checked: false,\n            sending:false\n        }\n    },\n    computed:{\n        ...mapState({\n            transfer: state => state.CurrentWallet.transfer,\n            redeem: state => state.CurrentWallet.redeem,\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n        })\n    },\n\n    mounted(){\n        //to support update vuex data\n        this.payers = this.transfer.coPayers;\n        const that = this\n\n        // dbService.findOne({address: this.transfer.coPayers[0].address}, function(err, doc) {\n        //     if(err) {\n        //         console.log(err)\n        //     }\n        //     that.sponsorWallet = doc.wallet\n        // })\n        this.sponsorWallet = this.transfer.coPayers[0]\n        //get ledger status\n        if(this.sponsorWallet.type === 'HardwareWallet') {\n            this.$store.dispatch('getLedgerStatus')\n        }\n    },\n    beforeDestroy(){\n        if(this.sponsorWallet.type === 'HardwareWallet') {\n            this.$store.dispatch('stopGetLedgerStatus')\n        }\n    },\n    methods:{\n        back(){\n            this.$emit('inputPassBack')\n        },\n        onChange(){\n            this.checked = !this.checked;\n        },\n        async submit() {\n            if(!this.sending) {\n            this.sending = true;\n            let tx, amount, gasPrice;\n            const tokenType = this.transfer.asset;\n            const gasLimit = '20000';\n            const gas = new BigNumber(this.transfer.gas).multipliedBy(1e9);\n            if(this.transfer.isRedeem) {\n                const from = new Crypto.Address(this.sharedWallet.sharedWalletAddress)\n                const to = from\n                const value = new BigNumber(this.redeem.claimableOng);\n                gasPrice = '500'\n                amount = value.multipliedBy(1e9).toString();\n                tx = OntAssetTxBuilder.makeWithdrawOngTx(from, to, amount, from, gasPrice, gasLimit);\n            } else {\n            //create transaction\n                gasPrice = gas.div(gasLimit).toString();\n                const from = new Crypto.Address(this.sharedWallet.sharedWalletAddress)\n                const to = new Crypto.Address(this.transfer.to);\n                if(tokenType === 'ONT' || tokenType === 'ONG') {\n                    amount = tokenType === 'ONT' ? this.transfer.amount : new BigNumber(this.transfer.amount).multipliedBy(1e9);\n\n                    tx = OntAssetTxBuilder.makeTransferTx(tokenType, from, to, amount, gasPrice, gasLimit, from);\n                } else { // now only supports oep4\n                    const contractAddr = new Crypto.Address(utils.reverseHex(this.transfer.scriptHash));\n                    const oep4 = new Oep4.Oep4TxBuilder(contractAddr);\n                    amount = new BigNumber(this.transfer.amount).multipliedBy(Math.pow(10, this.transfer.decimal)).toString()\n                    tx = oep4.makeTransferTx(from, to, amount, gasPrice, gasLimit, from);\n                }\n            }\n            this.$store.dispatch('showLoadingModals')\n            //sign tx\n            const M = this.sharedWallet.requiredNumber;\n            const pks = this.sharedWallet.coPayers.map(p => new Crypto.PublicKey(p.publickey))\n            //sponsorWallet\n\n            if (this.sponsorWallet.type === 'CommonWallet') {\n                const enc = new Crypto.PrivateKey(this.sponsorWallet.wallet.key)\n                let pri;\n                try {\n                    pri = enc.decrypt(this.password, new Crypto.Address(this.sponsorWallet.address), this.sponsorWallet.wallet.salt, DEFAULT_SCRYPT)\n                }catch(err) {\n                    this.$store.dispatch('hideLoadingModals')\n                    this.sending = false;\n                    console.log(err);\n                    this.$message.error(this.$t('common.pwdErr'))\n                    return;\n                }\n                TransactionBuilder.signTx(tx, M, pks, pri)\n            } else {\n                const txData = tx.serializeUnsignedData();\n                let res;\n                try {\n                    console.log('this.sponsorWallet.wallet',this.sponsorWallet.wallet);\n                    await checkPublicKeyIsInTheConnectedLedger(this.sponsorWallet.wallet.acct, this.sponsorWallet.wallet.neo, this.sponsorWallet.publickey);\n                    res = await legacySignWithLedger(txData,this.sponsorWallet.wallet.neo,this.sponsorWallet.wallet.acct)\n                } catch(err) {\n                    this.ledgerStatus = '';\n                      this.$store.dispatch('hideLoadingModals')\n                      alert(typeof err === 'string' ? err : err.message)\n                    return;\n                }\n                const sig = new TxSignature();\n                sig.M = M;\n                sig.pubKeys = pks;\n                sig.sigData = ['01' + res];\n                tx.sigs.push(sig);\n            }\n            const txHash = utils.reverseHex(tx.getHash());\n            const txData = tx.serialize();\n            //save transaction to backend\n            const net = localStorage.getItem('net')\n            const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD\n            const url = ontPassNode + ONT_PASS_URL.CreateSharedTransfer\n            const body = {\n                sendAddress: this.sharedWallet.sharedWalletAddress,\n                receiveAddress: this.transfer.isRedeem ? this.sharedWallet.sharedWalletAddress : this.transfer.to,\n                assetName: tokenType,\n                amount: (tokenType === 'ONT' || tokenType === 'ONG') ? amount : this.transfer.amount,\n                gasLimit,\n                gasPrice,\n                transactionIdHash: txHash,\n                transactionBodyHash: txData,\n                coPayers: this.payers\n            }\n            axios.post(url, body).then(res => {\n                console.log(res)\n                if(res.status === 200) {\n                    if(res.data && res.data.Error && res.data.Error !== 0) {\n                        this.$message.error(this.$t('sharedWalletHome.createTransferFailed'))\n                        this.$store.dispatch('hideLoadingModals')\n                        return;\n                    }\n                    this.sending = false;\n                    this.$emit('inputPassNext')\n                    this.$message.success(this.$t('sharedWalletHome.createTransferSuccess'))\n                    // //save signed tx\n                    // const url2 = ONT_PASS_NODE + ONT_PASS_URL.SignSharedTransfer\n                    // const body2 = {\n                    //     transactionIdHash:txHash,\n                    //     signedAddress: this.sponsorWallet.address,\n                    //     signedHash: tx.serialize()\n                    // }\n                    // axios.post(url2, body2).then(res => {\n                    //     if(res.status === 200) {\n                    //         this.$emit('inputPassNext')\n                    //     }\n                    // })\n\n                }\n                this.$store.dispatch('hideLoadingModals')\n            }).catch(err => {\n                this.$store.dispatch('hideLoadingModals')\n                this.sending = false;\n                console.log(err);\n                this.$message.error(this.$t('common.networkErr'))\n            })\n\n\n\n            }\n        }\n    }\n}\n</script>\n\n\n"
  },
  {
    "path": "src/components/SharedWallet/Transfer/PendingConfirm.vue",
    "content": "<style scoped>\n.confirm-container {\n    height: 400px;\n    padding-bottom: 20px;\n    overflow:auto;\n}\n\n.label-container {\n    position: relative;\n}\n.label {\n    font-weight: bold;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size:1.25rem;\n    margin:0;\n}\n\n.asset-table {\n    padding: 5px 50px;\n}\n.asset-item {\n    border-bottom: 1px solid #dddddd;\n    padding:10px 20px;\n}\n.asset-item span {\n    width: 30%;\n    display: inline-block;\n    text-align: left;\n}\n.asset-item :nth-child(2) {\n    width:69%;\n    display: inline-block;\n    text-align: right\n}\n.select-sponsor {\n    margin-left: 20px;\n    width:80%;\n    margin-bottom:15px;\n}\n.circle {\n    display: inline-block;\n    text-align: center;\n    border-radius:50%;\n    width:1.5rem;\n    height:1.5rem;\n    line-height: 1.5rem;\n}\n\n.circle-signed {\n    background:#FBE45A;\n}\n.circle-unsigned {\n    background:#F5F7FB;\n}\n.confirm-btns {\n    position: fixed;\n    bottom: 0;\n    left: 4rem;\n    height:5.3rem;\n    width:calc(100% - 4rem);\n    z-index: 1000;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    background:#ffffff;\n}\n.fee {\n    padding-left: 20px;\n    padding-top:10px;\n    margin-bottom:50px;\n}\n.sponsor-item {\n    padding-left: 4rem;\n    margin-bottom:12px;\n}\n.sponsor-item :nth-child(2) {\n    margin-left: 14px;\n}\n.sponsor-item :nth-child(3) {\n    float: right;\n    margin-right: 14px;\n}\n.sponsor-label {\n    margin-bottom:20px;\n}\n.sponsor-label :last-child {\n    float: right;\n}\n\n.payer-item {\n    height: 20px;\n    margin-top: 20px;\n    padding-left: 4rem;\n}\n\n.payer-item :nth-child(2) {\n    margin-left: 14px;\n}\n.payer-item :nth-child(3) {\n    float: right;\n    margin-right: 14px;\n}\n.btns-container {\n    width:500px;\n    margin:20px auto;\n    text-align: center;\n}\n\n</style>\n\n<template>\n    <div class=\"confirm-container clearfix\">\n            <p class=\"label\" v-if=\"!isRedeem\">{{$t('sharedWalletHome.send')}}</p>\n            <p class=\"label\" v-if=\"isRedeem\">{{$t('sharedWalletHome.redeemOng')}}</p>\n\n        <div class=\"asset-table\">\n            <div class=\"asset-item\">\n                <span class=\"font-medium\">{{$t('sharedWalletHome.amount')}}</span>\n                <span class=\"font-medium-black\">{{pendingTx.amount}} {{pendingTx.assetName}}</span>\n\n            </div>\n            <div class=\"asset-item\">\n                <span class=\"font-medium\">{{$t('sharedWalletHome.recipient')}}</span>\n                <span class=\"font-medium-black\">{{pendingTx.receiveaddress}}</span>\n            </div>\n            <div class=\"fee font-medium-black\">{{$t('sharedWalletHome.fee')}}: {{gas}} ONG</div>\n        </div>\n\n        <div >\n            <div class=\"sponsor-label\">\n                <span class=\"label\">{{$t('sharedWalletHome.sponsor')}}</span>\n                <span class=\"label\">[{{sharedWallet.requiredNumber}} - OF - {{sharedWallet.totalNumber}} ]</span>\n            </div>\n            <div class=\"sponsor-item\">\n                <span class=\"circle font-medium-black\" :class=\"pendingTx.coPayerSignDtos[0] && pendingTx.coPayerSignDtos[0].isSign? 'circle-signed': 'circle-unsigned'\">1</span>\n                <span class=\"font-medium-black\">{{pendingTx.coPayerSignDtos[0] && pendingTx.coPayerSignDtos[0].name}}</span>\n                <span class=\"font-medium\">{{pendingTx.coPayerSignDtos[0] && pendingTx.coPayerSignDtos[0].address}}</span>\n            </div>\n\n            <p class=\"label\">{{$t('sharedWalletHome.signSequence')}}\n            </p>\n            <div class=\"drag-item\" v-for=\"(payer,index) in pendingTx.coPayerSignDtos\" :key=\"payer.address\">\n                <div class=\"payer-item\" v-if=\"index!==0\">\n                    <span class=\"circle font-medium-black\" :class=\"payer.isSign? 'circle-signed': 'circle-unsigned'\">{{index+1}}</span>\n                    <span class=\"font-medium-black\">{{payer.name}}</span>\n                    <span class=\"font-medium\">{{payer.address}}</span>\n                </div>\n            </div>\n        </div>\n\n\n\n        <div class=\"confirm-btns\" v-if=\"showSign\">\n            <div class=\"btns-container\">\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{$t('sharedWalletHome.sign')}}</a-button>\n            </div>\n\n        </div>\n    </div>\n</template>\n<script>\nimport {mapState} from 'vuex'\nimport dbService from '../../../core/dbService'\nimport { BigNumber } from 'bignumber.js';\nexport default {\n    name: 'PendingConfirm',\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        const payers = sharedWallet.coPayers\n        return {\n            sharedWallet,\n            payers,\n            sponsorPayer:'',\n            showSign:false\n        }\n    },\n\n    computed:{\n        ...mapState({\n            pendingTx: state => state.CurrentWallet.pendingTx,\n            isRedeem: state => state.CurrentWallet.transfer.isRedeem\n        }),\n        gas: {\n            get() {\n                const gasPrice = new BigNumber(this.$store.state.CurrentWallet.pendingTx.gasprice)\n                const gasLimit = new BigNumber(this.$store.state.CurrentWallet.pendingTx.gaslimit)\n                const gas = gasPrice.multipliedBy(gasLimit).div(1e9).toString();\n                return gas;\n            }\n        }\n    },\n    mounted() {\n        this.updateShowSign()\n    },\n    methods: {\n        updateShowSign() {\n            var that = this;\n                const nextSigner = this.pendingTx.coPayerSignDtos.find((e)=> e.isSign=== false)\n                if(!nextSigner) {\n                    return;\n                }\n                const localCopayers = []\n                dbService.find({type: {$in: ['CommonWallet', 'HardwareWallet']}}, function (err, accounts) {\n                    if (err) {\n                        console.log(err)\n                        return;\n                    }\n                    for (let ac of accounts) {\n                        if (nextSigner.address === ac.address) {\n                            that.$store.commit('UPDATE_CURRENT_SIGNER', {account: {...ac.wallet, type: ac.type}})\n                            that.showSign = true;\n                            return;\n                        }\n                    }\n                })\n        },\n        handleChangeSponsor(value) {\n            const payers = []\n            for(let p of this.sharedWallet.coPayers) {\n                if(p.address !== value) {\n                    payers.push(p)\n                } else {\n                    this.sponsorPayer = p\n                }\n            }\n            this.payers = payers;\n        },\n        cancel(){\n            this.$emit('cancelEvent')\n        },\n        back(){\n            this.$emit('sendConfirmBack')\n        },\n        next(){\n            this.$emit('signEvent')\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/Transfer/PendingTxSign.vue",
    "content": "<style scoped>\n.label {\n    font-weight: bold;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size:1.25rem;\n    margin:0;\n}\n\n.asset-table {\n    padding: 10px 20px;\n}\n.asset-item {\n    border-bottom: 1px solid #dddddd;\n    padding:10px 10px;\n}\n.asset-item span {\n    width: 30%;\n    display: inline-block;\n    text-align: center;\n}\n.asset-item :nth-child(2) {\n    width:69%;\n    display: inline-block;\n}\n.select-sponsor {\n    margin-left: 20px;\n    width:80%;\n    margin-bottom:15px;\n}\n.circle {\n    display: inline-block;\n    text-align: center;\n    border:1px solid #dddddd;\n    border-radius:50%;\n    width:20px;\n    height:20px;\n    line-height: 20px;\n}\n.input-btns :last-child {\n    float: right;\n}\n.input-content {\n    padding-left: 4rem;\n}\n.input-check {\n    margin-top:12px;\n    margin-bottom: 40px;\n}\n.input-pass {\n    margin-bottom:50px;\n}\n</style>\n<template>\n    <div class=\"clearfix\">\n        <p class=\"label\">{{$t('sharedWalletHome.confirmation')}}</p>\n        <div class=\"input-content\">\n            <div>\n                <a-checkbox @change=\"onChange\" :checked=\"checked\" class=\"input-check\">{{$t('sharedWalletHome.agreeToSend')}}</a-checkbox>\n\n                <div v-if=\"currentSigner.type === 'CommonWallet'\">\n                    <a-input type=\"password\" class=\"input-pass\" :placeholder=\"$t('sharedWalletHome.inputPassToTransfer')\" v-model=\"password\"></a-input>\n                </div>\n\n                <div class=\"ledger-status\" v-if=\"currentSigner.type === 'HardwareWallet'\">\n                    <div class=\"font-bold\" style=\"margin-bottom: 15px;\">{{$t('ledgerWallet.connectApp')}}</div>\n                    <span class=\"font-medium-black\">{{$t('ledgerWallet.status')}}: </span>\n                    <span class=\"font-medium\">{{ledgerStatus}} </span>\n                </div>\n            </div>\n        <div class=\"input-btns\">\n            <a-button type=\"danger\" class=\"btn-cancel\" @click=\"back\">{{$t('sharedWalletHome.back')}}</a-button>\n            <a-button type=\"primary\" class=\"btn-next\" @click=\"submit\"\n            :disabled=\"sending || !checked\n                || currentSigner.type === 'CommonWallet' && !password\n                || currentSigner.type === 'HardwareWallet' && !ledgerPk\">\n                {{$t('sharedWalletHome.submit')}}\n                </a-button>\n        </div>\n        </div>\n\n    </div>\n</template>\n\n<script>\nimport {mapState} from 'vuex'\nimport {OntAssetTxBuilder, Crypto, TransactionBuilder, Transaction, RestClient, utils, TxSignature} from 'ontology-ts-sdk'\nimport {ONT_PASS_NODE, ONT_PASS_NODE_PRD, ONT_PASS_URL, DEFAULT_SCRYPT, TEST_NET, MAIN_NET} from '../../../core/consts'\nimport axios from 'axios'\nimport dbService from '../../../core/dbService'\nimport {legacySignWithLedger, checkPublicKeyIsInTheConnectedLedger} from '../../../core/ontLedger'\nimport { getRestClient } from '../../../core/utils';\n\nexport default {\n    name:'PendingTxSign',\n    data() {\n        const net = localStorage.getItem('net');\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        return {\n            sharedWallet,\n            payers: [],\n            password:'',\n            checked: false,\n            sending:false\n        }\n    },\n    computed:{\n        ...mapState({\n            pendingTx: state => state.CurrentWallet.pendingTx,\n            currentSigner: state => state.CurrentWallet.currentSigner,\n            ledgerStatus: state => state.LedgerConnector.ledgerStatus,\n            ledgerPk : state => state.LedgerConnector.publicKey,\n        })\n    },\n    mounted() {\n        if(this.currentSigner.type === 'HardwareWallet') {\n            this.$store.dispatch('getLedgerStatus')\n        }\n    },\n    beforeDestroy(){\n        if(this.currentSigner.type === 'HardwareWallet') {\n            this.$store.dispatch('stopGetLedgerStatus')\n        }\n    },\n    methods:{\n        back(){\n            this.$emit('backEvent')\n        },\n        onChange(){\n            this.checked = !this.checked;\n        },\n        async submit() {\n            if(!this.sending) {\n                this.sending = true;\n                this.$store.dispatch('showLoadingModals')\n                //sign and decide to send\n                const tx = Transaction.deserialize(this.pendingTx.transactionbodyhash);\n                const txHash = this.pendingTx.transactionidhash;\n                const M = tx.sigs[0].M;\n                const pks = tx.sigs[0].pubKeys;\n                 if (this.currentSigner.type === 'CommonWallet') {\n                    const enc = new Crypto.PrivateKey(this.currentSigner.key)\n                    let pri;\n                    try {\n                        pri = enc.decrypt(this.password, new Crypto.Address(this.currentSigner.address), this.currentSigner.salt, DEFAULT_SCRYPT)\n                    }catch(err) {\n                        this.$store.dispatch('hideLoadingModals')\n                        this.sending = false;\n                        console.log(err);\n                        this.$message.error(this.$t('common.pwdErr'))\n                        return;\n                    }\n                    TransactionBuilder.signTx(tx, M, pks, pri)\n                } else {\n                    const txData = tx.serializeUnsignedData();\n                    let res;\n                    try {\n                        console.log('this.currentSigner',this.currentSigner);\n                        await checkPublicKeyIsInTheConnectedLedger(this.currentSigner.acct, this.currentSigner.neo, this.currentSigner.publicKey);\n                        res = await legacySignWithLedger(txData,this.currentSigner.neo, this.currentSigner.acct)\n                    } catch(err) {\n                        this.ledgerStatus = '';\n                        this.$store.dispatch('hideLoadingModals')\n                        alert(typeof err === 'string' ? err : err.message)\n                        return;\n                    }\n                    const sig = new TxSignature();\n                    sig.M = M;\n                    sig.pubKeys = pks;\n                    const sigVal = '01' + res;\n                    tx.sigs[0].sigData.push(sigVal);\n                }\n                //send\n                const net = localStorage.getItem('net')\n                const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD\n                const url = ontPassNode + ONT_PASS_URL.SignSharedTransfer\n\n                const body = {\n                    transactionIdHash:txHash,\n                    signedAddress: this.currentSigner.address,\n                    signedHash: tx.serialize()\n                }\n                const res = await axios.post(url, body)\n                    if(res.data && res.data.Error && res.data.Error !== 0) {\n                        this.$message.error(res.data.Desc)\n                        this.$store.dispatch('hideLoadingModals')\n                        this.sending = false;\n                        return;\n                    }\n\n                // await this.httpService({\n                //     method: 'post',\n                //     data: body,\n                //     url\n                // })\n                //decide to send to chain\n                const sigNum = tx.sigs[0].sigData.length;\n                if(M <= sigNum) {\n                    //send tx\n                    const that = this;\n                    const restClient = getRestClient();\n                    const res = await restClient.sendRawTransaction(tx.serialize())\n                        console.log(res)\n                        this.$store.dispatch('hideLoadingModals')\n                        if(res.Error === 0) {\n                            this.$message.success(that.$t('common.transSentSuccess'))\n                            this.$emit('submitEvent')\n                            const title = that.$t('common.transSentSuccess')\n                            setTimeout(() => {\n                                this.$success({\n                                    title: title,\n                                    content: 'Transaction hash: ' + utils.reverseHex(tx.getHash())\n                                })\n                            }, 100)\n                            return;\n                        } else if(res.Error === -1) {\n                            alert(res.Result)\n                            return;\n                        }\n\n\n                }\n                this.$store.dispatch('hideLoadingModals')\n                this.$emit('submitEvent')\n            }\n        }\n    }\n}\n</script>\n\n\n"
  },
  {
    "path": "src/components/SharedWallet/Transfer/SendAsset.vue",
    "content": "<style scoped>\n.label {\n    font-weight: bold;\n    position: relative;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size:1.25rem;\n    margin:0;\n}\n.select-asset {\n    width:calc(100% - 4rem);\n    margin-top:12px;\n    margin-bottom: 24px;\n    margin-left: 4rem;\n}\n.input-amount {\n    margin-bottom:24px;\n    padding-left: 4rem;\n}\n\n\n.fee-label {\n    height: 36px;\n    line-height: 36px;\n    margin:0;\n}\n.fee-select {\n    margin-bottom:50px;\n    padding-left: 4rem;\n}\n.recipient-input {\n    padding-left: 4rem;\n}\n.error-to {\n    border-color:red !important;\n}\n.error-amount :first-child {\n    border-color:red !important;\n}\n</style>\n<template>\n    <div class=\" clearfix\">\n        <p class=\"label\">{{$t('sharedWalletHome.send')}}</p>\n        <a-select v-model=\"scriptHash\" @change=\"changeAsset\" class=\"select-asset\">\n                <a-select-option value=\"ONT\">ONT</a-select-option>\n                <a-select-option value=\"ONG\">ONG</a-select-option>\n                <a-select-option v-for=\"(oep4) of oep4s\" :key=\"oep4.contract_hash\" :value=\"oep4.contract_hash\">\n                    {{oep4.symbol}}\n                </a-select-option>\n        </a-select>\n        <a-input-search :placeholder=\"$t('sharedWalletHome.amount')\" class=\"input-amount\"\n        @change=\"validateAmount\" :class=\"validAmount? '': 'error-amount'\"\n        @search=\"maxAmount\" :enterButton=\"$t('sharedWalletHome.max')\" v-model=\"amount\" type=\"number\"/>\n\n        <a-row class=\"fee-select\">\n            <a-col :span=\"2\">\n                <label class=\"fee-label font-medium\">Fee:</label>\n            </a-col>\n            <a-col :span=\"16\">\n                <a-slider :min=\"0.01\" :max=\"0.02\" v-model=\"gas\" :step=\"0.001\" />\n            </a-col>\n            <a-col :span=\"6\">\n                <a-input-number\n                    :min=\"0.01\"\n                    :max=\"0.02\"\n                    :step=\"0.001\"\n                    v-model=\"gas\"\n                    style=\"width:60px;margin-right:10px;margin-left:10px;\"\n                />\n                <label class=\"font-medium\">ONG</label>\n            </a-col>\n      </a-row>\n\n      <p class=\"label\">{{$t('sharedWalletHome.to')}}</p>\n      <div class=\"recipient-input\">\n        <a-input v-model=\"to\" class=\"input\" :class=\"validToAddress? '': 'error-to' \"\n        :placeholder=\"$t('sharedWalletHome.recipient')\" @change=\"validateToAddress\"></a-input>\n      </div>\n\n      <div class=\"footer-btns\">\n          <div class=\"footer-btn-container\">\n            <a-button type=\"default\"  class=\"btn-cancel\" @click=\"cancel\">{{$t('sharedWalletHome.cancel')}}</a-button>\n            <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{$t('sharedWalletHome.next')}}</a-button>\n          </div>\n\n      </div>\n    </div>\n</template>\n\n<script>\nimport {varifyPositiveInt, varifyOngValue, varifyOpe4Value, validateAddress} from '../../../core/utils.js'\nimport {mapState} from 'vuex'\nimport { BigNumber } from 'bignumber.js';\n\nexport default {\n    name: 'SendAsset',\n    data(){\n        const net = localStorage.getItem('net')\n        // const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'));\n        return {\n            // address: currentWallet.address,\n            gas: 0.01,\n            asset:'ONT',\n            scriptHash: 'ONT',\n            decimal: 0,\n            amount: 0,\n            to:'',\n            validToAddress: true,\n            validAmount: true,\n            net,\n            selectedOep4: {}\n        }\n    },\n    computed: {\n        ...mapState({\n            balance: state => state.CurrentWallet.balance,\n            address: state => state.CurrentWallet.wallet.address,\n            oep4s: state => state.Tokens.oep4WithBalances\n        }),\n        // oep4s() {\n        //     return this.$store.state.Oep4s.oep4s.filter(item => item.net === this.net)\n        // }\n    },\n    mounted() {\n        // this.$store.dispatch('queryBalanceForOep4', this.address)\n        const transfer = this.$store.state.CurrentWallet.transfer\n        this.gas = transfer.gas;\n        this.asset = transfer.asset;\n        this.amount = transfer.amount;\n        this.to = transfer.to;\n    },\n\n    methods: {\n        validateToAddress() {\n            if(!this.to || !validateAddress(this.to)) {\n                this.validToAddress = false;\n                return;\n            }\n            this.validToAddress = true;\n        },\n        validateAmount() {\n            if(this.asset === 'ONT' && !varifyPositiveInt(this.amount)) {\n                this.validAmount = false;\n                return;\n            } else if(this.asset === 'ONG' && !varifyOngValue(this.amount)) {\n                this.validAmount = false;\n                return;\n            } else if (this.asset !== 'ONT' && this.asset !== 'ONG' && !varifyOpe4Value(this.amount, this.decimal)) {\n                this.validAmount = false;\n                return;\n            }\n            if(this.asset === 'ONT' && Number(this.amount) > Number(this.balance.ont)\n             || this.asset === 'ONG' && Number(this.amount) > Number(this.balance.ong)\n             || this.asset !== 'ONT' && this.asset !== 'ONG' && new BigNumber(this.amount).isGreaterThan(this.selectedOep4.balance)) {\n                 this.validAmount = false;\n                 this.$message.error(this.$t('transfer.exceedBalance'))\n                 return;\n             }\n\n            if (this.asset === \"ONG\" && new BigNumber(this.amount).plus(this.gas).isGreaterThan(this.balance.ong)) {\n                this.$message.error(this.$t('transfer.exceedBalance'))\n                this.validAmount = false;\n                return;\n            }\n            this.validAmount = true;\n        },\n        changeAsset(value) {\n            this.amount = '0';\n            if(value !== 'ONT' && value !=='ONG'){\n                for(let i=0; i<this.oep4s.length; i++){\n                    if(this.oep4s[i].contract_hash === value) {\n                        this.scriptHash = this.oep4s[i].contract_hash\n                        this.decimal = this.oep4s[i].decimal\n                        this.selectedOep4 = this.oep4s[i]\n                        this.asset = this.oep4s[i].symbol\n                        break;\n                    }\n                }\n            } else {\n                this.asset = value;\n            }\n\n            console.log(value)\n        },\n        maxAmount() {\n            if(this.asset === 'ONT') {\n                this.amount = this.balance.ont;\n            } else if(this.asset === 'ONG'){\n                this.amount = (new BigNumber(this.balance.ong).minus(this.gas)).toString();\n            } else {\n                for(let i=0; i<this.oep4s.length; i++){\n                    if(this.oep4s[i].symbol === this.asset) {\n                        this.amount = this.oep4s[i].balance\n                        break;\n                    }\n                }\n            }\n            this.validateAmount();\n        },\n        cancel() {\n            this.$store.commit('CLEAR_CURRENT_TRANSFER')\n            this.$emit('cancelEvent');\n        },\n        next() {\n            if(!this.amount || Number(this.amount) === 0 ||!this.validAmount) {\n                this.$message.error(this.$t('transfer.inputValidAmount'))\n                return;\n            }\n            if(!this.to || !this.validToAddress) {\n                this.$message.error(this.$t('transfer.inputValidAddress'))\n                return;\n            }\n            if(this.asset === 'ONG' && new BigNumber(this.amount).plus(this.gas).isGreaterThan(this.balance.ong) ) {\n                this.$message.error(this.$t('transfer.ongBalanceNotEnough'))\n                return;\n            }\n            if(this.amount && this.to) {\n                const transfer = {\n                    amount: this.amount,\n                    to: this.to,\n                    gas: this.gas,\n                    asset: this.asset,\n                    scriptHash: this.scriptHash,\n                    decimal: this.decimal\n                }\n                this.$store.commit('UPDATE_TRANSFER', {transfer})\n                this.$emit('sendAssetNext')\n            }\n        },\n    }\n}\n</script>\n\n\n"
  },
  {
    "path": "src/components/SharedWallet/Transfer/SendConfirm.vue",
    "content": "<style scoped>\n.confirm-container {\n\n}\n.drag-item {\n    cursor: pointer;\n}\n.label-container {\n    position: relative;\n}\n.label {\n    font-weight: bold;\n    font-family: 'AvenirNext-Bold';\n    color: #5E6369;\n    font-size:1.25rem;\n    margin:0;\n}\n\n.asset-table {\n    padding: 5px 50px;\n}\n.asset-item {\n    border-bottom: 1px solid #dddddd;\n    padding:10px 20px;\n}\n.asset-item span {\n    width: 30%;\n    display: inline-block;\n    text-align: left;\n}\n.asset-item :nth-child(2) {\n    width:69%;\n    display: inline-block;\n    text-align: right\n}\n.select-sponsor {\n    margin-left: 20px;\n    width:80%;\n    margin-bottom:15px;\n}\n.circle {\n    display: inline-block;\n    text-align: center;\n    border:1px solid #dddddd;\n    border-radius:50%;\n    width:1.5rem;\n    height:1.5rem;\n    line-height: 1.5rem;\n    background:#FBE45A;\n}\n.confirm-btns {\n    position: fixed;\n    bottom: 0;\n    left: 4rem;\n    height:5.3rem;\n    width:calc(100% - 4rem);\n    z-index: 1000;\n    box-shadow: 0 -1px 6px 0 #F2F2F2;\n    background:#ffffff;\n}\n.fee {\n    padding-left: 20px;\n    padding-top:10px;\n    margin-bottom:50px;\n    text-align: left !important;\n}\n.sponsor-select {\n    padding-left: 4rem;\n}\n.sponsor-label {\n    margin-bottom:20px;\n}\n.sponsor-label :last-child {\n    float: right;\n}\n.drag-container {\n    margin-top: 20px;\n    padding-left: 4rem;\n}\n.payer-item {\n    height: 30px;\n}\n.payer-item:hover {\n    background: #F5F7FB;\n}\n.payer-item:hover span {\n    color: #196BD8 !important;\n}\n.payer-item :nth-child(2) {\n    margin-left: 14px;\n}\n.payer-item :nth-child(3) {\n    float: right;\n    margin-right: 14px;\n}\n.btns-container {\n    width:500px;\n    margin:20px auto;\n}\n.btns-container :last-child {\n    float: right;\n}\n</style>\n\n<template>\n    <div class=\"confirm-container clearfix\">\n        <p class=\"label\" v-if=\"transfer.isRedeem\">{{$t('sharedWalletHome.redeemOng')}}</p>\n        <div class=\"asset-table\" v-if=\"transfer.isRedeem\">\n            <div class=\"asset-item\">\n                <span class=\"font-medium\">{{$t('sharedWalletHome.amount')}}</span>\n                <span class=\"font-medium-black\">{{redeem.claimableOng}} ONG</span>\n\n            </div>\n            <div class=\"fee font-medium-black\">{{$t('sharedWalletHome.fee')}}: 0.01 ONG</div>\n        </div>\n\n        <p class=\"label\" v-if=\"!transfer.isRedeem\">{{$t('sharedWalletHome.send')}}</p>\n        <div class=\"asset-table\" v-if=\"!transfer.isRedeem\">\n            <div class=\"asset-item\">\n                <span class=\"font-medium\">{{$t('sharedWalletHome.amount')}}</span>\n                <span class=\"font-medium-black\">{{transfer.amount}} {{transfer.asset}}</span>\n\n            </div>\n            <div class=\"asset-item\">\n                <span class=\"font-medium\">{{$t('sharedWalletHome.recipient')}}</span>\n                <span class=\"font-medium-black\">{{transfer.to}}</span>\n            </div>\n            <div class=\"fee font-medium-black\">{{$t('sharedWalletHome.fee')}}: {{transfer.gas}} ONG</div>\n        </div>\n\n        <div >\n            <div class=\"sponsor-label\">\n                <span class=\"label\">{{$t('sharedWalletHome.sponsor')}}</span>\n                <span class=\"label\">[{{sharedWallet.requiredNumber}} - OF - {{sharedWallet.totalNumber}} ]</span>\n            </div>\n            <div class=\"sponsor-select\">\n                <span class=\"circle font-medium-black\">1</span>\n                <a-select :options=\"localCopayers\" class=\"select-sponsor\"  @change=\"handleChangeSponsor\"></a-select>\n            </div>\n\n            <p class=\"label\">{{$t('sharedWalletHome.dragDecide')}}\n            </p>\n            <draggable v-model=\"payers\" @start=\"drag=true\" @end=\"drag=false\" class=\"drag-container\">\n                <div class=\"drag-item\" v-for=\"(payer,index) in payers\" :key=\"payer.address\">\n                    <div class=\"payer-item\">\n                        <span class=\"circle font-medium-black\">{{index+2}}</span>\n                        <span class=\"font-medium-black\">{{payer.name}}</span>\n                        <span class=\"font-medium\">{{payer.address}}</span>\n                    </div>\n                </div>\n            </draggable>\n        </div>\n\n\n\n        <div class=\"confirm-btns\">\n            <div class=\"btns-container\">\n                <a-button type=\"default\" class=\"btn-cancel\" @click=\"back\">{{$t('sharedWalletHome.back')}}</a-button>\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"next\">{{$t('sharedWalletHome.next')}}</a-button>\n            </div>\n\n        </div>\n    </div>\n</template>\n<script>\nimport draggable from 'vuedraggable'\nimport {mapState} from 'vuex'\nimport dbService from '../../../core/dbService'\nexport default {\n    name: 'SendConfirm',\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        const payers = sharedWallet.coPayers\n        return {\n            sharedWallet,\n            payers,\n            sponsorPayer:''\n        }\n    },\n    mounted(){\n        this.updateLocalCopayers()\n    },\n    components:{\n        draggable\n    },\n    computed:{\n        ...mapState({\n            transfer: state => state.CurrentWallet.transfer,\n            redeem: state => state.CurrentWallet.redeem\n        }),\n        localCopayers : {\n            get() {\n                const copayers = [...this.$store.state.CurrentWallet.localCopayers]\n                return copayers.map(c => Object.assign({}, c, {value: c.address, label: c.name}))\n            }\n        }\n    },\n    methods: {\n        updateLocalCopayers() {\n            var that = this;\n                const coPayers = this.sharedWallet.coPayers;\n                const localCopayers = []\n                dbService.find({type: {$in:['CommonWallet', 'HardwareWallet']}}, function (err, accounts) {\n                    debugger\n                    if (err) {\n                        console.log(err)\n                        return;\n                    }\n                    for (let cp of coPayers) {\n                        for (let ac of accounts) {\n                            if (cp.address === ac.address) {\n                                localCopayers.push(Object.assign({}, cp, {value:ac.address, label:ac.wallet.label, type: ac.type, wallet: ac.wallet}))\n                            }\n                        }\n                    }\n                    if (localCopayers.length > 0) {\n                        that.$store.commit('UPDATE_LOCAL_COPAYERS', {localCopayers})\n                    }\n                })\n        },\n        handleChangeSponsor(value,option) {\n            const payers = []\n            for(let p of this.sharedWallet.coPayers) {\n                if(p.address !== value) {\n                    payers.push(p)\n                } else {\n                    this.sponsorPayer = this.localCopayers.find(item=> item.address === value)\n                }\n            }\n            this.payers = payers;\n        },\n        cancel(){\n            this.$emit('cancelEvent')\n        },\n        back(){\n            this.$emit('sendConfirmBack')\n        },\n        next(){\n            if(this.sponsorPayer) {\n                const coPayers = [];\n                coPayers.push(this.sponsorPayer);\n                coPayers.push(...this.payers);\n                const transfer = { coPayers };\n                this.$store.commit('UPDATE_TRANSFER', { transfer })\n                this.$emit('sendConfirmNext')\n            }\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/Tx/SharedTxMgmt.vue",
    "content": "<style scoped>\n.pax-container {\n    text-align: center;\n    position: relative;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :routes=\"routes\" :current=\"$t('sharedWalletHome.txMgmt')\" @backEvent=\"handleBack\"></breadcrumb>\n        <div class=\"pax-container\">\n            <div class=\"pax-header\">\n\n                <a-radio-group :value=\"status\" @change=\"handleStatusChange\" class=\"status-group\">\n                    <a-radio-button value=\"0\">{{$t('sharedTx.startTx')}}</a-radio-button>\n                    <a-radio-button value=\"1\">{{$t('sharedTx.signTx')}}</a-radio-button>\n                </a-radio-group>\n\n            </div>\n            <div class=\"tx-content\">\n                <start-shared-tx v-if=\"status === '0'\" :localSigners=\"localCopayers\" :sharedWallet=\"sharedWallet\"></start-shared-tx>\n                <sign-shared-tx v-if=\"status === '1'\" :localSigners=\"localCopayers\" :sharedWallet=\"sharedWallet\"></sign-shared-tx>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nimport StartSharedTx from './StartSharedTx'\nimport SignSharedTx from './SignSharedTx'\nimport dbService from '../../../core/dbService'\n\nexport default {\n    name: 'SharedTxMgmt',\n    components: {\n        Breadcrumb,\n        StartSharedTx,\n        SignSharedTx\n    },\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'));\n        const routes = [\n            {name: sharedWallet.sharedWalletName, path:'/sharedWallet/home'}\n        ]\n        return {\n            routes,\n            status: '0',\n            localCopayers: [],\n            sharedWallet\n        }\n    },\n    mounted() {\n        this.updateLocalCopayers()\n    },\n    methods: {\n        handleStatusChange(e) {\n           this.status = e.target.value\n        },\n        handleBack() {\n            this.$router.push({path: '/Wallets'});\n        },\n        updateLocalCopayers() {\n            var that = this;\n                const coPayers = this.sharedWallet.coPayers;\n                const localCopayers = []\n                dbService.find({type: {$in:['CommonWallet', 'HardwareWallet']}}, function (err, accounts) {\n                    if (err) {\n                        console.log(err)\n                        return;\n                    }\n                    for (let cp of coPayers) {\n                        for (let ac of accounts) {\n                            if (cp.address === ac.address) {\n                                localCopayers.push(Object.assign({}, cp, {value:ac.address, label:ac.wallet.label, type: ac.type, wallet: ac.wallet}))\n                            }\n                        }\n                    }\n                    if (localCopayers.length > 0) {\n                        that.localCopayers = localCopayers;\n                    }\n                })\n        },\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/Tx/SignSharedTx.vue",
    "content": "<style scoped>\n.tx-container {\n    padding:20px 60px;\n    text-align: left;\n}\n.tx-title {\n    font-size: 18px;\n    font-weight: 500;\n}\n.tx-content {\n    margin:0 30px;\n}\n.input-item {\n    display: flex;\n    margin-bottom:15px;\n}\n.input-item input, textarea {\n    flex:1;\n}\n.input-itme textarea {\n    height:130px;\n}\n.label {\n    width:200px;\n    margin-right:10px;\n}\n.select-sponsor {\n    flex:1;\n}\n.btns-container {\n    margin: 30px auto;\n    text-align: center;\n}\n</style>\n<template>\n    <div class=\"tx-container\">\n        <p class=\"tx-title\">{{$t('sharedTx.addSign')}}</p>\n        <div class=\"tx-content\">\n             <div class=\"input-item\">\n                 <p class=\"label\">{{$t('sharedTx.txContent')}}</p>\n                 <a-textarea v-model=\"txbody\"></a-textarea>\n            </div>\n        </div>\n        <p class=\"tx-title\">{{$t('sharedTx.currentSign')}}</p>\n        <div class=\"tx-content\">\n            <div class=\"input-item\">\n                <span class=\"label\">{{$t('sharedTx.selectSigner')}}</span>\n                <a-select :options=\"localSigners\" class=\"select-sponsor\"  @change=\"handleChangeSigner\"></a-select>\n            </div>\n\n            <common-sign-shared\n                ref=\"commonSign\"\n                :wallet=\"signer\"\n                @sharedTxSigned=\"handleTxSigned\">\n            </common-sign-shared>\n        </div>\n\n        <div class=\"btns-container\">\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"confirm\">\n                {{$t('pax.confirm')}}</a-button>\n            </div>\n\n        <a-modal\n            :title=\"$t('sharedTx.addSign')\"\n            :visible=\"visible\"\n            @cancel=\"handleCopy\"\n            >\n            <template slot=\"footer\">\n                <a-button type=\"default\"  @click=\"handleCopy\">\n                {{$t('sharedTx.copy')}}\n                </a-button>\n                <a-button  type=\"primary\" key=\"submit\" :loading=\"loading\" @click=\"handleSend\" v-if=\"canSendTx\">\n                {{$t('sharedTx.send')}}\n                </a-button>\n            </template>\n            <p>{{$t('sharedTx.txSerialized')}} </p>\n            <p>{{serializedTx}}</p>\n            <p v-if=\"canSendTx\">{{$t('sharedTx.isSendTxTip')}}</p>\n        </a-modal>\n    </div>\n</template>\n<script>\nimport {getNodeUrl, getRestClient} from '../../../core/utils'\nimport {Transaction, Crypto, TransactionBuilder, TxSignature, utils, RestClient} from 'ontology-ts-sdk'\nimport CommonSignShared from '../../Common/CommonSignShared'\n\nexport default {\n    name: 'SignSharedTx',\n    props: ['localSigners', 'sharedWallet'],\n    data() {\n        return {\n            txbody: '',\n            signer: '',\n            canSendTx: false,\n            loading: false,\n            visible: false,\n            serializedTx: ''\n        }\n    },\n    components: {\n        CommonSignShared\n    },\n    methods: {\n        handleChangeSigner(value) {\n            for(let p of this.sharedWallet.coPayers) {\n                if(p.address !== value) {\n                } else {\n                    this.signer = this.localSigners.find(item=> item.address === value)\n                }\n            }\n        },\n        varifyForm() {\n            if(!this.txbody || !this.signer) {\n                return false;\n            } else {\n                return true;\n            }\n        },\n        confirm() {\n            const isFirstSign = false;\n            this.txbody = this.txbody.trim();\n            if(this.varifyForm()) {\n                this.$refs.commonSign.signSharedTx(isFirstSign, this.txbody);\n            } else {\n                this.$message.error(this.$t('sharedTx.paramsError'))\n            }\n        },\n         handleTxSigned(tx) {\n            const M = this.sharedWallet.requiredNumber;\n            const txBefore = Transaction.deserialize(tx)\n            const sigNumBefore = txBefore.sigs[0].sigData.length;\n            if(sigNumBefore >= M) {\n                this.canSendTx = true;\n            }\n            this.serializedTx = tx;\n            this.visible = true;\n        },\n        handleCopy() {\n            this.$copyText(this.serializedTx);\n            this.$message.success(this.$t('common.copied'))\n            this.clearData()\n        },\n        clearData() {\n            this.txbody = '';\n            this.serializedTx = '';\n            this.visible = false;\n        },\n\n        async handleSend() {\n             //send tx\n            const restClient = getRestClient();\n            this.$store.dispatch('showLoadingModals')\n            try {\n                const res = await restClient.sendRawTransaction(this.serializedTx)\n                console.log(res)\n                if(res.Error === 0) {\n                    this.$store.dispatch('hideLoadingModals')\n                    this.$message.success(this.$t('sharedTx.txSentSuccess'), 3)\n                    this.clearData();\n                    const title = this.$t('common.transSentSuccess')\n                    setTimeout(() => {\n                        this.$success({\n                            title: title,\n                            content: 'Transaction hash: ' + res.Result\n                        })\n                    }, 100)\n                    return res.Result;\n                } else {\n                    if(res.Result.indexOf('balance insufficient') > -1 ) {\n                        this.$message.error(this.$t('common.balanceInsufficient'), 5)\n                    } else if(res.Result.indexOf('cover gas cost') > -1){\n                        this.$message.error(this.$t('common.ongNoEnough'), 5)\n                    } else {\n                        this.$message.error(res.Result, 5)\n                    }\n                    this.$store.dispatch('hideLoadingModals')\n                    return '';\n                }\n            }catch(err) {\n                console.log(err)\n                this.$message.success(this.$t('commonWalletHome.networkError'))\n                return '';\n            }\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/Tx/StartSharedTx.vue",
    "content": "<style scoped>\n.tx-container {\n    padding:20px 60px;\n    text-align: left;\n}\n.tx-title {\n    font-size: 18px;\n    font-weight: 500;\n}\n.tx-content {\n    margin:0 30px;\n}\n.input-item {\n    display: flex;\n    margin-bottom:15px;\n}\n.input-item input, textarea {\n    flex:1;\n}\n.input-itme textarea {\n    height:130px;\n}\n.label {\n    width:200px;\n    margin-right:10px;\n}\n.select-sponsor {\n    flex:1;\n}\n.btns-container {\n    margin: 30px auto;\n    text-align: center;\n}\n</style>\n<template>\n    <div class=\"tx-container\">\n        <p class=\"tx-title\">{{$t('sharedTx.createTx')}}</p>\n        <div class=\"tx-content\">\n             <div class=\"input-item\">\n                 <p class=\"label\">{{$t('sharedTx.contractHash')}}</p>\n                 <a-input v-model=\"contractHash\"></a-input>\n            </div>\n            <div class=\"input-item\">\n                 <p class=\"label\">{{$t('sharedTx.method')}}</p>\n                 <a-input v-model=\"method\"></a-input>\n            </div>\n            <div class=\"input-item\">\n                 <p class=\"label\">{{$t('sharedTx.parameters')}}</p>\n                 <a-textarea row=\"3\" v-model=\"parameters\"></a-textarea>\n            </div>\n        </div>\n        <p class=\"tx-title\">{{$t('sharedTx.starterSign')}}</p>\n        <div class=\"tx-content\">\n            <div class=\"input-item\">\n                <span class=\"label\">{{$t('sharedTx.selectSponsor')}}</span>\n                <a-select :options=\"localSigners\" class=\"select-sponsor\"  @change=\"handleChangeSponsor\"></a-select>\n            </div>\n\n            <common-sign-shared\n                ref=\"commonSign\"\n                :tx=\"tx\"\n                :wallet=\"sponsorPayer\"\n                @sharedTxSigned=\"handleTxSigned\">\n            </common-sign-shared>\n        </div>\n\n        <div class=\"btns-container\">\n                <a-button type=\"primary\" class=\"btn-next\" @click=\"confirm\">\n                {{$t('pax.confirm')}}</a-button>\n            </div>\n\n        <a-modal\n            :title=\"$t('sharedTx.startTx')\"\n            :visible=\"visible\"\n            @cancel=\"handleOk\"\n            >\n            <template slot=\"footer\">\n                <a-button type=\"primary\"  @click=\"handleOk\">\n                {{$t('sharedTx.copy')}}\n                </a-button>\n            </template>\n            <p>{{$t('sharedTx.txSerialized')}} </p>\n            <p>{{serializedTx}}</p>\n        </a-modal>\n    </div>\n</template>\n<script>\nimport CommonSignShared from '../../Common/CommonSignShared'\nimport {utils, TransactionBuilder, Crypto, Parameter, ParameterType} from 'ontology-ts-sdk'\nimport {GAS_LIMIT, GAS_PRICE} from '../../../core/consts'\nexport default {\n    name: 'StartSharedTx',\n    props: ['sharedWallet','localSigners'],\n\n    components: {\n        CommonSignShared\n    },\n    data() {\n        return {\n            tx: '',\n            sponsorPayer: '',\n            visible: false,\n            serializedTx: '',\n            contractHash: '',\n            method: '',\n            parameters: ''\n        }\n    },\n    methods: {\n        handleChangeSponsor(value,option) {\n            const payers = []\n            for(let p of this.sharedWallet.coPayers) {\n                if(p.address !== value) {\n                    payers.push(p)\n                } else {\n                    this.sponsorPayer = this.localSigners.find(item=> item.address === value)\n                }\n            }\n        },\n        varifyForm() {\n            this.contractHash = this.contractHash.trim();\n            this.method = this.method.trim();\n            if(!this.contractHash || !this.method) {\n                return false;\n            }\n            if(this.parameters) {\n                try {\n                    const params = JSON.parse(this.parameters)\n                    if(!Array.isArray(params)) {\n                        return false;\n                    }\n                } catch(err) {\n                    return false;\n                }\n            }\n            return true;\n        },\n        convertParams() {\n            if(!this.parameters) {\n                return [];\n            }\n            const params = JSON.parse(this.parameters);\n            try {\n                return params.map(item => {\n                    if(item.type === 'Address') {\n                        item.value = new Crypto.Address(item.value.trim()).serialize();\n                    }\n                    return new Parameter('', item.type, item.value);\n                })\n            } catch (err) {\n                this.$message.error(this.$t('sharedTx.paramsError'))\n                return null\n            }\n\n        },\n        confirm() {\n            const isFirstSign = true;\n            if(this.varifyForm()) {\n                const contractAddr = new Crypto.Address(utils.reverseHex(this.contractHash))\n                const params = this.convertParams();\n                if(!params) {\n                    return;\n                }\n                const payer = new Crypto.Address(this.sharedWallet.sharedWalletAddress)\n                const tx = TransactionBuilder.makeInvokeTransaction(this.method, params, contractAddr, GAS_PRICE, GAS_LIMIT, payer);\n                this.tx = tx.serialize();\n                this.$refs.commonSign.signSharedTx(isFirstSign, this.tx);\n            } else {\n                this.$message.error(this.$t('sharedTx.paramsError'))\n            }\n        },\n        handleTxSigned(tx) {\n            this.serializedTx = tx;\n            this.visible = true;\n        },\n        handleOk() {\n            this.$copyText(this.serializedTx);\n            this.$message.success(this.$t('common.copied'))\n            this.clearData()\n        },\n        clearData() {\n            this.tx = '';\n            this.serializedTx = '';\n            this.visible = false;\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/SharedWallet/View/Details.vue",
    "content": "<template>\n  <div>\n    <div @click=\"toSharedWalletHome(wallet)\">\n      <div class=\"div-shared-wallet-sign\">{{ $t('common.sharedWallet') }}</div>\n      <div class=\"div-wallet-name\" >{{wallet.sharedWalletName}}</div>\n      <!--<img class=\"img-wallet-edit\" src=\"./../assets/edit.png\" alt=\"\">-->\n      <div class=\"div-wallet-address\">\n        <div>Wallet Address:</div>\n        {{wallet.sharedWalletAddress}}\n      </div>\n    </div>\n    <div v-show=\"addressCopied\" class=\"copied-label\">Copied</div>\n    <img class=\"img-wallet-copy\" src=\"../../../assets/copy.png\" @click=\"copyAddress(wallet)\" alt=\"\">\n    <div class=\"common-topRight-btns\">\n      <span class=\"common-delete-icon\" @click=\"deleteWallet()\" ></span>\n    </div>\n\n    <a-modal\n        :title=\"$t('common.confirmation')\"\n        :visible=\"showModal\"\n        @ok=\"handleDelete\"\n        @cancel=\"handleCancel\">\n          <div>\n              <p class=\"font-medium\">\n                {{$t('wallets.deleteingWallet') }}\n                 {{wallet.sharedWalletAddress}}</p>\n          </div>\n    </a-modal>\n  </div>\n</template>\n\n<script>\nimport dbService from '../../../core/dbService'\n\texport default {\n\t\tname: \"SharedWalletDetails\",\n    props: ['wallet'],\n    data() {\n      return {\n        addressCopied: false,\n        showModal : false\n      }\n    },\n    methods: {\n      toSharedWalletHome(wallet) {\n        sessionStorage.setItem('sharedWallet', JSON.stringify(wallet))\n        this.$router.push({path: '/sharedWallet/home'})\n      },\n      copyAddress(wallet) {\n        this.$copyText(wallet.sharedWalletAddress)\n        this.addressCopied = true\n        this.$nextTick(function () {\n          setInterval(this.addressCopiedDisabled, 3000);\n        })\n      },\n      addressCopiedDisabled() {\n        this.addressCopied = false\n      },\n      deleteWallet() {\n        this.showModal = true;\n      },\n      handleDelete() {\n        // remove from db\n        this.$store.dispatch('showLoadingModals')\n        const that = this;\n        dbService.remove({type:'SharedWallet', address: this.wallet.sharedWalletAddress}, {}, function(err, numRemoved) {\n          if(err) {\n            that.$store.dispatch('hideLoadingModals')\n            that.$message.error(that.$t('wallets.deleteFailed'));\n            return;\n          }\n           // remove from store\n          that.$store.commit('DELETE_SHARED_WALLET', {address: that.wallet.sharedWalletAddress})\n          that.$store.dispatch('hideLoadingModals')\n          that.$message.success(that.$t('wallets.deleteSucceess'))\n          that.showModal = false;\n        })\n      },\n      handleCancel() {\n        this.showModal = false;\n      }\n    }\n\t}\n</script>\n\n<style scoped>\n  .div-shared-wallet-sign {\n    margin-top: 0.88rem;\n    font-family: AvenirNext-Medium;\n    font-size: 14px;\n    color: #196BD8;\n    cursor: default;\n  }\n\n  .div-wallet-name {\n    margin-top: 1.75rem;\n    font-family: AvenirNext-Medium;\n    font-size: 18px;\n    color: #515457;\n    line-height: 24px;\n    word-wrap: break-word;\n    height:6rem;\n    cursor: pointer;\n  }\n\n  .img-wallet-edit {\n    position: absolute;\n    top: 4.13rem;\n    right: 1.41rem;\n  }\n\n  .div-wallet-address {\n    font-family: AvenirNext-Regular;\n    font-size: 14px;\n    color: #B2B2B3;\n    position:absolute;\n    bottom:10px;\n    cursor: default;\n  }\n\n  .img-wallet-copy {\n    position: absolute;\n    bottom:15px;\n    right: 1.29rem;\n  }\n\n  .copied-label {\n    position: absolute;\n    top: 9.56rem;\n    right: 2.69rem;\n    background-color: #8a9098;\n    border-radius: 2px;\n    padding: 3px 4px;\n    font-size: 10px;\n    font-weight: 100;\n    color: white;\n  }\n  .common-topRight-btns {\n    position: absolute;\n    top: 10px;\n    right: 1.29rem;\n  }\n  .common-delete-icon {\n    width:24px;\n    height: 24px;\n    display: inline-block;\n    cursor: pointer;\n    background:url('../../../assets/delete.png') center center;\n    background-repeat:no-repeat;\n  }\n\n</style>\n"
  },
  {
    "path": "src/components/SharedWallet/View/SharedWalletCopayer.vue",
    "content": "<style scoped>\n.wallet-info {\n    margin-bottom: 20px;\n}\n.wallet-info-item label {\n    font-weight: bold;\n}\n\n.choose-local-wallet {\n    margin-bottom:15px;\n}\n.choose-local-wallet label {\n    font-weight: bold;  \n}\n.input-select {\n    width:100%;\n}\n\n.local-wallet-info {\n    padding: 10px;\n    background:#52a2bb;\n    color: #ffffff;\n    margin-bottom:20px;\n}\n\n.input-btns {\n    position: absolute;\n    right: 100px;\n    bottom:100px;\n}\n\n.input-btns button {\n    margin-left:30px;\n}\n.label {\n    font-family: 'PingFangSC-Semibold';\n    font-size: 20px;\n    color: #5E6369;\n    margin-left: 172px;\n}\n.wallet-address {\n    margin-bottom: 40px;\n    margin-top: 14px;\n}\n.wallet-num {\n    width:540px;\n    margin:0 auto;\n    margin-bottom:30px;\n    padding-left: 38px;\n}\n.wallet-num-item {\n    padding:6px 3px;\n    border-bottom: 1px solid #DFE2E9;\n}\n\n.wallet-num-item :last-child {\n float: right;\n}\n.confirm-pk-box {\n    width:540px;\n    margin:20px auto;\n    margin-bottom:40px;\n}\n.confirm-pk-item {\n    margin-bottom:20px;\n}\n.confirm-requireNum {\n    width:540px;\n    margin:12px auto;\n}\n\n.confirm-select {\n    width:100%;\n}\n\n.circle {\n    display: inline-block;\n    text-align: center;\n    border-radius:50%;\n    width:1.5rem;\n    height:1.5rem;\n    line-height: 1.5rem;\n    background:#FBE45A;\n    font-family: 'AvenirNext-Medium';\n    font-size:14px;\n    color:#000000;\n    vertical-align: middle;\n    float: left;\n}\n\n.copayer-name {\n    margin-left: 20px;\n    font-family: 'AvenirNext-Medium';\n    font-size:14px;\n    color:#000000;\n    float: left;\n    display: block;\n    width:150px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n.copayer-address {\n    font-family: 'AvenirNext-Medium';\n    font-size:14px;\n    color:#5E6369;\n    float:right;\n}\n</style>\n<template>\n    <div>\n        <breadcrumb :current=\"$t('sharedWalletHome.copayers')\" :routes=\"routes\" v-on:backEvent=\"backToWallets\"></breadcrumb>\n        <div class=\"\">\n            <div class=\"wallet-info\" v-if=\"sharedWallet\">\n                <div class=\"label wallet-label\">{{sharedWallet.sharedWalletName}}</div>\n                <div class=\"label wallet-address\">\n                    {{sharedWallet.sharedWalletAddress}}\n                </div>\n                \n                <div class=\"wallet-num\">\n                    <div class=\"wallet-num-item\">\n                        <span class=\"font-medium\">{{$t('importSharedWallet.totalCopayerNumber')}}</span>\n                        <span class=\"font-medium-black\">{{sharedWallet.totalNumber}}</span>\n                    </div>\n                    <div class=\"wallet-num-item\">\n                        <span class=\"font-medium\">{{$t('importSharedWallet.requiredCopayerNumber')}}</span>\n                        <span class=\"font-medium-black\">{{sharedWallet.requiredNumber}}</span>\n                    </div>\n                </div>\n                <div class=\"confirm-pk-box\">\n                    <div class=\"confirm-pk-item clearfix\" v-for=\"(pk,index) in sharedWallet.coPayers\" :key=\"pk.publickey\">\n                        <span class=\"circle\">{{index+1}}</span>\n                        <span class=\"copayer-name\">{{pk.name}}</span>\n                        <span class=\"copayer-address\">{{pk.address}}</span>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</template>\n<script>\nimport Breadcrumb from '../../Breadcrumb'\nexport default {\n    name: 'SharedWalletCopayer',\n    components: {\n        Breadcrumb\n    },\n    data() {\n        const sharedWallet = JSON.parse(sessionStorage.getItem('sharedWallet'))\n        return {\n            sharedWallet,\n            routes:[{name:sharedWallet.sharedWalletName, path:'/sharedWallet/home'}]\n        }\n    },\n    methods: {\n        backToWallets() {\n            this.$router.push({name:'Wallets'})\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "src/components/TopLeftNav.vue",
    "content": "<template>\n  <div>\n    <div class=\"left-nav text-center\">\n      <router-link class=\"logo-div\" to=\"Home\">\n        <img class=\"logo-img\" src=\"./../assets/logo.png\" alt=\"\">\n      </router-link>\n\n        <router-link :to=\"{name:'Wallets'}\" active-class=\"nav-wallets-active\">\n          <a-tooltip placement=\"right\" :title=\"$t('setting.wallets')\">\n              <div class=\"nav-wallets\"></div>\n          </a-tooltip>\n        </router-link>\n\n      <!-- <router-link :to=\"{name:'Identitys'}\" active-class=\"nav-accounts-active\">\n        <a-tooltip placement=\"right\" :title=\"$t('setting.ontid')\">\n              <div class=\"nav-accounts\"></div>\n          </a-tooltip>\n      </router-link> -->\n\n      <router-link :to=\"{name:'Setting'}\" active-class=\"nav-setting-active\">\n        <a-tooltip placement=\"right\" :title=\"$t('setting.settings')\">\n               <div class=\"setting-img\"></div>\n          </a-tooltip>\n      </router-link>\n\n      <router-link :to=\"{name:'NodeManagement'}\" active-class=\"node-stake-active\" >\n        <a-tooltip placement=\"right\" :title=\"$t('setting.nodeStake')\">\n               <div class=\"node-stake-icon\"></div>\n          </a-tooltip>\n      </router-link>\n\n      <router-link :to=\"{name:'Dapps'}\" active-class=\"nav-dapps-active\">\n          <a-tooltip placement=\"right\" :title=\"$t('dapps.dapps')\">\n              <div class=\"nav-dapps\"></div>\n          </a-tooltip>\n        </router-link>\n\n        <!-- <div class=\"setting-img\" alt=\"\" @click=\"toSetting\"></div> -->\n\n      <a-tooltip placement=\"right\" :title=\"$t('setting.help')\">\n               <div class=\"nav-help\" @click=\"toHelp\"></div>\n          </a-tooltip>\n\n      <div class=\"nav-network\">{{network}}</div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { open } from '../core/utils'\n\nexport default {\n  name: \"TopLeftNav\",\n  computed: {\n    network: {\n      get() {\n        const net = this.$store.state.Setting.network;\n        return net === \"TEST_NET\" ? \"TestNet\" : \"MainNet\";\n      }\n    }\n  },\n  methods: {\n    toHelp() {\n      let url = \"https://medium.com/ontologynetwork/owallet-faq-7f4f96784253\";\n      open(url)\n    }\n  }\n};\n</script>\n\n<style scoped>\n.left-nav {\n  width: 4rem;\n  height: 100%;\n  position: fixed;\n  left: 0;\n  background-color: #373a42;\n  z-index: 1001;\n}\n\n.logo-img {\n  height: 4rem;\n  width: 4rem;\n}\n\n.logo-div {\n  height: 4rem;\n  width: 4rem;\n  background-color: #373a42;\n}\n\n.setting-img,\n.setting-btn {\n  height: 1.5rem;\n  width: 1.5rem;\n}\n\n.nav-setting-active div {\n  background: url(\"../assets/selectsetting.png\") center center;\n}\n\n.setting-img {\n  background: url(\"../assets/settingunselect.png\") center center;\n  background-size: contain;\n}\n\n.setting-img:hover {\n  background: url(\"../assets/selectsetting.png\") center center;\n}\n\n.setting-img {\n  cursor: pointer;\n  position: fixed;\n  bottom: 4rem;\n  left: 1.25rem;\n}\n\n.temp-top {\n  margin-top: 30px;\n}\n\n.nav-help {\n  width: 1.5rem;\n  height: 1.5rem;\n  position: absolute;\n  bottom: 8rem;\n  left: 1.25rem;\n  background: url(\"../assets/helpunselected.png\") center center;\n  cursor: pointer;\n}\n\n.node-stake-icon {\n  width: 24px;\n  height: 24px;\n  margin: 67px auto;\n  background: url(\"../assets/node.png\");\n  background-size: cover;\n  cursor: pointer;\n}\n\n.node-stake-active div {\n  background: url(\"../assets/nodeSelect.png\") center center;\n}\n.node-stake-icon:hover {\n  background: url(\"../assets/nodeSelect.png\") center center;\n}\n\n.nav-help:hover {\n  background: url(\"../assets/helpselect.png\");\n}\n\n.nav-network {\n  position: absolute;\n  bottom: 10px;\n  left: 0;\n  text-align: center;\n  font-family: PingFangSC-Regular;\n  font-size: 12px;\n  color: #ffffff;\n  width: 100%;\n}\n\n.nav-accounts {\n  width: 24px;\n  height: 24px;\n  margin: 67px auto;\n  background: url(\"../assets/accounts.png\");\n  background-size: cover;\n  cursor: pointer;\n}\n\n.nav-accounts-active div {\n  background: url(\"../assets/account-hover.png\");\n  background-size: cover;\n}\n\n.nav-accounts:hover {\n  background: url(\"../assets/account-hover.png\");\n  background-size: cover;\n}\n\n.nav-wallets {\n  width: 24px;\n  height: 24px;\n  margin: 67px auto;\n  background: url(\"../assets/unselectwallet.png\") center center;\n  background-size: cover;\n  cursor: pointer;\n}\n\n.nav-wallets-active div {\n  background: url(\"../assets/selectwallet.png\") center center;\n}\n\n.nav-wallets:hover {\n  background: url(\"../assets/selectwallet.png\") center center;\n}\n\n.nav-dapps {\n  width: 24px;\n  height: 24px;\n  margin: 67px auto;\n  background: url(\"../assets/dapps.png\") center center;\n  background-size: contain;\n  cursor: pointer;\n}\n\n.nav-dapps-active div {\n  background: url(\"../assets/dapps-hover.png\") center center;\n  background-size: contain;\n}\n\n.nav-dapps:hover {\n  background: url(\"../assets/dapps-hover.png\") center center;\n  background-size: contain;\n}\n</style>\n"
  },
  {
    "path": "src/components/Wallets.vue",
    "content": "<template>\n  <div class=\"negative-margin-top\">\n    <ul class=\"nav nav-pills wallets-nav-pills\" id=\"pills-tab\" role=\"tablist\">\n      <li class=\"nav-item\" @click=\"setActiveTab(1)\">\n        <a class=\"nav-link\" id=\"pills-common-tab\" data-toggle=\"pill\" href=\"#pills-common\" role=\"tab\"\n          :class=\"activeTab == 1 ? 'active show' : ''\" aria-controls=\"pills-common\" aria-selected=\"false\">{{\n            $t('wallets.common') }}</a>\n      </li>\n      <li class=\"nav-item\" @click=\"setActiveTab(2)\">\n        <a class=\"nav-link\" id=\"pills-shared-tab\" data-toggle=\"pill\" href=\"#pills-shared\" role=\"tab\"\n          :class=\"activeTab == 2 ? 'active show' : ''\" aria-controls=\"pills-shared\" aria-selected=\"false\">{{\n            $t('wallets.shared') }}</a>\n      </li>\n      <li class=\"nav-item\" @click=\"setActiveTab(3)\">\n        <a class=\"nav-link\" id=\"pills-ledger-tab\" data-toggle=\"pill\" href=\"#pills-ledger\" role=\"tab\"\n          :class=\"activeTab == 3 ? 'active show' : ''\" aria-controls=\"pills-ledger\" aria-selected=\"false\">{{\n            $t('wallets.ledger') }}</a>\n      </li>\n    </ul>\n\n    <div class=\"tab-content\" id=\"pills-tabContent\">\n\n      <!-- <div class=\"tab-pane fade show active\" id=\"pills-home\" role=\"tabpanel\" aria-labelledby=\"pills-home-tab\">\n        <div class=\"d-flex flex-wrap align-content-start center\">\n          <div class=\"normalWallet\" v-for=\"w in normalWallet\" :key=\"w.address\">\n            <json-wallet-details :wallet=\"w\"></json-wallet-details>\n          </div>\n\n          <div class=\"normalWallet\" v-for=\"w in sharedWallet\" :key=\"w.address\">\n            <shared-wallet-details :wallet=\"w\"></shared-wallet-details>\n          </div>\n          <div class=\"normalWallet\" v-for=\"w in hardwareWallet\" :key=\"w.address\">\n            <json-wallet-details :wallet=\"w\"></json-wallet-details>\n          </div>\n        </div>\n      </div> -->\n\n      <div class=\"tab-pane fade\" :class=\"activeTab == 1 ? 'active show' : ''\" id=\"pills-common\" role=\"tabpanel\"\n        aria-labelledby=\"pills-common-tab\">\n        <div class=\"d-flex flex-wrap align-content-start center\">\n          <div class=\"normalWallet\" v-for=\"w in normalWallet\" :key=\"w.address\">\n            <json-wallet-details :wallet=\"w\"></json-wallet-details>\n          </div>\n\n          <div class=\"div-create-wallet\" :class=\"[viewBtn ? 'div-create-wallet-bg-color' : '']\"\n            v-on:mouseenter=\"viewAllBtn(true)\" v-on:mouseleave=\"viewAllBtn(false)\">\n            <div class=\"div-create\" v-show=\"viewBtn\">\n              <router-link class=\"btn btn-default btn-create\" :to=\"{ name: 'CreateJsonWallet' }\">{{\n                $t('wallets.createCommonWallet') }}</router-link>\n            </div>\n            <div class=\"div-join\" v-show=\"viewBtn\">\n              <router-link class=\"btn btn-default btn-create\" :to=\"{ name: 'ImportJsonWallet' }\">{{\n                $t('wallets.importCommonWallet') }}</router-link>\n            </div>\n            <img class=\"img-wallet-create\" v-show=\"!viewBtn\" src=\"./../assets/create-wallet.png\" alt=\"\">\n          </div>\n        </div>\n      </div>\n\n      <div class=\"tab-pane fade\" :class=\"activeTab == 2 ? 'active show' : ''\" id=\"pills-shared\" role=\"tabpanel\"\n        aria-labelledby=\"pills-shared-tab\">\n        <div class=\"d-flex flex-wrap align-content-start center\">\n          <div class=\"normalWallet\" v-for=\"w in sharedWallet\" :key=\"w.address\">\n            <shared-wallet-details :wallet=\"w\"></shared-wallet-details>\n          </div>\n\n          <div class=\"div-create-wallet\" :class=\"[viewBtn ? 'div-create-wallet-bg-color' : '']\"\n            v-on:mouseenter=\"viewAllBtn(true)\" v-on:mouseleave=\"viewAllBtn(false)\">\n            <div class=\"div-create\" v-show=\"viewBtn\">\n              <router-link class=\"btn btn-default btn-create\" :to=\"{ name: 'CreateSharedWallet' }\">{{\n                $t('wallets.createSharedWallet') }}</router-link>\n            </div>\n            <div class=\"div-join\" v-show=\"viewBtn\">\n              <router-link class=\"btn btn-default btn-create\" :to=\"{ name: 'ImportSharedWallet' }\">{{\n                $t('wallets.joinSharedWallet') }}</router-link>\n            </div>\n            <img class=\"img-wallet-create\" v-show=\"!viewBtn\" src=\"./../assets/create-wallet.png\" alt=\"\">\n          </div>\n        </div>\n      </div>\n\n      <div class=\"tab-pane fade\" :class=\"activeTab == 3 ? 'active show' : ''\" id=\"pills-ledger\" role=\"tabpanel\"\n        aria-labelledby=\"pills-ledger-tab\">\n        <div class=\"d-flex flex-wrap align-content-start center\">\n          <div class=\"ledger-help-link\" @click=\"toLedgerHelp\">\n            {{ $t('wallets.ledgerHelpLink') }}\n          </div>\n          <div class=\"normalWallet\" v-for=\"w in hardwareWalletSort\" :key=\"w.address\">\n            <json-wallet-details :wallet=\"w\"></json-wallet-details>\n          </div>\n\n          <div class=\"div-create-wallet\" :class=\"[viewBtn ? 'div-create-wallet-bg-color' : '']\"\n            v-on:mouseenter=\"viewAllBtn(true)\" v-on:mouseleave=\"viewAllBtn(false)\">\n            <div class=\"div-join div-ledger-join\" v-show=\"viewBtn\">\n              <router-link class=\"btn btn-default btn-create\" :to=\"{ name: 'ImportLedgerWallet' }\">{{\n                $t('wallets.importLedgerWallet') }}</router-link>\n            </div>\n            <img class=\"img-wallet-create\" v-show=\"!viewBtn\" src=\"./../assets/create-wallet.png\" alt=\"\">\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <set-path-modal v-model=\"showPathModal\"></set-path-modal>\n  </div>\n</template>\n\n<script>\n// import $ from 'jquery'\nimport { mapState } from 'vuex'\nimport JsonWalletDetails from './JsonWallet/View/Details'\nimport SharedWalletDetails from './SharedWallet/View/Details'\nimport SetPathModal from './Modals/SetPath'\nimport { open } from '../core/utils'\nimport { cloneDeep } from 'lodash'\n\nexport default {\n  name: 'Wallets',\n  data() {\n    const net = localStorage.getItem('net')\n    const network = net === 'TEST_NET' ? this.$t('common.testNet') : this.$t('common.mainNet');\n    const index = sessionStorage.getItem('Wallets_Tab') || 1;\n    return {\n      network: network,\n      viewBtn: false,\n      activeTab: index,\n      showPathModal: false,\n    }\n  },\n  computed: {\n    ...mapState({\n      normalWallet: state => state.Wallets.NormalWallet,\n      sharedWallet: state => state.Wallets.SharedWallet,\n      hardwareWallet: state => state.Wallets.HardwareWallet\n    }),\n    hardwareWalletSort() {\n      return this.hardwareWallet.toSorted((a, b) => {\n        if (b.timestamp !== a.timestamp) {\n          return b.timestamp - a.timestamp;\n        } else {\n          return b.acct - a.acct;\n        }\n\n      });\n    }\n  },\n  mounted() {\n    this.$store.dispatch('fetchWalletsFromDb')\n    this.isSetPath()\n  },\n  methods: {\n    isSetPath() {\n      if (localStorage.getItem('isSavePath') !== 'true') {\n        // $(\"#setPathModal\").modal(\"show\")\n        this.showPathModal = true\n      }\n    },\n    ledgerLogin() {\n      this.$router.push({ name: 'LoginLedger' })\n    },\n    copyAddress(wallet) {\n      this.$copyText(wallet.address)\n    },\n    viewAllBtn(bool) {\n      this.viewBtn = bool\n    },\n    setActiveTab(index) {\n      sessionStorage.setItem('Wallets_Tab', index);\n    },\n    toLedgerHelp() {\n      // Load a remote URL\n      open('https://support.ledgerwallet.com/hc/en-us/articles/360007583514')\n    }\n  },\n  components: {\n    JsonWalletDetails,\n    SharedWalletDetails,\n    SetPathModal\n  }\n}\n</script>\n\n<style>\n.nav-item>a {\n  color: #A5A7A9;\n  font-size: 18px;\n}\n\n.nav-item>a:hover {\n  color: #196BD8;\n}\n\n.wallets-nav-pills .nav-link.active {\n  color: #196BD8;\n  background-color: transparent;\n  border-radius: 0;\n}\n\n.wallets-nav-pills {\n  line-height: 4rem;\n  font-family: AvenirNext-Medium;\n  font-size: 0.88rem;\n  padding: 0 1.7rem;\n}\n\n.nav-link {\n  padding: 0 1.7rem;\n}\n\n.nav-pills .show>.nav-link {\n  color: #196BD8;\n  background-color: transparent;\n}\n\n.center {\n  padding: 1.88rem 3rem;\n  position: relative;\n}\n\n.normalWallet,\n.div-create-wallet {\n  width: 24.63rem;\n  height: 13.19rem;\n  margin-right: 1.75rem;\n  margin-left: 1.75rem;\n  margin-bottom: 2.75rem;\n}\n\n.div-create-wallet {\n  border: 1px solid #dddddd;\n}\n\n.normalWallet {\n  background-color: #F5F7FB;\n  padding: 0 1.25rem;\n  position: relative;\n}\n\n.normalWallet:hover {\n  cursor: pointer;\n}\n\n.div-create-wallet {\n  background-color: #F5F7FB;\n  font-family: AvenirNext-Medium;\n  position: relative;\n}\n\n.div-create-wallet-bg-color {\n  background-color: #498FEF;\n}\n\n.img-wallet-create {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin-left: -30px;\n  margin-top: -30px;\n}\n\n.div-create-wallet>div>a {\n  font-size: 0.88rem;\n}\n\n.btn-create {\n  width: 8.25rem;\n  height: 2.13rem;\n  color: white;\n  border: white solid 1px;\n  border-radius: 0;\n}\n\n.div-create {\n  padding: 0px;\n  margin: 3.5rem auto 2rem;\n  text-align: center;\n}\n\n.div-join {\n  padding: 0px;\n  margin: 2rem auto;\n  text-align: center;\n}\n\n.div-ledger-join {\n  padding-top: 3.5rem;\n}\n\n/* TODO 以下样式可能需要删除：*/\n.boxBtns {\n  width: 290px;\n  height: 48px;\n  margin-bottom: 16px;\n  border-radius: 4px;\n  background-color: #edf2f5;\n  text-align: center;\n  line-height: 48px;\n}\n\n.boxBtns a {\n  font-size: 16px;\n  color: #35bfdf;\n}\n\n.ledgerBtn {\n  width: 210px;\n  height: 75.2px;\n  border-radius: 4px;\n  background-color: #edf2f5;\n  margin-left: 40px;\n  position: relative;\n  cursor: pointer;\n}\n\n.ledgerBtnInner {\n  text-align: center;\n  position: absolute;\n  left: 0;\n  right: 0;\n  top: 0;\n  border: 0;\n  margin: auto;\n}\n\n.ledgerBtnText1 {\n  font-family: SourceSansPro;\n  font-size: 14px;\n  color: #35bfdf;\n  display: block;\n  margin-top: 12px;\n}\n\n.ledgerBtnText2 {\n  font-family: SourceSansPro;\n  font-size: 18px;\n  font-weight: bold;\n  color: #35bfdf;\n}\n\n.ledger-help-link {\n  position: absolute;\n  width: 100%;\n  text-align: center;\n  top: -5px;\n  left: -5rem;\n  cursor: pointer;\n  color: #196BD8;\n}\n\n.ledger-help-link :hover {\n  text-decoration: underline;\n}\n</style>\n"
  },
  {
    "path": "src/core/asyncHelper.js",
    "content": "export default function asyncWrap (promise) {\n  return promise.then(data => {\n    return [null, data]\n  }).catch(err => [err])\n}\n"
  },
  {
    "path": "src/core/consts.js",
    "content": "// export const GAS_PRICE = '0';for test\nexport const GAS_PRICE = '500';\nexport const GAS_LIMIT = '20000';\n\nexport const ONT_CONTRACT = '0000000000000000000000000000000000000001';\nexport const TEST_NET = 'http://polaris1.ont.io';\nexport const MAIN_NET = 'http://dappnode1.ont.io';\n\nexport const TEST_NET_LIST = [\n    'http://polaris1.ont.io',\n    'http://polaris2.ont.io',\n    'http://polaris3.ont.io',\n    'http://polaris4.ont.io',\n    'http://polaris5.ont.io'\n]\n\nexport const MAIN_NET_LIST = [\n    'http://dappnode1.ont.io',\n    'http://dappnode2.ont.io',\n    'http://dappnode3.ont.io',\n    'http://dappnode4.ont.io',\n]\n//test environment\nexport const ONT_PASS_NODE = 'https://service-test.onto.app'\n//prod\nexport const ONT_PASS_NODE_PRD = 'https://service.onto.app'\n\nexport const ONT_PASS_URL = {\n    CreateSharedWallet: '/S5/api/v1/ontpass/SharedWallet/create',\n    QuerySharedWallet: '/S5/api/v1/ontpass/SharedWallet/getBySharedWalletAddress', //get\n    CreateSharedTransfer: '/S5/api/v1/ontpass/SharedTransfer/create',\n    SignSharedTransfer: '/S5/api/v1/ontpass/SharedTransfer/sign',\n    SendSharedTransfer: '/S5/api/v1/ontpass/SharedTransfer/isSendToChain', //get\n    QueryPendingTransfer: '/S5/api/v1/ontpass/SharedTransfer/listSigningBeforeTime',\n    // sharedAddress={sharedAddress}&assetName={assetName}&beforeTimeStamp={beforeTimeStamp},\n    ExchangeCurrency: '/S5/api/v1/ontpass/api/v1/onto/exchangerate/reckon/'\n    ///api/v1/onto/exchangerate/reckon/{currency}/{goaltype}/{amount}\n\n    //for node stake\n    ,\n    GetQualifiedState: '/S4/NodePledgeApi/v1/Nodepledge/getQuailifiedState',\n    // /NodePledgeApi/v1/Nodepledge/getQuailifiedState?ontid={ontid}&address={address}'\n    DelegateSendTx: '/S4/NodePledgeApi/v1/Nodepledge/delegateSendTransaction',\n    SetStakeInfo: '/S4/NodePledgeApi/v1/Nodepledge/setInfo',\n    GetStakeInfo: '/S4/NodePledgeApi/v1/Nodepledge/info',\n    // /NodePledgeApi/v1/Nodepledge/info?ontid={ontid}\n    GetVoteContract: '/S4/NodePledgeApi/v1/Nodepledge/vote-contract-address' // /{net_type}\n}\n\nexport const WALLET_TYPE = {\n    CommonWallet: 'CommonWallet',\n    SharedWallet: 'SharedWallet',\n    HardwareWallet: 'HardwareWallet'\n}\n\nexport const DEFAULT_SCRYPT = {\n    cost: 16384, // 除以2时间减半\n    blockSize: 8,\n    parallel: 8,\n    size: 64\n};\n\nexport const SWAP_ADDRESS = 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM'\n\nexport const NODE_DETAIL = 'https://explorer.ont.io/nodes/detail/'\nexport const NODE_NAME_LIST = 'https://ont.io/api/v1/candidate/info/All'\nexport const OFF_CHAIN_NODES = {\n    TEST_NET: 'https://polarisexplorer.ont.io/v2/nodes/off-chain-infos',\n    MAIN_NET: 'https://explorer.ont.io/v2/nodes/off-chain-infos'\n}\n\nexport const QUERY_NODE_INFO_API = {\n    TEST_NET: 'https://polarisexplorer.ont.io/v2/nodes/off-chain-info/public',\n    // TEST_NET: 'http://18.136.65.213:8585/v2/nodes/off-chain-info',\n    MAIN_NET: 'https://explorer.ont.io/v2/nodes/off-chain-info/public'\n}\n\nexport const UPDATE_NODE_INFO_API = {\n    TEST_NET: 'https://polarisexplorer.ont.io/v2/offchain/off-chain-info',\n    // TEST_NET: 'http://18.136.65.213:8585/v2/nodes/off-chain-info',\n    MAIN_NET: 'https://explorer.ont.io/v2/offchain/off-chain-info'\n}\n\nexport const UPDATE_LEDGER_NODE_INFO_API = {\n    TEST_NET: 'https://polarisexplorer.ont.io/v2/offchain/off-chain-info/ledger',\n    // TEST_NET: 'http://18.136.65.213:8585/v2/nodes/off-chain-info',\n    MAIN_NET: 'https://explorer.ont.io/v2/offchain/off-chain-info/ledger'\n}\n\nexport const NODE_CURRENT_STAKES = {\n    TEST_NET: 'https://polarisexplorer.ont.io/v2/nodes/current-stakes',\n    MAIN_NET: 'https://explorer.ont.io/v2/nodes/current-stakes'\n}\n\nexport const PAX_API = {\n    Host: 'http://18.138.83.180:20800',\n    // TestHost: 'http://172.168.3.61:20800',\n    TestHost: 'http://18.139.19.52:20800',\n    fetchApprovalList: '/api/v1/approvals',\n    updateApprovals: '/api/v1/processapplist',\n    validateTx: '/api/v1/validatetx',\n    EthScanTest: 'https://ropsten.etherscan.io/tx/',\n    EthScanMain: 'https://etherscan.io/tx/'\n}\n\nexport const PAX_SC_HASH = {\n    MAIN: '6bbc07bae862db0d7867e4e5b1a13c663e2b4bc8',\n    TEST: 'b06f8eaf757030c7a944ce2a072017bde1e72308'\n}\n\nexport const VOTE_ROLE = {\n    ADMIN: 'ADMIN',\n    VOTER: 'VOTER',\n    VISITOR: 'VISITOR'\n}\n\nexport const VALIDATE_DICTIONARY = {\n    zh: {\n        messages: {\n            required: (field, val) => `字段 ${field} 是必填项`,\n            min: (field, val) => `字段 ${field} 的长度不能少于${val[0]}`,\n            length: (field, val) => `字段 ${field} 的长度必须是${val[0]}`,\n            confirmed: (field, val) => `${field}的输入匹配错误`,\n            is: (field, val) => `${field}的输入匹配错误`\n        },\n        attributes: {\n            password: '密码',\n            name: '名称',\n            label: '名称',\n            rePassword: '确认密码',\n            keystore: 'keystore',\n            keystorePassword: ''\n        }\n    },\n    en: {\n        messages: {\n            required: (field, val) => `${field} is required`,\n            min: (field, val) => `The length of ${field} must be larger than ${val[0]}`,\n            length: (field, val) => `The length of ${field} must be ${val[0]}`,\n            confirmed: (field, val) => `Those two inputs didn't match.`,\n            is: (field, val) => `Those two inputs didn't match.`\n        },\n        attributes: {\n            password: 'Password',\n            name: 'Name',\n            label: 'Label',\n            rePassword: 'Confirm password',\n            keystore: 'keystore',\n            keystorePassword: ''\n        }\n    }\n}\n//申请注册 候选 共识 共识退出 候选退出 拉黑 已退出\nexport const GovernanceStatus = {\n    REGISTER: 0,\n    CANDIDATE: 1,\n    CONSENSUS: 2,\n    QUIT_CANDIDATE: 3,\n    QUIT_CONSENSUS: 4,\n    BLACKLIST: 5,\n    EXIXTED: 6\n}\n"
  },
  {
    "path": "src/core/dbService.js",
    "content": "// import path, { resolve } from 'path'\nimport electron from 'electron'\n// const app = electron.remote.app;\nimport { app } from '@electron/remote';\n\nconst userData = app.getPath('userData')\nconsole.log('appPath: ' + userData)\nif(!localStorage.getItem('savePath')) {\n    localStorage.setItem('savePath', userData)\n}\n//create db\nvar Datastore = require('nedb');\n\nconst savePath = localStorage.getItem('savePath')\n\nconst db = new Datastore({filename: savePath + '/keystore.db', autoload:true});\n\n//indexing\ndb.ensureIndex({fieldName: 'address', unique: true}, function(err) {\n    console.log(err)\n    if (err && err.code === 'ENOENT') {\n        localStorage.setItem('savePath', userData);\n        alert('Cannot find the keystore.db file. Please set the keystore.db file path.');\n    }\n});\n\n\ndb.loadDatabase();\n\nconst dbFind = (db, opt) => {\n    return new Promise((resolve, reject) => {\n        db.find(opt, function(err, docs) {\n            if (err) {\n                reject(err)\n            } else {\n                resolve(docs)\n            }\n        })\n    })\n}\n\nconst dbInsert = (db, doc) => {\n    return new Promise((resolve, reject) => {\n        db.insert(doc, function(err, newDoc) {\n            if(err) {\n                reject(err)\n            } else {\n                resolve(newDoc)\n            }\n        })\n    })\n}\n\nconst dbUpsert = (db, index ,doc) => {\n    return new Promise((resolve, reject) => {\n        db.update({[index] : doc.indexKey}, doc, {upsert: true}, function(err, numReplaced, upsert) {\n            if(err) {\n                reject(err)\n            } else {\n                resolve(upsert)\n            }\n        })\n    })\n}\n\nexport default db;\nexport {dbFind, dbUpsert};"
  },
  {
    "path": "src/core/fileHelper.js",
    "content": "\nexport default {\n    downloadFile(json, fileName) {\n        let content = new Blob([JSON.stringify(json)], { type: \"text/plain;charset=utf-8\" })\n        let urlObject = window.URL || window.webkitURL || window\n        let url = urlObject.createObjectURL(content)\n        let el = document.createElement('a')\n        el.href = url\n        el.download = fileName? `${fileName}.dat` : \"wallet.dat\"\n        document.body.appendChild(el)\n        el.click()\n        urlObject.revokeObjectURL(url)\n    },\n    readWalletFile($file) {\n\n        return new Promise(function (resolve, reject) {\n            var reader = new FileReader();\n            reader.onload = function (params) {\n                resolve(reader.result)\n            }\n            reader.onerror = reject\n\n            reader.readAsText($file)\n        })\n    }\n}\n"
  },
  {
    "path": "src/core/lang.js",
    "content": "export default {\n    setLang(lang) {\n        window.localStorage.setItem('user_lang', lang)\n    },\n    getLang(defaultLang) {\n        let localLang = window.localStorage.getItem('user_lang') || 'en'\n\n        if (localLang === null) {\n            return defaultLang\n        } else {\n            return localLang\n        }\n    }\n}"
  },
  {
    "path": "src/core/network.js",
    "content": "import {WebsocketClient} from 'ontology-ts-sdk';\nimport store from '../store'\nimport { MAIN_NET_LIST, TEST_NET_LIST } from './consts'\nlet client;\n\nlet net = localStorage.getItem('net'); // 'TEST_NET' or 'MAIN_NET'\nif(!net) {\n    net = 'MAIN_NET'\n    localStorage.setItem('net', net)\n}\n\nlet node = localStorage.getItem('nodeAddress')\nif(!node) {\n    node = MAIN_NET_LIST[0]\n    localStorage.setItem('nodeAddress', node)\n}\n\nconst WS_PORT = '20335'\n\nexport function initNetwork() {\n    reconnect()\n  window.setInterval(async () => {\n    try {\n      await client.sendHeartBeat();\n      store.commit('NETWORK_CONNECTED')\n    } catch (e) {\n      if (net) {\n        reconnect();\n      }\n\n      store.commit('NETWORK_DISCONNECTED');\n    }\n  }, 5000);\n}\n\n\nfunction reconnect() {\n  if (client !== undefined) {\n    try {\n      client.close();\n    } catch (e) {\n      // ignored\n    }\n  }\n\n  const url = `${node}:${WS_PORT}`;\n  client = new WebsocketClient(url, false, false);\n}\n\nexport function getClient() {\n  return client;\n}\n"
  },
  {
    "path": "src/core/nodes.json",
    "content": "[\n    {\n        \"name\": \"Dubhe\",\n        \"pk\": \"02bcdd278a27e4969d48de95d6b7b086b65b8d1d4ff6509e7a9eab364a76115af7\",\n        \"isConsensus\": true\n    },\n    {\n        \"name\": \"Merak\",\n        \"pk\": \"0251f06bc247b1da94ec7d9fe25f5f913cedaecba8524140353b826cf9b1cbd9f4\",\n        \"isConsensus\": true\n    },\n    {\n        \"name\": \"Phecda\",\n        \"pk\": \"022e911fb5a20b4b2e4f917f10eb92f27d17cad16b916bce8fd2dd8c11ac2878c0\",\n        \"isConsensus\": true\n    },\n    {\n        \"name\": \"Megrez\",\n        \"pk\": \"0253719ac66d7cafa1fe49a64f73bd864a346da92d908c19577a003a8a4160b7fa\",\n        \"isConsensus\": true\n    },\n    {\n        \"name\": \"Alioth\",\n        \"pk\": \"022bf80145bd448d993abffa237f4cd06d9df13eaad37afce5cb71d80c47b03feb\",\n        \"isConsensus\": true\n    },\n    {\n        \"name\": \"Mixar\",\n        \"pk\": \"02765d98bb092962734e365bd436bdc80c5b5991dcf22b28dbb02d3b3cf74d6444\",\n        \"isConsensus\": true\n    },\n    {\n        \"name\": \"Alkaid\",\n        \"pk\": \"03c8f63775536eb420c96228cdccc9de7d80e87f1b562a6eb93c0838064350aa53\",\n        \"isConsensus\": true\n    },\n    {\n        \"name\": \"Jumple Foundation\",\n        \"pk\": \"038602b1b03637be0de5305639756db44da31b5241acde4cff86f2a181f76d9fee\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Hashed\",\n        \"pk\": \"03ee9fd0557e56dab1eb7d9720e749d581fb0ebfd0a15f31bc973834c36e0b9c46\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Infinity Stones\",\n        \"pk\": \"0244c959ed3bcd0f96da35d4c615bcf99c8a2d7ddb875142fa8f731bbf681eee44\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"ONEROOT Foundation\",\n        \"pk\": \"025222dc49b168d47c12a77aa9ae3370f6319cfe97eab4f92b0e7f61597ebcc158\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Martview\",\n        \"pk\": \"03a0cf8494ef9901c7a78df98abb9a8a245961da77c157cb3f31e67db0325f070c\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"DAD\",\n        \"pk\": \"02872b863b9bee7a1bd15692330af591603bc3db3444272c00e51997a74ac1756c\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"SunStar\",\n        \"pk\": \"02584b9aa8d871017ff7d19fb8c7c934eeffbdc6b7de5501855e11c65ffbb67774\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"G&Q TECH LIMITED\",\n        \"pk\": \"036f29e06e57f36432ad6bb89dbfd8f81d12e42e7a1a5d454c322ac8e3b94a4bf0\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"InWeCrypto\",\n        \"pk\": \"026dd0e7b95843181e0f986ecb292f32a2165261ca62d097bba8c54195d527f73f\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"gf.network\",\n        \"pk\": \"031554b64b4145fb33e83f686081e9148188c2176aaf6a55c874b38fd093e1bc0c\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"J&D TECH LIMITED\",\n        \"pk\": \"033ad721e2443998bc036710b0415ac6ae67e2d490307ba9f4f8f41af62726f34d\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"ont-huobipool\",\n        \"pk\": \"03c793b05687137803952cb0327aaed8cfb1a7199badd23a34b2fa8417f614faae\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Accomplice\",\n        \"pk\": \"034a7069c3ba649a762191b62e29992f6b4ba4b670d6502259e15597199cea17d2\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Matrix Partners China\",\n        \"pk\": \"035e470667371300f87090c3410cfbb24a4b40c6955574ed7dd053644f94922632\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"CloudDesk\",\n        \"pk\": \"0349a0e3e018d275a09bb6d4237cb95ee199cf38c81c9a1228ecb72f2c6ab8fdfe\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Collider\",\n        \"pk\": \"02da86115d1c2450eb5780da3ffd21c0e68c9094f990f3c7c489e0c5d50b72ec43\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"CertiK\",\n        \"pk\": \"02b9000043dba3a3c91185a963babbb975daf73ebfc4f07ab7cb80dc7172145c3d\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Avocado\",\n        \"pk\": \"034b87ac6f457e44a33284fcd60d2b2f6ea2a508e553462bba5bf526a0dd285300\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Ontology Universe\",\n        \"pk\": \"02a0ca41d2544cdea25fe98102157ea9ca051ac1e565e43847c3f006c9caedc297\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"ONTLabo\",\n        \"pk\": \"037acf1bb88200138b44f5d645d0e0c063043addc30db0102eea508db2585f9171\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Blockchain Global Limited\",\n        \"pk\": \"03e96d1b80bfa4895763d640e6278c3e31323ba395cb32c9c578d54374e092e134\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"HZF Web\",\n        \"pk\": \"0292c695bb734f849d17ee65977d048ff8a9efae8317ee40589a944eb2bbcd9998\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Crypto World\",\n        \"pk\": \"0280d0bfde8e6b73e48c15ee062728f890e41f125339d5f36ed8a29430d41c6d57\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Points Foundation\",\n        \"pk\": \"035960c0a6b07532e149fd8e92d19f4670732735df5c0a419a9d79c1a06df8fc23\",\n        \"isConsensus\": false\n    },\n    {\n        \"name\": \"Trio Bravo\",\n        \"pk\": \"0287fe995c6f27ad0c1a7640f9cc6c2537ed47126cc430e738d96f0390583ac2d2\",\n        \"isConsensus\": false\n    }\n]\n"
  },
  {
    "path": "src/core/ontLedger.js",
    "content": "import LedgerNode from '@ledgerhq/hw-transport-node-hid'\nimport asyncWrap from './asyncHelper'\nimport { utils, Crypto } from 'ontology-ts-sdk'\nimport * as elliptic from 'elliptic';\nimport {message} from 'ant-design-vue'\nimport i18n from '../lang'\nimport OntLedgerNew from './ontLedgerNew'\n\nconst VALID_STATUS = 0x9000\nconst MSG_TOO_BIG = 0x6d08\nconst APP_CLOSED = 0x6e00\nconst TX_DENIED = 0x6985\nconst TX_PARSE_ERR = 0x6d07\n\n/**\n * Evaluates Transport Error thrown and rewrite the error message to be more user friendly.\n * @param {Error} err\n * @return {Error}\n */\nconst evalTransportError = err => {\n    switch (err.statusCode) {\n        case APP_CLOSED:\n            err.message = 'Your ONT app is closed! Please login.'\n            break\n        case MSG_TOO_BIG:\n            err.message = 'Your transaction is too big for the ledger to sign!'\n            break\n        case TX_DENIED:\n            err.message = 'You have denied the transaction on your ledger.'\n            break\n        case TX_PARSE_ERR:\n            err.message = 'Error parsing transaction. Make sure your ONT app version is up to date.'\n            break\n    }\n    return err\n}\n\nconst BIP44 = (acct = 0, neo = false, usePath = false) => {\n    const acctNumber = acct.toString(16)\n    if (usePath) {\n        const coinType = neo ? 888 : 1024;  // NEO 或 ONT 的币种类型\n        return `44'/${coinType}'/0'/0/${acct}`;\n    }\n    const coinType = neo ? '80000378' : '80000400';\n\n    return (\n        '8000002C' +\n        coinType +\n        '80000000' +\n        '00000000' +\n        '0'.repeat(8 - acctNumber.length) +\n        acctNumber\n    )\n}\n\nexport default class OntLedger {\n    path;\n    device;\n\n    constructor(path) {\n        this.path = path\n    }\n\n    /**\n     * Initialises by listing devices and trying to find a ledger device connected. Throws an error if no ledgers detected or unable to connect.\n     * @return {Promise<OntLedger>}\n     */\n    static async init() {\n        const supported = await LedgerNode.isSupported()\n        // if (!supported) { throw new Error(`Your computer does not support the ledger!`) }\n        if (!supported) { throw 'NOT_SUPPORT' }\n        const paths = await OntLedger.list()\n        // if (paths.length === 0) throw new Error('USB Error: No device found.')\n        if (paths.length === 0) throw 'NOT_FOUND'\n        const ledger = new OntLedger(paths[0])\n        return ledger.open()\n    }\n\n    static async list() {\n        return LedgerNode.list()\n    }\n\n    /**\n     * Opens an connection with the selected ledger.\n     * @return {Promise<OntLedger>}this\n     */\n    async open() {\n        try {\n            this.device = await LedgerNode.open(this.path)\n            return this\n        } catch (err) {\n            throw evalTransportError(err)\n        }\n    }\n\n    /**\n     * Closes the connection between the Ledger and the wallet.\n     * @return {Promise<void>}}\n     */\n    close() {\n        if (this.device) return this.device.close()\n        return Promise.resolve()\n    }\n\n    /**\n     * Retrieves the public key of an account from the Ledger.\n     * @param {number} [acct] - Account that you want to retrieve the public key from.\n     * @return {string} Public Key (Unencoded)\n     */\n    async getPublicKey(acct = 0, neo) {\n        const ledger = new OntLedgerNew(this.device)\n        const uncompressed = await ledger.getPublicKey(BIP44(acct, neo, true))\n\n        // const res = await this.send('80040000', BIP44(acct, neo), [VALID_STATUS])\n        // const uncompressed = res.toString('hex').substring(0, 130)\n        const ec = new elliptic.ec(Crypto.CurveLabel.SECP256R1.preset);\n        const keyPair = ec.keyFromPublic(uncompressed, 'hex');\n        const compressed = keyPair.getPublic(true, 'hex');\n        console.log(\"compressed\", compressed);\n        return compressed;\n    }\n\n    getDeviceInfo() {\n        try {\n            return this.device.device.getDeviceInfo()\n        } catch (err) {\n            throw evalTransportError(err)\n        }\n    }\n\n    /**\n     * Sends an message with params over to the Ledger.\n     * @param {string} params - params as a hexstring\n     * @param {string} msg - Message as a hexstring\n     * @param {number[]} statusList - Statuses to return\n     * @return {Promise<Buffer>} return value decoded to ASCII string\n     */\n    async send(params, msg, statusList) {\n        if (params.length !== 8) throw new Error(`params requires 4 bytes`)\n        // $FlowFixMe\n        const [cla, ins, p1, p2] = params\n            .match(/.{1,2}/g)\n            .map(i => parseInt(i, 16))\n        try {\n            return await this.device.send(\n                cla,\n                ins,\n                p1,\n                p2,\n                Buffer.from(msg, 'hex'),\n                statusList\n            )\n        } catch (err) {\n            throw evalTransportError(err)\n        }\n    }\n\n    /**\n     * Gets the ECDH signature of the data from Ledger using acct\n     * @param {string} data\n     * @param {number} [acct]\n     * @return {Promise<string>}\n     */\n    async getSignature(data, acct = 0, neo = false) {\n        const ledger = new OntLedgerNew(this.device)\n        const res = await ledger.signMessage(BIP44(acct, neo, true), data)\n        return res;\n        // old logic\n        // data += BIP44(acct, neo)\n        // let response = null\n        // const chunks = data.match(/.{1,510}/g) || [];\n        // if (!chunks.length) throw new Error(`Invalid data provided: ${data}`)\n        // for (let i = 0; i < chunks.length; i++) {\n        //     const p = i === chunks.length - 1 ? '80' : '00'\n        //     // $FlowFixMe\n        //     const chunk = chunks[i]\n        //     const params = `8002${p}00`\n        //     let [err, res] = await asyncWrap(\n        //         this.send(params, chunk, [VALID_STATUS])\n        //     )\n        //     if (err) throw evalTransportError(err)\n        //     response = res\n        // }\n        // if (response === 0x9000) {\n        //     throw new Error(`No more data but Ledger did not return signature!`)\n        // }\n        // // $FlowFixMe\n        // return assembleSignature(response.toString('hex'))\n    }\n}\n\n/**\n * The signature is returned from the ledger in a DER format\n * @param {string} response - Signature in DER format\n */\nconst assembleSignature = (response) => {\n    let ss = new utils.StringReader(response)\n    // The first byte is format. It is usually 0x30 (SEQ) or 0x31 (SET)\n    // The second byte represents the total length of the DER module.\n    ss.read(2)\n    // Now we read each field off\n    // Each field is encoded with a type byte, length byte followed by the data itself\n    ss.read(1) // Read and drop the type\n    const r = ss.readNextBytes()\n    ss.read(1)\n    const s = ss.readNextBytes()\n\n    // We will need to ensure both integers are 32 bytes long\n    const integers = [r, s].map(i => {\n        if (i.length < 64) {\n            i = i.padStart(64, '0')\n        }\n        if (i.length > 64) {\n            i = i.substr(-64)\n        }\n        return i\n    })\n\n    return integers.join('')\n}\n\nexport const getPublicKey = async (acct = 0, neo = false) => {\n    const ledger = await OntLedger.init()\n    try {\n        return await ledger.getPublicKey(acct, neo)\n    }\n    catch (err) {\n        return Promise.reject(err)\n    }\n    finally {\n        await ledger.close()\n    }\n}\n\nexport const getDeviceInfo = async () => {\n    const ledger = await OntLedger.init()\n    try {\n        return await ledger.getDeviceInfo()\n    } finally {\n        await ledger.close()\n    }\n}\n\n\nexport const legacySignWithLedger = async (unsignedTx, neo = false, acct = 0) => {\n    const ledger = await OntLedger.init()\n    try {\n        const signData = await ledger.getSignature(unsignedTx, acct, neo)\n        return signData;\n    } catch (err) {\n        return Promise.reject(err)\n    }\n    finally {\n        await ledger.close()\n    }\n}\n\nexport const checkPublicKeyIsInTheConnectedLedger = async (acct = 0, neo = false, publicKey) => {\n    try {\n        // 当前连接的Ledger需要和之前导入钱包的Ledger是同一个\n        const pk = await getPublicKey(acct, neo);\n        const isCorrect = pk === publicKey;\n        if (!isCorrect) {\n            throw i18n.t('common.invalidLedger');\n        }\n        return true;\n    } catch (err) {\n        console.error(err);\n        message.warning(err?.message || err);\n        throw err;\n    } \n\n}\n"
  },
  {
    "path": "src/core/ontLedgerNew.js",
    "content": "import { convertPathToBuffer } from \"./utils\";\nimport i18n from '../lang'\n\nconst STATUS_CODES = {\n  SW_DENY: 0x6985,\n  SW_WRONG_P1P2: 0x6a86,\n  SW_WRONG_DATA_LENGTH: 0x6a87,\n  SW_INS_NOT_SUPPORTED: 0x6d00,\n  SW_CLA_NOT_SUPPORTED: 0x6e00,\n  SW_WRONG_RESPONSE_LENGTH: 0xb000,\n  SW_DISPLAY_BIP32_PATH_FAIL: 0xb001,\n  SW_DISPLAY_ADDRESS_FAIL: 0xb002,\n  SW_DISPLAY_AMOUNT_FAIL: 0xb003,\n  SW_WRONG_TX_LENGTH: 0xb004,\n  SW_TX_PARSING_FAIL: 0xb005,\n  SW_TX_HASH_FAIL: 0xb006,\n  SW_BAD_STATE: 0xb007,\n  SW_SIGNATURE_FAIL: 0xb008,\n  SW_PERSON_MSG_PARSING_FAIL: 0xb009,\n  SW_PERSON_MSG_HASH_FAIL: 0xb00a,\n  SW_WRONG_PERSON_MSG_LENGTH: 0xb00b,\n  SW_TX_PAYLOAD_PARSING_FAIL: 0xb00c,\n  SW_OEP4_TX_PARSING_FAIL: 0xb00d,\n  SW_OEP4_TX_PAYLOAD_PARSING_FAIL: 0xb00e,\n  OK: 0x9000,\n};\n\nconst MAX_PAYLOAD = 255;\nconst LEDGER_CLA = 0x80;\nconst P1_NON_CONFIRM = 0x00;\nconst P1_CONFIRM = 0x01;\nconst P2_MORE = 0x80;\nconst P2_EXTEND = 0x00;\n\nconst INS = {\n  GET_VERSION: 0x03,\n  GET_ADDR: 0x04,\n  SIGN: 0x02,\n  SIGN_OFFCHAIN: 0x07,\n};\n\nclass OntLedgerNew {\n  constructor(transport, scrambleKey = \"ONT\") {\n    this.transport = transport;\n    transport.decorateAppAPIMethods(\n      this,\n      [\"getPublicKey\", \"signMessage\", \"signOffchainMessage\"],\n      scrambleKey\n    );\n  }\n  async #sendToDevice(path, instruction, msgBuffer) {\n    console.log(\"sendToDevice\");\n\n    console.log(path, instruction, msgBuffer);\n    const checkedVersion = await this.checkVersion();\n    if (!checkedVersion) {\n      throw new Error(\"Unsupported app version\");\n    }\n\n    try {\n      const acceptStatusList = [STATUS_CODES.OK];\n      const pathBuffer = this.pathToBuffer(path);\n      // const msgBuffer = Buffer.from(msg, \"hex\");\n      let custom_p1 = 0x00;\n\n      const firstReply = await this.transport.send(\n        LEDGER_CLA,\n        instruction,\n        custom_p1,\n        P2_MORE,\n        pathBuffer,\n        acceptStatusList\n      );\n      console.log(\"firstReply\", firstReply);\n\n      custom_p1++;\n\n      if (msgBuffer.length > MAX_PAYLOAD) {\n        while (msgBuffer.length - (custom_p1 - 1) * MAX_PAYLOAD > MAX_PAYLOAD) {\n          const buf = msgBuffer.slice(\n            (custom_p1 - 1) * MAX_PAYLOAD,\n            custom_p1 * MAX_PAYLOAD\n          );\n          await this.transport.send(\n            LEDGER_CLA,\n            instruction,\n            custom_p1,\n            P2_MORE,\n            buf,\n            acceptStatusList\n          );\n          custom_p1++;\n        }\n      }\n\n      const lastBuf = msgBuffer.slice((custom_p1 - 1) * MAX_PAYLOAD);\n      const reply = await this.transport.send(\n        LEDGER_CLA,\n        instruction,\n        custom_p1,\n        P2_EXTEND,\n        lastBuf,\n        [STATUS_CODES.OK]\n      );\n      return reply;\n    } catch (error) {\n      throw this._convertTransportError(error);\n    }\n  }\n\n  pathToBuffer(path) {\n    const PATH_REGEX = /^(\\d+'?(\\/\\d+'?)*)$/;\n    if (!PATH_REGEX.test(path.trim())) {\n      throw new Error(\"Invalid path format\");\n    }\n    const segments = path\n      .replace(/^m\\//, \"\") // delete \"m/\"\n      .split(\"/\")\n      .map((segment) => {\n        if (segment.endsWith(\"'\")) {\n          return (parseInt(segment.slice(0, -1), 10) | 0x80000000) >>> 0;\n        } else {\n          return parseInt(segment, 10) >>> 0;\n        }\n      });\n\n    const length = segments.length;\n    const uint8Array = new Uint8Array(1 + length * 4);\n\n    uint8Array[0] = length;\n    segments.forEach((value, index) => {\n      const offset = 1 + index * 4;\n      uint8Array[offset] = (value >> 24) & 0xff;\n      uint8Array[offset + 1] = (value >> 16) & 0xff;\n      uint8Array[offset + 2] = (value >> 8) & 0xff;\n      uint8Array[offset + 3] = value & 0xff;\n    });\n\n    return uint8Array;\n  }\n\n  getSignFromRelay(reply) {\n    const dataLength = reply[0];\n    const dataBuf = reply.slice(1, dataLength + 1);\n    let r_length = dataBuf[3];\n    let r = dataBuf.slice(4, 4 + r_length);\n    if (r_length === 33 && r[0] === 0) {\n      r = r.slice(1);\n    }\n    let s_length = dataBuf[r_length + 5];\n    let s = dataBuf.slice(r_length + 6);\n    if (s_length === 33 && s[0] === 0) {\n      s = s.slice(1);\n    }\n\n    const sign = Buffer.concat([r, s]).toString(\"hex\");\n    return sign;\n  }\n\n  async getVersion() {\n    try {\n      const result = await this.transport.send(\n        LEDGER_CLA,\n        INS.GET_VERSION,\n        P1_NON_CONFIRM,\n        P2_EXTEND,\n        Buffer.alloc(0),\n        [STATUS_CODES.OK]\n      );\n      return result;\n    } catch (error) {\n      if (error.statusCode === STATUS_CODES.SW_INS_NOT_SUPPORTED) {\n        return \"0000009000\";\n      }\n      throw this._convertTransportError(error);\n    }\n  }\n\n  /**\n   * Checks if the version meets the required criteria.·\n   * This function retrieves the version, converts it to a hexadecimal string,\n   * and checks if the first two characters represent a number greater than or equal to 2.\n   *\n   * @returns {Promise<boolean>} - A Promise that resolves to a boolean indicating\n   * whether the version is greater than or equal to 2.\n   */\n  async checkVersion() {\n    const versionReply = await this.getVersion();\n    const versionString = versionReply.toString(\"hex\");\n    console.log(\"versionString\", versionString);\n\n    const first = versionString.slice(0, 2);\n    if (Number(first) >= 2) {\n      return true;\n    }\n    return false;\n  }\n\n  async getPublicKey(path, showAddress = false) {\n    try {\n      const checkedVersion = await this.checkVersion();\n      console.log(\"checkedVersion\", checkedVersion);\n\n      if (!checkedVersion) {\n        let pathBuffer = convertPathToBuffer(path);\n        const result = await this.transport.send(\n          LEDGER_CLA,\n          INS.GET_ADDR,\n          showAddress ? P1_CONFIRM : P1_NON_CONFIRM,\n          P2_EXTEND,\n          pathBuffer,\n          [STATUS_CODES.OK]\n        );\n        return result.toString(\"hex\").substring(0, 130);\n      } else {\n        const pathBuffer = this.pathToBuffer(path);\n        let result = await this.transport.send(\n          LEDGER_CLA,\n          INS.GET_ADDR,\n          showAddress ? P1_CONFIRM : P1_NON_CONFIRM,\n          P2_EXTEND,\n          pathBuffer,\n          [STATUS_CODES.OK]\n        );\n\n        result = result.slice(1, result[0] + 1);\n        return result.toString(\"hex\");\n      }\n    } catch (error) {\n      console.log(error);\n\n      throw this._convertTransportError(error);\n    }\n  }\n\n  async signMessage(path, msg) {\n    const checkedVersion = await this.checkVersion();\n    console.log(\"checkedVersion\", checkedVersion);\n\n    if (!checkedVersion) {\n      const pathBuffer = convertPathToBuffer(path);\n      const data = msg + pathBuffer.toString(\"hex\");\n      const chunks = data.match(/.{1,500}/g) || [];\n      if (chunks.length === 0) {\n        throw new Error(`Invalid data provided: ${data}`);\n      }\n\n      let result = null;\n      for (let i = 0; i < chunks.length; i++) {\n        const p1 = i === chunks.length - 1 ? 0x80 : 0x00;\n        const chunk = Buffer.from(chunks[i], \"hex\");\n        result = await this.transport.send(0x80, 0x02, p1, 0x00, chunk, [\n          STATUS_CODES.OK,\n        ]);\n      }\n      const dataLength = result[1];\n      const dataBuf = result.slice(2, dataLength + 2);\n      const r_length = dataBuf[1];\n      let r = dataBuf.slice(2, 2 + r_length);\n      if (r_length === 33 && r[0] === 0) {\n        r = r.slice(1);\n      }\n      let s = dataBuf.slice(r_length + 4);\n      if (s.length === 33 && s[0] === 0) {\n        s = s.slice(1);\n      }\n      const sign = Buffer.concat([r, s]).toString(\"hex\");\n      return sign;\n    }\n    const msgBuffer = Buffer.from(msg, \"hex\");\n    const reply = await this.#sendToDevice(path, INS.SIGN, msgBuffer);\n\n    if (reply <= 2) {\n      throw new Error(\"No more data but Ledger did not return signature!\");\n    }\n    console.log(\"reply\", reply.toString(\"hex\"));\n\n    const sign = this.getSignFromRelay(reply);\n    return sign;\n  }\n\n  async signOffchainMessage(path, msg) {\n    const checkedVersion = await this.checkVersion();\n    if (!checkedVersion) {\n      throw new Error(\"Unsupported app version\");\n    }\n    const msgBuffer = Buffer.from(msg, \"hex\");\n\n    const relay = await this.#sendToDevice(path, INS.SIGN_OFFCHAIN, msgBuffer);\n    const sign = this.getSignFromRelay(relay);\n    return sign;\n  }\n\n  _convertTransportError(error) {\n    switch (error.statusCode) {\n      case STATUS_CODES.SW_DENY:\n        error.message = i18n.t(\"common.rejectedByUser\");\n        break;\n      default:\n        error.message = `${i18n.t(\"common.transactionFailed\")}: 0x${error.statusCode?.toString(16)?.toUpperCase()}`;\n        break;\n    }\n    return error;\n  }\n}\n\nexport default OntLedgerNew;\n"
  },
  {
    "path": "src/core/runtime.js",
    "content": "import {get} from 'lodash'\nimport {\n  Crypto\n} from 'ontology-ts-sdk';\n\n\nimport {\n  getClient\n} from './network';\n\n\nexport async function getBalance(addr) {\n    let address = new Crypto.Address(addr);\n\n  const client = getClient();\n  const response = await client.getBalance(address);\n  const ont = Number(get(response, 'Result.ont'));\n  const ong = Number(get(response, 'Result.ong'));\n\n  return {\n    ong,\n    ont,\n  };\n}\n\nexport async function getUnboundOng(addr) {\n    let address = new Crypto.Address(addr);\n\n  const client = getClient();\n  const response = await client.getUnboundong(address);\n  const unboundOng = Number(get(response, 'Result'));\n  return unboundOng;\n}\n\nexport async function getGrantOng(addr) {\n    let address = new Crypto.Address(addr);\n    const client = getClient();\n    const response = await client.getGrantOng(address);\n    const grantOng = Number(get(response, 'Result'));\n    return grantOng;\n}\n\nexport async function invokeTx(tx) {\n    const client = getClient();\n    await client.sendRawTransaction(tx.serialize(), false, true);\n}\n\nexport async function invokeReadTx(tx) {\n    const client = getClient();\n    await client.sendRawTransaction(tx.serialize(), true, true);\n}"
  },
  {
    "path": "src/core/utils.js",
    "content": "import {\n  TEST_NET,\n  MAIN_NET,\n  MAIN_NET_LIST,\n  DEFAULT_SCRYPT,\n  TEST_NET_LIST\n} from './consts'\nimport axios from 'axios'\nimport store from '../store'\nimport {message} from 'ant-design-vue'\nimport i18n from './lang'\nimport {\n  BigNumber\n} from 'bignumber.js'\nimport numeral from 'numeral'\nimport {Crypto, RestClient} from 'ontology-ts-sdk'\nconst opn = require('opn')\nconst {\n    BrowserWindow\n  } = require('@electron/remote');\n\nconst os = require('os')\nconst fs = require('fs')\n\nexport function open(url) {\n  try {\n    opn(url)\n  } catch(err) {\n    let win = new BrowserWindow({width: 800, height: 600, center: true});\n    win.on('closed', () => {\n      win = null\n    })\n\n    // Load a remote URL\n    win.loadURL(url)\n  }\n}\nexport function varifyPositiveInt(value) {\n    if (!/^[1-9]\\d*$/.test(value)) {\n        return false;\n    }\n    return true;\n}\n\nexport function varifyOngValue(value) {\n    if (!/^[0-9]+(\\.[0-9]{1,9})?$/.test(value)) {\n        return false;\n    }\n    return true;\n}\n\nexport function varifyOpe4Value(value, decimal) {\n  if (decimal > 0) {\n    if (!new RegExp(`^[0-9]+(\\\\.[0-9]{1,${decimal}})?$`).test(value)) {\n        return false;\n    }\n  } else {\n    return varifyPositiveInt(value);\n  }\n  return true;\n}\n\nexport function isHexString(str) {\n    const regexp = /^[0-9a-fA-F]+$/;\n    return regexp.test(str) && (str.length % 2 === 0);\n}\n\nexport function getNodeUrl() {\n    // const net = localStorage.getItem('net');\n    // return net === 'TEST_NET' ? TEST_NET + ':20334' : MAIN_NET + ':20334'\n    // return 'http://139.219.128.220:20334' //for test\n    const net = localStorage.getItem('net')\n    let node = localStorage.getItem('nodeAddress');\n    if(!node) {\n      node = net === 'TEST_NET' ? TEST_NET_LIST[0] : MAIN_NET_LIST[0]\n    }\n    // const node = localStorage.getItem('nodeAddress') || MAIN_NET_LIST[0]\n    // node = 'http://172.168.3.151'\n    return node + ':20334';\n}\n\nexport function getRestClient() {\n  let url = getNodeUrl();\n  const restClient = new RestClient(url);\n  return restClient;\n}\n\nexport function convertNumber2Str(num, decimal = 0, division) {\n    const val = new BigNumber(num).dividedBy(Math.pow(10, decimal))\n    if(division) {\n      return val.toFixed(8);\n    }\n    return val.toString();\n}\n\nexport function convertStr2Number(str, decimal = 0) {\n    const val = new BigNumber(str).times(Math.pow(10, decimal))\n    return val.toNumber();\n}\n\nexport function decryptWallet(wallet, password, scrypt = DEFAULT_SCRYPT) {\n    const enc = new Crypto.PrivateKey(wallet.key)\n    let pri;\n    try {\n      pri = enc.decrypt(password, new Crypto.Address(wallet.address), wallet.salt, scrypt)\n    } catch (err) {\n      console.log(err);\n      store.dispatch('hideLoadingModals')\n      message.error(i18n.t('common.pwdErr'))\n      return;\n    }\n    return pri;\n}\n\nexport function validateAddress(address) {\n  try {\n    const addr = new Crypto.Address(address)\n    addr.serialize();\n    return true;\n  }catch(err) {\n    return false;\n  }\n}\n\nexport function convertScryptParams({n, r, p, dkLen}) {\n  return {\n    cost: n,\n    blockSize: r,\n    parallel: p,\n    size: dkLen\n  }\n}\n\n// 创建axios实例\nconst service = axios.create({\n  timeout: 15000 // 请求超时时间\n});\n\n// request拦截器\nservice.interceptors.request.use(\n  config => {\n    if(config.method !== 'get') { // 定时查询的时候不希望页面显示loading\n      store.dispatch('showLoadingModals')\n    }\n    return config;\n  },\n  error => {\n    console.log('e')\n    store.dispatch('hideLoadingModals')\n    Promise.reject(error);\n  }\n);\n// respone拦截器\nservice.interceptors.response.use(\n  response => {\n    store.dispatch('hideLoadingModals')\n    const data = response.data;\n    return data;\n  },\n  error => {\n    store.dispatch('hideLoadingModals')\n    const response = error.response;\n    message.error(i18n.t('commonWalletHome.networkError'))\n    return Promise.reject((response && response.data) || error);\n  }\n);\n\nexport default service;\n\nexport function getExplorerUrl() {\n  const net = localStorage.getItem('net');\n  const url = net === 'TEST_NET' ? 'https://polarisexplorer.ont.io' : 'https://explorer.ont.io';\n  return url;\n}\n\nexport function getTransactionListUrl(address, page_size = 10, page_number =1) {\n  const api = `/v2/addresses/${address}/transactions?page_size=${page_size}&page_number=${page_number}`\n  const url = getExplorerUrl() + api;\n  return url;\n}\n\nexport function getBalanceUrl(address, token_type = 'NATIVE') {\n   const api = `/v2/addresses/${address}/${token_type}/balances`\n   const url = getExplorerUrl() + api;\n   return url;\n}\n\nexport function getTokenListUrl(token_type = 'oep4', page_size = 10, page_number = 1) {\n  const api = `/v2/tokens/${token_type}?page_size=${page_size}&page_number=${page_number}`\n  const url = getExplorerUrl() + api;\n  return url;\n}\n\nexport function getTokenBalanceUrl(token_type, address) {\n  const api = `/v2/addresses/${address}/${token_type}/balances`\n  const url = getExplorerUrl() + api;\n  return url;\n}\n\nexport function validateKeystorePath(path) {\n  const system = os.platform();\n  if(system.indexOf('win') > -1 && system !== 'darwin') {\n    const files = fs.readdirSync(path)\n    if(files && files.indexOf('resources') > -1 && files.indexOf('OWallet.exe') > -1) {\n      return false;\n    }\n    const cwd = process.cwd();\n    if(path && cwd !== '/' && (path === cwd || path.indexOf(cwd) > -1)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nexport function formatScryptParams(scrypt) {\n  return {\n    cost: scrypt.n || 16384, // 除以2时间减半\n    blockSize: scrypt.r || 8,\n    parallel: scrypt.p || 8,\n    size: scrypt.dkLen || 64\n  }\n}\n\nexport function splitPath(path) {\n  let result = [];\n  let components = path.split('/');\n  components.forEach(element => {\n    let number = parseInt(element, 10);\n    if (isNaN(number)) {\n      throw Error(`Path ${path} is invalid.`);\n    }\n    if (element.length > 1 && element[element.length - 1] === \"'\") {\n      number += 0x80000000;\n    }\n    result.push(number);\n  });\n  return result;\n}\n\nexport function convertPathToBuffer(path) {\n  const paths = splitPath(path);\n  const buffer = Buffer.alloc(paths.length * 4);\n  paths.forEach((element, index) => {\n    buffer.writeUInt32BE(element, 4 * index);\n  });\n  return buffer;\n}\n"
  },
  {
    "path": "src/lang/en.js",
    "content": "export default {\n  common: {\n    testNet: 'TestNet',\n    mainNet: 'MainNet',\n    copied: 'Copied!',\n    confirmPwdTips: 'Please confirm and input the password your wallet.',\n    confirmTips: 'Please confirm the transfer.',\n    transSentSuccess: 'Transaction has been sent successfully!',\n    pwdErr: 'Password error',\n    ongNoEnough: 'Transaction does not have enough ONG to process',\n    transferFailed: 'Transfer failed. ',\n    networkErr: 'Network error!',\n    normalWallet: 'Individual wallet',\n    sharedWallet: 'Shared wallet',\n    hardwareWallet: 'Ledger wallet',\n    export: 'Export',\n    ledgerNotOpen: 'Ledger not open',\n    ledgerNotSupported: 'Ledger not supported',\n    pluginDevice: 'Please plugin the device and login.',\n    readyToSubmit: 'Ready to submit',\n    waitForSign: 'Waiting for sign',\n    readyToImport: 'Ready to connect',\n    existLocal: 'The wallet is already in local',\n    importLedgerSuccess: 'Import ledger wallet successfully.',\n    readyToLogin: 'Ready to login',\n    walletAddress: 'Wallet Address',\n    authentication: 'Authentication',\n    confirmation: 'Confirmation',\n    enterWalletPassword: 'Please enter your wallet password',\n    enterIdentityPassword: 'Please enter your ONT ID password',\n    password: 'Password',\n    invalidLedger: 'The current ledger dose not match with the wallet.Please try with another ledger device.',\n    exportDat: 'Export .dat',\n    exportWIF: 'Export WIF',\n    changePassword: 'Change Password',\n    deleteWallet: 'Delete Wallet',\n    more: 'More',\n    neoCompatible: 'NEO Address Compatible',\n    versionUpdate: 'You can upgrade your OWallet.',\n    getLatestVersion: 'Get the latest version here.',\n    changePassSuccess: 'Change password successfully',\n    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.)',\n    download: 'Download .dat',\n    balanceInsufficient: 'Sorry, your balance is insufficient.',\n    exportIdentity: 'Export keystore',\n    deleteIdentity: 'Delete ONT ID',\n    savedbFailed: 'Save to db file failed.Please make sure you have set the path to save the keystore.db file and try again.',\n    selectOep4: 'Select OEP-4 token',\n    contractHash: 'Contract hash: ',\n    txFailed: 'Transaction failed',\n    availableNewVersion: 'A new version is available. In order to get a better user experience, please upgrade OWallet.',\n    toUpdate: 'Upgrade now',\n    cancel: 'Cancel',\n    transactionFailed: 'Transaction failed',\n    rejectedByUser: 'Rejected by user'\n  },\n\n  FormField: {\n    label: 'name',\n    password: 'password',\n    passwordConfirmation: 'password confirmation',\n    mnemonic: 'mnemonic',\n    privateKey: 'private key',\n    oldPassword: 'old password',\n    newPassword: 'new password',\n    newPasswordConfirmation: 'new password confirmation'\n  },\n\n  TopNav: {\n    new: 'New',\n    edit: 'Edit'\n  },\n\n  basicInfo: {\n    InvalidMnemonic: 'Invalid mnemonic.',\n    errWif: 'Please enter a valid WIF.'\n  },\n\n  SetPaths: {\n    name: 'Keystore File Path',\n    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.',\n    close: 'Close',\n    enter: 'Set file path'\n  },\n\n  identitys: {\n    pageTit: 'ONT ID',\n    createIdentity: 'Create ONT ID',\n    importIdentity: 'Import ONT ID',\n    identity: 'Identity',\n    ontid: 'ONT ID'\n  },\n\n  createIdentity: {\n    create: 'Create ONT ID',\n    basicInfo: 'Basic info',\n    confirmInfo: 'Confirm info',\n    label: 'Name of Identity (ONT ID)',\n    password: 'Password',\n    rePassword: 'Repeat password',\n    cancel: 'Cancel',\n    next: 'Next',\n    ontid: 'ONT ID',\n    selectWallet: 'Select Wallet to pay for the transaction fee',\n    commonWallet: 'Individual Wallet',\n    ledgerWallet: 'Ledger Wallet',\n    payerPassword: 'Input the password of your selected wallet',\n    selectCommonWallet: 'Select local individual wallet',\n    selectOneWallet: 'Please select one individual wallet',\n    enterPassword: 'Please enter the password of your selected wallet',\n    createSuccess: 'Create ONT ID successfully!'\n  },\n\n  importIdentity: {\n    import: 'Import ONT ID',\n    basicInfo: 'Basic info',\n    keystore: 'ONT ID Keystore',\n    ontidPassword: 'ONT ID Password',\n    label: '',\n    passError: 'Password error',\n    ontidNotExist: 'The ONT ID to import does not exist on the blockchain',\n    keystoreImport: 'ONT ID Keystore Import',\n    invalidKeystore: 'The keystore you input is invalid.',\n    ontidExist: 'The identity already exists in local.',\n    importSuccess: 'Import Identity succeed!'\n  },\n\n  wallets: {\n    all: 'All Wallets',\n    common: 'Individual Wallet',\n    shared: 'Shared Wallet',\n    temp: 'TEMP',\n    createCommonWallet: 'Create Wallet',\n    importCommonWallet: 'Import Wallet',\n    createSharedWallet: 'Create Wallet',\n    joinSharedWallet: 'Join Wallet',\n    importLedgerWallet: 'Connect Ledger',\n    ledger: 'Ledger Wallet',\n    comingSoon: 'Coming soon...',\n    ledgerHelpLink: 'How to use?',\n    deleteSucceess: 'Delete wallet successfully.',\n    deleteFailed: 'Delete wallet failed.',\n    deleteingWallet: 'You are about to delete wallet with address: ',\n    exportingWallet: 'You are about to export the .dat file of wallet with address: ',\n    exportingWIF: 'You are about to export the private key(WIF) of wallet with address: ',\n    oldPassword: 'Old password',\n    newPassword: 'New password',\n    reNewPassword: 'Repeat new password',\n    changePassSuccess: 'Change password successfully!',\n    exportOntid: 'You are about to export the keystore of identity with ONT ID:',\n    deleteIdentityFailed: 'Delete ONT ID failed',\n    deleteIdentitySuccess: 'Delete ONT ID successfully',\n    exportedWIF: 'Your private key (WIF) is:'\n  },\n\n  dashboard: {\n    getTransErr: 'Fetch transaction history failed. Network error. Please try later.',\n    getBalanceErr: 'Fetch balance failed. Network error. Please try later.'\n  },\n\n  createJsonWallet: {\n    create: 'Create Individual Wallet',\n    basicInfo: 'Basic info',\n    label: 'Name of Individual Wallet',\n    password: 'Password',\n    rePassword: 'Repeat password',\n    next: 'Next',\n    cancel: 'Cancel',\n    back: 'Back',\n    details: '',\n    confirmInfo: 'Confirm info',\n    labelN: 'Label',\n    addressN: 'Address',\n    pubKeyN: 'Public key',\n    signatureSchemeN: 'Signature scheme',\n    wif: 'WIF',\n    mnemonic: 'Mnemonic phrase',\n    privateKey: 'Private Key',\n    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.',\n    createSuccess: 'Create individual wallet successfully.',\n    createFail: 'Create individual wallet failed. Please try again.',\n    download: \"Download .dat\",\n    privateKey64Hex: 'Private key (64 Hex)',\n    priavteKeywif: 'Private key (WIF)',\n    keystoreDat: 'Keystore (.dat)'\n  },\n\n  importJsonWallet: {\n    datFile: 'Select file',\n    invalidDatFile: 'Please select the valid keystore (.dat) file.',\n    selectedDatFile: 'Selected file: ',\n    dat: '.dat File',\n    datImportPassword: 'Password to decrypt keystore (.dat)',\n    create: 'Import Individual Wallet',\n    basicInfo: 'Basic info',\n    label: 'Set a new name for the wallet',\n    wif: 'WIF',\n    wifTip: 'Please enter 52-bit WIF',\n    privateKeyTip: 'Please enter private key with 64 byte hex format',\n    datPassword: 'New Password',\n    datRePassword: 'Repeat New password',\n    password: 'Password',\n    rePassword: 'Repeat password',\n    next: 'Import',\n    cancel: 'Cancel',\n    back: 'Back',\n    details: '',\n    confirmInfo: 'Confirm info',\n    mnemonic: 'Please use a space to separate each of the words.',\n    privateKey: 'Private Key',\n    createSuccess: 'Create Individual wallet successfully!',\n    confirmImport: 'Confirm Import',\n    confirmImportExist: 'The wallet to import is already in your local. Still want to import it?',\n    success: 'Import wallet successfully!',\n    saveDbFailed: 'Save to keystore failed. Please try later.',\n    invalidPrivateKey: 'Please enter valid private key.',\n    setPassword: 'Set password',\n    importFirstDefault: 'Will only import the default wallet or the first wallet in the .dat file'\n  },\n\n  createSharedWallet: {\n    basicInfo: 'Basic info',\n    copayers: 'Co-payers',\n    processing: 'Processing',\n    label: 'Name of shared wallet',\n    copayers2_12: 'Co-payers(2-12)',\n    address: 'Address',\n    inputPks: 'Input 2 - 12 public keys\\' info',\n    name: 'Name',\n    publicKey: 'Public key',\n    add: '+ Add',\n    next: 'Next',\n    cancel: 'Cancel',\n    back: 'Back',\n    importSharedWallet: 'Import shared wallet',\n    requiredSigNum: 'Number of required signatures ',\n    success: 'Success',\n    duplicateCreate: 'The shared wallet is already existed.Please import it.',\n    createFailed: 'Failed. Please try later.',\n    createSuccess: 'Create shared wallet successfully.',\n    create: 'Create Shared Wallet',\n    walletNameErr: 'Wallet name can not be more than 12 characters',\n    emptyLabel: 'Wallet name can not be empty',\n    pksLte2: 'The number of co-payers can not be less than 2. ',\n    invalidPk: 'Invalid public key',\n    duplicatePks: 'There must be no duplicate public key among the co-payers',\n    duplicateNames: 'There must be no duplicate names key among the co-payers'\n  },\n\n  importSharedWallet: {\n    import: 'Join shared wallet',\n    basicInfo: 'Basic info',\n    inputPass: 'Input password',\n    importSuccess: 'Success',\n    inputAddress: 'Address of shared wallet',\n    search: 'Search',\n    name: 'Shared wallet name',\n    totalCopayerNumber: 'Total number of co-payers',\n    requiredCopayerNumber: 'Required number of co-payers',\n    allCopayers: 'Address of all Co-payers',\n    noResult: 'No result',\n    address: 'Address',\n    chooseLocalWallet: 'Select local wallet to join',\n    localWalletInfo: 'Local wallet detail',\n    walletName: 'Wallet name',\n    pk: 'Public key',\n    next: 'Next',\n    cancel: 'Cancel',\n    back: 'Back',\n    join: 'Join',\n    inputPassword: 'Enter password to join',\n    joinBefore: 'You have joined this wallet before.',\n    success: 'Join shared wallet succeed!',\n    passwordError: 'Password error.',\n    sorry: 'Sorry!',\n    notFound: 'The shared wallet you are looking for is not found.'\n  },\n\n  importLedgerWallet: {\n    import: 'Connect Ledger Wallet',\n    label: 'Name of Ledger Wallet',\n    next: 'Connect',\n    neoCompatible: 'NEO Address Compatible'\n  },\n\n  sharedWalletHome: {\n    send: 'Send',\n    receive: 'Receive',\n    claim: 'Claim',\n    rule: 'Rule',\n    copayers: 'Co-payers',\n    pendingTx: 'Pending transactions',\n    completedTx: 'Completed transactions',\n    owners: 'Owners',\n    address: 'Address',\n    amount: 'Amount',\n    max: 'MAX',\n    to: 'To',\n    recipient: 'Recipient address',\n    cancel: 'Cancel',\n    next: \"Next\",\n    back: 'Back',\n    submit: 'Submit',\n    asset: 'Asset',\n    sponsor: 'Sponsor',\n    dragDecide: 'Drag to decide sign sequence',\n    fee: 'Fee',\n    inputPassword: 'Input Password',\n    inputPassToTransfer: 'Input password to complete transfer',\n    walletAddress: 'Wallet address',\n    createTime: 'Creation time',\n    balance: 'Balance',\n    confirmation: 'Confirmation',\n    agreeToSend: 'I confirm the asset amount and recipient address are correct.',\n    signSequence: 'Sign sequence',\n    sign: 'Sign',\n    checkMore: 'Check more',\n    publicKey: 'Public key',\n    redeemOng: 'Redeem ONG',\n    paxMgmt: 'PAX management',\n    unprocessed: 'Unprocessed',\n    processing: 'In processing',\n    completed: 'Completed',\n    txMgmt: 'Transaction management',\n    createTransferFailed: 'Create transfer transaction failed.',\n    createTransferSuccess: 'Create transfer transaction succeed.',\n    txSendingTochain: 'This transaction is sending to the blockchain now.'\n  },\n\n  pax: {\n    ethAddress: 'Eth Address',\n    ontAddress: 'Ont Address',\n    amount: 'Amount',\n    date: 'Date',\n    toProcess: 'To process',\n    paxStart: 'Start',\n    paxSign: 'Sign',\n    selectCurrentSigner: 'Select current signer: ',\n    back: 'Back',\n    confirm: 'Confirm',\n    sponsorSign: 'Sponsor sign',\n    inputPassword: 'Input the password of current signer',\n    queryEthScan: 'Query Total Eth amount',\n    currentSign: 'Current signer sign',\n    txToSend: 'Number of transactions to send: ',\n    txSent: 'Number of transactions sent succeed: ',\n    sendingTx: 'Sending transactions',\n    selectedNum: 'Number of selected orders: ',\n    totalAmount: 'Total amount of selected orders: ',\n    ethTotal: 'Total amount of received ETH: ',\n    startProcessSuccess: 'Start process succeed.',\n    signSuccess: 'Sign transactions succeed.',\n    ledgerSignMultiTimes: 'You may have to sign multi times on your ledger device',\n    hasSignedSent: 'These transactions has been signed and sent. Please review the completed data.',\n    toEthScan: 'To Eth Scan',\n    txCompleted: 'Transaction completed',\n    txDetail: 'Detail',\n    toVarify: 'Verify',\n    varifySuccess: 'Verify succeed!',\n    varifyFailed: 'Verify failed!',\n    varifyResult: 'Verified result',\n    failedTxhashes: 'Failed transaction hash:'\n  },\n\n  sharedTx: {\n    startTx: 'Start multi-sign transaction',\n    signTx: 'Sign multi-sign transaction',\n    selectSponsor: 'Select sponsor',\n    createTx: 'Create Transaction',\n    contractHash: 'Contract hash',\n    method: 'Method',\n    parameters: 'Parameters',\n    starterSign: 'Start sign',\n    txSerialized: 'Signed and serialized transaction：',\n    addSign: 'Add signature',\n    txContent: 'Transaction data',\n    currentSign: 'Current signer',\n    selectSigner: 'Select wallet to sign',\n    copy: 'Copy',\n    send: 'Send now',\n    isSendTxTip: 'The transaction can be sent to the blockchain now. Confirm to send?',\n    txSentSuccess: 'Send transaction succeed.',\n    paramsError: 'Error parameters. Please check the input.'\n  },\n\n  commonWalletHome: {\n    claimableOng: 'Claimable ONG',\n    unboundOng: 'Unbound ONG',\n    redeem: 'Redeem',\n    receive: 'Receive',\n    swap: 'Swap',\n    walletQrCode: 'Wallet QR code',\n    walletAddress: 'Wallet address',\n    publicKey: 'Public key',\n    redeemCharge: 'Each redeem charges 0.01 ONG',\n    inputPass: 'Please input your wallet password',\n    emptyPass: 'Password can not be empty',\n    cancel: 'Cancel',\n    submit: 'Submit',\n    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',\n    stepFollow: 'Just do as follows:',\n    step1: '1. Import your private key(from your NEO wallet) to create a wallet',\n    step2: '2. Press [Swap] button to start the swap',\n    step3: '3. View the status of your token swap',\n    swapAmount: 'Swap Amount',\n    nep5Balance: 'Balance of NEP-5 ONT:',\n    password: 'Password',\n    validAmount: 'Please input valid amount',\n    checkMore: 'Check more',\n    balance: 'Balance',\n    scriptHash: 'Script hash',\n    add: '+ Add',\n    addOep4: 'Add OEP-4 Token',\n    enterScripthash: 'Please enter the OEP-4 token script hash',\n    invalidScriptHash: 'The script hash is invalid',\n    addOep4Success: 'Add OEP-44 token succeed!',\n    noOep4Contract: 'The OEP-44 contract is not found',\n    networkError: 'Network error! Please try later.',\n    oep4Exists: 'You have already added this OEP-4 token.',\n    go: 'Go'\n  },\n\n  transfer: {\n    inputValidAmount: 'Please input valid transfer amount.',\n    inputValidAddress: 'Please input valid receiver address.',\n    exceedBalance: 'Amount of transfer can not exceed your balance.',\n    ongBalanceNotEnough: 'Your ONG balance is not enough for transfer and fee.',\n    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?'\n  },\n\n  setting: {\n    name: 'Setting',\n    net: 'Network',\n    lang: 'Language',\n    testNet: 'TestNet',\n    mainNet: 'MainNet',\n    en: 'English',\n    zh: '中文',\n    pathTit: 'Path: ',\n    path: 'Save keystore file path（Please do not set to the installation location of OWallet!）',\n    change: 'Change',\n    setNetworkSuccess: 'The network has been set to: ',\n    wallets: 'Wallets',\n    ontid: 'ONT ID',\n    nodeStake: 'Node Stake',\n    help: 'Help',\n    settings: 'Settings',\n    nodeAddress: 'Node address',\n    setNodeSuccess: 'The node address has been set t: ',\n    notInstallationPath: 'Please do not set to the installation location of OWallet.',\n    notSetPath: 'You did not set the keystore path.'\n  },\n\n  ledgerWallet: {\n    nameOfLedgerWallet: 'Name of your ledger wallet',\n    info: 'Ledger Info',\n    connectApp: 'Please connect to your ledger device and open the ONT app on it.',\n    status: 'Device Status',\n    labelEmpty: 'Label can not be empty.',\n    deviceError: 'Can not connect to device.Please try again.',\n    signFailed: 'Sign with ledger failed.',\n    selectAccount:\"Please select the account(s) on your Ledger device.\",\n    normalMode:'Normal Mode',\n    advancedMode:'Advanced Mode',\n    alreadyImported:\"Some selected accounts already imported\",\n    specifyPath:\"Please select and specify the path to import the account\",\n    pleaseSelectWallet:\"Please select the wallet you want to import and enter a name\",\n  },\n\n  ledgerStatus: {\n    NOT_FOUND: 'Ledger not open',\n    NOT_SUPPORT: 'Ledger not supported',\n    NO_DEVICE: 'Please plugin the device and login.',\n    READY: 'Ledger is Ready',\n    NOT_OPEN: 'The ONT app on ledger is not open.'\n  },\n  nodeStake: {\n    iHaveKnown: 'I Have Known',\n    ontid: 'ONT ID',\n    nodeStake: 'Node Stake',\n    stakeWalletAddress: 'Stake Wallet Address',\n    nodePk: 'Node Public Key',\n    contract: 'Contract',\n    commitmentQuantity: 'Commitment Amount',\n    stakeQuantity: 'Stake Amount',\n    claimableQuantity: 'Claimable Amount',\n    stake: 'Stake',\n    feeTip: 'Stake needs 500 ONG for service fee',\n    selectOntid: 'Select ONT ID',\n    selectStakeWallet: 'Select stake wallet',\n    next: 'Next',\n    selectIdentity: 'Please select your ONT ID',\n    selectIndividualWallet: 'Please select your individual wallet',\n    selectLedgerWallet: 'Please connect your ledger and open ONT app on it.',\n    invalidOntid: 'Invalid ONT ID ',\n    invalidAddress: 'Invalid stake wallet address',\n    stakeQuantityEmpty: 'Please enter valid stake quantity',\n    password: 'Enter Password',\n    signWithOntid: 'Sign with ONT ID',\n    signWithWallet: 'Select wallet',\n    enterOntidPass: 'Please enter the password of your ONT ID',\n    enterWalletPass: 'Please enter the password of the selected wallet',\n    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.',\n    back: 'Back',\n    recall: 'Recall',\n    refund: 'Refund',\n    quitNode: 'Quit Node',\n    newStake: 'New Stake',\n    passwordEmpty: 'Password can not be empty',\n    search: 'Search'\n  },\n  nodeStakeStatus: {\n    transfering: 'Transferring',\n    transfered: 'Transferred',\n    transferFailed: 'Transfer Failed',\n    audit: 'Audit',\n    auditing: 'Auditing',\n    audited: 'Audited',\n    auditFailed: 'Audit Failed',\n    stake: 'Stake',\n    staked: 'Staked',\n    nodeExited: 'Node Exited',\n    refund: 'Refund',\n    refunding: 'Refunding',\n    refunded: 'Refunded',\n    refundFailed: 'Refund Failed',\n    stakeExited: 'Stake Exited',\n    quitStake: 'Quit Stake',\n    unfrozenToRefund: 'Unfreeze successfully, you can refund now',\n    transferNeedTime: 'Transfer needs a period of time',\n    serviceFee: 'Stake needs 500 ONG for service fee',\n    auditNeedTime: 'Audit needs a period of time',\n    refundNeedTime: 'Refund needs a period of time',\n    txFailed: 'Transaction failed.'\n  },\n  redeemInfo: {\n    info: 'Redeem Info',\n    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.`,\n    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).`,\n    claimableOngName: 'Claimable ONG: ',\n    unboundOngName: 'Unbound ONG: ',\n    noClaimableOng: 'Your claimable ONG is 0. When a transaction of ONT is made in your address, the claimable ONG balance will update'\n  },\n\n  nodeMgmt: {\n    nodeUser: 'If you are a candidate node, you can stake and manage your stake here.',\n    nodeStakeMgmt: 'Node Stake Management',\n    normalUser: 'If you are a normal user, you can participate in stake authorization here.',\n    stakeAuthorizaton: 'Stake Authorization',\n    nodeStake: 'Node Stake',\n    userStakeAuthorization: 'User Stake Authorization',\n    newStake: 'Submit A New Stake',\n    allowStakes: 'Allow stakes from other users',\n    deny: 'Deny',\n    permit: 'Permit',\n    yourStakeAmount: 'Your node stake amount',\n    stakeLimit: 'Total max stake limit',\n    userNumber: 'Current number of users staking',\n    userStakeAmount: 'Current total stake of users',\n    rewardsPerMonth: 'Estimate total rewards per month',\n    rewardsTip: 'Estimate total rewards per month includes your rewards and the rewards of other uesrs staking.',\n    rewardProportion: 'Fee Sharing Ratio: ',\n    nodeRewardProportion: 'Fee Sharing Ratio (Node)',\n    userRewardProportion: 'Fee Sharing Ratio (User)',\n    current: 'current',\n    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).',\n    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).',\n    confirm: 'Confirm',\n    changesTakeEffect: ' Changes will take effect in two consensus rounds (each round is approximately every 30 days). ',\n    stakeAuthorization: 'Stake Authorization',\n    toNextRound: 'Next round in',\n    rank: 'Rank',\n    name: 'Name',\n    currentStake: 'Current total stake',\n    process: 'Stake progress',\n    changes: 'Changes',\n    userParticipate: 'Only proceed if you want to participate in stake authorization!',\n    nodeName: 'Node name',\n    walletAddress: 'Your wallet address',\n    inAuthorization: 'Total authorized stake',\n    cancelStakeAuthorization: 'Cancel stake authorization',\n    locked: 'Canceled(locked)',\n    claimable: 'Redeemable',\n    redeem: 'Redeem',\n    profit: 'Profit',\n    rewards: 'Rewards',\n    newStakeAuthorization: 'Submit new stake authorization',\n    cancelAuthorization: 'Cancel stake authorization',\n    units: 'Units of stake authorization',\n    stakeAmountTip: 'Stake amount = input number * 1 ONT/unit.',\n    stakeAmount: 'Stake amount',\n    submit: 'Submit',\n    allowedStakeUnits: 'Allowed stake unit',\n    allowedStakeAmount: 'Allowed stake amount',\n    noChange: 'You did not make a change.',\n    noRewards: 'No rewards to redeem.',\n    switchWallet: 'Switch wallet',\n    noClaimableOnt: 'No redeemable ONT',\n    amountToCancel: 'Amount to cancel',\n    unitToCancel: 'Units to cancel',\n    invalidInput: 'Please enter valid value.',\n    peerNotAllowAuthorize: 'This peer does not allow authorization now.',\n    addInitPos: 'Add to stake',\n    reduceInitPos: 'Reduce stake',\n    amountToAdd: 'Amount To Add',\n    amountToReduce: 'Amount To Reduce',\n    notThanCommitment: 'Stake quantity can not be less than the commitment stake quantity.',\n    notLessTotalPos: 'The initial stake amount is too small.',\n    notThanMax: 'Allowed stake can not be more than the max stake limit.',\n    refresh: 'Refresh',\n    totalStakeAmount: 'Total Authorization Amount',\n    blocks: 'Blocks',\n    proportionNextRound: \"Fee Sharing Ratio (Node/User)\",\n    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.',\n    authorizationFAQ: 'OWallet Stake Authorization FAQ',\n    nodeAndUser: 'Node / User',\n    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.`,\n    rewardTip: `All transactions fees received by Ontology are distributed to all candidate nodes and consensus nodes - 50% to each group.\nWithin their 50% share each candidate node will receive their share linearly according to their stake amount.\nWithin 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.\n`,\n    unboundOng: 'Unbound ONG',\n    activeT: 'Active in current round',\n    activeT1: 'Active in next round',\n    activeT2: 'Active in next 2 round',\n    changeRewardProportion: 'Change Fee Sharing Ratio',\n    edit: 'Edit',\n    stakeHistory: 'My Stake',\n    cancelUnits: 'units',\n    stakeWalletAddress: 'Stake wallet address',\n    lastUpdate: 'Last update time',\n    walletRewardTip: 'This is all the reward of your wallet in current round.',\n    switchMainnet: 'Please switch to MainNet.',\n    consensusNode: 'Consensus node',\n    candidateNode: 'Candidate consensus node',\n    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.',\n    unboundONG: 'This is the unbound ONG amount of your authorized ONT stake.',\n    profitONG: 'This is the transaction fee profit you have made. This will update at the beginning of each new consensus round.',\n    getProfitPart: 'Already receiving profit portion',\n    newStakePart: 'New stake portion',\n    claimableONT: 'Claimable ONT',\n    redeemInitPos: 'Redeem claimable stake',\n    initPosInLock: \"Locked\",\n    initPosRedeemable: 'Claimable',\n    noClaimbleInitPos: 'No claimable ONT.',\n    redeemInitPosOk: 'Redeem',\n    hasClaimableInitPos: 'You have redeemable init pos. Please redeem this part first.',\n    noClaimbleToRefund: 'No redeemable ONT to refund.',\n    newNodeApply: 'New Node Apply',\n    nodeApplyTip: ''\n  },\n  vote: {\n    node: 'Node',\n    vote: 'Vote',\n    voteTip: \"For authorized users, vote here\",\n    login: 'Sign in',\n    notSeeWallet: \"Didn't see your wallet? Import one \",\n    importHere: 'here',\n    notStart: 'Not started',\n    inProgress: 'In Progress',\n    finished: 'Finished',\n    canceled: 'Canceled',\n    nodeCanVoteOnly: '*Only users from consensus nodes are allowed to vote.',\n    title: 'Title',\n    detail: 'Detail',\n    votingStarts: 'Vote start time',\n    votingEnds: 'Vote end time',\n    back: 'Back',\n    submit: 'Submit',\n    submitVoteSuccess: 'Vote succeeded',\n    submitVoteFail: 'Vote failed',\n    stopVoteSuccess: 'Vote cancelled',\n    stopVoteFail: 'Vote cancellation failed',\n    createVoteSuccess: 'Vote created',\n    createVoteFail: 'Vote creation failed',\n    onlySupportEnglish: 'Only English is allowed',\n    fillBlanks: 'Please fill in the blanks.',\n    endTimeError: \"The vote must end in a future time.\",\n    votingTopics: 'Voting Topics',\n    votingDetail: 'Voting Detail',\n    stopVote: 'Cancel Voting',\n    info: 'Info',\n    startTime: 'Starting time',\n    endTime: 'Ending time',\n    hash: 'Hash',\n    creatorAddress: 'Creator address',\n    votingStatus: 'Vote status',\n    myVotes: 'My vote(s)',\n    approval: 'Approved',\n    opposition: 'Denied',\n    allVotes: 'All votes',\n    created: 'Created by me',\n    duration: 'Duration',\n    notAllowVote: 'You cannot vote now, the vote is: ',\n    notAllowStop: 'You cannot stop the vote now, the vote is : ',\n    name: 'Name',\n    address: 'Address',\n    votes: 'Number of votes',\n    selectWallet: 'Select node operation wallet',\n    startTimeError: 'Start time cannot be later than end time.',\n    new: 'New'\n  },\n  nodeApply: {\n    newNodeApply: 'New node apply',\n    stakeWallet: 'Stake wallet',\n    operationWallet: 'Node operation wallet',\n    selectOperationWallet: 'Select operation wallet',\n    operationPk: 'Operation wallet public key',\n    enterOperationPk: 'Enter operation wallet public key',\n    invalidOperationPk: 'Invalid operation wallet',\n    stakeAmount: 'Stake amount',\n    inputStakeAmount: 'Enter stake amount',\n    next: 'Next',\n    ok: 'OK',\n    cancel: 'Cancel',\n    operationWalletPublickey: 'Node operation wallet publickey',\n    registerSuccess: 'Congratulations on the successful node registration',\n    completeNodeInfo: 'Complete node info now',\n    later: 'Later',\n    sameWalletNotAllowed: 'The operation wallet and staking wallet can not be the same',\n    operationWalletRequired: 'Operation wallet is required',\n    stakeWalletRequired: 'Stake wallet is required',\n    stakeAmountRequired: 'Stake amount is required',\n    minStateAmount: 'The stake amount is at least 10,000 ONT',\n    proxyServiceTip: 'The Ontology community now provides node operation by proxy service.',\n    proxyServiceLink: 'Click here to find out more.',\n    unsupportedLedger:\"Ledger hardware wallet is currently not supported as operation wallet for node registration.\",\n  },\n  myNode: {\n    myNode: 'My nodes',\n    stakeWalletAddress: 'Stake wallet address',\n    operationWalletPk: 'Operation wallet public key',\n    manage: 'Manage',\n    applyNode: 'Apply new node'\n  },\n  nodeInfo: {\n    nodeInfo: 'Node info',\n    name: 'Name',\n    enterName: 'Name',\n    logo: 'Logo',\n    enterLogo: 'Url of logo',\n    location: 'Region',\n    enterLocation: 'Region of node',\n    ip: 'IP',\n    enterIp: 'Ip of node',\n    description: 'Description',\n    enterDesc: 'Description of node',\n    website: 'Website',\n    enterWebsite: 'Website of node',\n    telegram: 'Telegram',\n    enterTelegram: 'Telegram of node',\n    twitter: 'Twitter',\n    enterTwitter: 'Twitter',\n    facebook: 'Facebook',\n    enterFacebook: 'Facebook',\n    contactOntologyEmail: 'Email to contact with Ontology',\n    enterContactEmail: 'Email to contact with Ontology',\n    openEmail: 'Open email',\n    enterOpenEmail: 'Open email',\n    ifOpenInfo: 'Switch to open info',\n    submit: 'Submit',\n    updateSuccess: 'Update node info succeed',\n    updateFailed: 'Update node info failed',\n    ledgerWalletNotSupportForNow: 'Nodes registered with ledger currently do not support updating node-related information. Please email to: '\n  },\n  exchange: {\n    exchange: 'Exchange',\n    changelly: 'Changelly',\n    cryptonex: 'Cryptonex',\n    loading: 'Loading latest pricing information, please wait..'\n  },\n  dapps: {\n    dapps: 'DApps',\n    sesameSeed: 'Sesameseed',\n    sesameseedDesc: 'Sesameseed voting management',\n    notification: 'Notification',\n    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.',\n    ontidMgmt: 'ONT ID management. This feature will be removed in the future. Please backup ONT ID related data'\n  },\n  sesameseed: {\n    stakeAmountTip: 'Stake amount for Sesameseed is 1 unit equals 1 ONT',\n    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.',\n    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.',\n    pendingWithdrawals: 'Pending canceled stake authorization'\n  }\n}\n"
  },
  {
    "path": "src/lang/index.js",
    "content": "import Vue from \"vue\";\nimport VueI18n from \"vue-i18n\";\nimport en from \"./en\";\nimport zh from \"./zh\";\nimport LangStorage from \"../core/lang\";\n\nVue.use(VueI18n);\n\nconst messages = {\n  en,\n  zh\n};\n\nconst i18n = new VueI18n({\n  locale: \"en\", //LangStorage.getLang(\"en\"),\n  messages\n});\n\nexport default i18n;\n"
  },
  {
    "path": "src/lang/zh.js",
    "content": "export default {\n  common: {\n    testNet: 'TestNet',\n    mainNet: 'Main Net',\n    copied: '已复制！',\n    confirmPwdTips: '请确认并输入钱包密码。',\n    confirmTips: '请确认转账',\n    transSentSuccess: '交易已成功发送',\n    pwdErr: '密码错误',\n    ongNoEnough: 'ONG不足，无法支付转账手续费。',\n    transferFailed: '交易失败。',\n    networkErr: '网络错误！',\n    normalWallet: '普通钱包',\n    sharedWallet: '共享钱包',\n    hardwareWallet: 'Ledger钱包',\n    export: '导出',\n    ledgerNotOpen: 'Ledger未打开',\n    ledgerNotSupported: 'Ledger不支持',\n    pluginDevice: '请连接设备并登录.',\n    readyToSubmit: '可以提交',\n    waitForSign: '等待签名',\n    readyToImport: '可以连接Ledger钱包',\n    existLocal: '本地已有此钱包',\n    importLedgerSuccess: '导入Ledger钱包成功',\n    readyToLogin: '可以登录',\n    walletAddress: '钱包地址',\n    authentication: '验证',\n    confirmation: '确认',\n    enterWalletPassword: '请输入钱包密码',\n    enterIdentityPassword: '请输入ONT ID密码',\n    password: '密码',\n    invalidLedger: '当前Ledger设备与要打开的钱包不匹配，请尝试正确的ledger设备。',\n    exportDat: '导出.dat',\n    exportWIF: '导出WIF',\n    changePassword: '修改密码',\n    deleteWallet: '删除钱包',\n    more: '更多',\n    neoCompatible: '兼容NEO地址',\n    versionUpdate: '您可以升级OWallet。',\n    getLatestVersion: '下载最新版本。',\n    changePassSuccess: '修改密码成功',\n    changePassSuccessTip: '您已经修改了钱包密码。我们建议您下载并备份钱包的.dat文件。(旧的.dat文件可以被替换或者删除)',\n    download: 'Download',\n    balanceInsufficient: '抱歉，您的余额不足',\n    exportIdentity: '导出keystore',\n    deleteIdentity: '删除ONT ID',\n    savedbFailed: '保存到keystore.db文件失败。请确保已设置keystore.db保存路径后重新尝试。',\n    selectOep4: '选择OEP-4 Token',\n    contractHash: '合约哈希：',\n    txFailed: '该交易在区块链上失败。',\n    availableNewVersion: '有新版本可用。为了获得更好的使用体验，请升级OWallet。',\n    toUpdate: '立即升级',\n    cancel: '取消',\n    transactionFailed: '交易失败',\n    rejectedByUser: '用户拒绝'\n  },\n\n  FormField: {\n    label: '名称',\n    password: '密码',\n    passwordConfirmation: '确认密码',\n    mnemonic: '助记词',\n    privateKey: '私钥',\n    oldPassword: '旧密码',\n    newPassword: '新密码',\n    newPasswordConfirmation: '确认新的密码'\n  },\n\n  TopNav: {\n    new: '新建',\n    edit: '编辑'\n  },\n\n  basicInfo: {\n    InvalidMnemonic: '无效的助记词。',\n    errWif: '无效的WIF'\n  },\n\n  SetPaths: {\n    name: '钱包文件存储路径',\n    tips: '* 钱包文件keystore.db保存着您的加密私钥，请确保您的PC安全和做好keystore.db文件的备份。您需要设置keystore文件的保存路径。请不要设置到OWallet的安装位置以免更新时被覆盖。',\n    close: '关闭',\n    enter: '去设置'\n  },\n\n  identitys: {\n    pageTit: 'ONT ID',\n    createIdentity: '创建ONT ID账户',\n    importIdentity: '导入ONT ID账户',\n    identity: 'Identity',\n    ontid: 'ONT ID'\n  },\n\n  createIdentity: {\n    create: '创建ONT ID账户',\n    basicInfo: '基本信息',\n    confirmInfo: '确认信息',\n    label: 'ONT ID账户昵称',\n    password: '账户密码',\n    rePassword: '确认密码',\n    cancel: '取消',\n    next: '继续',\n    ontid: 'ONT ID',\n    selectWallet: '请选择钱包来支付交易费用',\n    commonWallet: '普通钱包',\n    ledgerWallet: 'Ledger钱包',\n    payerPassword: '输入所选钱包的密码',\n    selectCommonWallet: '选择本地普通钱包',\n    selectOneWallet: '请选择一个本地钱包',\n    enterPassword: '请输入钱包密码',\n    createSuccess: '创建ONT ID成功！'\n  },\n\n  importIdentity: {\n    import: '导入ONT ID',\n    basicInfo: '基本信息',\n    keystore: 'ONT ID Keystore',\n    ontidPassword: 'ONT ID 密码',\n    label: '',\n    passError: '密码错误',\n    ontidNotExist: '要导入的ONT ID不存在于区块链上',\n    keystoreImport: '导入ONT ID Keystore',\n    invalidKeystore: '您输入的keystore不正确。',\n    ontidExist: '要导入的ONT ID本地已存在。',\n    importSuccess: '导入ONT ID成功。'\n  },\n\n  wallets: {\n    all: '全部钱包',\n    common: '普通钱包',\n    shared: '共享钱包',\n    temp: '之前的临时功能',\n    createCommonWallet: '创建钱包',\n    importCommonWallet: '导入钱包',\n    createSharedWallet: '创建钱包',\n    joinSharedWallet: '加入钱包',\n    importLedgerWallet: '连接Ledger钱包',\n    ledger: 'Ledger钱包',\n    comingSoon: '敬请期待',\n    ledgerHelpLink: '如何使用',\n    deleteSucceess: '删除钱包成功.',\n    deleteFailed: '删除钱包失败.',\n    deleteingWallet: '您正在删除钱包，钱包地址是：',\n    exportingWallet: '您正在导出钱包.dat文件，钱包地址是：',\n    exportingWIF: '您正在导出钱包的私钥(WIF), 钱包地址是：',\n    oldPassword: '旧密码',\n    newPassword: '新密码',\n    reNewPassword: '重复新密码',\n    changePassSuccess: '修改密码成功！',\n    exportOntid: '您正要导出ONT ID的keystore:',\n    deleteIdentityFailed: '删除ONT ID失败',\n    deleteIdentitySuccess: '删除ONT ID成功。',\n    exportedWIF: '您的私钥（WIF）是：'\n  },\n\n  dashboard: {\n    getTransErr: '交易记录获取失败，网络错误。请稍后重试。',\n    getBalanceErr: '余额获取失败。网络错误，请稍后重试。'\n  },\n\n  createJsonWallet: {\n    create: '新建普通钱包',\n    basicInfo: '基本信息',\n    label: '钱包名称',\n    password: '输入密码',\n    rePassword: '重复密码',\n    next: '继续',\n    cancel: '取消',\n    back: '返回',\n    details: '详情',\n    confirmInfo: '确认信息',\n    labelN: '名称',\n    addressN: '地址',\n    pubKeyN: '公钥',\n    signatureSchemeN: '签名算法',\n    wif: 'WIF',\n    mnemonic: '助记词',\n    privateKey: '私钥',\n    backupWallet: '请备份好以上数据并保存好.dat文件。如果您忘记了钱包密码，您的私钥（WIF）将会是恢复钱包的唯一方式。',\n    createSuccess: '创建普通钱包成功！',\n    createFail: '创建普通钱包失败。请重试。',\n    download: '下载.dat文件',\n    privateKey64Hex: '私钥(64 Hex格式)',\n    priavteKeywif: '私钥(WIF格式)',\n    keystoreDat: 'Keystore(.dat)'\n  },\n\n  importJsonWallet: {\n    datFile: '选择文件',\n    invalidDatFile: '请选择正确的keystore(.dat)文件',\n    selectedDatFile: '已选择文件： ',\n    dat: '.dat文件',\n    datImportPassword: '解密keystore文件(.dat)的密码',\n    create: '导入普通钱包',\n    basicInfo: '基本信息',\n    label: '钱包名称',\n    wif: 'WIF',\n    wifTip: '请输入52位的WIF文本',\n    privateKeyTip: '请输入64位HEX格式的密钥',\n    datPassword: '输入新密码',\n    datRePassword: '重复新密码',\n    password: '输入密码',\n    rePassword: '重复密码',\n    next: '继续',\n    cancel: '取消',\n    back: '返回',\n    details: '详情',\n    confirmInfo: '确认信息',\n    mnemonic: '请用空格分隔助记词',\n    privateKey: '私钥',\n    confirmImport: '确认导入',\n    confirmImportExist: '要导入的钱包本地已存在。仍然要导入？',\n    success: '导入钱包成功',\n    saveDbFailed: '保存到Keystore失败。请稍后重试。',\n    invalidPrivateKey: '请输入正确的私钥',\n    setPassword: '设置密码',\n    importFirstDefault: '只导入.dat文件中的默认钱包或第一个钱包'\n  },\n\n  createSharedWallet: {\n    basicInfo: '基本信息',\n    copayers: '联合支付人',\n    processing: '处理中',\n    label: '共享钱包名称',\n    copayers2_12: '联合支付人(2-12)',\n    address: '地址',\n    inputPks: '输入 2 - 12 公钥\\' 信息',\n    name: '名字',\n    publicKey: '公钥',\n    add: '+ 增加',\n    next: '继续',\n    cancel: '取消',\n    back: '返回',\n    importSharedWallet: '导入共享钱包',\n    requiredSigNum: '选择签名数量',\n    success: '成功',\n    duplicateCreate: '共享钱包已存在，请导入.',\n    createFailed: '错误，请稍后重试。',\n    createSuccess: '创建共享钱包成功',\n    create: '创建共享钱包',\n    walletNameErr: '钱包名称长度不可超过12个字符。',\n    emptyLabel: '钱包名称不能为空.',\n    pksLte2: '联合支付人数量不能少于2人。',\n    invalidPk: '输入的公钥不正确',\n    duplicatePks: '联合支付人中不能有重复的公钥',\n    duplicateNames: '联合支付人中不能有重复的名称'\n  },\n\n  importSharedWallet: {\n    import: '加入共享钱包',\n    basicInfo: '基本信息',\n    inputPass: '输入密码',\n    importSuccess: '成功',\n    inputAddress: '共享钱包地址',\n    search: '查询',\n    name: 'Shared Wallet 名字',\n    totalCopayerNumber: '联合支付人数',\n    requiredCopayerNumber: '最少签名数',\n    allCopayers: '全部联合支付人地址',\n    noResult: '没有结果',\n    address: '地址',\n    chooseLocalWallet: '选择本地钱包加入',\n    localWalletInfo: '本地钱包详情',\n    walletName: '钱包名字',\n    pk: '公钥',\n    next: '继续',\n    cancel: '取消',\n    back: '返回',\n    join: '加入',\n    inputPassword: '输入密码加入',\n    joinBefore: '你已经加入过这个钱包。',\n    success: '已经成功加入钱包！',\n    passwordError: '密码错误。',\n    sorry: '对不起！',\n    notFound: '找不到该共享钱包。'\n  },\n\n  importLedgerWallet: {\n    import: '连接Ledger钱包',\n    label: '钱包名称',\n    next: '连接',\n    neoCompatible: '兼容NEO地址'\n  },\n\n  sharedWalletHome: {\n    send: '发送',\n    receive: '接收',\n    claim: '认领',\n    rule: '规则',\n    copayers: '联合支付人',\n    pendingTx: '待处理交易',\n    completedTx: '已完成交易',\n    owners: '所属人',\n    address: '地址',\n    amount: '数量',\n    max: '最大',\n    to: '接收',\n    recipient: '接收方地址',\n    cancel: '取消',\n    next: '继续',\n    back: '返回',\n    submit: '提交',\n    asset: '资产',\n    sponsor: '发起人',\n    dragDecide: '拖动序号决定顺序',\n    fee: '费用',\n    inputPassword: '输入密码',\n    inputPassToTransfer: '输入密码完成转账',\n    walletAddress: '钱包地址',\n    createTime: '创建时间',\n    balance: '余额',\n    confirmation: '确认',\n    agreeToSend: '我同意发送资产',\n    signSequence: '签名顺序',\n    sign: '签名',\n    checkMore: '查看更多',\n    publicKey: '公钥',\n    redeemOng: '提取ONG',\n    paxMgmt: 'PAX管理',\n    unprocessed: '未处理',\n    processing: '处理中',\n    completed: '已完成',\n    txMgmt: '多签交易管理',\n    createTransferFailed: '创建转账交易失败',\n    createTransferSuccess: '创建转账交易成功',\n    txSendingTochain: '该交易正在发送上链。'\n  },\n\n  pax: {\n    ethAddress: 'Eth 地址',\n    ontAddress: 'ONT 地址',\n    amount: '数额',\n    date: '日期',\n    toProcess: '去处理',\n    paxStart: '发起',\n    paxSign: '签名',\n    selectCurrentSigner: '选择当前签名钱包: ',\n    back: '返回',\n    confirm: '确认',\n    sponsorSign: '发起人签名',\n    inputPassword: '输入当前签名钱包密码',\n    queryEthScan: '查询Eth转出总额',\n    currentSign: '当前签名者签名',\n    txToSend: '要发送上链的交易个数:',\n    txSent: '已发送上链的交易个数: ',\n    sendingTx: '正在发送交易上链:',\n    selectedNum: '已选择条目数量: ',\n    totalAmount: '已选择条目的PAX总额: ',\n    ethTotal: '已收到的ETH总额: ',\n    startProcessSuccess: '发起处理流程成功',\n    signSuccess: '签名交易成功',\n    ledgerSignMultiTimes: '您可能需要在ledger设备上进行多次签名',\n    hasSignedSent: '注意！这些交易已经被签名并已发送到链上。请检查已完成的数据。',\n    toEthScan: '查看ETH Scan',\n    txCompleted: '已上链',\n    txDetail: '查看交易',\n    toVarify: '验证',\n    varifySuccess: '验证通过',\n    varifyFailed: '验证失败',\n    varifyResult: '验证结果',\n    failedTxhashes: '验证失败的交易哈希'\n  },\n\n  sharedTx: {\n    startTx: '发起多签交易',\n    signTx: '签名多签交易',\n    selectSponsor: '选择发起人',\n    createTx: '构建多签交易',\n    contractHash: '合约哈希',\n    method: '方法名',\n    parameters: '参数列表',\n    starterSign: '发起人签名',\n    txSerialized: '签名后的交易：',\n    addSign: '增加签名',\n    txContent: '交易内容',\n    currentSign: '当前签名地址',\n    selectSigner: '选择签名地址',\n    copy: '复制',\n    send: '立即发送',\n    isSendTxTip: '该交易的签名数量已满足要求。是否立即发送交易上链？',\n    txSentSuccess: '发送交易上链成功。',\n    paramsError: '输入参数有误。请检查。'\n  },\n\n  commonWalletHome: {\n    claimableOng: '可提取的ONG',\n    unboundOng: '未绑定的ONG',\n    redeem: '提取',\n    receive: '接收',\n    swap: '映射',\n    walletQrCode: '钱包地址二维码',\n    walletAddress: '钱包地址',\n    publicKey: '公钥',\n    redeemCharge: '提取ONG需要支付0.01ONG',\n    inputPass: '请输入钱包密码',\n    emptyPass: '密码不能为空',\n    cancel: '取消',\n    submit: '提交',\n    swapText: '欢迎使用“一站式”主网ONT切换。用户可以在这里将NEP-5 ONT映射成主网ONT。映射将在一个月内完成，您可以登录swap.ont.io查询映射状态。',\n    stepFollow: '您只需要使用以下步骤执行操作：',\n    step1: '导入NEO钱包的私钥创建钱包',\n    step2: '点击映射按钮发起映射',\n    step3: '查看映射进度',\n    swapAmount: '映射数额',\n    nep5Balance: 'NEP-5 ONT 余额:',\n    password: '密码',\n    validAmount: \"请输入正确数额\",\n    checkMore: '查看更多',\n    balance: '余额',\n    scriptHash: '合约哈希',\n    add: '+ 添加',\n    addOep4: '添加OEP-4 Token',\n    enterScripthash: '请输入OEP-4的合约哈希',\n    invalidScriptHash: '请输入正确的合约哈希',\n    addOep4Success: '添加OEP-4 token成功！',\n    noOep4Contract: '在链上找不到该OEP4合约',\n    networkError: '网络错误！请稍后重试。',\n    oep4Exists: '您已经添加过该OEP-4 Token。',\n    go: '查看详情'\n  },\n\n  transfer: {\n    inputValidAmount: '请输入有效的转账金额。',\n    inputValidAddress: '请输入有效的转账地址。',\n    exceedBalance: '转账金额不能超余额',\n    ongBalanceNotEnough: '您的ONG余额不足以支付转账和手续费。',\n    //Needs translation\n    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?'\n  },\n  setting: {\n    name: '设置',\n    net: '网络',\n    lang: '语言',\n    testNet: 'ONT测试网络',\n    mainNet: 'ONT主网',\n    en: 'English',\n    zh: '中文',\n    pathTit: '当前路径： ',\n    path: '钱包保存路径(请不要设到OWallet的安装位置！)',\n    change: '修改',\n    setNetworkSuccess: '网络成功设置为：',\n    wallets: '钱包',\n    ontid: 'ONT ID',\n    nodeStake: '节点质押',\n    help: '帮助',\n    settings: '设置',\n    nodeAddress: '节点',\n    setNodeSuccess: '节点成功设置为：',\n    notInstallationPath: '请不要设置到Owallet的安装位置。',\n    notSetPath: '未设置keystore保存路径。'\n  },\n  ledgerWallet: {\n    nameOfLedgerWallet: 'Ledger钱包名称',\n    info: 'Ledger钱包信息',\n    connectApp: '请连接您的ledger设备并打开ONT app.',\n    status: '设备状态',\n    labelEmpty: '钱包名称不能为空.',\n    deviceError: '不能连接到设备，请重试.',\n    signFailed: '使用ledger签名交易失败。',\n    selectAccount:\"请选择您Ledger设备里的账户（可多选）\",\n    normalMode:'普通模式',\n    advancedMode:'高级模式',\n    alreadyImported:\"部分选中账户已导入\",\n    specifyPath:\"请选择并指定导入帐户的路径\",\n    pleaseSelectWallet:\"请选择想导入的钱包并输入名称\",\n  },\n  ledgerStatus: {\n    NOT_FOUND: 'Ledger没有打开',\n    NOT_SUPPORT: 'Ledger不支持',\n    NO_DEVICE: '请连接Ledger并打开',\n    READY: 'Ledger准备就绪',\n    NOT_OPEN: 'Ledger上的ONT app没有打开'\n  },\n  nodeStake: {\n    iHaveKnown: '我已知晓',\n    ontid: 'ONT ID',\n    nodeStake: '节点质押',\n    stakeWalletAddress: '质押钱包地址',\n    nodePk: '节点公钥',\n    contract: '质押合约',\n    commitmentQuantity: '承诺质押数量',\n    stakeQuantity: '实际质押数量',\n    claimableQuantity: '可提取质押数量',\n    stake: '质押',\n    feeTip: '质押需要收取500ONG作为服务费',\n    selectOntid: '选择ONT ID',\n    selectStakeWallet: '选择质押钱包',\n    next: '下一步',\n    selectIdentity: '选择你的ONT ID',\n    selectIndividualWallet: '请选择普通钱包',\n    selectLedgerWallet: '请连接您的ledger设备并打开ONT',\n    invalidOntid: '无效的ONT ID',\n    invalidAddress: '无效的质押钱包地址',\n    stakeQuantityEmpty: '请输入质押数量',\n    password: '输入密码',\n    signWithOntid: '使用ONT ID签名',\n    signWithWallet: '选择钱包',\n    enterOntidPass: '请输入ONT ID的密码',\n    enterWalletPass: '请输入钱包的密码',\n    quitWarmMsg: '选择退出节点，则可退回所有初始质押。候选节点退出后一周期可以退回质押，共识节点需要两周期。退出节点后，如果想要再次运行节点，需要重新注册。',\n    back: '返回',\n    recall: '撤销',\n    refund: '退款',\n    quitNode: '退出节点',\n    newStake: '新质押',\n    passwordEmpty: '密码不能为空',\n    search: 'Search'\n\n  },\n  nodeStakeStatus: {\n    transfering: '转账中',\n    transfered: '转账完成',\n    transferFailed: '转账失败',\n    audit: '审核',\n    auditing: '审核中',\n    audited: '审核完成',\n    auditFailed: '审核失败',\n    stake: '质押',\n    staked: '质押完成',\n    nodeExited: '节点退出',\n    refund: '退款',\n    refunding: '退款中',\n    refunded: '退款完成',\n    refundFailed: '退款失败',\n    stakeExited: '质押退出',\n    quitStake: '退出质押',\n    unfrozenToRefund: '解除冻结成功，可以申请退款',\n    transferNeedTime: '转账需要一定时间',\n    serviceFee: '质押需要收取500ONG作为服务费',\n    auditNeedTime: '审核需要一定时间',\n    refundNeedTime: '退款需要一定时间',\n    txFailed: '交易失败'\n\n  },\n  redeemInfo: {\n    info: '提取ONG',\n    claimableOng: '可提取ONG是您可以提取的ONG的数量，手续费为0.01个ONG。每次钱包中完成一笔交易后，该余额会更新。',\n    unboundOng: '已解绑的ONG是指尚未添加到您的可提取ONG余额（仅会在您钱包做出一笔ONT交易后更新）中的ONG。当您的地址完成一笔交易后，您可提取的ONG余额将会更新（即将已解绑的ONG数额将添加到您可提取的ONG余额中去。）',\n    claimableOngName: '可提取ONG：',\n    unboundOngName: '已解绑的ONG：',\n    noClaimableOng: '您没有可提取的ONG。当您地址上完成一笔ONT转出交易后，可提取的ONG余额将会更新。'\n  },\n  nodeMgmt: {\n    nodeUser: '您是节点用户，从这里可以管理节点质押',\n    nodeStakeMgmt: '节点质押管理',\n    normalUser: '您是普通用户，从这里可以参加授权质押',\n    stakeAuthorizaton: '节点授权质押',\n    nodeStake: '节点质押',\n    userStakeAuthorization: '用户授权质押',\n    newStake: '提交新的节点质押',\n    allowStakes: '允许其他用户授权质押',\n    deny: '拒绝',\n    permit: '允许',\n    yourStakeAmount: '您的节点质押数额',\n    stakeLimit: '节点质押数额上限',\n    userNumber: '当前参与授权质押的用户数量',\n    userStakeAmount: '当前用户授权质押数额',\n    rewardsPerMonth: '预计每月收益总额',\n    rewardsTip: '预计每月收益总额包括节点的和参与授权质押用户的收益总额',\n    rewardProportion: '收益分配比例: ',\n    nodeRewardProportion: '节点质押收益分配比例',\n    userRewardProportion: '用户质押收益分配比例',\n    current: '当前',\n    nodeRewardProportionTip: '节点质押收益分配比例：表示节点获得节点质押部分的ONT收到的交易手续费和解绑ONG收益的百分比。',\n    userRewardProportionTip: '用户质押收益分配比例：表示节点获得用户质押部分的ONT收到的交易手续费和解绑ONG收益的百分比。',\n    confirm: '确认',\n    changesTakeEffect: '更改需在经过两轮共识周期后生效(每轮周期大约30天)。',\n    stakeAuthorization: '授权质押',\n    toNextRound: '到下一轮还有',\n    rank: '排名',\n    name: '节点名称',\n    currentStake: '当前质押总额',\n    process: '进度',\n    changes: '排名变化',\n    userParticipate: '请确保您是想要参与授权质押的用户。',\n    nodeName: '节点名称',\n    walletAddress: '您的钱包地址',\n    inAuthorization: '授权质押中',\n    cancelStakeAuthorization: '取消授权质押',\n    locked: '取消的授权质押（锁定中）',\n    claimable: '可提取',\n    redeem: '提取',\n    profit: '收益',\n    rewards: '收益',\n    newStakeAuthorization: '提交新的授权质押',\n    cancelAuthorization: '取消授权质押',\n    units: '授权质押份数',\n    stakeAmountTip: '质押数额 = 份数 * 1 ONT/每份.',\n    stakeAmount: '质押数额',\n    submit: '提交',\n    allowedStakeUnits: '允许授权质押份数',\n    allowedStakeAmount: '允许授权质押数额',\n    noChange: '您没有修改',\n    noRewards: '没有可提取的收益',\n    switchWallet: '切换钱包',\n    noClaimableOnt: '没有可提取的ONT',\n    amountToCancel: '要取消的质押数额',\n    unitToCancel: '要取消的质押份数',\n    invalidInput: '请输入合理的值',\n    peerNotAllowAuthorize: '此节点当前不允许授权质押',\n    addInitPos: '增加初始质押',\n    reduceInitPos: '减少初始质押',\n    amountToAdd: '要增加的质押数额',\n    amountToReduce: '要减少的质押数额',\n    notThanCommitment: '质押数额不能少于承诺质押数额。',\n    notLessTotalPos: '初始质押数太小。',\n    notThanMax: '允许授权质押数额不能超过节点质押数额上限。',\n    refresh: '刷新',\n    totalStakeAmount: '授权质押总额',\n    blocks: '区块',\n    proportionNextRound: '质押用户收益分配比例（节点/用户）',\n    proportionNextRoundTip: '这是节点选择的在下一轮共识中，分享给授权质押用户的节点自身质押部分ONT和用户质押部分ONT收到的手续费收益和解绑ONG收益的比例。\\n请注意，并非所有节点都与授权质押用户分享本体基金会的奖励。点击下面的链接查看更多相关信息。',\n    authorizationFAQ: '节点授权质押常见问题解答',\n    nodeAndUser: '节点 / 用户',\n    authorizeTip: '用户对该节点的授权抵押金额，包括本轮新授权的ONT和已生效的授权ONT，取消授权会优先取消本轮新授权的ONT，取消后进入用户的可提取ONT中。本轮新授权的ONT不足则会取消已生效的授权ONT，按照节点是候选/共识状态分别锁定1轮或2轮，之后进入用户的可提取ONT中。',\n    rewardTip: '本体网络收到的所有手续费按照50%/50%的比例分给所有候选节点和共识节点，其中候选节点部分按照节点总抵押大小线性分配到每个候选节点，每个候选节点先拿走自己的部分（百分比），剩下的按照每个地址授权ONT的多少线性分配到每个地址。其中共识节点部分按照分润曲线分配到每个共识节点，每个共识节点先拿走自己的部分（百分比），剩下的按照每个地址授权ONT的多少线性分配到每个地址。',\n    unboundOng: '解绑的 ONG',\n    activeT: '本轮生效',\n    activeT1: '下一轮生效',\n    activeT2: '下下轮生效',\n    changeRewardProportion: '修改收益分配比例',\n    edit: '修改',\n    stakeHistory: '我的质押',\n    cancelUnits: '份',\n    stakeWalletAddress: '质押钱包地址',\n    lastUpdate: '上次更新时间',\n    walletRewardTip: '这是当前周期内您的钱包所有的授权质押收益',\n    switchMainnet: '请切换到主网。',\n    consensusNode: '共识节点',\n    candidateNode: '候选节点',\n    lockedONT: '当前锁定的ONT是由智能合约暂时持有的用户授权质押数额。锁定期满后，会在可提取的ONT中显示并可提取',\n    unboundONG: '这是用户授权质押的ONT所解绑的ONG。',\n    profitONG: '这是您已获得的交易费收益。该收益会在每轮共识周期开始时更新。',\n    getProfitPart: '产生收益中',\n    newStakePart: '新的质押',\n    claimableONT: '可提取ONT',\n    redeemInitPos: '提取可提取质押',\n    initPosInLock: \"锁定中\",\n    initPosRedeemable: '可提取',\n    noClaimbleInitPos: '没有可提取的初始质押。',\n    redeemInitPosOk: '确认提取',\n    hasClaimableInitPos: '您还有可提取的初始质押。请先提取该部分ONT。',\n    noClaimbleToRefund: '没有可提取的ONT。无法提款。',\n    newNodeApply: '注册新节点',\n    nodeApplyTip: '注册成为本体的节点',\n  },\n  vote: {\n    node: 'Node',\n    vote: '治理投票',\n    voteTip: \"如果您是已授权的用户，从这里可以参与Ontology的治理投票\",\n    login: '登录',\n    notSeeWallet: '没有看到您的钱包？导入一个。',\n    importHere: '由此导入',\n    notStart: '未开始',\n    inProgress: '进行中',\n    finished: '已结束',\n    canceled: '已取消',\n    nodeCanVoteOnly: '当前仅北斗共识节点用户可以参与投票',\n    title: '标题',\n    detail: '内容',\n    votingStarts: '投票开始时间',\n    votingEnds: '投票结束时间',\n    back: '返回',\n    submit: '提交',\n    submitVoteSuccess: '投票成功!',\n    submitVoteFail: '投票失败!',\n    stopVoteSuccess: '取消投票成功!',\n    stopVoteFail: '取消投票失败!',\n    createVoteSuccess: '创建投票成功!',\n    createVoteFail: '创建投票失败!',\n    onlySupportEnglish: '目前仅支持输入英文内容',\n    fillBlanks: '请填写空白',\n    endTimeError: \"投票结束时间必须是将来时间\",\n    votingTopics: '投票主题',\n    votingDetail: '投票内容',\n    stopVote: '停止投票',\n    info: '信息',\n    startTime: '开始时间',\n    endTime: '结束时间',\n    hash: 'Hash',\n    creatorAddress: '创建者地址',\n    votingStatus: '投票状态',\n    myVotes: '我的投票',\n    approval: '赞成',\n    opposition: '反对',\n    allVotes: '所有投票',\n    created: '我创建的',\n    duration: '持续时间',\n    notAllowVote: '您现在不能投票。该项投票现在是: ',\n    notAllowStop: '您现在不能结束投票。该项投票现在是: ',\n    name: '名称',\n    address: '地址',\n    votes: '投票数',\n    selectWallet: '请选择节点运营钱包',\n    startTimeError: '投票开始时间不能晚于结束时间',\n    new: '新建'\n  },\n  nodeApply: {\n    newNodeApply: '注册新节点',\n    stakeWallet: '节点质押钱包',\n    operationWallet: '节点运营钱包',\n    selectOperationWallet: '选择运营钱包',\n    operationPk: '运营钱包公钥',\n    enterOperationPk: '输入运营钱包公钥',\n    invalidOperationPk: '错误的运营钱包',\n    stakeAmount: '质押金额',\n    inputStakeAmount: '输入质押金额',\n    next: '下一步',\n    ok: '确认',\n    cancel: '取消',\n    operationWalletPublickey: '运营钱包公钥',\n    registerSuccess: '恭喜注册节点成功',\n    completeNodeInfo: '立刻完善节点信息',\n    later: '稍后再说',\n    sameWalletNotAllowed: '运营钱包和质押钱包不能是同一个钱包',\n    operationWalletRequired: '运营钱包是必需的',\n    stakeWalletRequired: '质押钱包是必需的',\n    stakeAmountRequired: '质押金额是必需的',\n    minStateAmount: '质押金额至少是10,000 ONT',\n    proxyServiceTip: '本体社区提供了节点代运营服务。',\n    proxyServiceLink: '点击这里查看详情。',\n    unsupportedLedger:\"节点启动时，暂不支持选择Ledger硬件钱包作为运营钱包\",\n\n  },\n  myNode: {\n    myNode: '我的节点',\n    stakeWalletAddress: '质押钱包地址',\n    operationWalletPk: '运营钱包公钥',\n    manage: '管理',\n    applyNode: '注册新节点'\n  },\n  nodeInfo: {\n    nodeInfo: '节点信息',\n    name: '名称',\n    enterName: '节点名称',\n    logo: 'Logo',\n    enterLogo: 'Logo链接',\n    location: '地区',\n    enterLocation: '节点所在地区',\n    ip: 'IP',\n    enterIp: '节点的IP',\n    description: '描述',\n    enterDesc: '节点的描述',\n    website: '网站',\n    enterWebsite: '节点网站',\n    telegram: 'Telegram',\n    enterTelegram: '节点的Telegram',\n    twitter: 'Twitter',\n    enterTwitter: '节点的Twitter',\n    facebook: 'Facebook',\n    enterFacebook: '节点的Facebook',\n    contactOntologyEmail: '联系Ontology的邮箱',\n    enterContactEmail: '联系邮箱',\n    openEmail: '公开的邮箱',\n    enterOpenEmail: '公开的邮箱',\n    ifOpenInfo: '是否公开节点信息',\n    submit: '提交',\n    updateSuccess: '更新成功',\n    updateFailed: '更新失败',\n    ledgerWalletNotSupportForNow: '使用Ledger注册的节点，暂时不支持更新节点相关信息.请发送邮件至：'\n  },\n  exchange: {\n    exchange: 'Exchange',\n    changelly: 'Changelly',\n    cryptonex: 'Cryptonex',\n    loading: 'Loading latest pricing information, please wait..'\n  },\n  dapps: {\n    dapps: 'DApps',\n    sesameSeed: '芝麻籽',\n    sesameseedDesc: 'Sesameseed voting management',\n    notification: '注意',\n    userPolicy: '您将跳转至第三方dApp页面，在第三方dApp上的使用行为将适用该第三方dApp的《用户协议》和《隐私政策》，由该第三方dApp直接并单独向您承担责任',\n    ontidMgmt: '管理ONT ID。该功能以后会被移除。请备份ONT ID相关数据。'\n  },\n  sesameseed: {\n    stakeAmountTip: 'Stake amount for Sesameseed is 1 unit equals 1 ONT',\n    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.',\n    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.',\n    pendingWithdrawals: 'Pending canceled stake authorization'\n  }\n}\n"
  },
  {
    "path": "src/main.js",
    "content": "import Vue from 'vue'\nimport axios from 'axios'\nimport VueAxios from 'vue-axios'\n\nimport App from './App'\nimport router from './router'\nimport store from './store'\n\n\nimport 'font-awesome/css/font-awesome.css'\nimport {Button, message, Steps, Input ,Form, Icon, Select, Spin, Alert, Modal, Slider,Radio, Pagination,Switch, DatePicker, TimePicker,\n  Row, Col, InputNumber, Layout, Menu, Breadcrumb, Checkbox, Tooltip, Table, Dropdown, Card, Tabs,Space } from 'ant-design-vue'\n\nimport VueClipboard from 'vue-clipboard2'\nVueClipboard.config.autoSetContainer = true // add this line\nVue.use(VueClipboard)\n\nimport i18n from './lang'\nimport VeeValidate from 'vee-validate'\nimport { VALIDATE_DICTIONARY } from './core/consts'\nimport validationMessages_en from 'vee-validate/dist/locale/en';\nimport validationMessages_zh from 'vee-validate/dist/locale/zh_CN';\n\nVue.use(VeeValidate, {\n  i18n,\n  dictionary: {\n      en: Object.assign({},validationMessages_en, VALIDATE_DICTIONARY.en),\n      zh: Object.assign({},validationMessages_zh, VALIDATE_DICTIONARY.zh)\n  }\n})\nimport service from './core/utils'\nVue.prototype.httpService = service;\n\nimport { VOTE_ROLE } from './core/consts'\nconst mixin = {\n    data () {\n        return {\n            VOTE_ROLE: VOTE_ROLE\n        }\n    }\n}\nVue.mixin(mixin)\n\n\nif (!process.env.IS_WEB) Vue.use(require('vue-electron'))\nVue.http = Vue.prototype.$http = axios\nVue.config.productionTip = false\nVue.use(VueAxios, axios)\n\n\nVue.component(Button.name, Button)\nVue.component(Steps.name, Steps)\nVue.component(Steps.Step.name, Steps.Step)\nVue.component(Input.name, Input)\nVue.component(Input.TextArea.name, Input.TextArea)\nVue.component(Form.name, Form)\nVue.component(Form.Item.name, Form.Item)\nVue.component(Icon.name, Icon)\nVue.component(Select.name, Select)\nVue.component(Select.Option.name, Select.Option)\nVue.component(Spin.name, Spin)\nVue.component(Alert.name, Alert)\nVue.component(Input.Search.name, Input.Search)\nVue.component(InputNumber.name, InputNumber)\nVue.component(Modal.name, Modal)\nVue.component(Slider.name, Slider)\nVue.component(Row.name, Row)\nVue.component(Col.name, Col)\nVue.component(Layout.name, Layout)\nVue.component(Layout.Header.name, Layout.Header)\nVue.component(Layout.Footer.name, Layout.Footer)\nVue.component(Layout.Sider.name, Layout.Sider)\nVue.component(Layout.Content.name, Layout.Content)\nVue.component(Menu.name, Menu)\nVue.component(Menu.Item.name, Menu.Item)\nVue.component(Menu.SubMenu.name, Menu.SubMenu)\nVue.component(Menu.Divider.name, Menu.Divider)\nVue.component(Menu.ItemGroup.name, Menu.ItemGroup)\nVue.component(Breadcrumb.name, Breadcrumb)\nVue.component(Breadcrumb.Item.name, Breadcrumb.Item)\n// Vue.component(Checkbox.name, Checkbox)\nVue.component(Radio.name, Radio)\nVue.component(Radio.Group.name, Radio.Group)\nVue.component(Radio.Button.name, Radio.Button)\nVue.component(Tooltip.name, Tooltip)\nVue.component(Table.name, Table)\nVue.component(Dropdown.name, Dropdown)\nVue.component(Pagination.name, Pagination)\nVue.component(Switch.name, Switch)\nVue.component(Card.name, Card)\nVue.component(DatePicker.name, DatePicker)\nVue.component(TimePicker.name, TimePicker)\nVue.use(Tabs)\nVue.use(Checkbox)\nVue.use(Space)\n\nVue.prototype.$message = message\nVue.prototype.$confirm = Modal.confirm\nVue.prototype.$success = Modal.success\nVue.prototype.$info = Modal.info\n\n/* eslint-disable no-new */\nnew Vue({\n  router,\n  store,\n  i18n,\n  render: h => h(App)\n}).$mount('#app')\n"
  },
  {
    "path": "src/router/index.js",
    "content": "import Vue from 'vue'\nimport Router from 'vue-router'\n\nVue.use(Router)\n\nexport default new Router({\n    routes: [{\n        path: '/Dashboard',\n        name: 'Dashboard',\n        component: require('@/components/Dashboard').default\n    },\n    {\n        path: '/identitys',\n        name: 'Identitys',\n        component: require('@/components/Identitys').default\n    },\n    {\n        path: '/Wallets',\n        name: 'Wallets',\n        component: require('@/components/Wallets').default\n    },\n    {\n        path: '/loginLedger',\n        name: 'LoginLedger',\n        component: require('@/components/LedgerWallet/LoginLedger').default\n    },\n    {\n        path: '/setting',\n        name: 'Setting',\n        component: require('@/components/Setting').default\n    },\n    {\n        path: '/dapps',\n        name: 'Dapps',\n        component: require('@/components/Dapps').default\n    },\n    {\n        path: '/identitys/createIdentity',\n        name: 'CreateIdentity',\n        component: require('@/components/Identitys/CreateIdentity').default\n    },\n    {\n        path: '/identitys/importIdentity',\n        name: 'ImportIdentity',\n        component: require('@/components/Identitys/ImportIdentity').default\n    },\n    {\n        path: '/Wallets/createJsonWallet',\n        name: 'CreateJsonWallet',\n        component: require('@/components/JsonWallet/CreateJsonWallet').default\n    },\n    {\n        path: '/Wallets/importJsonWallet',\n        name: 'ImportJsonWallet',\n        component: require('@/components/JsonWallet/ImportJsonWallet').default\n    },\n    {\n        path: '/Wallets/importLedgerWallet',\n        name: 'ImportLedgerWallet',\n        component: require('@/components/LedgerWallet/ImportLedgerWallet').default\n    },\n    {\n        path: '/Wallets/createSharedWallet',\n        name: 'CreateSharedWallet',\n        component: require('@/components/SharedWallet/CreateSharedWallet').default\n    },\n    {\n        path: '/Wallets/importSharedWallet',\n        name: 'ImportSharedWallet',\n        component: require('@/components/SharedWallet/ImportSharedWallet').default\n    },\n    {\n        path: '/sharedWallet',\n        name: 'SharedWalletDetail',\n        component: require('@/components/SharedWallet/SharedWalletDetail').default,\n        children: [{\n            path: 'home',\n            name: 'SHaredWalletHome',\n            component: require('@/components/SharedWallet/SharedWalletHome').default,\n        },\n        {\n            path: '/sharedWallet/sendTransfer',\n            component: require('@/components/SharedWallet/SharedWalletSend').default\n        },\n        {\n            path: '/sharedWallet/pendingTxHome',\n            component: require('@/components/SharedWallet/PendingTxHome').default\n        },\n        {\n            path: '/sharedWallet/copayers',\n            name: 'SharedWalletCopayer',\n            component: require('@/components/SharedWallet/View/SharedWalletCopayer').default,\n        },\n        {\n            path: '/sharedWallet/paxMgmt',\n            name: 'PaxMgmt',\n            component: require('@/components/SharedWallet/PAX/PaxMgmt').default,\n        },\n        {\n            path: '/sharedWallet/startProcess',\n            name: 'StartProcess',\n            component: require('@/components/SharedWallet/PAX/StartProcess').default,\n        },\n        {\n            path: '/sharedWallet/signProcess',\n            name: 'SignProcess',\n            component: require('@/components/SharedWallet/PAX/SignProcess').default,\n        },\n        {\n            path: '/sharedWallet/txMgmt',\n            name: 'SharedTxMgmt',\n            component: require('@/components/SharedWallet/Tx/SharedTxMgmt').default\n        }\n\n        ]\n    },\n    {\n        path: '/vote',\n        name: 'NodeVote',\n        component: require('@/components/Node/Vote/index').default,\n        children: [\n            {\n                path: 'login',\n                name: 'VoteLogin',\n                component: require('@/components/Node/Vote/Login').default\n            },\n            {\n                path: 'votes',\n                name: 'VoteList',\n                component: require('@/components/Node/Vote/List').default\n            },\n            {\n                path: 'create',\n                name: 'VoteCreate',\n                component: require('@/components/Node/Vote/Create').default\n            },\n            {\n                path: 'detail',\n                name: 'VoteDetail',\n                component: require('@/components/Node/Vote/Detail').default\n            },\n        ]\n        },\n        {\n            path: '/node/apply',\n            name: 'NodeApply',\n            component: require('@/components/Node/NodeApply/Register').default\n        },\n        {\n            path: '/node/applysuccess',\n            name: 'NodeApplySuccess',\n            component: require('@/components/Node/NodeApply/RegisterSuccess').default\n        },\n        {\n            path: '/node/mynode',\n            name: 'MyNode',\n            component: require('@/components/Node/NodeManagement/MyNode').default\n        },\n    {\n        path: '/commonWalletSend',\n        name: 'CommonSendHome',\n        component: require('@/components/CommonWallet/SendHome').default\n    },\n    {\n        path: '/commonWalletReceive/:walletType',\n        name: 'CommonReceive',\n        component: require('@/components/CommonWallet/CommonReceive').default\n    },\n    {\n        path: '/commonWalletRedeem/:walletType',\n        name: 'CommonRedeem',\n        component: require('@/components/CommonWallet/CommonRedeem').default\n    },\n    {\n        path: '/commonTokenSwap',\n        name: 'CommonTokenSwap',\n        component: require('@/components/CommonWallet/CommonTokenSwap').default\n    },\n    {\n        path: '/node/nodeStakeIntro',\n        name: 'NodeStakeIntro',\n        component: require('@/components/Node/NodeStake/NodeStakeIntro').default\n    },\n    {\n        path: '/node/nodeStakeRegister',\n        name: 'NodeStakeRegister',\n        component: require('@/components/Node/NodeStake/NodeStakeRegister').default\n    },\n    {\n        path: '/node/nodeStakeInfo',\n        name: 'NodeStakeInfo',\n        component: require('@/components/Node/NodeStake/NodeStakeInfo').default\n    },\n    {\n        path: '/node',\n        name: 'NodeManagement',\n        component: require('@/components/Node/Node').default\n    },\n    // {\n    //   path: '/node/nodeLogin',\n    //   name: 'NodeLogin',\n    //   component: require('@/components/Node/NodeManagement/NodeLogin').default\n    // },\n    {\n        path: '/node/nodeStakeMgmt',\n        name: 'NodeStakeManagement',\n        component: require('@/components/Node/NodeManagement/NodeStakeManagement').default\n    },\n    {\n        path: '/node/nodeList',\n        name: 'NodeList',\n        component: require('@/components/Node/NodeAuthorize/NodeList').default\n    },\n    {\n        path: '/node/stakeHistory',\n        name: 'StakeHistory',\n        component: require('@/components/Node/NodeAuthorize/StakeHistory').default\n    },\n    {\n        path: '/node/authorizeLogin',\n        name: 'AuthorizeLogin',\n        component: require('@/components/Node/NodeAuthorize/AuthorizeLogin').default\n    },\n    {\n        path: '/dapps/authorizeLoginSesameseed',\n        name: 'AuthorizeLoginSesameseed',\n        component: require('@/components/Node/NodeAuthorize/Sesameseed/AuthorizeLoginSesameseed').default\n    },\n    {\n        path: '/node/authorizationMgmt',\n        name: 'AuthorizationMgmt',\n        component: require('@/components/Node/NodeAuthorize/AuthorizationMgmt').default\n    },\n    {\n        path: '/dapps/authorizationMgmtSesameseed',\n        name: 'AuthorizationMgmtSesameseed',\n        component: require('@/components/Node/NodeAuthorize/Sesameseed/AuthorizationMgmtSesameseed').default\n    },\n    {\n        path: '/node/newAuthorization',\n        name: 'NewAuthorization',\n        component: require('@/components/Node/NodeAuthorize/NewAuthorization').default\n    },\n    {\n        path: '/dapps/newAuthorizationSesameseed',\n        name: 'NewAuthorizationSesameseed',\n        component: require('@/components/Node/NodeAuthorize/Sesameseed/NewAuthorizationSesameseed').default\n    },\n    {\n        path: '/oep4Home',\n        name: 'Oep4Home',\n        component: require('@/components/Common/Oep4Home').default\n    },\n    {\n        path: '*',\n        redirect: '/'\n    },\n    {\n        path: '/',\n        name: 'Home',\n        component: require('@/components/Home').default\n    },\n    ]\n})\n"
  },
  {
    "path": "src/store/index.js",
    "content": "import Vue from 'vue'\nimport Vuex from 'vuex'\n\nimport modules from './modules'\n\nVue.use(Vuex)\n\nexport default new Vuex.Store({\n  modules,\n  strict: process.env.NODE_ENV !== 'production'\n})\n"
  },
  {
    "path": "src/store/modules/CreateIdentity.js",
    "content": "import { Wallet, Identity, Crypto, OntidContract, TransactionBuilder } from \"ontology-ts-sdk\";\nimport {GAS_PRICE, GAS_LIMIT} from '../../core/consts'\nconst state = {\n  currentStep: 0,\n  label: '',\n  ontid: '',\n  identity: '',\n  tx: ''\n}\n\nconst mutations = {\n  ADD_CREATE_IDENTITY_STEP(state, payload) {\n    state.currentStep += 1;\n  },\n  SUB_CREATE_IDENTITY_STEP(state, payload) {\n    if(state.currentStep > 0) {\n      state.currentStep -= 1;\n    }\n  },\n  CREATE_IDENTITY(state, payload) {\n    state.label = payload.label\n    state.ontid = payload.ontid\n    state.identity = payload.identity,\n    state.tx = payload.tx\n  },\n  INIT_CREATE_IDENTITY(state, payload) {\n    state.currentStep = 0\n    state.label = ''\n    state.ontid = ''\n    state.identity = '',\n    state.tx = ''\n  }\n}\n\nconst actions = {\n  createIdentityWithPrivateKey({commit}, body) {\n    // wallet.scrypt.n = 16384;\n\n    // let params = {\n    //   cost: 16384,\n    //   blockSize: 8,\n    //   parallel: 8,\n    //   size: 64\n    // };\n\n    let identity = Identity.create(body.privateKey, body.password, body.label)\n    const publicKey = body.privateKey.getPublicKey();\n    const tx = OntidContract.buildRegisterOntidTx(identity.ontid, publicKey, GAS_PRICE, GAS_LIMIT);\n    tx.payer = body.payer;\n    TransactionBuilder.signTransaction(tx, body.privateKey);\n    identity = identity.toJsonObj();\n    commit('CREATE_IDENTITY', {\n      label: body.label,\n      ontid: identity.ontid,\n      identity,\n      tx: tx\n    })\n\n    return tx\n  }\n}\n\nexport default {\n  state,\n  mutations,\n  actions\n}\n"
  },
  {
    "path": "src/store/modules/CreateJsonWallet.js",
    "content": "import { Wallet, Account, Crypto } from \"ontology-ts-sdk\";\n\nconst state = {\n  currentStep: 0,\n  label: '',\n  address: '',\n  publicKey: '',\n  account: '',\n  downloadContent: '',\n  wif: ''\n}\n\nconst mutations = {\n  ADD_CREATE_JSON_STEP(state, payload) {\n    state.currentStep += 1;\n  },\n  SUB_CREATE_JSON_STEP(state, payload) {\n    if(state.currentStep > 0) {\n      state.currentStep -= 1;\n    }\n  },\n  CREATE_JSON_WALLET(state, payload) {\n    state.label = payload.label\n    state.account = payload.account\n    state.downloadContent = payload.content\n    state.address = payload.account.address\n    state.publicKey = payload.account.publicKey,\n    state.wif = payload.wif\n  },\n  INIT_JSON_WALLET(state, payload) {\n    state.currentStep = 0\n    state.label = ''\n    state.account = ''\n    state.downloadContent = ''\n    state.address = ''\n    state.publicKey = '',\n    state.wif = ''\n  }\n}\n\nconst actions = {\n  createJsonWalletWithPrivateKey({commit}, body) {\n    let wallet = Wallet.create(body.label || \"\")\n    wallet.scrypt.n = 16384;\n\n    let params = {\n      cost: 16384,\n      blockSize: 8,\n      parallel: 8,\n      size: 64\n    };\n\n    let account = Account.create(body.privateKey, body.password, body.label, params)\n    account.isDefault = true;\n\n    // 生成下载钱包的内容\n    wallet.addAccount(account);\n    \n    account = account.toJsonObj();\n    commit('CREATE_JSON_WALLET', {\n      label: body.label,\n      account: account,\n      content: wallet.toJsonObj(),\n      wif: body.wif\n    })\n\n    return account\n  }\n}\n\nexport default {\n  state,\n  mutations,\n  actions\n}\n"
  },
  {
    "path": "src/store/modules/CreateSharedWallet.js",
    "content": "import axios from 'axios';\nimport { ONT_PASS_NODE, ONT_PASS_NODE_PRD, ONT_PASS_URL } from '../../core/consts'\nimport dbService from '../../core/dbService'\nconst state = {\n    currentStep: 0,\n    label: '',\n    address: '',\n    copayers: [\n        { name: '', publickey: ''},\n        { name: '', publickey: '' }\n    ],\n    requiredSigNum:2\n}\n\nconst mutations = {\n    CREATE_SHARED_WALLET(state, payload) {\n        state.label = payload.sharedWalletName,\n            state.address = payload.sharedWalletAddress\n    },\n\n    UPDATE_CREATE_SHARED_LABEL(state, payload) {\n        state.label = payload.label;\n    },\n    UPDATE_REQUIRED_SIG_NUMBER(state, payload) {\n        state.requiredSigNum = payload.requiredSigNum;\n    },\n    ADD_CREATE_SHARED_STEP(state, payload) {\n        state.currentStep += 1;\n    },\n    SUB_CREATE_SHARED_STEP(state, payload) {\n        if(state.currentStep > 0) {\n            state.currentStep -= 1;\n        }\n    },\n    UPDATE_CREATE_SHARED_COPAYERS(state, payload) {\n        state.copayers = payload.copayers\n    },\n    CLEAR_CREATE_SHARED_STATE(state,payload) {\n        state.currentStep = 0;\n        state.label = '';\n        state.address = '';\n        state.copayers = [\n            { name: '', publickey: '' },\n            { name: '', publickey: '' }\n        ],\n        state.requiredSigNum = 2;\n    }\n}\n\nconst actions = {\n    createSharedWallet({ commit, dispatch }, body) {\n        const net = localStorage.getItem('net')\n        const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD\n        dispatch('showLoadingModals')\n        return axios.post(ontPassNode + ONT_PASS_URL.CreateSharedWallet, body).then(res => {\n            if (res.status === 200 && res.data.Error === 0) {\n                commit('CREATE_SHARED_WALLET', {\n                    label: body.sharedWalletName,\n                    address: body.sharedWalletAddress\n                })\n                //save to db\n                const wallet = {\n                    type: 'SharedWallet',\n                    address: body.sharedWalletAddress,\n                    wallet: body\n                }\n                dbService.insert(wallet);\n                dispatch('hideLoadingModals')\n                return res.data.Error;\n            } else {\n                dispatch('hideLoadingModals')\n                return res.data.Error;\n            }\n        }).catch(err => {\n            console.log(err)\n            dispatch('hideLoadingModals')\n            return err;\n        })\n    }\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/CurrentWallet.js",
    "content": "import axios from 'axios'\nimport {\n  getBalanceUrl\n } from '../../core/utils'\n\nconst state = {\n    wallet : {\n        // for json and hardware wallet\n        publicKey: '',\n        address: '',\n        name: '',\n        //for shared wallet\n        coPayers: [],\n        requiredNumber:'',\n        totalNumber:''\n    },\n    balance: {\n        ont: 0,\n        ong: 0,\n        waitBoundOng:0,\n        unboundOng: 0\n    },\n    transfer: {\n        balance : {\n            ont: 0,\n            ong: 0\n        },\n        oep4s:[],\n        from:'',\n        to: '',\n        amount:0,\n        asset:'ONT',\n        gas:0.01,\n        coPayers : [],\n        sponsorPayer:'',\n        isRedeem: false\n    },\n    pendingTx: {\n\n    },\n    currentSigner: '',\n    localCopayers : [],\n    redeem: {\n        claimableOng: 0,\n        balanceOng: 0\n    },\n    nep5Ont: 0\n}\n\nconst mutations = {\n    UPDATE_CURRENT_WALLET(state, payload){\n        state.wallet = Object.assign({}, state.wallet, payload.wallet);\n    },\n    UPDATE_TRANSFER(state, payload) {\n        state.transfer = Object.assign({}, state.transfer, payload.transfer)\n    },\n    UPDATE_LOCAL_COPAYERS(state, payload) {\n        state.localCopayers = payload.localCopayers\n    },\n    UPDATE_PENDINGTX(state, payload) {\n        state.pendingTx = payload.pendingTx\n    },\n    UPDATE_CURRENT_SIGNER(state, payload) {\n        state.currentSigner = payload.account\n    },\n    UPDATE_NATIVE_BALANCE(state, payload) {\n        state.balance = payload.balance\n    },\n    CLEAR_NATIVE_BALANCE(state, payload) {\n        state.balance = {}\n    },\n    CLEAR_CURRENT_TRANSFER(state, payload) {\n        state.transfer = {\n            balance: {\n                ont: 0,\n                ong: 0\n            },\n            oep4s: [],\n            from: '',\n            to: '',\n            amount: 0,\n            asset: 'ONT',\n            gas: 0.01,\n            coPayers: [],\n            sponsorPayer: ''\n        }\n    },\n    UPDATE_CURRENT_REDEEM(state, payload) {\n        state.redeem = payload.redeem\n    },\n    UPDATE_NEP5_ONT(state, payload) {\n        state.nep5Ont = payload.nep5Ont\n    },\n    UPDATE_TRANSFER_REDEEM_TYPE(state, payload) {\n        state.transfer.isRedeem = payload.type;\n        state.transfer.asset = payload.type ? 'ONG' : 'ONT'\n    }\n\n}\n\nconst actions = {\n    clearTransferBalance({commit}) {\n        commit('CLEAR_CURRENT_TRANSFER')\n    },\n    getNativeBalance({commit}, {address}) {\n        const url = getBalanceUrl(address, 'NATIVE');\n        const balance = {}\n        return axios.get(url).then(res => {\n          if (res.data.result) {\n            for (let r of res.data.result) {\n              if (r.asset_name === 'ong') {\n                balance.ong = r.balance;\n              }\n              if (r.asset_name === 'waitboundong') {\n                balance.waitBoundOng = r.balance;\n              }\n              if (r.asset_name === 'unboundong') {\n                balance.unboundOng = r.balance;\n              }\n              if (r.asset_name === 'ont') {\n                balance.ont = r.balance;\n              }\n            }\n            commit('UPDATE_NATIVE_BALANCE', {\n              balance\n            })\n            return balance; // get balance succeed\n          }\n        }).catch(err => {\n          console.log(err)\n          return null; // get balance failed\n        })\n    }\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/Identities.js",
    "content": "import dbService, { dbFind } from '../../core/dbService';\n\nconst state = {\n    Identities: []\n}\n\nconst mutations = {\n    FETCH_IDENTITIES(state, payload) {\n        state.Identities = payload.identities\n    },\n    DELETE_IDENTITY(state, payload) {\n        const identities = state.Identities.slice();\n        const index = identities.findIndex((w) => w.ontid === payload.ontid)\n        identities.splice(index, 1)\n        state.Identities = identities;\n    }\n}\n\nconst actions = {\n    async fetchIdentitiesFromDb({ commit }, pk) {\n        try {\n            const IdentityDocs = await dbFind(dbService, { type: 'Identity' });\n            const identities = IdentityDocs.map(item => item.wallet)\n\n            commit('FETCH_IDENTITIES', { identities });\n        } catch (err) {\n            alert(err)\n        }\n        return true;\n    }\n}\n\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/ImportSharedWallet.js",
    "content": "import axios from 'axios';\nimport { ONT_PASS_NODE, ONT_PASS_URL } from '../../core/consts'\nimport dbService from '../../core/dbService'\nconst state = {\n    currentStep: 0,\n    localCopayers: [],\n    sharedWallet:{}\n}\n\nconst mutations = {\n    ADD_IMPORT_SHARED_STEP(state, payload) {\n        state.currentStep += 1;\n    },\n    SUB_IMPORT_SHARED_STEP(state, payload) {\n        if (state.currentStep > 0) {\n            state.currentStep -= 1;\n        }\n    },\n    UPDATE_LOCAL_COPAYERS(state, payload) {\n        state.localCopayers = payload.localCopayers\n    },\n    UPDATE_SHARED_WALLET(state, payload) {\n        state.sharedWallet = payload.sharedWallet;\n    },\n    CLEAR_IMPORT_SHARED_STATE(state, payload) {\n        state.currentStep = 0;\n        state.sharedWallet = {}\n    }\n}\n\nconst actions = {\n\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/LedgerConnector.js",
    "content": "import { getDeviceInfo, getPublicKey } from '../../core/ontLedger'\nimport en from '../../lang/en'\nimport zh from '../../lang/zh'\nimport { Crypto } from 'ontology-ts-sdk'\n\n\nfunction formatLedgerStatus(status) {\n    const lang = localStorage.getItem('user_lang') || 'en'\n    return lang === 'en' ? en.ledgerStatus[status] : zh.ledgerStatus[status]\n}\n\nfunction getDevice(commit, state) {\n    // if(state.publicKey) {\n    //     return;\n    // }\n     getDeviceInfo().then(res => {\n        console.log('device: ' + res)\n        getLedgerPublicKey(commit, state)\n         commit('UPDATE_LEDGER_DEVICE_INFO', {deviceInfo: res});\n    }).catch(err => {\n        console.log(err)\n        commit('UPDATE_LEDGER_PUBLICKEY', { publicKey: '' })\n        const ledgerWallet = {\n            address: '',\n            publicKey: ''\n        }\n        commit('UPDATE_LEDGER_CONNECTOR_WALLET', {ledgerWallet})\n        if (err === 'NOT_FOUND') {\n            commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('NOT_FOUND')})\n        } else if (err === 'NOT_SUPPORT') {\n            commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('NOT_SUPPORT') })\n        } else {\n            commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('NO_DEVICE') })\n        }\n    })\n}\n\nfunction getLedgerPublicKey(commit, state) {\n    // if (state.publicKey) {\n    //     return;\n    // }\n    getPublicKey().then(res => {\n        console.log('pk info: ' + res);\n        commit('UPDATE_LEDGER_PUBLICKEY', { publicKey: res })\n        commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('READY') })\n        getLedgerWallet(commit, res)\n    }).catch(err => {\n        console.log(err.message)\n        commit('UPDATE_LEDGER_STATUS', { ledgerStatus: formatLedgerStatus('NOT_OPEN') })\n    })\n}\n\nfunction getLedgerWallet(commit, pk) {\n    const publicKey = new Crypto.PublicKey(pk);\n    const address = Crypto.Address.fromPubKey(publicKey).toBase58();\n    const ledgerWallet = {\n        publicKey: pk,\n        address: address\n    }\n    commit('UPDATE_LEDGER_CONNECTOR_WALLET', {ledgerWallet: ledgerWallet})\n}\nconst state = {\n    ledgerStatus: '',\n    deviceInfo: '',\n    publicKey: '',\n    intervalId:'',\n    ledgerWallet: {\n        address: '',\n        publicKey: ''\n    }\n}\n\nconst mutations = {\n    UPDATE_LEDGER_DEVICE_INFO(state, payload){\n        state.deviceInfo = payload.deviceInfo\n    },\n    UPDATE_LEDGER_PUBLICKEY(state, payload) {\n        state.publicKey = payload.publicKey\n    },\n    UPDATE_LEDGER_STATUS(state, payload) {\n        state.ledgerStatus = payload.ledgerStatus\n    },\n    UPDATE_LEDGER_CONNECTOR_INTERVALID(state, payload) {\n        state.intervalId = payload.intervalId\n    },\n    UPDATE_LEDGER_CONNECTOR_WALLET(state, payload) {\n        state.ledgerWallet = payload.ledgerWallet;\n    }\n}\n\nconst LEDGER_CONNECTOR_INTERVAL = 'ledger_connector_intervalId'\n\nconst actions = {\n    getLedgerStatus({dispatch,commit,state}, interval) {\n        dispatch('stopGetLedgerStatus');\n        let time = interval || 5000;\n        getDevice(commit, state)\n        const intervalId = setInterval(() => {\n            getDevice(commit, state)\n        }, time)\n        localStorage.setItem(LEDGER_CONNECTOR_INTERVAL, intervalId)\n    },\n    stopGetLedgerStatus({commit, state}) {\n        const intervalId = localStorage.getItem(LEDGER_CONNECTOR_INTERVAL) || ''\n        clearInterval(intervalId)\n        localStorage.removeItem(LEDGER_CONNECTOR_INTERVAL)\n        commit('UPDATE_LEDGER_PUBLICKEY', {publicKey: ''})\n    }\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/LedgerWallet.js",
    "content": "import { Crypto } from 'ontology-ts-sdk'\nimport { WALLET_TYPE} from '../../core/consts'\nimport dbService from '../../core/dbService'\nconst state = {\n    publicKey: '',\n    address: '',\n    isHardwareLogin: true\n}\n\nconst mutations = {\n    LOGIN_WITH_LEDGER(state, payload) {\n        state.publicKey = payload.publicKey;\n        state.address = payload.address;\n    }\n}\n\nconst actions = {\n    someAsyncTask({ commit }) {\n        // do something async\n        commit('INCREMENT_MAIN_COUNTER')\n    },\n    loginWithLedger({ commit }, pk) {\n        const publicKey = new Crypto.PublicKey(pk);\n        const address = Crypto.Address.fromPubKey(publicKey).toBase58();\n        const currentWallet = JSON.parse(sessionStorage.getItem('currentWallet'))\n        if(currentWallet.address !== address) {\n            return false;\n        } else {\n            commit('LOGIN_WITH_LEDGER', { publicKey:pk, address })\n            return true;\n        }\n    },\n    createLedgerWalletWithPk({commit}, body) {\n        const publicKey = new Crypto.PublicKey(body.pk);\n        const address = Crypto.Address.fromPubKey(publicKey).toBase58();\n        const ledgerWallet =  {\n                publicKey: body.pk,\n                address,\n                neo: body.neo || false,\n                acct:body.acct,\n                timestamp: new Date().getTime(),\n            }\n        return ledgerWallet;\n    }\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/LoadingModal.js",
    "content": "// import $ from 'jquery'\nconst state = {\n  showLoading: false\n}\n\nconst mutations = {\n  SHOW_LOADING_MODALS(state) {\n    state.showLoading = true;\n  },\n  HIDE_LOADING_MODALS(state) {\n    state.showLoading = false\n  }\n}\n\nconst actions = {\n  showLoadingModals({commit}) {\n    // $(\"#loadingModal\").modal('show')\n    commit('SHOW_LOADING_MODALS')\n  },\n  hideLoadingModals({commit}) {\n    // Wait for the animation to end\n    const tid = setTimeout( () => {\n      commit('HIDE_LOADING_MODALS')\n      clearTimeout(tid)\n    }, 500)\n    \n        // setTimeout(()=>{\n        //   $(\"#loadingModal\").modal('hide')\n        //   $('body').removeClass('modal-open');\n        //   if ($('.modal-backdrop')) {\n        //     $('.modal-backdrop').remove();\n        //   }\n        // }, 500)\n    \n  }\n}\n\nexport default {\n  actions,\n  mutations,\n  state\n}\n"
  },
  {
    "path": "src/store/modules/NodeAuthorization.js",
    "content": "import { getNodeUrl} from '../../core/utils'\nimport {NODE_DETAIL, NODE_NAME_LIST, OFF_CHAIN_NODES, NODE_CURRENT_STAKES} from '../../core/consts'\nimport numeral from 'numeral'\nimport { Crypto, RestClient, utils, GovernanceTxBuilder} from 'ontology-ts-sdk'\nimport {BigNumber} from 'bignumber.js'\nimport {dbUpsert, dbFind} from '../../core/dbService'\nimport axios from 'axios';\nimport {\n  message\n} from 'ant-design-vue'\nimport i18n from '../../lang';\nvar dateFormat = require('dateformat');\n// import nodes from '../../core/nodes.json'\n\n//@Deprecated\nasync function matchNodeName(list) {\n    let nodes = []\n    const net = localStorage.getItem('net');\n    try {\n         if(net === 'MAIN_NET') { // only MainNet nodes have names\n            const res = await axios.get(NODE_NAME_LIST)\n            if (res && res.data && res.data.Result) {\n              nodes = res.data.Result\n            }\n         }\n    } catch(err) {\n        console.log(err)\n    }\n    console.log(nodes)\n    if (net === 'TEST_NET') {\n        list.forEach(item => {\n           item.name = 'Node_' + item.pk.substr(0, 6);\n        })\n        return;\n    }\n    for(const item of list) {\n        for (const cnode of nodes) {\n            if (cnode.PublicKey === item.pk || cnode.PublicKey  === item.peerPubkey) {\n                item.name = cnode.Name\n                break;\n            }\n            else if (!cnode || !cnode.PublicKey) {\n                if (item.address) {\n                    item.name = 'Node_' + (item.address.toBase58 ? item.address.toBase58().substr(0, 6) : item.address.substr(0, 6));\n                } else {\n                    item.name = 'Node_' + item.pk.substr(0, 6)\n                }\n            }\n        }\n    }\n}\n\nasync function fetchRoundBlocks() {\n    const net = localStorage.getItem('net');\n    let url = net === 'TEST_NET' ? 'https://polarisexplorer.ont.io/v2/nodes/block-count-to-next-round'\n        : 'https://explorer.ont.io/v2/nodes/block-count-to-next-round'\n    const res = await axios.get(url);\n    if (res.data && res.data.result) {\n        const {max_staking_change_count, count_to_next_round} = res.data.result\n        return Number(count_to_next_round);\n    } else {\n        throw new Error('Network error when fetch block counts.')\n    }\n}\n\nfunction delay(s) {\n    return new Promise((resolve, reject) => {\n        setTimeout(resolve, s);\n    })\n}\n\n\nfunction formatAuthorizationInfo(info) {\n    const authorizationInfo = info;\n    let inAuthorization = authorizationInfo.consensusPos + authorizationInfo.freezePos\n        + authorizationInfo.newPos;\n    inAuthorization = numeral(inAuthorization).format('0,0');\n    const newStakePortion = numeral(authorizationInfo.newPos).format('0,0')\n    const receiveProfitPortion = numeral(authorizationInfo.consensusPos + authorizationInfo.freezePos).format('0,0')\n    let locked = authorizationInfo.withdrawPos + authorizationInfo.withdrawFreezePos;\n    locked = numeral(locked).format('0,0')\n    let claimableVal = authorizationInfo.withdrawUnfreezePos;\n    const claimable = numeral(claimableVal).format('0,0')\n    return {\n        inAuthorization,\n        locked,\n        claimable,\n        claimableVal,\n        newStakePortion,\n        receiveProfitPortion\n    }\n}\n\nconst state = {\n    current_peer:{ // for node user\n        peerPubkey: '',\n        address: '',\n        status: 0,\n        initPos: 0,\n        initPosStr: '0',\n        totalPos: 0,\n        totalPosStr: '0'\n    },\n    peer_attrs: {\n        peerPubkey: '',\n        maxAuthorize: 0,\n        maxAuthorizeStr: '0',\n        t2PeerCost: 0,\n        t1PeerCost: 0,\n        tPeerCost: 0,\n        t2StakeCost: 0,\n        t1StakeCost: 0,\n        tStakeCost: 0,\n    },\n    current_node: '',\n    authorizationInfo:'',\n    splitFee: {\n        address: '',\n        amount: 0\n    },\n    countdown: 0,\n    node_list: [],\n    posLimit: 10,\n    peerUnboundOng: 0,\n    stakeHistory: [],\n    stake_authorization_wallet: '',\n    peerPoolMap:[],\n    sortedNodeList: []\n}\n\nconst mutations = {\n    UPDATE_CURRENT_PEER(state, payload) {\n        state.current_peer = {\n            peerPubkey: payload.peerItem.peerPubkey,\n            address: payload.peerItem.address?payload.peerItem.address.toBase58() : '',\n            status: payload.peerItem.status,\n            initPos: payload.peerItem.initPos,\n            initPosStr: numeral(payload.peerItem.initPos).format('0,0'),\n            totalPos: payload.peerItem.totalPos,\n            totalPosStr: numeral(payload.peerItem.totalPos).format('0,0')\n        }\n    },\n    UPDATE_PEER_ATTRS(state, payload) {\n        state.peer_attrs = {\n            peerPubkey: payload.peerAttrs.peerPubkey,\n            maxAuthorize: payload.peerAttrs.maxAuthorize,\n            maxAuthorizeStr: numeral(payload.peerAttrs.maxAuthorize).format('0,0'),\n            t2PeerCost: payload.peerAttrs.t2PeerCost,\n            t1PeerCost: payload.peerAttrs.t1PeerCost,\n            tPeerCost: payload.peerAttrs.tPeerCost,\n            t2StakeCost: payload.peerAttrs.t2StakeCost,\n            t1StakeCost: payload.peerAttrs.t1StakeCost,\n            tStakeCost: payload.peerAttrs.tStakeCost\n        }\n    },\n    UPDATE_CURRENT_NODE(state, payload) {\n        state.current_node = payload.current_node\n    },\n    UPDATE_AUTHORIZATION_INFO(state, payload) {\n        const {\n            inAuthorization,\n            locked,\n            claimable,\n            claimableVal,\n            newStakePortion,\n            receiveProfitPortion\n        } = formatAuthorizationInfo(payload.info)\n        state.authorizationInfo = {\n            ...payload.info,\n            inAuthorization,\n            locked,\n            claimable,\n            claimableVal,\n            newStakePortion,\n            receiveProfitPortion\n        }\n    },\n    UPDATE_SPLIT_FEE(state, payload) {\n        state.splitFee = payload.splitFee\n    },\n    UPDATE_COUNTDOWN_BLOCK(state, payload) {\n        state.countdown = payload.countdown;\n    },\n    UPDATE_NODE_LIST(state, payload) {\n        state.node_list = payload.list\n    },\n    UPDATE_POS_LIMIT(state, payload) {\n        state.posLimit = payload.posLimit\n    },\n    UPDATE_PEER_UNBOUND_ONG(state, payload) {\n        state.peerUnboundOng = payload.peerUnboundOng\n    },\n    UPDATE_STAKE_HISTORY(state, payload) {\n        state.stakeHistory = payload.history\n    },\n    UPDATE_STAKE_AUTHORIZATION_WALLET(state, payload) {\n        state.stake_authorization_wallet = payload.stakeWallet\n    },\n    UPDATE_PEER_POOL_MAP(state, payload) {\n        state.peerPoolMap = payload.peerMap\n    },\n    CLEAR_STAKE_HISTORY(state, payload) {\n        state.stakeHistory = []\n    },\n    UPDATE_SORTED_NODE_LIST(state, {list}) {\n        state.sortedNodeList = list;\n    }\n}\n\nconst actions = {\n    async fetchPeerItem({commit}, pk){\n        const url = getNodeUrl();\n        const peerMap = await GovernanceTxBuilder.getPeerPoolMap(url);\n        if(!pk) {\n            return peerMap;\n        }\n        if(pk && peerMap[pk]) {\n            commit('UPDATE_CURRENT_PEER', {peerItem: peerMap[pk]})\n            return peerMap[pk]\n        } else {\n            const peerItem = {\n                peerPubkey: '',\n                address: '',\n                status: 0,\n                initPos: 0,\n                initPosStr: '0',\n                totalPos: 0,\n                totalPosStr: '0'\n            }\n            commit('UPDATE_CURRENT_PEER', { peerItem })\n            return null;\n        }\n    },\n\n    async fetchPeerAttributes({commit}, pk) {\n        const url = getNodeUrl();\n        const peerAttrs = await GovernanceTxBuilder.getAttributes(pk, url);\n        if (peerAttrs) {\n            commit('UPDATE_PEER_ATTRS', {peerAttrs})\n            return peerAttrs;\n        }\n    },\n    async fetchAuthorizationInfo({commit}, {pk, address}) {\n        const url = getNodeUrl();\n        const userAddr = new Crypto.Address(address);\n        const authorizeInfo = await GovernanceTxBuilder.getAuthorizeInfo(pk, userAddr, url)\n        if(authorizeInfo) {\n            commit('UPDATE_AUTHORIZATION_INFO', {info: authorizeInfo})\n            return authorizeInfo\n        }\n    },\n    async fetchSplitFee({commit}, address) {\n        const url = getNodeUrl();\n        const userAddr = new Crypto.Address(address);\n        const splitFee = await GovernanceTxBuilder.getSplitFeeAddress(userAddr, url)\n        if(splitFee) {\n            if(splitFee.amount) {\n                splitFee.amount = new BigNumber(splitFee.amount).div(1e9).toFixed(9)\n            }\n            commit('UPDATE_SPLIT_FEE', {splitFee})\n            return splitFee\n        }\n    },\n    async searchStakeHistory({commit, dispatch, state}, {address}) {\n        const url = getNodeUrl();\n        const list = []\n        const net = localStorage.getItem('net')\n        const off_chain_nodes_url = OFF_CHAIN_NODES[net];\n        const userAddr = new Crypto.Address(address);\n        try {\n            const res = await axios.get(off_chain_nodes_url);\n            const nodes = res.data.result.filter(node => node.public_key.indexOf('00aaaaaaaaa') < 0); //00aaaaaaaaa开头是无效的公钥\n            const infoTemp = await Promise.all(nodes.map(async item => {\n                const authorizeInfo = await GovernanceTxBuilder.getAuthorizeInfo(item.public_key, userAddr, url)\n                return {\n                  ...authorizeInfo,\n                  nodeAddress: item.address\n                }\n            }))\n            infoTemp.forEach(item => {\n                if (item.nodeAddress === address) {\n                  return;\n                }\n                let inAuthorization = item.consensusPos + item.freezePos +\n                  item.newPos;\n                let locked = item.withdrawPos + item.withdrawFreezePos;\n                let claimableVal = item.withdrawUnfreezePos;\n                if (inAuthorization > 0 || locked > 0 || claimableVal > 0) {\n                  const record = formatAuthorizationInfo(item)\n                  record.name = '';\n                  record.pk = item.peerPubkey;\n                  record.stakeWallet = address;\n                  list.push(record)\n                }\n            })\n            list.forEach(item => {\n                for (let i = 0; i < nodes.length; i++) {\n                    if (item.pk === nodes[i].public_key) {\n                        item.name = nodes[i].name ? nodes[i].name : 'Node_' + nodes[i].public_key.substr(0, 6)\n                    }\n                }\n            })\n            commit('UPDATE_STAKE_HISTORY', {history: list})\n            dispatch('hideLoadingModals')\n            return list;\n        } catch(err) {\n            dispatch('hideLoadingModals')\n            console.log(err)\n            message.error(i18n.t('commonWalletHome.networkError'))\n            return [];\n        }\n    },\n    //@Deprecated\n    async fetchAllSortedNodeList({commit, dispatch}) {\n        const url = getNodeUrl();\n        try {\n            const peerMap = await GovernanceTxBuilder.getPeerPoolMap(url);\n            const list = []\n            for (let k in peerMap) {\n              let item = peerMap[k];\n              if (item.status !== 1 && item.status !== 2) { // consensus nodes and candidate nodes\n                continue;\n              }\n              item.pk = item.peerPubkey;\n              list.push(item)\n            }\n            list.sort((v1, v2) => {\n                if ((v2.initPos + v2.totalPos) > (v1.initPos + v1.totalPos)) {\n                    return 1;\n                } else if ((v2.initPos + v2.totalPos) < (v1.initPos + v1.totalPos)) {\n                    return -1;\n                } else {\n                    return 0;\n                }\n            })\n            list.forEach((item, index) => {item.rank = index + 1})\n            await matchNodeName(list);\n            commit('UPDATE_SORTED_NODE_LIST', {list})\n            dispatch('hideLoadingModals')\n            return list;\n        } catch(err) {\n            console.log(err)\n            dispatch('hideLoadingModals')\n            message.error(i18n.t('commonWalletHome.networkError'))\n            return [];\n        }\n    },\n    //Deprecated\n    async fetchNodeList({commit, dispatch, state}, {pageSize, pageNum}) {\n        const url = getNodeUrl();\n        if(state.sortedNodeList.length === 0) {\n            await dispatch('fetchAllSortedNodeList')\n        }\n        try{\n            const nodes = state.sortedNodeList.slice(pageNum*pageSize, (pageNum+1) * pageSize).filter(item => item.peerPubkey)\n            console.log(nodes)\n            const listTemp = await Promise.all(nodes.map((item) => {\n              return GovernanceTxBuilder.getAttributes(item.peerPubkey, url)\n            }))\n            nodes.forEach((item, i) => {\n                const attr = listTemp[i];\n                item.maxAuthorize = attr.maxAuthorize;\n                item.maxAuthorizeStr = numeral(item.maxAuthorize).format('0,0')\n                item.totalPosStr = numeral(item.totalPos).format('0,0')\n                const nodeProportion = attr.t1PeerCost + '%'\n                const userProportion = (100 - attr.t1PeerCost) + '%'\n                // item.nodeProportion = nodeProportion + ' / ' + userProportion\n                item.nodeProportion = userProportion\n            })\n            const list = nodes;\n            list.forEach((item, index) => {\n                item.currentStake = numeral(item.initPos + item.totalPos).format('0,0');\n                let process = Number((item.totalPos + item.initPos) * 100 / (item.initPos + item.maxAuthorize)).toFixed(2)\n                if(process > 100) {\n                    process = 100;\n                }\n                item.process = process + '%'\n                item.detailUrl = NODE_DETAIL + item.peerPubkey;\n            })\n            console.log(JSON.stringify(list))\n\n            commit('UPDATE_NODE_LIST', {list});\n            dispatch('hideLoadingModals')\n            return list.length;\n        } catch(err) {\n            console.log(err)\n            commit('UPDATE_NODE_LIST', {list: []});\n            dispatch('hideLoadingModals')\n            return 0;\n        }\n    },\n\n    async fetchNodeListNew({commit, dispatch}, {pageSize, pageNum}) {\n        const net = localStorage.getItem('net')\n        const url = NODE_CURRENT_STAKES[net];\n        try {\n            const res = await axios.get(url)\n            console.log(res)\n            if(res.data.code === 0 && res.data.result) {\n                const result = res.data.result;\n                const total = result.length;\n                const list = result.slice(pageNum * pageSize, (pageNum + 1) * pageSize).map(item => {\n                    item.rank = item.node_rank;\n                    item.nodeProportion = item.node_proportion;\n                    item.userProportion = item.user_proportion;\n                    item.currentStake = numeral(item.current_stake).format('0,0');\n                    item.process = item.progress;\n                    item.maxAuthorize = item.max_authorize;\n                    item.maxAuthorizeStr = numeral(item.max_authorize).format('0,0')\n                    item.totalPos = item.total_pos;\n                    item.initPos = item.init_pos;\n                    item.pk = item.public_key;\n                    item.detailUrl = item.detail_url;\n                    item.totalPosStr = numeral(item.totalPos).format('0,0')\n                    if (!item.name) {\n                        item.name = 'Node_' + item.public_key.substr(0, 6)\n                    }\n                    return item;\n                })\n                commit('UPDATE_NODE_LIST', {list})\n                return total;\n            } else {\n                throw new Error('Network error when fetch node list.')\n                // return 0;\n            }\n        }catch(err) {\n            console.log(err)\n            commit('UPDATE_NODE_LIST', {list: []});\n            dispatch('hideLoadingModals')\n            message.error(i18n.t('commonWalletHome.networkError'))\n            return 0;\n        }\n\n    },\n    async fetchBlockCountdown({commit}) {\n        const url = getNodeUrl();\n        const rest = new RestClient(url);\n        try {\n            // const view = await GovernanceTxBuilder.getGovernanceView(url);\n            // const blockRes = await rest.getBlockHeight();\n            // const blockHeight = blockRes.Result;\n            // const blockCounts = await fetchRoundBlocks()\n            // const countdown = blockCounts - (blockHeight - view.height);\n            // if (countdown < 0) {\n            //     throw new Error('Network error for fetch block countdown.')\n            // }\n            const countdown = await fetchRoundBlocks()\n            commit('UPDATE_COUNTDOWN_BLOCK', {countdown})\n            return countdown;\n        }catch(err) {\n            // alert('Network error.')\n            console.log(err)\n        }\n    },\n    async fetchPosLimit({commit}) {\n        const url = getNodeUrl();\n        try {\n            const globalParams = await GovernanceTxBuilder.getGlobalParam(url);\n            if(globalParams.posLimit) {\n                commit('UPDATE_POS_LIMIT', {posLimit: globalParams.posLimit});\n                return globalParams.posLimit;\n            }\n        }catch(err) {\n            console.log(err);\n        }\n    },\n    async fetchPeerUnboundOng({commit}, address) {\n        const url = getNodeUrl();\n        const addr = new Crypto.Address(address);\n        try {\n            let peerUnboundOng = await GovernanceTxBuilder.getPeerUnboundOng(addr, url);\n            peerUnboundOng = new BigNumber(peerUnboundOng).div(1e9).toNumber();\n            commit('UPDATE_PEER_UNBOUND_ONG', {peerUnboundOng})\n            return peerUnboundOng;\n        } catch(err) {\n            console.log(err);\n        }\n    },\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/NodeAuthorizationSesameseed.js",
    "content": "import { utils } from 'ontology-ts-sdk'\nimport axios from 'axios';\n\nconst state = {\n    sesameseed: { // for node user\n        votes: 0,\n        pendingWithdrawals: 0\n    }\n}\n\nconst mutations = {\n    UPDATE_CURRENT_SS_PEER(state, payload) {\n        state.sesameseed = {\n            votes: payload.votes,\n            pendingWithdrawals: payload.pendingWithdrawals\n        }\n    }\n}\n\nconst actions = {\n    async fetchSSPerInfo({ commit }, address) {\n        try {\n            const baseUrl = 'https://api.sesameseed.org/voting/v1/address/'\n\n            const pendingWithdrawalsPromise = axios.get(baseUrl + 'unstaked/' + address)\n            const votesPromise = axios.get(baseUrl + 'staked/' + address)\n\n            const [pendingWithdrawalsResponse, votesResponse] = await Promise.all([pendingWithdrawalsPromise, votesPromise])\n\n            let votes = 0\n            let pendingWithdrawals = 0\n\n            if (pendingWithdrawalsResponse.status === 200 && pendingWithdrawalsResponse.data) {\n                const resultPending = pendingWithdrawalsResponse.data\n                pendingWithdrawals = resultPending.value ? resultPending.value : 0\n            }\n\n            if (votesResponse.status === 200 && votesResponse.data) {\n                const resultVotes = votesResponse.data\n                votes = resultVotes.value ? resultVotes.value : 0\n            }\n\n            commit('UPDATE_CURRENT_SS_PEER', { votes, pendingWithdrawals })\n            return { votes, pendingWithdrawals };\n        } catch (err) {\n            console.log(err)\n            return 0;\n        }\n    }\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/NodeStake.js",
    "content": "import axios from 'axios'\nimport en from '../../lang/en'\nimport zh from '../../lang/zh'\nimport { ONT_PASS_NODE, ONT_PASS_NODE_PRD, ONT_PASS_URL, QUERY_NODE_INFO_API,\n    UPDATE_NODE_INFO_API, UPDATE_LEDGER_NODE_INFO_API } from '../../core/consts'\n\nconst state = {\n    detail: {\n        publickey: ''\n    },\n    nodePublicKey: '',\n    stakeWallet: {\n        address: '',\n        key: ''\n    },\n    stakeIdentity: {\n        ontid: ''\n    },\n    status: '',\n    status1: '',\n    status2: '',\n    status3: '',\n    current: 0,\n    statusTip: '',\n    btnText: '',\n    menuTabIndex: 1\n}\n\nconst mutations = {\n    UPDATE_STAKE_IDENTITY(state, payload) {\n        state.stakeIdentity = payload.stakeIdentity\n    },\n    UPDATE_STAKE_WALLET(state, payload) {\n        state.stakeWallet = payload.stakeWallet\n    },\n    UPDATE_NODE_PUBLICKEY(state, payload) {\n        state.nodePublicKey = payload.nodePublicKey\n    },\n    UPDATE_NODE_STATUS(state, payload) {\n        state.status = payload.status\n    },\n    UPDATE_STAKE_STATUS(state, payload) {\n        state.status1 = payload.status1\n        state.status2 = payload.status2\n        state.status3 = payload.status3\n        state.current = payload.current\n        state.statusTip = payload.statusTip\n    },\n    UPDATE_STAKE_DETAIL(state, payload) {\n        state.detail = payload.detail\n    },\n    UPDATE_MENU_TAB_INDEX(state, index) {\n        state.menuTabIndex = index\n    }\n}\n\nfunction formatStatusText(status){\n    const lang = localStorage.getItem('user_lang') || 'en'\n    return lang === 'en' ? en.nodeStakeStatus[status] : zh.nodeStakeStatus[status]\n}\n\nfunction getStatus(status) {\n    let status1 = '',\n        status2 = '',\n        status3 = '',\n        current = 0,\n        statusTip = '',\n        btnText = ''\n    switch (status) {\n        case 0: // 没了\n             status1 = formatStatusText('transfering')\n             status2 = formatStatusText('audit')\n             status3 = formatStatusText('stake')\n             current = 0\n             statusTip = formatStatusText('transferNeedTime')\n            break;\n        case 1: // 没了\n             status1 = formatStatusText('transferFailed')\n             status2 = formatStatusText('audit')\n             status3 = formatStatusText('stake')\n             statusTip = ''\n             current = 0\n            break;\n        case 2: // 没了\n             status1 = formatStatusText('transfered')\n             status2 = formatStatusText('auditing')\n             status3 = formatStatusText('stake')\n             statusTip = formatStatusText('auditNeedTime')\n             current = 1\n            break;\n        case 3: // 没了\n             status1 = formatStatusText('transfered')\n             status2 = formatStatusText('auditFailed')\n             status3 = formatStatusText('stake')\n             statusTip = ''\n             current = 1\n            break;\n        case 4: // 没了\n             status1 = formatStatusText('nodeExited')\n             status2 = formatStatusText('refund')\n             status3 = formatStatusText('quitStake')\n             statusTip = formatStatusText('unfrozenToRefund')\n             current = 0\n            break;\n        case 5:\n             status1 = formatStatusText('nodeExited')\n             status2 = formatStatusText('refunding')\n             status3 = formatStatusText('quitStake')\n             current = 1\n             statusTip = formatStatusText('refundNeedTime')\n            break;\n        case 6:\n             status1 = formatStatusText('nodeExited')\n             status2 = formatStatusText('refunded')\n             status3 = formatStatusText('stakeExited')\n             current = 2\n             statusTip = ''\n            break;\n        case 7:\n             status1 = formatStatusText('nodeExited')\n             status2 = formatStatusText('refundFailed')\n             status3 = formatStatusText('stakeExited')\n             current = 1\n            statusTip = ''\n            break;\n        case 8:\n             status1 = formatStatusText('transfered')\n             status2 = formatStatusText('audited')\n             status3 = formatStatusText('staked')\n             current = 2\n            statusTip = ''\n            break;\n        case 9:\n             status1 = formatStatusText('nodeExited')\n             status2 = formatStatusText('refund')\n             status3 = formatStatusText('quitStake')\n             current = 0\n            statusTip = ''\n            break;\n        case 10:\n            status1 = formatStatusText('nodeExited')\n             status2 = formatStatusText('refund')\n             status3 = formatStatusText('quitStake')\n             current = 0\n            statusTip = ''\n            break;\n\n        default:\n            break;\n    }\n    return {\n        status1, status2, status3, current, statusTip\n    }\n}\n\nconst actions = {\n    fetchStakeDetail({commit}, {address, public_key}){\n        const net = localStorage.getItem(\"net\");\n        const ontPassNode =\n            net === \"TEST_NET\" ? ONT_PASS_NODE : ONT_PASS_NODE_PRD;\n        axios.get(ontPassNode + ONT_PASS_URL.GetStakeInfo, {\n            params: {\n               address,\n               publickey: public_key\n            }\n        }).then(res => {\n            commit('UPDATE_STAKE_DETAIL', { detail:res.data})\n            const status = getStatus(res.data.status);\n            commit('UPDATE_STAKE_STATUS', status)\n            return res.data;\n        })\n        // const status = getStatus(2);\n        // commit('UPDATE_STAKE_STATUS', status)\n    },\n    async fetchNodeInfo({ }, public_key) {\n        const net = localStorage.getItem(\"net\");\n        const url = QUERY_NODE_INFO_API[net]\n        const res = await axios.get(url, {\n            params: {\n                public_key\n            }\n        })\n        return res.data.result\n    },\n    async updateNodeInfo({ }, info) {\n        const net = localStorage.getItem(\"net\");\n        const url = UPDATE_NODE_INFO_API[net]\n        const res = await axios.post(url, info)\n        return res.data\n    },\n    async updateLedgerNodeInfo({ }, info) {\n        const net = localStorage.getItem(\"net\");\n        const url = UPDATE_LEDGER_NODE_INFO_API[net]\n        const res = await axios.post(url, info)\n        return res.data\n    },\n    async newStakeInfo({ }, info) {\n        const net = localStorage.getItem(\"net\");\n        const url = UPDATE_NODE_INFO_API[net] + '/new'\n        const res = await axios.post(url, info)\n        return res.data\n    }\n}\n\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/Oep4s.js",
    "content": "import {Oep4, RestClient, Crypto, utils} from 'ontology-ts-sdk'\nimport {TEST_NET, MAIN_NET} from '../../core/consts'\nimport { BigNumber } from 'bignumber.js';\nimport axios from 'axios';\nimport {\n  getRestClient,\n  getTokenListUrl\n} from '../../core/utils'\n\n\n// Deprecated\nconst oep4s = localStorage.getItem('oep4s')? JSON.parse(localStorage.getItem('oep4s')) : [];\n\nconst oep4_selected = {\n    'TEST_NET': [],\n    'MAIN_NET': []\n}\n\nconst state = {\n    oep4s,\n    completedTx: []\n}\n\nconst mutations = {\n    ADD_OEP4(state, payload) {\n        const oep4s = [...state.oep4s, payload.newOep4]\n        localStorage.setItem('oep4s', JSON.stringify(oep4s))\n        state.oep4s = oep4s;\n    },\n    UPDATE_OEP4S(state, payload) {\n        state.oep4s = payload.oep4s\n    },\n    UPDATE_OEP4_TX_LIST(state, payload) {\n        state.completedTx = payload.txList\n    }\n}\n\nconst actions = {\n    async addOep4Token({commit, dispatch, state}, {scriptHash, address})  {\n        try {\n            const restClient = getRestClient()\n            const res = await restClient.getContract(scriptHash);\n            console.log(res)\n            if (!res.Result) {\n                return 'NO_CONTRACT'\n            } else {\n                const name = await dispatch('queryOep4Name', scriptHash)\n                const symbol = await dispatch('queryOep4Symbol', scriptHash)\n                const decimal = await dispatch('queryOep4Decimal', scriptHash)\n                const balance = await dispatch('queryOep4Balance', {scriptHash, address, decimal})\n                const net = localStorage.getItem('net')\n                const newOep4 = {name, symbol, scriptHash, decimal, balance, net}\n                commit('ADD_OEP4', {newOep4})\n                dispatch('registerOep4Info', scriptHash)\n                dispatch('queryTxForOep4', {address, oep4s: [...state.oep4s, newOep4]})\n                return 'ADD_SUCCESS'\n            }\n        } catch(err) {\n            console.log(err)\n            return 'NETWORK_ERROR'\n        }\n    },\n\n    async registerOep4Info({commit, dispatch}, scriptHash) {\n        const net = localStorage.getItem('net');\n        let url = ''\n        if(net === 'TEST_NET') {\n            url = 'https://polarisexplorer.ont.io/api/v1/explorer/oep4/info'\n        } else {\n            url = 'https://explorer.ont.io/api/v1/explorer/oep4/info'\n        }\n        axios.post(url, {\n            scriptHash\n        }).then(res => {\n            console.log(res)\n        }).catch(err => {\n            console.log(err)\n        })\n    },\n\n    async queryOep4Name({commit}, scriptHash) {\n        const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));\n        const oep4 = new Oep4.Oep4TxBuilder(contractAddr);\n        const tx = oep4.queryName();\n        const restClient = getRestClient()\n        const res = await restClient.sendRawTransaction(tx.serialize(), true);\n        if(res.Result.Result) {\n            const val = utils.hexstr2str(res.Result.Result);\n            return val;\n        } else {\n            return 'OEP4'\n        }\n    },\n    async queryOep4Symbol({ commit }, scriptHash) {\n        const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));\n        const oep4 = new Oep4.Oep4TxBuilder(contractAddr);\n        const tx = oep4.querySymbol();\n        const restClient = getRestClient()\n        const res = await restClient.sendRawTransaction(tx.serialize(), true);\n        if (res.Result.Result) {\n            const val = utils.hexstr2str(res.Result.Result);\n            return val;\n        } else {\n            return 'OEP4'\n        }\n    },\n    async queryOep4Decimal({ commit }, scriptHash) {\n        const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));\n        const oep4 = new Oep4.Oep4TxBuilder(contractAddr);\n        const tx = oep4.queryDecimals();\n        const restClient = getRestClient()\n        const res = await restClient.sendRawTransaction(tx.serialize(), true);\n        if (res.Result.Result) {\n            const val = parseInt(res.Result.Result, 16);\n            return val;\n        } else {\n            return 0\n        }\n    },\n    async queryOep4Balance({commit}, {scriptHash, address, decimal=0}) {\n        const contractAddr = new Crypto.Address(utils.reverseHex(scriptHash));\n        const oep4 = new Oep4.Oep4TxBuilder(contractAddr);\n        const tx = oep4.queryBalanceOf(new Crypto.Address(address));\n        const restClient = getRestClient()\n        const res = await restClient.sendRawTransaction(tx.serialize(), true);\n        if(res.Result.Result) {\n            const bi = new BigNumber(utils.reverseHex(res.Result.Result), 16)\n\n            const val = bi.dividedBy(Math.pow(10,decimal)).toNumber()\n            return val;\n        } else {\n            return 0;\n        }\n    },\n    async queryBalanceForOep4({commit, dispatch, state}, address) {\n        dispatch('showLoadingModals');\n        try {\n            const net = localStorage.getItem('net');\n\n            const temp = await Promise.all(state.oep4s.map((item) => {\n                    if(item.net !== net) { // 避免多余的查询\n                        return Promise.resolve(0)\n                    }\n                    return dispatch('queryOep4Balance', {\n                        scriptHash: item.scriptHash,\n                        address,\n                        decimal: item.decimal\n                    })\n                })\n            )\n            console.log(temp);\n            const newOep4s = state.oep4s.map((item, index) => ({\n                ...item,\n                balance: temp[index]\n            }))\n            commit('UPDATE_OEP4S', {oep4s: newOep4s})\n            dispatch('hideLoadingModals');\n        } catch(err) {\n            dispatch('hideLoadingModals');\n            console.log(err);\n            alert('Network error.Please try later.')\n        }\n    },\n    async queryTxForOep4({commit, dispatch}, {address,oep4s}) {\n        const net = localStorage.getItem('net')\n        const url = net === 'TEST_NET' ? 'https://polarisexplorer.ont.io' : 'https://explorer.ont.io';\n        axios.get(url + '/api/v1/explorer/address/' + address + '/10/1').then(response => {\n            if (response.status === 200 && response.data && response.data.Result) {\n                const txlist = response.data.Result.TxnList;\n                const completed = []\n                for (const t of txlist) {\n                    // if(t.TransferList.length === 1 && t.TransferList[0].ToAddress === ONG_GOVERNANCE_CONTRACT) {\n                    //   continue;\n                    // }\n                    for (const tx of t.TransferList) {\n                        if(tx.AssetName === 'ong'){\n                            continue;\n                        }\n                        for(let o of oep4s) {\n                            let amount = tx.Amount\n                            if(o.symbol === tx.AssetName || tx.AssetName === 'LCY') { // They give the wrong symbol for token LUCKY\n                                if (tx.FromAddress === address) {\n                                    amount = '-' + amount;\n                                } else {\n                                    amount = '+' + amount;\n                                }\n                                completed.push({\n                                    txHash: t.TxnHash,\n                                    asset: tx.AssetName,\n                                    amount: amount\n                                })\n                                break;\n                            }\n                        }\n\n                    }\n\n                }\n                commit('UPDATE_OEP4_TX_LIST', {txList: completed})\n            }\n        }).catch(err => {\n            dispatch('hideLoadingModals');\n            console.log(err)\n        })\n    }\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/PaxMgmt.js",
    "content": "const state = {\n    unprocess_list: [\n       \n    ],\n    processing_list: [\n         {\n           cosigners: []\n         }\n    ],\n    currentSigner: ''\n}\n\nconst mutations = {\n    UPDATE_UNPROCESS_LIST(state, {list}) {\n        state.unprocess_list = list;\n    },\n    UPDATE_PROCESSING_LIST(state, {list}) {\n        state.processing_list = list;\n    },\n    UDPATE_CURRENT_SIGNER(state, {signer}) {\n        state.currentSigner = signer\n    }\n}\nconst actions = {}\n\nexport default {\n  state,\n  mutations,\n  actions\n}"
  },
  {
    "path": "src/store/modules/Setting.js",
    "content": "import dbService, { dbFind } from '../../core/dbService';\n\nconst net = localStorage.getItem('net');\nconst state = {\n    network:net,\n    connected: false\n}\n\nconst mutations = {\n    UPDATE_SETTING_NETWORK(state, payload) {\n        state.network = payload.network\n    },\n    NETWORK_CONNECTED(state, payload) {\n        state.connected = true;\n    },\n    NETWORK_DISCONNECTED(state, payload) {\n        state.connected = false;\n    }\n}\n\nconst actions = {\n\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/Tokens.js",
    "content": "import httpService, {\n  getRestClient,\n  getTokenListUrl,\n  getTokenBalanceUrl\n} from '../../core/utils'\n\n// should contain native, oep4, oep5, oep8 tokens\nconst oep4_default = {\n  'TEST_NET': {},\n  'MAIN_NET': {}\n}\nconst oep4Tokens = localStorage.getItem('oep4Tokens') ? JSON.parse(localStorage.getItem('oep4Tokens')) : oep4_default;\n\n\n\n/*\n\n*/\n\nconst state = {\n    oep4Tokens,\n    oep4WithBalances: []\n}\n\nconst mutations = {\n    UPDATE_OEP4_TOKENS(state, {oep4s}) {\n        const net = localStorage.getItem('net')\n        state.oep4Tokens[net] = oep4s;\n        localStorage.setItem('oep4Tokens', JSON.stringify(state.oep4Tokens))\n    },\n    UPDATE_OEP4_TOKEN(state, {oep4}) {\n        const net = localStorage.getItem('net')\n        const oep4s = Object.assign({}, state.oep4Tokens[net]);\n        if(oep4s[oep4.contract_hash]) {\n            for (let k of Object.keys(oep4s)) {\n              if (oep4s[k].contract_hash === oep4.contract_hash) {\n                  if(oep4.selected) {\n                      oep4s[k].selected = oep4.selected;\n                  } else {\n                      delete oep4s[k];\n                  }\n                break;\n              }\n            }\n        } else {\n            oep4s[oep4.contract_hash] = oep4;\n        }\n\n        state.oep4Tokens[net] = oep4s;\n        localStorage.setItem('oep4Tokens', JSON.stringify(state.oep4Tokens))\n    },\n    UPDATE_OEP4_BALANCES(state, {balances}) {\n        state.oep4WithBalances = balances;\n    },\n    CLEAR_OEP4S_BALANCES(state) {\n        state.oep4WithBalances = []\n    }\n}\n\nconst actions = {\n    async fetchOep4Selections({commit, state}, {page_size, page_number}) {\n        const url = getTokenListUrl('oep4', page_size, page_number);\n        const net = localStorage.getItem('net')\n        const res = await httpService.get(url)\n        console.log(res)\n        const list = res.result.records.map(item => {\n            item.selected = false;\n            for(let k of Object.keys(state.oep4Tokens[net])) {\n                const o = state.oep4Tokens[net][k]\n                if(o.contract_hash === item.contract_hash) {\n                    item.selected = o.selected;\n                    break;\n                }\n            }\n            return item;\n        })\n        const total = res.result.total;\n        // commit('UPDATE_OEP4_SELECTIONS', {list, total})\n        return {list, total}\n    },\n\n    async fetchTokenBalances({commit,state}, {address}) {\n        const url = getTokenBalanceUrl('oep4',address)\n        const net = localStorage.getItem('net')\n        const res = await httpService.get(url)\n        const balances = [];\n        const oep4s = state.oep4Tokens[net];\n        for (let k of Object.keys(oep4s)) {\n            const oep4 = oep4s[k]\n            const item = Object.assign({}, oep4)\n            item.balance = 0;\n            for(let r of res.result) {\n                console.log(r.asset_name, oep4.symbol)\n                if (r.asset_name === oep4.symbol) {\n                    item.balance = r.balance;\n                    break;\n                }\n            }\n            balances.push(item)\n        }\n        console.log(balances)\n        commit('UPDATE_OEP4_BALANCES', {\n          balances\n        })\n        return balances\n    }\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/Vote.js",
    "content": "import { NODE_CURRENT_STAKES,OFF_CHAIN_NODES,  VOTE_ROLE, DEFAULT_SCRYPT, ONT_PASS_NODE, ONT_PASS_NODE_PRD,\n    ONT_PASS_URL } from '../../core/consts'\nimport httpService, { getRestClient } from '../../core/utils'\nimport { TransactionBuilder, Crypto, utils, Parameter, ParameterType, TxSignature, WebsocketClient } from 'ontology-ts-sdk'\nimport {\n    message\n} from 'ant-design-vue'\nimport i18n from '../../lang';\nimport axios from 'axios';\n\nconst gasPrice = '500'\nconst gasLimit = '200000'\nconst contract_hash = {\n    MAIN_NET: 'c0df752ca786a99755b2e8950060ade9fa3d4e1b',\n    TEST_NET: '32a7403e17eb9a2bbeeb7bc3eaa6dee7b0ae3829'\n}\nconst contract_hash_old = {\n    MAIN_NET: 'c0df752ca786a99755b2e8950060ade9fa3d4e1b',\n    TEST_NET: 'a088ae3b508794e666ab649d890213e66e0c3a2e'\n}\nconst state = {\n    contract_hash: '',\n    voteWallet: '',\n    voteWalletType: '', // commonWallet or ledgerWallet\n    role: [],  // 可能同时是admin和voter\n    all_votes: [],\n    admin_votes: [], // admin 创建的votes\n    all_votes_hash: [],\n    admin_votes_hash: [],\n    currentVote: {},\n    my_weight: 0,\n    all_voters: [], // 当前是所有节点用户\n    current_vote_records: [] // 当前vote的投票情况\n}\n\nexport const VOTE_STATUS_TEXT = {\n    NOT_START: 'NOT_START',\n    IN_PROGRESS: 'IN_PROGRESS',\n    FINISHED: 'FINISHED',\n    CANCELED: 'CANCELED'\n}\n\nexport const MY_VOTED = {\n    'APPROVED': 'APPROVED',\n    'REJECTED': 'REJECTED',\n    'NOT_VOTED': 'NOT_VOTED'\n}\n\nconst formatNumber = function (val) {\n    return parseInt(utils.reverseHex(val), 16)\n}\n\nconst formatOldVoteInfo = function (infos) {\n    if (!infos) {\n        return [];\n    }\n    const votes = []\n    for (const info of infos) {\n        let item = info;\n        if (info && info.Result && info.Result.Result) {\n            item = info.Result.Result\n        }\n        const vote = {\n            admin: new Crypto.Address(item[0]).toBase58(),\n            title: utils.hexstr2str(item[1]),\n            content: utils.hexstr2str(item[2]),\n            voters: item[3] ? item[3].map(i => {\n                return {\n                    address: new Crypto.Address(i[0]).toBase58(),\n                    weight: parseInt(utils.reverseHex(i[1]), 16)\n                }\n            }) : [],\n            startTime: String(formatNumber(item[4])).length <= 10 ?  formatNumber(item[4]) * 1000 : formatNumber(item[4]),\n            endTime: String(formatNumber(item[5])).length <= 10 ?  formatNumber(item[5]) * 1000 : formatNumber(item[5]),\n            approves: formatNumber(item[6]),\n            rejects: formatNumber(item[7]),\n            status: formatNumber(item[8]),\n            hash: item[9]\n        }\n        if (vote.status === 0) {\n            vote.statusText = VOTE_STATUS_TEXT.CANCELED\n        } else {\n            const now = Date.now()\n            if (vote.startTime > now) {\n                vote.statusText = VOTE_STATUS_TEXT.NOT_START\n            } else if (vote.startTime <= now && vote.endTime >= now) {\n                vote.statusText = VOTE_STATUS_TEXT.IN_PROGRESS\n            } else if (vote.endTime < now) {\n                vote.statusText = VOTE_STATUS_TEXT.FINISHED\n            }\n        }\n\n        votes.push(vote)\n    }\n    return votes;\n}\n\n\nfunction formatVoteInfo(infos) {\n    if (!infos) {\n        return []\n    }\n        const votes = []\n        for (const data of infos) {\n            const sr = new utils.StringReader(data);\n            const hasValue = sr.readVarUint() > 0;\n            if (hasValue) {\n                const admin = new Crypto.Address(sr.read(20)).toBase58();\n                // tslint:disable:variable-name\n                const topic_title_length = sr.readVarUint();\n                const topic_title = utils.hexstr2str(sr.read(topic_title_length));\n                const topic_detail_length = sr.readVarUint();\n                const topic_detail = utils.hexstr2str(sr.read(topic_detail_length));\n                const voters_length = sr.readVarUint();\n                const voters = [];\n                for (let i = 0; i < voters_length; i++) {\n                    const voter_addr = new Crypto.Address(sr.read(20)).toBase58();\n                    const weight = sr.readUint128();\n                    voters.push({\n                        address: voter_addr,\n                        weight\n                    });\n                }\n                const start_time = sr.readUint64();\n                const end_time = sr.readUint64();\n                const approves = sr.readUint64();\n                const rejects = sr.readUint64();\n                const status = sr.readUint8();\n                const hash = sr.readH256();\n                const vote = {\n                    admin,\n                    title: topic_title,\n                    content: topic_detail,\n                    voters,\n                    startTime: start_time * 1000,\n                    endTime: end_time * 1000,\n                    approves,\n                    rejects,\n                    status,\n                    hash\n                };\n                if (vote.status === 0) {\n                    vote.statusText = VOTE_STATUS_TEXT.CANCELED\n                } else {\n                    const now = Date.now()\n                    if (vote.startTime > now) {\n                        vote.statusText = VOTE_STATUS_TEXT.NOT_START\n                    } else if (vote.startTime <= now && vote.endTime >= now) {\n                        vote.statusText = VOTE_STATUS_TEXT.IN_PROGRESS\n                    } else if (vote.endTime < now) {\n                        vote.statusText = VOTE_STATUS_TEXT.FINISHED\n                    }\n                }\n                votes.push(vote)\n            }\n        }\n    return votes\n}\n\nconst handleSignTx = async function (tx, wallet, password, walletType = 'commonWallet') {\n    if (walletType === 'commonWallet') {\n        const enc = new Crypto.PrivateKey(wallet.key);\n        let pri;\n        try {\n            pri = enc.decrypt(\n                password,\n                new Crypto.Address(wallet.address),\n                wallet.salt,\n                DEFAULT_SCRYPT\n            );\n        } catch (err) {\n            console.log(err);\n            message.error(i18n.t('common.pwdErr'))\n            return;\n        }\n        TransactionBuilder.signTransaction(tx, pri);\n    } else {\n        const pk = new Crypto.PublicKey(wallet.publicKey);\n        const txSig = new TxSignature();\n        txSig.M = 1;\n        txSig.pubKeys = [pk];\n        const txData = tx.serializeUnsignedData();\n        // TODO\n        // eslint-disable-next-line no-undef\n        const res = await legacySignWithLedger(txData)\n        // console.log('txSigned: ' + res);\n        const sign = '01' + res; //ECDSAwithSHA256\n        txSig.sigData = [sign]\n        tx.sigs.push(txSig);\n    }\n    return tx;\n}\n\nconst mutations = {\n    UPDATE_VOTE_WALLET(state, { voteWallet }) {\n        state.voteWallet = voteWallet\n    },\n    UPDATE_VOTE_ROLE(state, { role }) {\n        state.role = role\n    },\n    UPDATE_ALL_VOTES(state, { votes }) {\n        state.all_votes = votes\n    },\n    UPDATE_ADMIN_VOTES(state, { votes }) {\n        state.admin_votes = votes\n    },\n    UPDATE_VOTE_WALLET_TYPE(state, { type }) {\n        state.voteWalletType = type\n    },\n    UPDATE_CURRENT_VOTE(state, { vote }) {\n        state.currentVote = vote\n    },\n    UPDATE_MY_WEIGHT(state, { weight }) {\n        state.my_weight = weight\n    },\n    UPDATE_ALL_VOTERS(state, { all_voters }) {\n        state.all_voters = all_voters\n    },\n    UPDATE_CURRENT_VOTE_RECORDS(state, { records }) {\n        state.current_vote_records = records\n    },\n    UPDATE_VOTE_CONTRACT(state, contract_hash) {\n        state.contract_hash = contract_hash\n    }\n}\n\nconst actions = {\n    async fetchVoteContract({commit}) {\n        const net = localStorage.getItem('net')\n        const ontPassNode = net === 'TEST_NET' ? ONT_PASS_NODE : ONT_PASS_NODE_PRD\n        const url = ontPassNode + ONT_PASS_URL.GetVoteContract + '/' + net;\n        const res = await axios.get(url)\n        if(res && res.data && res.data.vote_contract_address) {\n            commit('UPDATE_VOTE_CONTRACT', res.data.vote_contract_address)\n        }\n    },\n    //从接口获取节点钱包地址，和从合约获取amdin地址，判断role\n    async getVoteRole({ commit, dispatch, state }, { address }) {\n        dispatch('showLoadingModals')\n        const net = localStorage.getItem('net');\n        const url = NODE_CURRENT_STAKES[net]\n        try {\n            //从接口查询admin信息\n            const res1 = await httpService({\n                url,\n                method: 'get'\n            })\n            // console.log(res1)\n            const client = getRestClient()\n            const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n            const tx = TransactionBuilder.makeWasmVmInvokeTransaction('listGovNodes', [], contract, gasPrice, gasLimit) // 从链上查询admin信息\n            const res2 = await client.sendRawTransaction(tx.serialize(), true);\n            console.log(res2)\n            let is_voter = false\n            let is_admin = false\n            let weight = 0\n            const all_voters = []\n            const sr1 = new utils.StringReader(res2.Result.Result)\n            const all_voters_length = sr1.readVarUint()\n            for(let i = 0; i< all_voters_length; i++) {\n                all_voters.push({\n                    name: '',\n                    weight: 0,\n                    address: new Crypto.Address(sr1.read(20)).toBase58() // 节点运营钱包\n                })\n            }\n            for(const admin_from_chain of all_voters) {\n                for(const admin_from_api of res1.result) {\n                    const pk_address = Crypto.Address.fromPubKey(new Crypto.PublicKey(admin_from_api.public_key)).toBase58()\n                    if(pk_address === admin_from_chain.address) {\n                        admin_from_chain.name = admin_from_api.name\n                        admin_from_chain.weight = admin_from_api.current_stake\n                        break;\n                    } else {\n                        admin_from_chain.name = admin_from_chain.address.substr(0,8)\n                    }\n                }\n            }\n            // const all_voters = res1.result.map(item => ({ name: item.name, address: item.address, weight: item.current_stake }))\n            commit('UPDATE_ALL_VOTERS', { all_voters })\n            for (let node of all_voters) {\n                if (node.address === address) {\n                    is_voter = true;\n                    is_admin = true;\n                    weight = node.weight\n                    break;\n                }\n            }\n            // let is_admin = false\n            // const result = res2.Result.Result\n            // const sr = new utils.StringReader(result);\n            // const addr_length = sr.readVarUint();\n            // for (let i = 0; i < addr_length; i++) {\n            //     if (new Crypto.Address(sr.read(20)).toBase58() === address) {\n            //         is_admin = true;\n            //         break;\n            //     }\n            // }\n            // for (let voter of all_voters) {\n            //     if (new Crypto.Address(addr).toBase58() === address) {\n            //         is_admin = true;\n            //         break;\n            //     }\n            // }\n            let role = [];\n            if (is_voter) role.push(VOTE_ROLE.VOTER)\n            if (is_admin) role.push(VOTE_ROLE.ADMIN)\n            console.log(role)\n            commit('UPDATE_VOTE_ROLE', { role })\n            commit('UPDATE_MY_WEIGHT', { weight })\n            dispatch('hideLoadingModals')\n        } catch (err) {\n            console.log(err)\n            dispatch('hideLoadingModals')\n            message.error(i18n.t('common.networkErr'))\n        }\n    },\n    async getAllVotes({ commit, dispatch, state }, {showLoading}) {\n        showLoading && dispatch('showLoadingModals')\n        const net = localStorage.getItem('net');\n        const client = getRestClient()\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const tx = TransactionBuilder.makeWasmVmInvokeTransaction('listTopics', [], contract, gasPrice, gasLimit)\n        try {\n            const res2 = await client.sendRawTransaction(tx.serialize(), true);\n            if (res2.Error !== 0) {\n                throw res2;\n            }\n            // 处理结果\n            const result = res2.Result.Result\n            const sr = new utils.StringReader(result);\n            const hash_length = sr.readVarUint();\n            const hashes = []\n            for (let i = 0; i < hash_length; i++) {\n                hashes.push(sr.read(32))\n            }\n            // const hashes = res2.Result.Result || []\n            console.log(hashes)\n            const txes = hashes.map(hash => {\n                return TransactionBuilder.makeWasmVmInvokeTransaction('getTopicInfo', [new Parameter('', ParameterType.H256, hash)], contract, gasPrice, gasLimit)\n            })\n\n            let infos = await Promise.all(txes.map(tx => { return client.sendRawTransaction(tx.serialize(), true) }))\n            // infos = infos.map(item => item.Result.Result)\n            let infoList = []\n            for(const info of infos) {\n                if(info && info.Result && info.Result.Result) {\n                    infoList.push(info.Result.Result)\n                }\n            }\n            console.log(infos)\n            let votes = formatVoteInfo(infoList)\n            // 根据hash过滤出查询失败的topic，从老的neo合约中继续查找\n            const oldHashes = []\n            for(const hash of hashes) {\n                let used = false;\n                for(const vote of votes) {\n                    if(hash === vote.hash) {\n                        used = true;\n                        break;\n                    }\n                }\n                if(!used){\n                    oldHashes.push(hash)\n                }\n            }\n            if(oldHashes.length > 0) {\n                const contractOld = new Crypto.Address(utils.reverseHex(contract_hash_old[net]))\n                const old_txes = oldHashes.map(hash => {\n                    return TransactionBuilder.makeInvokeTransaction('getTopicInfo', [new Parameter('', ParameterType.ByteArray, hash)], contractOld, gasPrice, gasLimit)\n                })\n\n                let infosOld = await Promise.all(old_txes.map(tx => { return client.sendRawTransaction(tx.serialize(), true) }))\n                // infos = infos.map(item => item.Result.Result)\n                let infoListOld = []\n                for(const info_old of infosOld) {\n                    if(info_old && info_old.Result && info_old.Result.Result) {\n                        infoListOld.push(info_old)\n                    }\n                }\n                const votesOld = formatOldVoteInfo(infoListOld)\n                votes = votes.concat(votesOld)\n            }\n\n            // console.log(votes)\n            commit('UPDATE_ALL_VOTES', { votes })\n            dispatch('hideLoadingModals')\n        } catch (err) {\n            console.log(err)\n            dispatch('hideLoadingModals')\n            message.error(i18n.t('common.networkErr'))\n        }\n\n    },\n    async getAdminVotes({ commit, dispatch, state }) {\n        // dispatch('showLoadingModals')\n        const address = state.voteWallet.address;\n        const all_votes = state.all_votes\n\n        let admin_votes = []\n        for(let item of all_votes) {\n            if(item.admin === address) {\n                admin_votes.push(item)\n            }\n        }\n        console.log(admin_votes)\n        commit('UPDATE_ADMIN_VOTES', { votes: admin_votes })\n    },\n    submitVote({ commit, state }, { type, hash }) {\n        const net = localStorage.getItem('net');\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const address = state.voteWallet.address\n        const addr = new Crypto.Address(address)\n        const params = [\n            new Parameter('', ParameterType.H256, hash),\n            new Parameter('', ParameterType.Address, addr),\n            new Parameter('', ParameterType.Boolean, type)\n        ]\n        let tx = TransactionBuilder.makeWasmVmInvokeTransaction('voteTopic', params, contract, gasPrice, gasLimit, addr)\n        return tx;\n    },\n    stopVote({ commit, dispatch, state }, { hash }) {\n        const net = localStorage.getItem('net');\n        const client = getRestClient()\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const address = state.voteWallet.address\n        const addr = new Crypto.Address(address)\n        const params = [\n            new Parameter('', ParameterType.H256, hash)\n        ]\n        let tx = TransactionBuilder.makeWasmVmInvokeTransaction('cancelTopic', params, contract, gasPrice, gasLimit, addr)\n        return tx;\n    },\n    createVote({ commit, dispatch, state }, { vote }) {\n        const net = localStorage.getItem('net');\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const address = state.voteWallet.address\n        const addr = new Crypto.Address(address)\n        const voters = state.all_voters;\n        const params = [\n            new Parameter('', ParameterType.Address, addr),\n            new Parameter('', ParameterType.String, vote.title),\n            new Parameter('', ParameterType.String, vote.content),\n            new Parameter('', ParameterType.Integer, vote.startTime),\n            new Parameter('', ParameterType.Integer, vote.endTime)\n        ]\n        let tx = TransactionBuilder.makeWasmVmInvokeTransaction('createTopic', params, contract, gasPrice, gasLimit, addr)\n        return tx;\n    },\n\n    async setVoters({ commit, dispatch, state }, { hash, voters }) {\n        dispatch('showLoadingModals')\n        const net = localStorage.getItem('net');\n        const client = getRestClient()\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const address = state.voteWallet.address\n        const addr = new Crypto.Address(address)\n        const params = [\n            new Parameter('', ParameterType.H256, hash),\n            new Parameter('', ParameterType.Array, voters) //TODO format voters to arrays\n        ]\n        let tx = TransactionBuilder.makeWasmVmInvokeTransaction('setVoterForTopic', params, contract, gasPrice, gasLimit, addr)\n        // TODO\n        // eslint-disable-next-line no-undef\n        tx = await handleSignTx(tx, state.voteWallet, password, state.voteWalletType);\n        if (!tx) {\n            return;\n        }\n        // TODO change to websocket\n        const res = await client.sendRawTransaction(tx.serialize(), false);\n        dispatch('hideLoadingModals')\n        return res;\n    },\n\n    // 查询\n    async getVoters({ commit, state }, { hash }) {\n        const net = localStorage.getItem('net');\n        const client = getRestClient()\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const param = new Parameter('', ParameterType.H256, hash)\n        const tx = TransactionBuilder.makeWasmVmInvokeTransaction('getVoters', [param], contract, gasPrice, gasLimit)\n        const res = await client.sendRawTransaction(tx.serialize(), true);\n        if (res.Error === 0) {\n            const voters = res.Result.Result.map(i => {\n                return {\n                    address: new Crypto.Address(i[0]).toBase58(),\n                    weight: parseInt(utils.reverseHex(i[1]), 16)\n                }\n            })\n            console.log(voters)\n            return voters;\n        } else {\n            console.log(res)\n            return []\n        }\n    },\n\n    async isVoter({ commit, dispatch, state }, { hash }) {\n        // const voters = await dispatch('getVoters', {hash})\n        const all_voters = state.all_voters\n        const address = state.voteWallet.address;\n        if (all_voters.find(item => item.address === address)) {\n            return true;\n        } else {\n            return false;\n        }\n    },\n\n    async getVotedInfo({ commit, state }, { hash, address }) {\n        const net = localStorage.getItem('net');\n        const client = getRestClient()\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const params = [\n            new Parameter('', ParameterType.H256, hash),\n            new Parameter('', ParameterType.Address, new Crypto.Address(address))\n        ]\n        const tx = TransactionBuilder.makeWasmVmInvokeTransaction('getVotedInfo', params, contract, gasPrice, gasLimit)\n        const res = await client.sendRawTransaction(tx.serialize(), true);\n        console.log(res)\n        if (res.Error === 0) {\n            // return res.Result.Result // 1 赞成；2反对；其他：未投票\n            const sr = new utils.StringReader(res.Result.Result)\n            const result = sr.readVarUint()\n            if (result == 1) {\n                return MY_VOTED.APPROVED\n            } else if (result == 2) {\n                return MY_VOTED.REJECTED\n            } else {\n                return MY_VOTED.NOT_VOTED\n            }\n        }\n        return;\n    },\n\n    async getVotedRecords({ commit, dispatch, state }, { hash }) {\n        const net = localStorage.getItem('net');\n        const client = getRestClient()\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const params = [\n            new Parameter('', ParameterType.H256, hash)\n        ]\n        const tx = TransactionBuilder.makeWasmVmInvokeTransaction('getVotedAddress', params, contract, gasPrice, gasLimit)\n        const res = await client.sendRawTransaction(tx.serialize(), true);\n        console.log(res)\n        if (res.Error === 0) {\n            const result = res.Result.Result\n            const sr = new utils.StringReader(result)\n            const records_length = sr.readVarUint()\n            const records = []\n            if(records_length > 0) {\n                for(let i = 0; i < records_length; i++) {\n                    const address = new Crypto.Address(sr.read(20)).toBase58()\n                    const weight = sr.readUint64()\n                    const isApproval = sr.readBoolean()\n                    records.push({\n                        address,\n                        weight,\n                        isApproval\n                    })\n                }\n                for (let item of records) {\n                    const voter_with_name = state.all_voters.find(voter => item.address === voter.address)\n                    item.name = voter_with_name ? voter_with_name.name : ''\n                }\n            }\n\n            commit('UPDATE_CURRENT_VOTE_RECORDS', {records})\n        }\n        return;\n    },\n\n    setCurrentVote({ commit }, { vote }) {\n        commit('UPDATE_CURRENT_VOTE', {vote})\n    },\n    async updateCurrentVote({ commit, state }, { hash }) {\n        const net = localStorage.getItem('net');\n        const client = getRestClient()\n        const contract = new Crypto.Address(utils.reverseHex(state.contract_hash))\n        const params = [\n            new Parameter('', ParameterType.H256, hash)\n        ]\n        const tx = TransactionBuilder.makeWasmVmInvokeTransaction('getTopicInfo', params, contract, gasPrice, gasLimit)\n        const res = await client.sendRawTransaction(tx.serialize(), true);\n        console.log(res)\n        if (res.Error === 0) {\n            const votes = formatVoteInfo([res.Result.Result])\n            console.log('updateCurrentVote',JSON.stringify(votes))\n            commit('UPDATE_CURRENT_VOTE', { vote: votes[0]})\n        } else { // 从老的合约查询\n            const contractOld = new Crypto.Address(utils.reverseHex(contract_hash_old[net]))\n            const paramsOld = [\n                new Parameter('', ParameterType.ByteArray, hash)\n            ]\n            const txOld = TransactionBuilder.makeInvokeTransaction('getTopicInfo', paramsOld, contractOld, gasPrice, gasLimit)\n            const resOld = await client.sendRawTransaction(txOld.serialize(), true);\n            if(resOld.Error === 0) {\n                const votesOld = formatOldVoteInfo([resOld])\n                console.log('updateCurrentVote',JSON.stringify(votesOld))\n                commit('UPDATE_CURRENT_VOTE', { vote: votesOld[0]})\n            }\n        }\n    }\n\n}\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/Wallets.js",
    "content": "import dbService, {dbFind} from '../../core/dbService';\n\nconst state = {\n    NormalWallet:[],\n    SharedWallet: [],\n    HardwareWallet: []\n}\n\nconst mutations = {\n    FETCH_WALLETS(state, payload) {\n        state.NormalWallet = payload.NormalWallet;\n        state.SharedWallet = payload.SharedWallet;\n        state.HardwareWallet = payload.HardwareWallet;\n    },\n    DELETE_COMMON_WALLET(state, payload) {\n        const normalWallet = state.NormalWallet.slice();\n        const index = normalWallet.findIndex((w) => w.address === payload.address )\n        normalWallet.splice(index,1)\n        state.NormalWallet = normalWallet;\n    },\n    DELETE_SHARED_WALLET(state, payload) {\n        const normalWallet = state.SharedWallet.slice();\n        const index = normalWallet.findIndex((w) => w.sharedWalletAddress === payload.address)\n        normalWallet.splice(index, 1)\n        state.SharedWallet = normalWallet;\n    },\n    DELETE_HARDWARE_WALLET(state, payload) {\n        const normalWallet = state.HardwareWallet.slice();\n        const index = normalWallet.findIndex((w) => w.address === payload.address)\n        normalWallet.splice(index, 1)\n        state.HardwareWallet = normalWallet;\n    }\n}\n\nconst actions = {\n    async fetchWalletsFromDb({ commit }, pk) {\n        try {\n            const NormalWalletDocs = await dbFind(dbService, {type:'CommonWallet'});\n            const SharedWalletDocs = await dbFind(dbService, {type:'SharedWallet'});\n            const HardwareWalletDocs = await dbFind(dbService, {type:'HardwareWallet'});\n            const NormalWallet = NormalWalletDocs.map(item => item.wallet)\n            const SharedWallet = SharedWalletDocs.map(item => item.wallet)\n            const HardwareWallet = HardwareWalletDocs.map(item => item.wallet)\n            commit('FETCH_WALLETS', { NormalWallet, SharedWallet, HardwareWallet });\n        }catch(err) {\n            alert(err)\n        }\n        return true;\n    }\n}\n\n\nexport default {\n    state,\n    mutations,\n    actions\n}\n"
  },
  {
    "path": "src/store/modules/index.js",
    "content": "/**\n * The file enables `@/store/index.js` to import all vuex modules\n * in a one-shot manner. There should not be any reason to edit this file.\n */\n\nconst files = require.context('.', false, /\\.js$/)\nconst modules = {}\n\nfiles.keys().forEach(key => {\n  if (key === './index.js') return\n  modules[key.replace(/(\\.\\/|\\.js)/g, '')] = files(key).default\n})\n\nexport default modules\n"
  },
  {
    "path": "vue.config.js",
    "content": "module.exports = {\n  pluginOptions: {\n    electronBuilder: {\n      nodeIntegration: true,\n      externals: [\"node-hid\", \"usb\", \"nedb\"],\n      builderOptions: {\n        productName: process.env.VUE_APP_TITLE,\n        appId: \"com.ontio.owallet\",\n        nsis: {\n          oneClick: false,\n          perMachine: true,\n          allowToChangeInstallationDirectory: true,\n        },\n        afterSign: \"build/after-sign.js\",\n        win: {\n          target: [\n            {\n              target: \"nsis\",\n              arch: [\"x64\"],\n            },\n          ],\n          icon: \"src/assets/icons/icon.ico\",\n          artifactName: \"${productName}-${version}-${os}.${ext}\",\n        },\n        linux: {\n          target: [\n            {\n              target: \"deb\",\n              arch: [\"x64\"],\n            },\n            {\n              target: \"AppImage\",\n              arch: [\"x64\"],\n            },\n          ],\n          category: \"Utility\",\n          icon: \"src/assets/icons\",\n          artifactName: \"${productName}-${version}-${os}.${ext}\",\n        },\n        mac: {\n          target: [\n            {\n              target: \"dmg\",\n              arch: [\"x64\", \"arm64\"],\n            },\n          ],\n          forceCodeSigning: false,\n          identity: null,\n          icon: \"src/assets/icons/icon.icns\",\n          artifactName: \"${productName}-${version}-${os}-${arch}.${ext}\",\n        },\n      },\n    },\n  },\n  css: {\n    loaderOptions: {\n      sass: {},\n    },\n  },\n};\n"
  }
]