├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md ├── contributing.md ├── pull_request_template.md └── workflows │ └── node.js.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── inspectionProfiles │ └── Project_Default.xml ├── js-conflux-sdk.iml ├── jsLibraryMappings.xml ├── jsLinters │ └── eslint.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── .prettierrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── README.md ├── SUMMARY.md ├── commitlint.config.js ├── dist ├── anyweb-js-sdk.umd.min.js ├── anyweb-js-sdk.umd.min.js.map ├── package.json └── src │ ├── index.d.ts │ ├── index.js │ ├── interface │ ├── provider.d.ts │ └── provider.js │ ├── provider.d.ts │ ├── provider.js │ └── utils │ ├── address.d.ts │ ├── address.js │ ├── common.d.ts │ ├── common.js │ ├── types.d.ts │ └── types.js ├── example └── basic-dapp │ ├── anyweb-js-sdk.umd.min.js │ ├── anyweb-js-sdk.umd.min.js.map │ ├── index.html │ ├── index.js │ ├── js-conflux-sdk.js │ └── pico.min.css ├── jest.config.js ├── package-lock.json ├── package.json ├── scripts ├── build-frontend.js ├── document.mjs └── jsdoc-to-md.js ├── src ├── index.ts ├── interface │ └── provider.ts ├── provider.ts └── utils │ ├── address.ts │ ├── common.ts │ └── types.ts ├── test └── provider.test.js ├── tsconfig.json └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const ignoreNames = ['Window', '__dirname', '__filename', '[A-Z][a-z]+Actions','cfx_.+'] 2 | const ignoreFilter = { 3 | regex: `^(${ignoreNames.join('|')})$`, 4 | match: false, 5 | } 6 | 7 | module.exports = { 8 | env: { 9 | browser: true, 10 | es2021: true, 11 | }, 12 | root: true, 13 | extends: [ 14 | 'plugin:@typescript-eslint/recommended', 15 | 'plugin:prettier/recommended', 16 | ], 17 | parser: '@typescript-eslint/parser', 18 | parserOptions: { 19 | ecmaFeatures: { 20 | jsx: true, 21 | }, 22 | ecmaVersion: 12, 23 | sourceType: 'module', 24 | }, 25 | plugins: ['@typescript-eslint', 'prettier'], 26 | rules: { 27 | 'import/first': 'off', 28 | 'import/no-commonjs': 'off', 29 | // 通用规范开始 30 | '@typescript-eslint/naming-convention': [ 31 | 'warn', 32 | { 33 | selector: 'default', 34 | format: ['camelCase'], 35 | filter: ignoreFilter, 36 | }, 37 | { 38 | selector: 'variable', 39 | format: ['camelCase', 'UPPER_CASE', 'PascalCase'], 40 | filter: ignoreFilter, 41 | }, 42 | { 43 | selector: 'function', 44 | format: ['camelCase', 'PascalCase'], 45 | filter: ignoreFilter, 46 | }, 47 | { 48 | selector: 'parameter', 49 | format: ['camelCase', 'PascalCase'], 50 | leadingUnderscore: 'allow', 51 | filter: ignoreFilter, 52 | }, 53 | { 54 | selector: 'memberLike', 55 | modifiers: ['private'], 56 | format: ['camelCase'], 57 | leadingUnderscore: 'allow', 58 | filter: ignoreFilter, 59 | }, 60 | { 61 | selector: 'typeLike', 62 | format: ['PascalCase'], 63 | filter: ignoreFilter, 64 | }, 65 | { 66 | selector: 'objectLiteralProperty', 67 | format: ['camelCase', 'UPPER_CASE', 'PascalCase', 'snake_case'], 68 | leadingUnderscore: 'allow', 69 | filter: ignoreFilter, 70 | }, 71 | { 72 | selector: 'typeProperty', 73 | format: ['camelCase', 'UPPER_CASE', 'PascalCase', 'snake_case'], 74 | leadingUnderscore: 'allow', 75 | filter: ignoreFilter, 76 | }, 77 | { 78 | selector: 'enumMember', 79 | format: ['PascalCase', 'camelCase'], 80 | filter: ignoreFilter, 81 | }, 82 | { 83 | selector: 'interface', 84 | format: ['PascalCase'], 85 | filter: { 86 | regex: `^(${ignoreNames.join('|')})$`, 87 | match: false, 88 | }, 89 | custom: { 90 | regex: '^I[A-Z]', 91 | match: true, 92 | }, 93 | }, 94 | ], // 强制各类命名规范 95 | '@typescript-eslint/explicit-module-boundary-types': 'off', 96 | '@typescript-eslint/no-explicit-any': [ 97 | 'warn', 98 | { 99 | fixToUnknown: false, 100 | ignoreRestArgs: true, 101 | }, 102 | ], // 禁止使用除了...args之外的any 并修复为unknown 103 | '@typescript-eslint/semi': ['error', 'never'], 104 | 'spaced-comment': [ 105 | 'error', 106 | 'always', 107 | { 108 | line: { 109 | markers: ['/'], 110 | exceptions: ['-', '+'], 111 | }, 112 | block: { 113 | markers: ['!'], 114 | exceptions: ['*'], 115 | balanced: true, 116 | }, 117 | }, 118 | ], // 强制注释规范 119 | 'no-console': 'off', // 禁止控制台输出 120 | '@typescript-eslint/explicit-member-accessibility': ['off'], // 强制规范类成员访问修饰符 121 | '@typescript-eslint/no-var-requires': 'off', 122 | }, 123 | settings: { 124 | react: { 125 | version: 'detect', 126 | }, 127 | }, 128 | } 129 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the bug 11 | A clear and concise description of what the bug is. 12 | 13 | ### To Reproduce 14 | Steps to reproduce the behavior: 15 | 1. 16 | 17 | ### Log 18 | Error logs. 19 | 20 | ### Screenshots 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | ### Device Info: 24 | - OS: [e.g. iOS 15.0] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | ### Additional context 29 | Add any other context about the problem here. 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: 'custom' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'feature' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the feature 11 | A clear and concise description of what the problem is. 12 | 13 | Ex. I'm always frustrated when [...] 14 | 15 | ### Describe alternatives you've considered 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | ### Additional context 19 | Add any other context or screenshots about the feature request here. 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | # AnyWeb Contributing Guide 2 | 3 | Hi! We're really excited that you are interested in contributing to AnyWeb. Before submitting your contribution, please make sure to take a moment and read through the following guidelines: 4 | 5 | - [Issue Reporting Guidelines](#issue-reporting-guidelines) 6 | - [Pull Request Guidelines](#pull-request-guidelines) 7 | - [Development Setup](#development-setup) 8 | - [Project Structure](#project-structure) 9 | 10 | ## Issue Reporting Guidelines 11 | 12 | - Always follow the issue template to create new issues. 13 | - Here is some [templates](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/issues/new/choose) to report a bug, Please use it when reporting a bug. 14 | 15 | ## Pull Request Guidelines 16 | 17 | - Checkout a topic branch from a base branch, e.g. `main`, and merge back against that branch. 18 | 19 | - Title format: 20 | - feat - new feature 21 | - fix - fix bugs 22 | - docs - documentation only changes 23 | - style - style changes 24 | - test - add tests 25 | - chore - changes that don't affect the meaning of the code 26 | - revert - revert to a commit 27 | - close - close an issue 28 | - release - release 29 | ``` 30 | # Title Example 31 | feat: add new feature 32 | docs: update install info 33 | fix: fix undefined error 34 | close: #1, #3 35 | ``` 36 | 37 | - Make sure tests pass! 38 | 39 | - Commit messages must follow the [Angular commit message convention](https://gist.github.com/brianclements/841ea7bffdb01346392c) so that the changelog can be automatically generated. Commit messages are automatically validated before commit. 40 | 41 | 42 | ## Development Setup 43 | 44 | You will need [Node.js](http://nodejs.org) **version 12+**, and [Yarn](https://classic.yarnpkg.com/en/docs/install). 45 | 46 | After cloning the repo, run: 47 | 48 | ```bash 49 | $ yarn # install the dependencies of the project 50 | ``` 51 | 52 | A high level overview of tools used: 53 | 54 | - [TypeScript](https://www.typescriptlang.org/) as the development language 55 | - [Babel](https://babeljs.io) for bundling 56 | - [Prettier](https://prettier.io/) for code formatting 57 | 58 | ## Scripts 59 | 60 | ### `yarn build` 61 | 62 | The `build` script builds AnyWeb. 63 | 64 | ```bash 65 | # build the AnyWeb. 66 | yarn build 67 | ``` 68 | 69 | ### `yarn test` 70 | 71 | The `yarn test` script runs all checks: 72 | 73 | ```bash 74 | # run all tests. 75 | $ yarn test 76 | ``` 77 | 78 | ## Project Structure 79 | 80 | Vue Router source code can be found in the `src` directory: 81 | 82 | - `src/utils`: contains small utility functions. 83 | - `src/errors`: different internal and external errors 84 | - `src/interface`: contains all interface 85 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Why: 10 | 11 | Closes [issue link] 12 | 13 | 16 | 17 | ### What's being changed: 18 | 19 | 20 | ### Check off the following: 21 | 22 | - [ ] I have read the [CONTRIBUTING.md](./contributing.md). 23 | - [ ] I have pass the `yarn lint`. 24 | 25 | 26 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [14.x, 16.x] # 14.x, 16.x 20 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v2 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | cache: 'yarn' 29 | - run: yarn 30 | - run: npm run lint 31 | - run: npm run test 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /coverage/ 3 | /esm/ 4 | /lib/ 5 | /docs/tmp.md 6 | /.idea 7 | /.vscode 8 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit "$1" 5 | #commitlint -E HUSKY_GIT_PARAMS 6 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | npm run lint:fix 4 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 基于编辑器的 HTTP 客户端请求 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 14 | 15 | 23 | 24 | 33 | 34 | 37 | 38 | 39 | 43 | 44 | 45 | 52 | 53 | 79 | 80 | 81 | 84 | 85 | 86 | 89 | 90 | 91 | 94 | 95 | 96 | 97 | 100 | 101 | 102 | 103 | 106 | 107 | 108 | 131 | 132 | 137 | 138 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | -------------------------------------------------------------------------------- /.idea/js-conflux-sdk.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/jsLinters/eslint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "eslintIntegration": true, 3 | "stylelintIntegration": true, 4 | "singleQuote": true, 5 | "semi": false 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [1.3.6](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.3.4...v1.3.6) (2023-01-07) 6 | 7 | 8 | ### Features 9 | 10 | * **add cfx_personalSign:** add cfx_personalSign ([f2e9bdf](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/f2e9bdf37a8b739665562090e21fed8c086d142b)) 11 | * **add global:** add personal sign ([f18d393](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/f18d3938d2f533d4e775e4ccd7d4f431b7c9f633)) 12 | 13 | 14 | ### Bug Fixes 15 | 16 | * **Fix bug:** fix personal_sign demo ([21e950a](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/21e950a5c9bf23852235309df5108678301d966a)) 17 | 18 | ### [1.3.5](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.3.4...v1.3.5) (2022-12-27) 19 | 20 | ### [1.3.4](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.3.1...v1.3.4) (2022-10-26) 21 | 22 | 23 | ### Features 24 | 25 | * **add global:** add global ([1223fa0](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/1223fa08d95977805775b3c7ee7e1630f50c1b1e)) 26 | 27 | 28 | ### Bug Fixes 29 | 30 | * **Fix bug:** fix bug that iframe cannot be closed ([adbd9c1](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/adbd9c1fcf47266f4798be646f4450d479561a5a)) 31 | * **logger:** support set logger to null ([9458f2c](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/9458f2ca57e5c2482b6bc23fe8a54421f88f4980)) 32 | 33 | ### [1.3.3](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.3.2...v1.3.3) (2022-09-12) 34 | 35 | 36 | ### Bug Fixes 37 | 38 | * **Fix bug:** fix bug that iframe cannot be closed ([adbd9c1](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/adbd9c1fcf47266f4798be646f4450d479561a5a)) 39 | 40 | ### [1.3.2](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.3.1...v1.3.2) (2022-08-08) 41 | 42 | ### [1.3.1](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.3.0...v1.3.1) (2022-08-02) 43 | 44 | 45 | ### Bug Fixes 46 | 47 | * **close button error:** fix the error of close button ([e5a6484](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/e5a6484b6a224e07cb84e0d5dfe4ea4b134862f0)) 48 | 49 | ## [1.3.0](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.2.4...v1.3.0) (2022-07-24) 50 | 51 | 52 | ### Bug Fixes 53 | 54 | * **iframe size:** fix iframe size error ([eb8f418](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/eb8f4185e41d3113279f2684f0b8f0a2f0912cf5)) 55 | 56 | ### [1.2.4](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.2.3...v1.2.4) (2022-07-24) 57 | 58 | 59 | ### Features 60 | 61 | * **add sign function:** add sign function ([f11f05d](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/f11f05dc2ea4479121f0ff83acdf2c708ef83c10)) 62 | * **add some feat:** improve SDK ([41f2fd5](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/41f2fd51391d2269dff6fec46182319e246d6fe6)) 63 | * **app url:** support set app url ([74a42b8](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/74a42b878cca5079e477cffa5b92974790fad37f)) 64 | 65 | 66 | ### Bug Fixes 67 | 68 | * **fix iframe size:** fix iframe size ([47c76a5](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/47c76a5be6bfd54620676d5088c2eb21b122c470)) 69 | * **hide scrollbar:** hide scrollbar in Safari ([17f0b98](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/17f0b98712589fe8a2d449ee44328b8b603ced40)) 70 | 71 | ### [1.2.3](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.2.2...v1.2.3) (2022-06-13) 72 | 73 | ### [1.2.2](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.2.1...v1.2.2) (2022-06-03) 74 | 75 | 76 | ### Features 77 | 78 | * **support error message and data:** support get error message and data from the SDK ([5974d18](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/5974d188b722613c12237d8d9d77498cb5cd243d)) 79 | 80 | 81 | ### Bug Fixes 82 | 83 | * **conflux sdk:** download the conflux js sdk to local ([976758a](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/976758a4630d47cacc64875ca1ba5f30f0071dbf)) 84 | 85 | ### [1.2.1](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.2.0...v1.2.1) (2022-05-25) 86 | 87 | 88 | ### Features 89 | 90 | * **support error from app:** support throw the error message form the app ([78be87d](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/78be87d800c16b248a12cd7b0e2b995465785d87)) 91 | 92 | 93 | ### Bug Fixes 94 | 95 | * **error standard:** throw error standard ([11760fb](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/11760fbc9d194f84d8f1669376503641f509f3b8)) 96 | 97 | ## [1.2.0](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.1.11...v1.2.0) (2022-05-18) 98 | 99 | 100 | ### Features 101 | 102 | * **single mode and support ready event:** single mode and support ready event ([44f5636](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/44f5636089453942dc2ac54fc93b0a32bd3a9955)) 103 | 104 | 105 | ### Bug Fixes 106 | 107 | * **support uniapp:** fix provider with uniapp ([420d8d9](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/420d8d9a4a2c116da3f3597c4ff8a77de17c8b0b)) 108 | 109 | ### [1.1.11](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.1.10...v1.1.11) (2022-05-16) 110 | 111 | 112 | ### Features 113 | 114 | * **support check login state:** support check login state and add silent mode of identify ([a391500](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/a391500b2704a7c565d289e897a73bbb9f6b49b3)) 115 | 116 | ### [1.1.10](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.1.9...v1.1.10) (2022-05-09) 117 | 118 | 119 | ### Features 120 | 121 | * **silent auth:** support auth account with silent mode ([43352e3](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/43352e3051eabc7b78bff2099a6f93c12f751f83)) 122 | 123 | 124 | ### Bug Fixes 125 | 126 | * **example DApp:** fix the problem of example DApp ([4f9d3c3](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/4f9d3c36e96ec7ec192afd78e393b50c5501724f)) 127 | 128 | ### [1.1.9](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.1.7...v1.1.9) (2022-05-09) 129 | 130 | 131 | ### Features 132 | 133 | * **silent mode:** support silent mode ([9eebebf](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/9eebebffca4185ae2bdafd6193c10b95db9d5419)) 134 | 135 | ### [1.1.7](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.1.2...v1.1.7) (2022-05-06) 136 | 137 | 138 | ### Features 139 | 140 | * **add identify function:** add the function of jumping to verify the identity page ([c601365](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/c601365e486cfaef9767dca0b92dcda3b5103842)) 141 | * **insensitive loading iframe:** now we can load the iframe without waiting ([cd6b363](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/cd6b36387c8f121c30b94447f8b78d61961d573f)) 142 | * **support logout:** support logout ([ce8fa87](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/ce8fa87a0d865b72ee5f8e6ea71d701110a438bc)) 143 | 144 | 145 | ### Bug Fixes 146 | 147 | * **eslint:** fix the eslint problem ([cb3b994](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/cb3b99471793bb13214c4b483f5f89f21edcfbf5)) 148 | * **params as any:** params as any ([8d1886c](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/8d1886ce6cbdef6c557eb5963e1cf7660ab1b77d)) 149 | 150 | ### [1.1.6](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.1.4...v1.1.6) (2022-04-26) 151 | 152 | ### [1.1.4](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.1.3...v1.1.4) (2022-04-25) 153 | 154 | 155 | ### Features 156 | 157 | * **add identify function:** add the function of jumping to verify the identity page ([c601365](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/c601365e486cfaef9767dca0b92dcda3b5103842)) 158 | 159 | ### [1.1.3](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.1.2...v1.1.3) (2022-04-19) 160 | 161 | 162 | ### Bug Fixes 163 | 164 | * **eslint:** fix the eslint problem ([cb3b994](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/cb3b99471793bb13214c4b483f5f89f21edcfbf5)) 165 | 166 | ### [1.1.2](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.13...v1.1.2) (2022-04-19) 167 | 168 | 169 | ### Bug Fixes 170 | 171 | * **Usage Modification:** modification of usage ([ae9a1f8](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/ae9a1f8ee8c826bc274b5910048cd5a2c9eea00a)) 172 | 173 | ### [1.1.1](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.13...v1.1.1) (2022-04-18) 174 | 175 | 176 | ### Bug Fixes 177 | 178 | * **Usage Modification:** modification of usage ([ae9a1f8](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/ae9a1f8ee8c826bc274b5910048cd5a2c9eea00a)) 179 | 180 | ## [1.1.0](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.13...v1.1.0) (2022-04-18) 181 | 182 | ### [1.0.13](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.12...v1.0.13) (2022-04-02) 183 | 184 | 185 | ### Bug Fixes 186 | 187 | * **chrome window problem:** fix the chrome window problem ([67d82f6](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/67d82f66371615b9a185ec02eb95200eb433c0a9)) 188 | 189 | ### [1.0.12](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.11...v1.0.12) (2022-04-02) 190 | 191 | 192 | ### Bug Fixes 193 | 194 | * **logout problem:** fix the logout fail problem and remove the cache of SDK ([a662f07](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/a662f0735ac45331c7da0151bbf4537fe2921145)) 195 | * **scope name:** fix the error scope name ([633f860](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/633f86043b7c4c843c26af252f5939367fd4642b)) 196 | 197 | ### [1.0.11](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.10...v1.0.11) (2022-03-22) 198 | 199 | 200 | ### Features 201 | 202 | * **support logout and change OAuth API:** add logout API and change the way of getting OAuth Code ([38831b4](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/38831b4dbed1196297589a9adeb9271ef610bf80)) 203 | * **support more scopes:** support more scopes ([6a020f3](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/6a020f31f9bb95bf57a918bc857be786b4d1bc38)) 204 | 205 | ### [1.0.10](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.9...v1.0.10) (2022-03-22) 206 | 207 | 208 | ### Bug Fixes 209 | 210 | * **package src file path:** fix the error of the path ([7f0c0d5](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/7f0c0d5c46f839227a2db5b76b138fe12bab2dc2)) 211 | 212 | ### [1.0.9](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.8...v1.0.9) (2022-03-19) 213 | 214 | 215 | ### Features 216 | 217 | * **example support OAuth:** example add method about OAuth ([6c1ba0f](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/6c1ba0f09abff76ad94e9b13726ff117adc52a82)) 218 | * **support network change:** support network change in SDK ([3fbe249](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/3fbe249829abc3673f258a4978db5878ece6d35c)) 219 | * **support OAuth:** add new API for OAuth ([bcdd0a9](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/bcdd0a9add7d87f98d8bb5f764be08234ad3a29a)) 220 | * **support set available network list:** support set available network list to limit network ([6e2ea6e](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/6e2ea6e84527b7c5414e3c29dec641ee2cff274e)) 221 | 222 | ## [1.0.8](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.7...v1.0.8) (2022-03-14) 223 | 224 | ## [1.0.7](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.6...v1.0.7) (2022-03-07) 225 | 226 | 227 | ### Features 228 | 229 | * **support import privateKey:** support import account from DApp by SDK with privateKey ([6f85079](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/6f85079a1597d669d2cecc89889be5f69e4e7d1c)) 230 | 231 | 232 | ### Bug Fixes 233 | 234 | * **height overrun:** fixed height overrun and error import problems ([4aacc8e](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/4aacc8ee7be7f02d29345ee7a97ac48ff83dbdd8)) 235 | 236 | ## [1.0.6](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.5...v1.0.6) (2022-03-02) 237 | 238 | 239 | ### Features 240 | 241 | * **support import read-only account:** support import account from DApp by SDK without key ([7562c1f](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/7562c1f03a7494022acc419389713de0ae93a710)) 242 | 243 | 244 | ### Bug Fixes 245 | 246 | * **rolling penetration:** fixed rolling penetration when open the iframe second time ([2f91490](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/2f91490306420238ae006d7f1393b850f06ccc8a)) 247 | 248 | ## [1.0.5](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.4...v1.0.5) (2022-02-23) 249 | 250 | 251 | ### Bug Fixes 252 | 253 | * **iOS scroll penetration:** fix the iOS scroll penetration and remove the release.yml ([eb4d4ce](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/eb4d4ce538543df97fd8064b1b2043688091ffb9)) 254 | * **safari page auto reload:** fixed Safari auto refresh and other issues ([b83ca43](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/b83ca4351684edaac8d13ca79afab6455b4a1ca5)) 255 | * **user cancel error:** fix the error of cancel auth, and optimize DApp interactive experience ([fafbd47](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/fafbd47e8c8ea8e4463f7149abfe627fb8127c21)) 256 | 257 | ## [1.0.4](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.3...v1.0.4) (2022-02-22) 258 | 259 | 260 | ### Bug Fixes 261 | 262 | * **optimize iframe and example DApp:** optimize the iframe experience and fix some bug in example ([d83bccc](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/d83bcccdf556f492ee397a6eb7fa2c1d1c0c5b57)) 263 | 264 | ## [1.0.3](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.2...v1.0.3) (2022-02-21) 265 | 266 | ### Features 267 | 268 | * **call contract example:** add new example of CFX Faucet ([1975b26](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/1975b26ed9841e6f55a9946d038c35bac7c0fa3d)) 269 | * **closable iframe:** iframe closeable ([28c0a66](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/28c0a6696a7e056e6b6e15a9e69fb413bf62c69e)) 270 | 271 | 272 | ### Bug Fixes 273 | 274 | * **iframe:** fix the iframe too height ([5b88f26](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/5b88f26b228c5d6f9d87f8a8847ca74481e3afd4)) 275 | 276 | ## [1.0.1](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/compare/v1.0.0...v1.0.1) (2022-02-18) 277 | 278 | 279 | ### Bug Fixes 280 | 281 | * **Fix test error:** fix the test error and fix some problem of document ([b4ef24d](https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/commit/b4ef24dcb052c719692ca0578cd136a350621060)) 282 | 283 | ## 1.0.0 (2022-02-18) 284 | 285 | 286 | ### Features 287 | 288 | * **add on event:** add on event ([48787a9](https://github.com/AnyWeb/anyweb-js-sdk/commit/48787a956559bb430f07c5330400464649b17205)) 289 | * **Available Cache:** add New Cache and NetworkId / ChainId ([608b5de](https://github.com/AnyWeb/anyweb-js-sdk/commit/608b5deff642b7f9c0f57ab147cf71fd02508e69)) 290 | * **support iframe:** Now support H5 to call the iframe, auto set the window.conflux, and some new function ([c2eea34](https://github.com/AnyWeb/anyweb-js-sdk/commit/c2eea346bdea9d7f189478eb00cdc7f58ce03319)) 291 | * **support more api and demo page:** add AnyWeb some API,dapp demo page and new Document. ([f4eb613](https://github.com/AnyWeb/anyweb-js-sdk/commit/f4eb61319aa0e3280c9aaedd9e14068a5dd80700)) 292 | 293 | 294 | ### Bug Fixes 295 | 296 | * **test:** test bug in node ([9de2ea2](https://github.com/AnyWeb/anyweb-js-sdk/commit/9de2ea283946a4edb48f874c9c91531f8a97e7c6)) 297 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AnyWeb JS SDK 2 | 3 | AnyWeb JS SDK 是为 [Anyweb](https://anyweb.cc) 开发的SDK,提供了一套简单的API,方便开发者快速将 Dapp 接入到 AnyWeb 中实现便捷的钱包服务。 4 | 5 | Features: 6 | 7 | * 支持在移动端和PC端调用钱包服务 8 | * 支持网页内和跳转App调用钱包服务 9 | * 支持多链钱包服务 10 | * 支持 ` 热钱包 ` 和 ` 冷钱包 ` 11 | * 简单易用快速上手 12 | 13 | ## 支持性 14 | 15 | ### 已支持 16 | 17 | * Conflux 18 | 19 | ### 待支持 20 | 21 | * Conflux EVM Space 22 | 23 | ## Docs 24 | 25 | * [AnyWeb 介绍](https://wiki.anyweb.cc/docs/AnyWeb/intro) 26 | * [SDK 介绍](https://wiki.anyweb.cc/docs/SDK/intro) 27 | * [快速开始](https://wiki.anyweb.cc/docs/SDK/quick_start) 28 | * [API](https://wiki.anyweb.cc/docs/SDK/usage) 29 | * [Release notes](https://wiki.anyweb.cc/docs/SDK/CHANGELOG) 30 | 31 | 前往[ 官网文档 ](https://wiki.anyweb.cc)了解更多 32 | 33 | ## 开始之前 34 | 35 | 请先在[ AnyWeb开放平台 ](https://open.anyweb.cc)注册账号获取到AppId等相关信息。 36 | 37 | ## 安装 38 | 39 | ` npm ` 安装 40 | 41 | ```sh 42 | $ npm install --save @idealight-labs/anyweb-js-sdk 43 | ``` 44 | 45 | ## 引用方法 46 | 47 | ### ESM 48 | 49 | ```javascript 50 | import { Provider } from '@idealight-labs/anyweb-js-sdk'; 51 | 52 | const provider = new Provider({ 53 | logger: console, 54 | appId: '从open.anyweb.cc拿到的AppId', 55 | }); 56 | ``` 57 | 58 | > logger可以传入null来禁用日志打印,或传入自定义的日志工具,默认为`window.console` 59 | 60 | ### UMD 61 | 62 | 从 `anyweb-js-sdk` 的 `dist` 目录中进行引用 `umd` 版本. 63 | 64 | ```html 65 | 66 | 68 | 69 | 75 | ``` 76 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [Home](README.md) 4 | * [Quick Start](docs/quick_start.md) 5 | * [API](docs/api/modules.md) 6 | * [Provider](docs/api/classes/default.md) 7 | * [Release notes](CHANGELOG.md) 8 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] } 2 | -------------------------------------------------------------------------------- /dist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@idealight-labs/anyweb-js-sdk", 3 | "description": "AnyWeb JavaScript Software Development Kit", 4 | "version": "1.3.6", 5 | "license": "LGPL-3.0", 6 | "author": "common@idealight.ltd", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/IdeaLightLabs/AnyWeb-JS-SDK.git" 10 | }, 11 | "keywords": [ 12 | "anyweb", 13 | "sdk" 14 | ], 15 | "main": "dist/src/index.js", 16 | "types": "dist/src/index.d.ts", 17 | "browser": "dist/src/index.js", 18 | "browserify-browser": { 19 | "secp256k1": "secp256k1/elliptic" 20 | }, 21 | "files": [ 22 | "dist", 23 | "src", 24 | "lib", 25 | "types", 26 | "anyweb-js-sdk.umd.min.js" 27 | ], 28 | "browserslit": "cover 99.5%", 29 | "dependencies": { 30 | "@commitlint/config-conventional": "^16.0.0", 31 | "@conflux-dev/conflux-address-js": "^1.3.12", 32 | "abi-util-lite": "^0.1.0", 33 | "big.js": "^5.2.2", 34 | "commander": "^8.0.0", 35 | "conventional-changelog-cli": "^2.2.2", 36 | "js-conflux-sdk": "^2.0.0", 37 | "keccak": "^2.0.0", 38 | "node-forge": "^1.2.1", 39 | "rlp": "^2.2.7", 40 | "scrypt-js": "^3.0.1", 41 | "secp256k1": "^3.7.1", 42 | "superagent": "^6.1.0", 43 | "typescript": "^4.5.5", 44 | "websocket": "^1.0.31" 45 | }, 46 | "devDependencies": { 47 | "@babel/core": "^7.8.4", 48 | "@babel/plugin-transform-runtime": "^7.8.3", 49 | "@babel/preset-env": "^7.8.4", 50 | "@babel/preset-typescript": "^7.16.7", 51 | "@babel/runtime": "^7.8.4", 52 | "@commitlint/cli": "^16.1.0", 53 | "@commitlint/config-angular": "^16.0.0", 54 | "@types/jest": "^27.4.0", 55 | "@types/node": "^14.0.23", 56 | "@types/node-forge": "^1.0.0", 57 | "@typescript-eslint/eslint-plugin": "^5.10.2", 58 | "@typescript-eslint/parser": "^5.10.2", 59 | "babel-plugin-lodash": "^3.3.4", 60 | "babelify": "^10.0.0", 61 | "browserify": "^16.5.1", 62 | "commitizen": "^4.2.4", 63 | "concurrently": "^5.1.0", 64 | "cz-conventional-changelog": "^3.3.0", 65 | "eslint": "^7.12.0", 66 | "eslint-config-airbnb-base": "^14.0.0", 67 | "eslint-config-prettier": "^8.3.0", 68 | "eslint-plugin-import": "^2.18.2", 69 | "eslint-plugin-prettier": "^4.0.0", 70 | "exorcist": "^1.0.1", 71 | "fs-extra": "^8.1.0", 72 | "husky": "^7.0.0", 73 | "jest": "^27.4.7", 74 | "jsbi": "^3.1.4", 75 | "jsdoc-to-markdown": "^7.1.0", 76 | "minify-stream": "^2.0.1", 77 | "mold-source-map": "^0.4.0", 78 | "prettier": "^2.5.1", 79 | "solc": "^0.6.10", 80 | "standard-version": "^9.3.2", 81 | "ts-jest": "^27.1.3", 82 | "tsify": "^5.0.4", 83 | "typedoc": "^0.22.11", 84 | "typedoc-plugin-markdown": "^3.11.12" 85 | }, 86 | "resolutions": { 87 | "tinyify/acorn-node/acorn": "7.1.1", 88 | "eslint/espree/acorn": "7.1.1", 89 | "tinyify/unassertify/unassert/acorn": "7.1.1", 90 | "**/minimist": "^1.2.3", 91 | "**/kind-of": "^6.0.3", 92 | "**/elliptic": "^6.5.3", 93 | "**/lodash": "^4.17.20", 94 | "**/babel-jest": "^26.6.0", 95 | "jest/jest-cli/jest-config/jest-environment-jsdom/jsdom/acorn-globals/acorn": "6.4.1" 96 | }, 97 | "scripts": { 98 | "lint": "eslint ./src ./test", 99 | "lint:fix": "eslint ./src ./test --fix", 100 | "build": "node scripts/build-frontend.js", 101 | "document": "typedoc --plugin typedoc-plugin-markdown --out docs/api/ src/index.ts", 102 | "prepublishOnly": "npm run build:lib && npm run build", 103 | "test": "jest --coverage", 104 | "build:lib": "tsc", 105 | "dev": "tsc --watch", 106 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1", 107 | "commit": "git cz", 108 | "release": "standard-version --release-as", 109 | "prepare": "husky install" 110 | }, 111 | "config": { 112 | "commitizen": { 113 | "path": "./node_modules/cz-conventional-changelog" 114 | } 115 | }, 116 | "bugs": { 117 | "url": "https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/issues" 118 | }, 119 | "homepage": "https://github.com/IdeaLightLabs/AnyWeb-JS-SDK#readme", 120 | "directories": { 121 | "example": "example", 122 | "lib": "lib", 123 | "test": "test" 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /dist/src/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from './provider'; 2 | export { Provider }; 3 | -------------------------------------------------------------------------------- /dist/src/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.Provider = void 0; 4 | const provider_1 = require("./provider"); 5 | Object.defineProperty(exports, "Provider", { enumerable: true, get: function () { return provider_1.Provider; } }); 6 | module.exports = { 7 | Provider: provider_1.Provider, 8 | }; 9 | -------------------------------------------------------------------------------- /dist/src/interface/provider.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Littleor 3 | * @since 2022/2/4 4 | */ 5 | import { ConsoleLike } from '../utils/types'; 6 | /** 7 | * Request Args 8 | */ 9 | export interface IRequestArguments { 10 | readonly method: string; 11 | readonly params?: unknown[]; 12 | readonly chainId?: number; 13 | } 14 | export interface IBaseProviderOptions { 15 | logger?: ConsoleLike | null; 16 | appId: string; 17 | global?: boolean; 18 | } 19 | /** 20 | * Base Provider 21 | */ 22 | export interface IProvider { 23 | /** 24 | * Request 25 | * @param args {IRequestArguments} Request Arguments: {method, params} 26 | * @returns {Promise} 27 | */ 28 | request(args: IRequestArguments): Promise; 29 | /** 30 | * monitor information 31 | * @param type {string} monitor type 32 | * @param listener {Function} callback 33 | */ 34 | on(type: string, listener: (...args: any[]) => void): void; 35 | } 36 | /** 37 | * @author Littleor 38 | * @since 2022/2/18 39 | */ 40 | export interface IAuthResult { 41 | chainId: number; 42 | networkId: number; 43 | address: string[]; 44 | url: string; 45 | code: string; 46 | scopes: string[]; 47 | } 48 | export interface IProviderRpcError extends Error { 49 | message: string; 50 | code: number; 51 | data?: unknown; 52 | } 53 | export interface IProviderConnectInfo { 54 | readonly chainId: string; 55 | } 56 | export interface IProviderMessage { 57 | readonly type: string; 58 | readonly data: unknown; 59 | } 60 | export declare type IMethodType = 'account' | 'createContract' | 'callContract' | 'createTransaction' | 'importAccount' | 'exitAccounts' | 'signTypedData' | 'logout' | 'checkAuth' | 'checkLogin' | 'home' | 'unknownType' | 'identify' | 'checkIdentify' | 'personalSign'; 61 | export interface IIframeOptions { 62 | appId: string; 63 | params: string; 64 | chainId: number; 65 | scopes?: string[]; 66 | waitResult?: boolean; 67 | silence?: boolean; 68 | } 69 | export interface IIframeData { 70 | type: 'event' | 'callback' | 'router' | 'default'; 71 | data: unknown; 72 | success?: boolean; 73 | message?: string; 74 | code: number; 75 | } 76 | export interface IIframeEventData { 77 | type: 'changeNetwork' | 'changeChain'; 78 | data: unknown; 79 | } 80 | export declare type IRequestParams = IRequestParamsAccounts | { 81 | payload: IPayload; 82 | gatewayPayload?: IGatewayPayload; 83 | } | IPayload; 84 | export interface IRequestParamsAccounts { 85 | scopes: string[]; 86 | [key: string]: unknown; 87 | } 88 | export interface IPayload { 89 | to: string; 90 | [key: string]: unknown; 91 | } 92 | export interface IGatewayPayload { 93 | [key: string]: unknown; 94 | } 95 | -------------------------------------------------------------------------------- /dist/src/interface/provider.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /dist/src/provider.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Littleor 3 | * @since 2022/2/2 4 | */ 5 | import { IBaseProviderOptions, IProvider, IProviderConnectInfo, IProviderMessage, IProviderRpcError, IRequestArguments } from './interface/provider'; 6 | import { ConsoleLike } from './utils/types'; 7 | /** 8 | * AnyWeb Provider 9 | * @class Provider 10 | * @author Littleor 11 | * @since 2020/2/2 12 | * @example 13 | * const provider = new Provider() 14 | */ 15 | export declare class Provider implements IProvider { 16 | logger: ConsoleLike | null; 17 | readonly appId: string; 18 | private chainId; 19 | private static instance; 20 | static ready: boolean; 21 | appUrl: string | undefined; 22 | events: { 23 | onConnect?: (connectInfo: IProviderConnectInfo) => void; 24 | onDisconnect?: (error: IProviderRpcError) => void; 25 | onChainChanged?: (chainId: string) => void; 26 | onAccountsChanged?: (accounts: string[]) => void; 27 | onMessage?: (message: IProviderMessage) => void; 28 | onNetworkChanged?: (networkId: string) => void; 29 | onReady?: () => void; 30 | }; 31 | constructor({ logger, appId, global }: IBaseProviderOptions, appUrl?: string); 32 | static getInstance(params?: IBaseProviderOptions): Provider; 33 | /** 34 | * Deprecated: use `request` instead 35 | * @param arg 36 | */ 37 | send(...arg: any[]): Promise; 38 | /** 39 | * Deprecated: use `request` instead 40 | * @param arg 41 | */ 42 | call(...arg: any[]): Promise; 43 | /** 44 | * Submits an RPC request 45 | * @param args {IRequestArguments} Request Arguments: {method, params} 46 | * @returns {Promise} 47 | * @example 48 | * const result = await provider.request({ method: 'cfx_sendTransaction', params}) 49 | */ 50 | request(args: IRequestArguments): Promise; 51 | /** 52 | * Deprecated: use `request` instead 53 | */ 54 | enable(): Promise; 55 | /** 56 | * Submits an RPC request 57 | * @param method 58 | * @param params 59 | * @protected 60 | */ 61 | protected rawRequest(method: string, params?: any[]): Promise; 62 | /** 63 | * Monitor information 64 | * @param type {string} Type of information 65 | * @param listener {Function} Event listener 66 | * @example 67 | * provider.on('connected', listener) 68 | */ 69 | on(type: string, listener: (...args: any[]) => void): void; 70 | } 71 | -------------------------------------------------------------------------------- /dist/src/provider.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * @author Littleor 4 | * @since 2022/2/2 5 | */ 6 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 7 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 8 | return new (P || (P = Promise))(function (resolve, reject) { 9 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 10 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 11 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 12 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 13 | }); 14 | }; 15 | var __importDefault = (this && this.__importDefault) || function (mod) { 16 | return (mod && mod.__esModule) ? mod : { "default": mod }; 17 | }; 18 | Object.defineProperty(exports, "__esModule", { value: true }); 19 | exports.Provider = void 0; 20 | const common_1 = require("./utils/common"); 21 | const package_json_1 = __importDefault(require("../package.json")); 22 | const address_1 = require("./utils/address"); 23 | /** 24 | * AnyWeb Provider 25 | * @class Provider 26 | * @author Littleor 27 | * @since 2020/2/2 28 | * @example 29 | * const provider = new Provider() 30 | */ 31 | class Provider { 32 | constructor({ logger = console, appId, global = false }, appUrl = 'https://app.anyweb.cc/#/') { 33 | this.logger = console; 34 | this.chainId = 1; 35 | this.events = {}; 36 | if (global) { 37 | appUrl = 'https://global.app.anyweb.cc/#/'; 38 | } 39 | if (Provider.instance) { 40 | return Provider.instance; 41 | } 42 | Provider.instance = this; 43 | this.logger = logger; 44 | this.appId = appId; 45 | this.appUrl = appUrl; 46 | // bind functions (to prevent consumers from making unbound calls) 47 | this.request = this.request.bind(this); 48 | this.call = this.call.bind(this); 49 | this.send = this.call.bind(this); 50 | this.enable = this.enable.bind(this); 51 | if (typeof window !== 'undefined') { 52 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 53 | // @ts-ignore 54 | window.anyweb = this; 55 | } 56 | const messageHandler = (event) => { 57 | var _a; 58 | if (event.data && 59 | (0, common_1.isObject)(event.data) && 60 | 'type' in event.data && 61 | event.data.type === 'anyweb') { 62 | const IframeData = event.data.data; 63 | if (IframeData.type == 'event' && 64 | IframeData.data == 'ready' && 65 | IframeData.success) { 66 | (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug('[AnyWeb] SDK初始化完成'); 67 | Provider.ready = true; 68 | this.events.onReady && this.events.onReady(); 69 | window.removeEventListener('message', messageHandler); 70 | } 71 | } 72 | }; 73 | window.addEventListener('message', messageHandler); 74 | (0, common_1.createIframe)('pages/index/home', this.appUrl, this.logger) 75 | .then() 76 | .catch((e) => { var _a; return (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error('[AnyWeb] createIframe error', e); }); 77 | } 78 | static getInstance(params) { 79 | if (!Provider.instance) { 80 | if (params) { 81 | Provider.instance = new Provider(params); 82 | } 83 | else { 84 | throw new common_1.ProviderRpcError(common_1.ProviderErrorCode.SDKNotReady, 'Provider is not initialized'); 85 | } 86 | } 87 | return Provider.instance; 88 | } 89 | /** 90 | * Deprecated: use `request` instead 91 | * @param arg 92 | */ 93 | send(...arg) { 94 | var _a; 95 | return __awaiter(this, void 0, void 0, function* () { 96 | (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info('[AnyWeb] `send` is deprecated, use `request` instead'); 97 | if (arg.length > 1) { 98 | return yield this.request({ method: arg[0], params: arg[1] }); 99 | } 100 | throw new common_1.ProviderRpcError(common_1.ProviderErrorCode.ParamsError, 'Invalid arguments'); 101 | }); 102 | } 103 | /** 104 | * Deprecated: use `request` instead 105 | * @param arg 106 | */ 107 | call(...arg) { 108 | var _a; 109 | return __awaiter(this, void 0, void 0, function* () { 110 | (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info('[AnyWeb] `call` is deprecated, use `request` instead', arg); 111 | if (arg.length > 1) { 112 | return yield this.request({ method: arg[0], params: arg[1] }); 113 | } 114 | else { 115 | return this.enable(); 116 | } 117 | }); 118 | } 119 | /** 120 | * Submits an RPC request 121 | * @param args {IRequestArguments} Request Arguments: {method, params} 122 | * @returns {Promise} 123 | * @example 124 | * const result = await provider.request({ method: 'cfx_sendTransaction', params}) 125 | */ 126 | request(args) { 127 | var _a, _b; 128 | return __awaiter(this, void 0, void 0, function* () { 129 | if (!args || typeof args !== 'object' || Array.isArray(args)) { 130 | throw new common_1.ProviderRpcError(common_1.ProviderErrorCode.ParamsError, 'Invalid request arguments'); 131 | } 132 | const { method, params } = args; 133 | if (!method || method.trim().length === 0) { 134 | throw new common_1.ProviderRpcError(common_1.ProviderErrorCode.ParamsError, 'Invalid request arguments: Method is required'); 135 | } 136 | (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`[AnyWeb] request ${method} with`, params); 137 | const result = yield this.rawRequest(method, params); 138 | (_b = this.logger) === null || _b === void 0 ? void 0 : _b.debug(`[AnyWeb] request(${method}):`, result); 139 | return result; 140 | }); 141 | } 142 | /** 143 | * Deprecated: use `request` instead 144 | */ 145 | enable() { 146 | return __awaiter(this, void 0, void 0, function* () { 147 | return yield this.request({ 148 | method: 'cfx_requestAccounts', 149 | }); 150 | }); 151 | } 152 | /** 153 | * Submits an RPC request 154 | * @param method 155 | * @param params 156 | * @protected 157 | */ 158 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 159 | rawRequest(method, params = []) { 160 | var _a, _b, _c, _d, _e, _f, _g; 161 | return __awaiter(this, void 0, void 0, function* () { 162 | if (!Provider.ready) { 163 | throw new common_1.ProviderRpcError(common_1.ProviderErrorCode.SDKNotReady, "Provider is not ready, please use on('ready', callback) to listen to ready event"); 164 | } 165 | try { 166 | switch (method) { 167 | case 'cfx_requestAccounts': 168 | return this.rawRequest('cfx_accounts'); 169 | case 'cfx_accounts': 170 | (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug('[AnyWeb]', { params }); 171 | const scopes = params[0].scopes; 172 | let result; 173 | try { 174 | result = (yield (0, common_1.callIframe)('checkAuth', { 175 | appId: this.appId, 176 | params: params ? params[0] : {}, 177 | chainId: this.chainId, 178 | scopes: scopes, 179 | silence: true, 180 | }, this)); 181 | (_b = this.logger) === null || _b === void 0 ? void 0 : _b.debug('[AnyWeb]', 'silent auth result', result); 182 | } 183 | catch (e) { 184 | (_c = this.logger) === null || _c === void 0 ? void 0 : _c.debug('[AnyWeb]', 'need to auth', e); 185 | result = (yield (0, common_1.callIframe)('account', { 186 | appId: this.appId, 187 | params: params ? params[0] : {}, 188 | chainId: this.chainId, 189 | scopes: scopes, 190 | }, this)); 191 | } 192 | result.scopes = scopes; 193 | this.events.onAccountsChanged && 194 | this.events.onAccountsChanged(result.address); 195 | this.events.onChainChanged && 196 | this.events.onChainChanged(String(result.chainId)); 197 | this.events.onNetworkChanged && 198 | this.events.onNetworkChanged(String(result.networkId)); 199 | if (scopes.length > 0) { 200 | return { 201 | address: result.address, 202 | code: result.code, 203 | scopes: scopes, 204 | chainId: result.chainId, 205 | networkId: result.networkId, 206 | }; 207 | } 208 | else { 209 | return false; 210 | } 211 | case 'cfx_signTypedData': 212 | const from = params[0]; 213 | const data = params[1]; 214 | return yield (0, common_1.callIframe)('signTypedData', { 215 | appId: this.appId, 216 | chainId: this.chainId, 217 | params: params 218 | ? JSON.stringify({ 219 | from, 220 | data, 221 | }) 222 | : '', 223 | }, this); 224 | case 'cfx_personalSign': 225 | return yield (0, common_1.callIframe)('personalSign', { 226 | appId: this.appId, 227 | chainId: this.chainId, 228 | params: params 229 | ? JSON.stringify({ 230 | from: params[0], 231 | message: params[1], 232 | }) 233 | : '', 234 | }, this); 235 | case 'cfx_sendTransaction': 236 | let authType; 237 | const payload = params[0]; 238 | const to = payload.to; 239 | if (to) { 240 | authType = 241 | (0, address_1.getAddressType)(to, this.logger) === address_1.AddressType.CONTRACT 242 | ? 'callContract' 243 | : 'createTransaction'; 244 | } 245 | else { 246 | authType = 'createContract'; 247 | } 248 | return yield (0, common_1.callIframe)(authType, { 249 | appId: this.appId, 250 | chainId: this.chainId, 251 | params: params 252 | ? JSON.stringify({ 253 | payload: params[0], 254 | gatewayPayload: params[1], 255 | }) 256 | : '', 257 | }, this); 258 | case 'anyweb_importAccount': 259 | return yield (0, common_1.callIframe)('importAccount', { 260 | appId: this.appId, 261 | chainId: this.chainId, 262 | params: params ? params[0] : {}, 263 | }, this); 264 | case 'anyweb_version': 265 | return package_json_1.default.version; 266 | case 'anyweb_home': 267 | return yield (0, common_1.callIframe)('home', { 268 | appId: this.appId, 269 | chainId: this.chainId, 270 | params: params ? JSON.stringify(params) : '', 271 | waitResult: false, 272 | }, this); 273 | case 'exit_accounts': 274 | return this.rawRequest('anyweb_revoke', params); 275 | case 'anyweb_revoke': 276 | return yield (0, common_1.callIframe)('exitAccounts', { 277 | appId: this.appId, 278 | chainId: this.chainId, 279 | params: params ? JSON.stringify(params) : '', 280 | silence: true, 281 | }, this); 282 | case 'anyweb_identify': 283 | let identifyResult; 284 | try { 285 | identifyResult = yield (0, common_1.callIframe)('checkIdentify', { 286 | appId: this.appId, 287 | chainId: this.chainId, 288 | params: params ? JSON.stringify(params) : '', 289 | silence: true, 290 | }, this); 291 | (_d = this.logger) === null || _d === void 0 ? void 0 : _d.debug('[AnyWeb]', 'Check identify result', identifyResult); 292 | } 293 | catch (e) { 294 | (_e = this.logger) === null || _e === void 0 ? void 0 : _e.debug('[AnyWeb]', 'need to identify', e); 295 | identifyResult = yield (0, common_1.callIframe)('identify', { 296 | appId: this.appId, 297 | chainId: this.chainId, 298 | params: params ? JSON.stringify(params) : '', 299 | }, this); 300 | } 301 | return identifyResult; 302 | case 'anyweb_logout': 303 | // Logout the account of AnyWeb 304 | return yield (0, common_1.callIframe)('logout', { 305 | appId: this.appId, 306 | chainId: this.chainId, 307 | params: params ? JSON.stringify(params) : '', 308 | silence: true, 309 | }, this); 310 | case 'anyweb_loginstate': 311 | try { 312 | return yield (0, common_1.callIframe)('checkLogin', { 313 | appId: this.appId, 314 | params: '', 315 | chainId: this.chainId, 316 | silence: true, 317 | }, this); 318 | } 319 | catch (e) { 320 | (_f = this.logger) === null || _f === void 0 ? void 0 : _f.debug('[AnyWeb]', 'need to login', e); 321 | return false; 322 | } 323 | default: 324 | throw new common_1.ProviderRpcError(common_1.ProviderErrorCode.UnsupportedMethod, 'Unsupported Method: ' + method); 325 | } 326 | } 327 | catch (e) { 328 | // const codeList = { 329 | // cfx_sendTransaction: ProviderErrorCode.SendTransactionError, 330 | // anyweb_importAccount: ProviderErrorCode.ImportAddressError, 331 | // } 332 | (_g = this.logger) === null || _g === void 0 ? void 0 : _g.info(`Error when handler request '${method}'!`); 333 | throw new common_1.ProviderRpcError(common_1.ProviderErrorCode.RequestError, (0, common_1.isObject)(e) && 'message' in e ? e.message : e, (0, common_1.isObject)(e) && 'data' in e ? e.data : {}); 334 | } 335 | }); 336 | } 337 | /** 338 | * Monitor information 339 | * @param type {string} Type of information 340 | * @param listener {Function} Event listener 341 | * @example 342 | * provider.on('connected', listener) 343 | */ 344 | on(type, listener) { 345 | var _a; 346 | (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug('[AnyWeb] on', { 347 | type, 348 | listener, 349 | }); 350 | switch (type) { 351 | case 'connect': 352 | this.events.onConnect = listener; 353 | break; 354 | case 'disconnect': 355 | this.events.onDisconnect = listener; 356 | break; 357 | case 'chainChanged': 358 | this.events.onChainChanged = listener; 359 | break; 360 | case 'accountsChanged': 361 | this.events.onAccountsChanged = listener; 362 | break; 363 | case 'message': 364 | this.events.onMessage = listener; 365 | break; 366 | case 'networkChanged': 367 | this.events.onNetworkChanged = listener; 368 | break; 369 | case 'ready': 370 | this.events.onReady = listener; 371 | break; 372 | default: 373 | break; 374 | } 375 | } 376 | } 377 | exports.Provider = Provider; 378 | Provider.ready = false; 379 | -------------------------------------------------------------------------------- /dist/src/utils/address.d.ts: -------------------------------------------------------------------------------- 1 | import { ConsoleLike } from './types'; 2 | export declare enum AddressType { 3 | USER = "user", 4 | CONTRACT = "contract", 5 | BUILTIN = "builtin", 6 | NULL = "null" 7 | } 8 | /** 9 | * Get the type of an address. 10 | * @param address 11 | * @param logger 12 | */ 13 | export declare const getAddressType: (address: string, logger?: ConsoleLike | null) => AddressType; 14 | -------------------------------------------------------------------------------- /dist/src/utils/address.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.getAddressType = exports.AddressType = void 0; 4 | const conflux_address_js_1 = require("@conflux-dev/conflux-address-js"); 5 | var AddressType; 6 | (function (AddressType) { 7 | AddressType["USER"] = "user"; 8 | AddressType["CONTRACT"] = "contract"; 9 | AddressType["BUILTIN"] = "builtin"; 10 | AddressType["NULL"] = "null"; 11 | })(AddressType = exports.AddressType || (exports.AddressType = {})); 12 | /** 13 | * Get the type of an address. 14 | * @param address 15 | * @param logger 16 | */ 17 | const getAddressType = (address, logger = console) => { 18 | const decodeResult = (0, conflux_address_js_1.decode)(address); 19 | logger === null || logger === void 0 ? void 0 : logger.debug('[AnyWeb] decodeResult', decodeResult); 20 | if (Object.keys(decodeResult).includes('type')) { 21 | return decodeResult.type; 22 | } 23 | else { 24 | return AddressType.USER; 25 | } 26 | }; 27 | exports.getAddressType = getAddressType; 28 | -------------------------------------------------------------------------------- /dist/src/utils/common.d.ts: -------------------------------------------------------------------------------- 1 | import { IIframeData, IIframeOptions, IMethodType, IProviderRpcError } from '../interface/provider'; 2 | import { Provider } from '../provider'; 3 | import { ConsoleLike } from './types'; 4 | export declare const getFrameWidth: () => number; 5 | export declare const getFrameHeight: () => number; 6 | /** 7 | * Check the window width to decide whether to show in full screen 8 | */ 9 | export declare const isFullScreen: () => boolean; 10 | /** 11 | * SHA512加密 12 | * @param str 13 | */ 14 | export declare function sha512(str: string): string; 15 | export declare const isObject: (obj: unknown) => boolean; 16 | export declare const sendMessageToApp: ({ data, type, success, code, }: IIframeData) => void; 17 | export declare const sendMessage: (localWindow: any, { data, type, success, code, message }: IIframeData) => any; 18 | export declare const createIframe: (url: string, appUrl: string, logger?: ConsoleLike | null | undefined) => Promise; 19 | export declare const getIframe: (method: IMethodType, appUrl: string, params: Record, onClose: () => void, silence?: boolean, logger?: ConsoleLike | undefined) => Promise<() => void>; 20 | export declare const callIframe: (method: IMethodType, { appId, params, chainId, scopes, waitResult, silence, }: IIframeOptions, provider: Provider) => Promise; 21 | export declare const writeStorage: (key: string, content: Record, expiresTime?: number) => void; 22 | export declare const isArrEqual: (arr1: T[], arr2: T[]) => boolean; 23 | export declare const isIncluded: (arr1: T[], arr2: T[]) => boolean; 24 | export declare enum ProviderErrorCode { 25 | UserRejectedRequest = 4001, 26 | Unauthorized = 4100, 27 | UnsupportedMethod = 4200, 28 | Disconnected = 4900, 29 | ChainDisconnected = 4901, 30 | SDKNotReady = 5000, 31 | SDKTimeOut = 5001, 32 | ParamsError = 6000, 33 | RequestError = 7000, 34 | SendTransactionError = 7001, 35 | ImportAddressError = 7002 36 | } 37 | export declare class ProviderRpcError extends Error implements IProviderRpcError { 38 | code: number; 39 | data?: unknown; 40 | constructor(code: ProviderErrorCode, message: string, data?: {}, logger?: ConsoleLike); 41 | } 42 | -------------------------------------------------------------------------------- /dist/src/utils/common.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 10 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 11 | }) : function(o, v) { 12 | o["default"] = v; 13 | }); 14 | var __importStar = (this && this.__importStar) || function (mod) { 15 | if (mod && mod.__esModule) return mod; 16 | var result = {}; 17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 18 | __setModuleDefault(result, mod); 19 | return result; 20 | }; 21 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 22 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 23 | return new (P || (P = Promise))(function (resolve, reject) { 24 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 25 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 26 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 27 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 28 | }); 29 | }; 30 | var __importDefault = (this && this.__importDefault) || function (mod) { 31 | return (mod && mod.__esModule) ? mod : { "default": mod }; 32 | }; 33 | Object.defineProperty(exports, "__esModule", { value: true }); 34 | exports.ProviderRpcError = exports.ProviderErrorCode = exports.isIncluded = exports.isArrEqual = exports.writeStorage = exports.callIframe = exports.getIframe = exports.createIframe = exports.sendMessage = exports.sendMessageToApp = exports.isObject = exports.sha512 = exports.isFullScreen = exports.getFrameHeight = exports.getFrameWidth = void 0; 35 | /** 36 | * @author Littleor 37 | * @since 2022/2/11 38 | */ 39 | const forge = __importStar(require("node-forge")); 40 | const package_json_1 = __importDefault(require("../../package.json")); 41 | const getFrameWidth = () => { 42 | if (window.innerHeight < 736) { 43 | return ((window.innerHeight - 18) * 9.0) / 16.0; 44 | } 45 | else { 46 | return 414; 47 | } 48 | }; 49 | exports.getFrameWidth = getFrameWidth; 50 | const getFrameHeight = () => { 51 | if (window.innerHeight < 736) { 52 | return window.innerHeight - 18; 53 | } 54 | else { 55 | return 736; 56 | } 57 | }; 58 | exports.getFrameHeight = getFrameHeight; 59 | /** 60 | * Check the window width to decide whether to show in full screen 61 | */ 62 | const isFullScreen = () => { 63 | return window.innerWidth < 500; 64 | }; 65 | exports.isFullScreen = isFullScreen; 66 | /** 67 | * SHA512加密 68 | * @param str 69 | */ 70 | function sha512(str) { 71 | const md = forge.md.sha512.create(); 72 | md.update(str); 73 | return md.digest().toHex(); 74 | } 75 | exports.sha512 = sha512; 76 | const setBodyNonScrollable = () => { 77 | document.body.style.overflow = 'hidden'; 78 | const scrollTop = document.body.scrollTop || document.documentElement.scrollTop; 79 | document.body.style.cssText += 80 | 'position:fixed;width:100%;top:-' + scrollTop + 'px;'; 81 | document.addEventListener('touchmove', (e) => { 82 | e.stopPropagation(); 83 | }, { passive: false }); 84 | }; 85 | const setBodyScrollable = () => { 86 | document.body.style.overflow = ''; 87 | document.body.style.position = ''; 88 | const top = document.body.style.top; 89 | document.body.scrollTop = document.documentElement.scrollTop = -parseInt(top); 90 | document.body.style.top = ''; 91 | document.removeEventListener('touchmove', (e) => { 92 | e.stopPropagation(); 93 | }); 94 | }; 95 | const isObject = (obj) => { 96 | return Object.prototype.toString.call(obj) === '[object Object]'; 97 | }; 98 | exports.isObject = isObject; 99 | const closeIframe = (root, logger) => { 100 | logger === null || logger === void 0 ? void 0 : logger.debug('[AnyWeb]', 'closeIframe', root.style); 101 | setBodyScrollable(); 102 | root.style.visibility = 'hidden'; 103 | }; 104 | const sendMessageToApp = ({ data, type, success = true, code = 0, }) => { 105 | const iframe = document.getElementById('anyweb-iframe'); 106 | if (!iframe) { 107 | return; 108 | } 109 | (0, exports.sendMessage)(iframe.contentWindow, { data, type, success, code }); 110 | }; 111 | exports.sendMessageToApp = sendMessageToApp; 112 | const sendMessage = (localWindow, { data, type, success = true, code = 0, message }) => { 113 | return (localWindow && 114 | localWindow.postMessage({ 115 | data: { 116 | data, 117 | type, 118 | success, 119 | code, 120 | message, 121 | }, 122 | type: 'anyweb', 123 | }, '*')); 124 | }; 125 | exports.sendMessage = sendMessage; 126 | const createIframe = (url, appUrl, logger) => __awaiter(void 0, void 0, void 0, function* () { 127 | logger === null || logger === void 0 ? void 0 : logger.debug('[AnyWeb] createIframe', url); 128 | const mask = document.createElement('div'); 129 | const div = document.createElement('div'); 130 | const iframe = document.createElement('iframe'); 131 | const button = document.createElement('div'); 132 | const style = document.createElement('style'); 133 | style.innerHTML = ` 134 | .iframe::-webkit-scrollbar{ 135 | visibility: hidden; 136 | } 137 | .iframe-mask { 138 | position: fixed; 139 | top: 0; 140 | left: 0; 141 | width: 100%; 142 | height: 100%; 143 | background-color: rgba(247, 247, 247, 0.8); 144 | z-index: 99999; 145 | } 146 | .iframe-contain { 147 | position: fixed; 148 | z-index: 999999999; 149 | ${(0, exports.isFullScreen)() 150 | ? ` 151 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); 152 | border-radius: 15px;` 153 | : ''} 154 | 155 | width: ${(0, exports.isFullScreen)() ? '100%' : `${(0, exports.getFrameWidth)()}px`}; 156 | height: ${(0, exports.isFullScreen)() ? '100%' : `${(0, exports.getFrameHeight)()}px`}; 157 | transform: translate(-50%, -50%); 158 | top: 50%; 159 | left: 50%; 160 | } 161 | 162 | .iframe { 163 | border-radius: ${(0, exports.isFullScreen)() ? '0' : '15px'}; 164 | height: 100%; 165 | width: 100%; 166 | z-index: 999999; 167 | overflow-x: hidden; 168 | } 169 | 170 | .iframe-contain-button { 171 | border-radius: 9px; 172 | width: 18px; 173 | height: 18px; 174 | z-index: 9999999; 175 | position: absolute; 176 | top: 36px; 177 | right: 36px; 178 | cursor: pointer; 179 | } 180 | 181 | .iframe-contain-button:before { 182 | position: absolute; 183 | content: ''; 184 | width: 2px; 185 | height: 24px; 186 | background: black; 187 | top: 50%; 188 | left: 50%; 189 | transform: translate(-50%, -50%) rotate(45deg); 190 | } 191 | 192 | .iframe-contain-button:after { 193 | content: ''; 194 | position: absolute; 195 | width: 2px; 196 | height: 24px; 197 | background: black; 198 | transform: translate(-50%, -50%) rotate(-45deg); 199 | top: 50%; 200 | left: 50%; 201 | }`; 202 | mask.className = 'iframe-mask'; 203 | div.className = 'iframe-contain'; 204 | button.className = 'iframe-contain-button'; 205 | iframe.className = 'iframe'; 206 | iframe.id = 'anyweb-iframe'; 207 | mask.id = 'anyweb-iframe-mask'; 208 | document.body.appendChild(style); 209 | document.body.insertBefore(mask, document.body.firstElementChild); 210 | iframe.setAttribute('style', 'height: 100%; width: 100%;'); 211 | iframe.setAttribute('src', `${appUrl}${url}`); 212 | iframe.setAttribute('frameborder', '0'); 213 | iframe.setAttribute('scrolling', 'no'); 214 | div.insertBefore(iframe, div.firstElementChild); 215 | !(0, exports.isFullScreen)() && mask.insertBefore(button, mask.firstElementChild); 216 | mask.insertBefore(div, mask.firstElementChild); 217 | // Hide before call the method 218 | mask.style.visibility = 'hidden'; 219 | // setBodyScrollable() 220 | button.onclick = () => { 221 | closeIframe(mask); 222 | window && 223 | (0, exports.sendMessage)(window, { 224 | data: {}, 225 | type: 'callback', 226 | message: 'User canceled the operation', 227 | code: ProviderErrorCode.Unauthorized, 228 | success: false, 229 | }); 230 | }; 231 | }); 232 | exports.createIframe = createIframe; 233 | const getIframe = (method, appUrl, params, onClose, silence = false, logger) => __awaiter(void 0, void 0, void 0, function* () { 234 | if (!(document.getElementById('anyweb-iframe-mask') && 235 | document.getElementById('anyweb-iframe'))) { 236 | logger === null || logger === void 0 ? void 0 : logger.warn('[AnyWeb] Something wrong with the iframe, recreating...'); 237 | yield (0, exports.createIframe)('', appUrl); 238 | } 239 | (0, exports.sendMessageToApp)({ 240 | type: 'event', 241 | data: { 242 | params: Object.assign(Object.assign({}, params), { version: package_json_1.default.version }), 243 | method: method, 244 | }, 245 | code: 0, 246 | }); 247 | const mask = document.getElementById('anyweb-iframe-mask'); 248 | if (!silence) { 249 | setTimeout(() => { 250 | mask.style.visibility = 'visible'; 251 | setBodyNonScrollable(); 252 | }, 300); 253 | } 254 | return () => { 255 | onClose(); 256 | if (!silence) { 257 | closeIframe(mask); 258 | } 259 | }; 260 | }); 261 | exports.getIframe = getIframe; 262 | const callIframe = (method, { appId, params, chainId, scopes = [], waitResult = true, silence = false, }, provider) => __awaiter(void 0, void 0, void 0, function* () { 263 | if (waitResult) { 264 | return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () { 265 | let callback = undefined; 266 | const close = yield (0, exports.getIframe)(method, provider.appUrl, { 267 | appId, 268 | authType: method, 269 | random: Math.floor(Math.random() * 1000), 270 | chainId, 271 | params, 272 | scopes, 273 | }, () => { 274 | if (timer) { 275 | clearTimeout(timer); 276 | } 277 | }, silence); 278 | const timer = setTimeout(() => { 279 | close(); 280 | reject({ 281 | code: ProviderErrorCode.SDKTimeOut, 282 | message: 'Timeout', 283 | data: {}, 284 | }); 285 | }, 10 * 60 * 1000); 286 | // Set Listeners 287 | window.addEventListener('message', function receiveMessageFromIframePage(event) { 288 | var _a; 289 | if (event.data && 290 | (0, exports.isObject)(event.data) && 291 | 'type' in event.data && 292 | event.data.type === 'anyweb') { 293 | (_a = provider.logger) === null || _a === void 0 ? void 0 : _a.debug('[AnyWeb] SDK收到子页面信息: ', event.data); 294 | callback = event.data.data; 295 | if (callback.type === 'callback') { 296 | window.removeEventListener('message', receiveMessageFromIframePage); 297 | clearTimeout(timer); 298 | close(); 299 | if (callback.success) { 300 | resolve(callback.data); 301 | } 302 | else { 303 | reject({ 304 | code: callback.code, 305 | message: callback.message, 306 | data: callback.data || {}, 307 | }); 308 | } 309 | } 310 | else if (callback.type === 'event') { 311 | const eventData = callback.data; 312 | switch (eventData.type) { 313 | case 'changeNetwork': 314 | provider.events.onNetworkChanged && 315 | provider.events.onNetworkChanged(String(eventData.data)); 316 | break; 317 | case 'changeChain': 318 | provider.events.onChainChanged && 319 | provider.events.onChainChanged(String(eventData.data)); 320 | break; 321 | default: 322 | break; 323 | } 324 | } 325 | } 326 | }, false); 327 | })); 328 | } 329 | else { 330 | yield (0, exports.getIframe)(method, provider.appUrl, { 331 | appId, 332 | authType: method, 333 | random: Math.floor(Math.random() * 1000), 334 | chainId, 335 | params, 336 | scopes, 337 | }, () => { 338 | return; 339 | }, silence); 340 | return 'ok'; 341 | } 342 | }); 343 | exports.callIframe = callIframe; 344 | const writeStorage = (key, content, expiresTime = 5 * 60 * 1000) => { 345 | window.localStorage && 346 | window.localStorage.setItem(`anyweb_${key}`, JSON.stringify(Object.assign(Object.assign({}, content), { expires: expiresTime + new Date().getTime() }))); 347 | }; 348 | exports.writeStorage = writeStorage; 349 | const isArrEqual = (arr1, arr2) => { 350 | return arr1.length === arr2.length && arr1.every((ele) => arr2.includes(ele)); 351 | }; 352 | exports.isArrEqual = isArrEqual; 353 | const isIncluded = (arr1, arr2) => { 354 | return arr1.length === new Set([...arr1, ...arr2]).size; 355 | }; 356 | exports.isIncluded = isIncluded; 357 | var ProviderErrorCode; 358 | (function (ProviderErrorCode) { 359 | ProviderErrorCode[ProviderErrorCode["UserRejectedRequest"] = 4001] = "UserRejectedRequest"; 360 | ProviderErrorCode[ProviderErrorCode["Unauthorized"] = 4100] = "Unauthorized"; 361 | ProviderErrorCode[ProviderErrorCode["UnsupportedMethod"] = 4200] = "UnsupportedMethod"; 362 | ProviderErrorCode[ProviderErrorCode["Disconnected"] = 4900] = "Disconnected"; 363 | ProviderErrorCode[ProviderErrorCode["ChainDisconnected"] = 4901] = "ChainDisconnected"; 364 | ProviderErrorCode[ProviderErrorCode["SDKNotReady"] = 5000] = "SDKNotReady"; 365 | ProviderErrorCode[ProviderErrorCode["SDKTimeOut"] = 5001] = "SDKTimeOut"; 366 | ProviderErrorCode[ProviderErrorCode["ParamsError"] = 6000] = "ParamsError"; 367 | ProviderErrorCode[ProviderErrorCode["RequestError"] = 7000] = "RequestError"; 368 | ProviderErrorCode[ProviderErrorCode["SendTransactionError"] = 7001] = "SendTransactionError"; 369 | ProviderErrorCode[ProviderErrorCode["ImportAddressError"] = 7002] = "ImportAddressError"; 370 | })(ProviderErrorCode = exports.ProviderErrorCode || (exports.ProviderErrorCode = {})); 371 | class ProviderRpcError extends Error { 372 | constructor(code, message, data = {}, logger = console) { 373 | super(message); 374 | logger.error(`[AnyWeb] Throw the error(${code}):`, '\n Message: ', message, '\n Data: ', data); 375 | this.code = code; 376 | this.name = ProviderErrorCode[code]; 377 | this.data = data; 378 | } 379 | } 380 | exports.ProviderRpcError = ProviderRpcError; 381 | -------------------------------------------------------------------------------- /dist/src/utils/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Littleor 3 | * @since 2022/2/4 4 | */ 5 | export declare type ConsoleLike = Pick; 6 | -------------------------------------------------------------------------------- /dist/src/utils/types.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /example/basic-dapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AnyWeb Demo - Basic Dapp 7 | 8 | 10 | 11 | 13 | 14 | 15 | 16 |
17 | 24 |
25 |
26 | Install 27 |
28 |

AnyWeb Wallet is not 29 | installed

30 |
31 | AnyWeb Version: N/A 32 |
33 |
34 |
35 |
36 |
37 | Initialize 38 |
39 |

AnyWeb Wallet is initializing

41 |
42 | chainId: N/A
43 | networkId: N/A 44 |
45 |
46 |
47 |
48 | Connect 49 |
50 | 54 | 57 | 60 | 63 |
64 |

Address: N/A

65 |

OAuth Code: N/A

66 |
67 |
68 |
69 |
70 | 合约调用示例 71 |
72 |
73 | 74 |
75 | 78 |
79 | Result: N/A 80 |
81 |
82 | 83 |
84 |
85 | 使用AnyWeb网关的合约调用示例 86 |
87 |
88 | 89 |
90 | 93 |
94 | Result: N/A 95 |
96 |
97 | 98 |
99 |
100 | 获取签名 101 |
102 |
103 | 104 |
105 | 107 |
108 | Result: N/A 109 |
110 |
111 | 112 |
113 |
114 | personal_sign 115 |
116 |
117 | 118 |
119 | 121 |
122 | Result: N/A 123 |
124 |
125 | 126 |
127 |
128 | Deploy Contract 129 |
130 | 133 |
134 | Result: N/A 135 |
136 |
137 |
138 |
139 | 导入地址 140 |
141 |
142 | 146 | 150 |
151 | 154 |
155 | Result: N/A 156 |
157 |
158 |
159 |
160 | 跳转AnyWeb进行身份验证 161 |
162 | 165 |
166 | Result: N/A 167 |
168 |
169 | 170 |
171 |
172 | 检查登录状态 173 |
174 | 176 |
177 | Result: N/A 178 |
179 |
180 |
181 | 182 | 188 | 189 | 192 |
193 | 194 | 195 | -------------------------------------------------------------------------------- /example/basic-dapp/index.js: -------------------------------------------------------------------------------- 1 | // import js-conflux-sdk 2 | // more info about js-conflux-sdk 3 | // https://github.com/Conflux-Chain/js-conflux-sdk#readme 4 | import { Conflux } from './js-conflux-sdk.js' 5 | 6 | const dappAddress = 'cfxtest:aca8paka2w86tpgmmh7ufdv005u2cheb76578khwd2' 7 | const onlineAddress = 'cfx:acgtf56ceymsvw2r0nsffveafatu5v6jz6me8m4m85' 8 | 9 | const confluxFaucetAddress = 10 | 'cfxtest:acejjfa80vj06j2jgtz9pngkv423fhkuxj786kjr61' 11 | const exampleContract = new Conflux().Contract({ 12 | abi: [ 13 | { 14 | inputs: [ 15 | { 16 | internalType: 'string', 17 | name: '_name', 18 | type: 'string', 19 | }, 20 | { 21 | internalType: 'uint8', 22 | name: '_decimals', 23 | type: 'uint8', 24 | }, 25 | { 26 | internalType: 'string', 27 | name: '_symbol', 28 | type: 'string', 29 | }, 30 | { 31 | internalType: 'uint256', 32 | name: '_totalSupply', 33 | type: 'uint256', 34 | }, 35 | ], 36 | stateMutability: 'nonpayable', 37 | type: 'constructor', 38 | }, 39 | { 40 | anonymous: false, 41 | inputs: [ 42 | { 43 | indexed: true, 44 | internalType: 'address', 45 | name: '_owner', 46 | type: 'address', 47 | }, 48 | { 49 | indexed: true, 50 | internalType: 'address', 51 | name: '_spender', 52 | type: 'address', 53 | }, 54 | { 55 | indexed: false, 56 | internalType: 'uint256', 57 | name: '_value', 58 | type: 'uint256', 59 | }, 60 | ], 61 | name: 'Approval', 62 | type: 'event', 63 | }, 64 | { 65 | anonymous: false, 66 | inputs: [ 67 | { 68 | indexed: true, 69 | internalType: 'address', 70 | name: '_from', 71 | type: 'address', 72 | }, 73 | { 74 | indexed: true, 75 | internalType: 'address', 76 | name: '_to', 77 | type: 'address', 78 | }, 79 | { 80 | indexed: false, 81 | internalType: 'uint256', 82 | name: '_value', 83 | type: 'uint256', 84 | }, 85 | ], 86 | name: 'Transfer', 87 | type: 'event', 88 | }, 89 | { 90 | inputs: [ 91 | { 92 | internalType: 'address', 93 | name: '_owner', 94 | type: 'address', 95 | }, 96 | { 97 | internalType: 'address', 98 | name: '_spender', 99 | type: 'address', 100 | }, 101 | ], 102 | name: 'allowance', 103 | outputs: [ 104 | { 105 | internalType: 'uint256', 106 | name: 'remaining', 107 | type: 'uint256', 108 | }, 109 | ], 110 | stateMutability: 'view', 111 | type: 'function', 112 | }, 113 | { 114 | inputs: [ 115 | { 116 | internalType: 'address', 117 | name: '', 118 | type: 'address', 119 | }, 120 | { 121 | internalType: 'address', 122 | name: '', 123 | type: 'address', 124 | }, 125 | ], 126 | name: 'allowed', 127 | outputs: [ 128 | { 129 | internalType: 'uint256', 130 | name: '', 131 | type: 'uint256', 132 | }, 133 | ], 134 | stateMutability: 'view', 135 | type: 'function', 136 | }, 137 | { 138 | inputs: [ 139 | { 140 | internalType: 'address', 141 | name: '_spender', 142 | type: 'address', 143 | }, 144 | { 145 | internalType: 'uint256', 146 | name: '_value', 147 | type: 'uint256', 148 | }, 149 | ], 150 | name: 'approve', 151 | outputs: [ 152 | { 153 | internalType: 'bool', 154 | name: 'success', 155 | type: 'bool', 156 | }, 157 | ], 158 | stateMutability: 'nonpayable', 159 | type: 'function', 160 | }, 161 | { 162 | inputs: [ 163 | { 164 | internalType: 'address', 165 | name: '_owner', 166 | type: 'address', 167 | }, 168 | ], 169 | name: 'balanceOf', 170 | outputs: [ 171 | { 172 | internalType: 'uint256', 173 | name: 'balance', 174 | type: 'uint256', 175 | }, 176 | ], 177 | stateMutability: 'view', 178 | type: 'function', 179 | }, 180 | { 181 | inputs: [ 182 | { 183 | internalType: 'address', 184 | name: '', 185 | type: 'address', 186 | }, 187 | ], 188 | name: 'balances', 189 | outputs: [ 190 | { 191 | internalType: 'uint256', 192 | name: '', 193 | type: 'uint256', 194 | }, 195 | ], 196 | stateMutability: 'view', 197 | type: 'function', 198 | }, 199 | { 200 | inputs: [], 201 | name: 'decimals', 202 | outputs: [ 203 | { 204 | internalType: 'uint8', 205 | name: '', 206 | type: 'uint8', 207 | }, 208 | ], 209 | stateMutability: 'view', 210 | type: 'function', 211 | }, 212 | { 213 | inputs: [], 214 | name: 'name', 215 | outputs: [ 216 | { 217 | internalType: 'string', 218 | name: '', 219 | type: 'string', 220 | }, 221 | ], 222 | stateMutability: 'view', 223 | type: 'function', 224 | }, 225 | { 226 | inputs: [], 227 | name: 'symbol', 228 | outputs: [ 229 | { 230 | internalType: 'string', 231 | name: '', 232 | type: 'string', 233 | }, 234 | ], 235 | stateMutability: 'view', 236 | type: 'function', 237 | }, 238 | { 239 | inputs: [], 240 | name: 'totalSupply', 241 | outputs: [ 242 | { 243 | internalType: 'uint256', 244 | name: '', 245 | type: 'uint256', 246 | }, 247 | ], 248 | stateMutability: 'view', 249 | type: 'function', 250 | }, 251 | { 252 | inputs: [ 253 | { 254 | internalType: 'address', 255 | name: '_to', 256 | type: 'address', 257 | }, 258 | { 259 | internalType: 'uint256', 260 | name: '_value', 261 | type: 'uint256', 262 | }, 263 | ], 264 | name: 'transfer', 265 | outputs: [ 266 | { 267 | internalType: 'bool', 268 | name: 'success', 269 | type: 'bool', 270 | }, 271 | ], 272 | stateMutability: 'nonpayable', 273 | type: 'function', 274 | }, 275 | { 276 | inputs: [ 277 | { 278 | internalType: 'address', 279 | name: '_from', 280 | type: 'address', 281 | }, 282 | { 283 | internalType: 'address', 284 | name: '_to', 285 | type: 'address', 286 | }, 287 | { 288 | internalType: 'uint256', 289 | name: '_value', 290 | type: 'uint256', 291 | }, 292 | ], 293 | name: 'transferFrom', 294 | outputs: [ 295 | { 296 | internalType: 'bool', 297 | name: 'success', 298 | type: 'bool', 299 | }, 300 | ], 301 | stateMutability: 'nonpayable', 302 | type: 'function', 303 | }, 304 | ], 305 | bytecode: 306 | '0x60806040523480156200001157600080fd5b50604051620010ca380380620010ca833981810160405260808110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b838201915060208201858111156200006f57600080fd5b82518660018202830111640100000000821117156200008d57600080fd5b8083526020830192505050908051906020019080838360005b83811015620000c3578082015181840152602081019050620000a6565b50505050905090810190601f168015620000f15780820380516001836020036101000a031916815260200191505b5060405260200180519060200190929190805160405193929190846401000000008211156200011f57600080fd5b838201915060208201858111156200013657600080fd5b82518660018202830111640100000000821117156200015457600080fd5b8083526020830192505050908051906020019080838360005b838110156200018a5780820151818401526020810190506200016d565b50505050905090810190601f168015620001b85780820380516001836020036101000a031916815260200191505b50604052602001805190602001909291905050508360009080519060200190620001e49291906200026e565b5082600160006101000a81548160ff021916908360ff1602179055508160029080519060200190620002189291906200026e565b508060038190555080600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050506200031d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b157805160ff1916838001178555620002e2565b82800160010185558215620002e2579182015b82811115620002e1578251825591602001919060010190620002c4565b5b509050620002f19190620002f5565b5090565b6200031a91905b8082111562000316576000816000905550600101620002fc565b5090565b90565b610d9d806200032d6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063313ce56711610071578063313ce567146102935780635c658165146102b757806370a082311461032f57806395d89b4114610387578063a9059cbb1461040a578063dd62ed3e14610470576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b557806327e235e31461023b575b600080fd5b6100b66104e8565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f610678565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061067e565b604051808215151515815260200191505060405180910390f35b61027d6004803603602081101561025157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506109e9565b6040518082815260200191505060405180910390f35b61029b610a01565b604051808260ff1660ff16815260200191505060405180910390f35b610319600480360360408110156102cd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a14565b6040518082815260200191505060405180910390f35b6103716004803603602081101561034557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a39565b6040518082815260200191505060405180910390f35b61038f610a82565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103cf5780820151818401526020810190506103b4565b50505050905090810190601f1680156103fc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104566004803603604081101561042057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b20565b604051808215151515815260200191505060405180910390f35b6104d26004803603604081101561048657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ce0565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057e5780601f106105535761010080835404028352916020019161057e565b820191906000526020600020905b81548152906001019060200180831161056157829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60035481565b600080600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156107b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f62616c616e636573206e6f7420656e6f7567680000000000000000000000000081525060200191505060405180910390fd5b8281101561082b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f616c6c6f77616e6365206e6f7420656e6f75676800000000000000000000000081525060200191505060405180910390fd5b82600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555082600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156109785782600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b60046020528060005260406000206000915090505481565b600160009054906101000a900460ff1681565b6005602052816000526040600020602052806000526040600020600091509150505481565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60028054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b185780601f10610aed57610100808354040283529160200191610b18565b820191906000526020600020905b815481529060010190602001808311610afb57829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015610bd7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f62616c616e636573206e6f7420656e6f7567680000000000000000000000000081525060200191505060405180910390fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490509291505056fea2646970667358221220ba3544f95832f9a6f264be220893ae1c951498e955e1908563105ee727d890c064736f6c634300060a0033', 307 | }) 308 | const confluxFaucetContract = new Conflux().Contract({ 309 | abi: [ 310 | { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, 311 | { 312 | inputs: [ 313 | { 314 | internalType: 'address', 315 | name: 'newManager', 316 | type: 'address', 317 | }, 318 | ], 319 | name: 'changeManager', 320 | outputs: [], 321 | stateMutability: 'nonpayable', 322 | type: 'function', 323 | }, 324 | { 325 | inputs: [], 326 | name: 'claimCfx', 327 | outputs: [], 328 | stateMutability: 'nonpayable', 329 | type: 'function', 330 | }, 331 | { 332 | inputs: [], 333 | name: 'claimCfxRegardingSenderBalance', 334 | outputs: [], 335 | stateMutability: 'nonpayable', 336 | type: 'function', 337 | }, 338 | { 339 | inputs: [ 340 | { 341 | internalType: 'address', 342 | name: 'tokenContractAddress', 343 | type: 'address', 344 | }, 345 | ], 346 | name: 'claimToken', 347 | outputs: [], 348 | stateMutability: 'nonpayable', 349 | type: 'function', 350 | }, 351 | { 352 | inputs: [ 353 | { 354 | internalType: 'address', 355 | name: 'tokenContractAddress', 356 | type: 'address', 357 | }, 358 | ], 359 | name: 'claimTokenRegardingSenderBalance', 360 | outputs: [], 361 | stateMutability: 'nonpayable', 362 | type: 'function', 363 | }, 364 | { 365 | inputs: [], 366 | name: 'defaultAmount', 367 | outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], 368 | stateMutability: 'view', 369 | type: 'function', 370 | }, 371 | { 372 | inputs: [], 373 | name: 'defaultInterval', 374 | outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], 375 | stateMutability: 'view', 376 | type: 'function', 377 | }, 378 | { 379 | inputs: [ 380 | { 381 | internalType: 'address', 382 | name: 'tokenContractAddress', 383 | type: 'address', 384 | }, 385 | ], 386 | name: 'getClaimAmount', 387 | outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], 388 | stateMutability: 'view', 389 | type: 'function', 390 | }, 391 | { 392 | inputs: [ 393 | { 394 | internalType: 'address', 395 | name: 'tokenContractAddress', 396 | type: 'address', 397 | }, 398 | ], 399 | name: 'getClaimInterval', 400 | outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], 401 | stateMutability: 'view', 402 | type: 'function', 403 | }, 404 | { 405 | inputs: [ 406 | { 407 | internalType: 'address[]', 408 | name: 'tokenList', 409 | type: 'address[]', 410 | }, 411 | ], 412 | name: 'retrieveToken', 413 | outputs: [], 414 | stateMutability: 'nonpayable', 415 | type: 'function', 416 | }, 417 | { 418 | inputs: [ 419 | { 420 | internalType: 'address', 421 | name: 'tokenContractAddress', 422 | type: 'address', 423 | }, 424 | { internalType: 'uint256', name: 'interval', type: 'uint256' }, 425 | { 426 | internalType: 'uint256', 427 | name: 'amount', 428 | type: 'uint256', 429 | }, 430 | ], 431 | name: 'setClaimSetting', 432 | outputs: [], 433 | stateMutability: 'nonpayable', 434 | type: 'function', 435 | }, 436 | { 437 | inputs: [ 438 | { 439 | internalType: 'uint256', 440 | name: 'amount', 441 | type: 'uint256', 442 | }, 443 | ], 444 | name: 'setDefaultAmount', 445 | outputs: [], 446 | stateMutability: 'nonpayable', 447 | type: 'function', 448 | }, 449 | { 450 | inputs: [ 451 | { 452 | internalType: 'uint256', 453 | name: 'intervalSeconds', 454 | type: 'uint256', 455 | }, 456 | ], 457 | name: 'setDefaultIntervalSeconds', 458 | outputs: [], 459 | stateMutability: 'nonpayable', 460 | type: 'function', 461 | }, 462 | { stateMutability: 'payable', type: 'receive' }, 463 | ], 464 | address: confluxFaucetAddress, 465 | }) 466 | 467 | const abi = [ 468 | { 469 | inputs: [ 470 | { 471 | internalType: 'address', 472 | name: '_gateway', 473 | type: 'address', 474 | }, 475 | ], 476 | stateMutability: 'nonpayable', 477 | type: 'constructor', 478 | }, 479 | { 480 | inputs: [ 481 | { 482 | internalType: 'bytes', 483 | name: 'gatewayData', 484 | type: 'bytes', 485 | }, 486 | { 487 | internalType: 'bytes', 488 | name: 'gatewaySig', 489 | type: 'bytes', 490 | }, 491 | ], 492 | name: 'test', 493 | outputs: [ 494 | { 495 | internalType: 'string', 496 | name: '', 497 | type: 'string', 498 | }, 499 | ], 500 | stateMutability: 'nonpayable', 501 | type: 'function', 502 | }, 503 | { 504 | inputs: [], 505 | name: 'testNoGuard', 506 | outputs: [ 507 | { 508 | internalType: 'string', 509 | name: '', 510 | type: 'string', 511 | }, 512 | ], 513 | stateMutability: 'nonpayable', 514 | type: 'function', 515 | }, 516 | ] 517 | 518 | const msgParams = { 519 | types: { 520 | CIP23Domain: [ 521 | { 522 | name: 'name', 523 | type: 'string', 524 | }, 525 | { 526 | name: 'version', 527 | type: 'string', 528 | }, 529 | { 530 | name: 'chainId', 531 | type: 'uint256', 532 | }, 533 | { 534 | name: 'verifyingContract', 535 | type: 'address', 536 | }, 537 | ], 538 | Person: [ 539 | { 540 | name: 'name', 541 | type: 'string', 542 | }, 543 | { 544 | name: 'wallet', 545 | type: 'address', 546 | }, 547 | ], 548 | Mail: [ 549 | { 550 | name: 'from', 551 | type: 'Person', 552 | }, 553 | { 554 | name: 'to', 555 | type: 'Person', 556 | }, 557 | { 558 | name: 'contents', 559 | type: 'string', 560 | }, 561 | ], 562 | }, 563 | primaryType: 'Mail', 564 | domain: { 565 | name: 'Ether Mail', 566 | version: '1', 567 | chainId: 1, 568 | verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', 569 | }, 570 | message: { 571 | from: { 572 | name: 'Cow', 573 | wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', 574 | }, 575 | to: { 576 | name: 'Bob', 577 | wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', 578 | }, 579 | contents: 'Hello, Bob!', 580 | }, 581 | } 582 | 583 | // 初始化钱包 584 | // const provider = new window.AnyWeb.Provider({ 585 | // appId: '693b6401-135a-4dc3-846b-1c05ad2572f6', 586 | // }) 587 | // 初始化钱包 588 | const provider = new window.AnyWeb.Provider( 589 | { 590 | appId: '693b6401-135a-4dc3-846b-1c05ad2572f6', 591 | }, 592 | `https://${window.location.host}/#/` 593 | ) 594 | console.log('开始监听是否准备好') 595 | provider.on('ready', async () => { 596 | await walletInitialized() 597 | window.addEventListener('load', async () => { 598 | if (!isAnyWebInstall()) { 599 | return 600 | } 601 | getElement('installed').innerHTML = 'installed' 602 | if (window.localStorage.getItem('__FLUENT_USE_MODERN_PROVIDER_API__')) { 603 | getElement('installed-section').style.display = 'block' 604 | } 605 | if (isAnyWebInstall()) { 606 | console.log('DApp 已经检查到OK了') 607 | provider.request({ method: 'anyweb_version' }).then((version) => { 608 | getElement('version').innerHTML = version 609 | }) 610 | } else { 611 | alert('找不到AnyWeb SDK, 请检查是否正确配置') 612 | } 613 | }) 614 | }) 615 | 616 | function getElement(id) { 617 | return document.getElementById(id) 618 | } 619 | 620 | function isAnyWebInstall() { 621 | return window.AnyWeb !== undefined 622 | } 623 | 624 | let address = [] 625 | let networkId = -1 626 | let chainId = -1 627 | let url = '' 628 | 629 | // dappContract 630 | let dappContract = new Conflux().Contract({ 631 | abi: abi, 632 | address: networkId === 1029 ? onlineAddress : dappAddress, 633 | }) 634 | 635 | function setState(data) { 636 | address = data.address 637 | networkId = data.networkId 638 | chainId = data.chainId 639 | url = data.url 640 | dappContract = new Conflux().Contract({ 641 | abi: abi, 642 | address: networkId === 1029 ? onlineAddress : dappAddress, 643 | }) 644 | } 645 | 646 | function reset() { 647 | address = [] 648 | networkId = -1 649 | chainId = -1 650 | url = '' 651 | dappContract = new Conflux().Contract({ 652 | abi: abi, 653 | address: networkId === 1029 ? onlineAddress : dappAddress, 654 | }) 655 | } 656 | 657 | async function walletInitialized() { 658 | // connect 659 | const connectButton = getElement('connect') 660 | const DeauthorizeButton = getElement('Deauthorize') 661 | const logoutButton = getElement('Logout') 662 | const getCFXButton = getElement('get-cfx') 663 | const gatewayTestButton = getElement('gateway_test') 664 | const importAddressButton = getElement('import_address_button') 665 | const importAddressInput = getElement('import_address_input') 666 | const phoneInput = getElement('phone_input') 667 | const importAddressNameInput = getElement('import_address_name_input') 668 | const identifyButton = getElement('identify_button') 669 | const checkLoginButton = getElement('checklogin_button') 670 | const signButton = getElement('sign_button') 671 | const personalSignButton = getElement('personal_sign_button') 672 | 673 | const deployContract = getElement('deploy_contract') 674 | 675 | function authed(address, oauthCode = undefined) { 676 | if (!address || address === '') { 677 | return unAuthed() 678 | } 679 | getElement('address').innerHTML = address 680 | if (oauthCode) { 681 | getElement('oauth_code').innerHTML = oauthCode 682 | } 683 | console.log('authed address: ', address) 684 | deployContract.disabled = false 685 | getCFXButton.disabled = false 686 | gatewayTestButton.disabled = false 687 | connectButton.disabled = true 688 | DeauthorizeButton.disabled = false 689 | logoutButton.disabled = false 690 | importAddressButton.disabled = false 691 | identifyButton.disabled = false 692 | signButton.disabled = false 693 | personalSignButton.disabled = false 694 | } 695 | 696 | function unAuthed() { 697 | getElement('address').innerHTML = 'N/A' 698 | getElement('oauth_code').innerHTML = 'N/A' 699 | console.log('unauthed') 700 | getCFXButton.disabled = true 701 | gatewayTestButton.disabled = true 702 | deployContract.disabled = true 703 | connectButton.disabled = false 704 | DeauthorizeButton.disabled = true 705 | logoutButton.disabled = true 706 | importAddressButton.disabled = true 707 | identifyButton.disabled = true 708 | signButton.disabled = true 709 | personalSignButton.disabled = true 710 | } 711 | 712 | try { 713 | provider.request({ method: 'anyweb_version' }).then((version) => { 714 | getElement('version').innerHTML = version 715 | }) 716 | 717 | const data = await provider.request({ 718 | method: 'cfx_accounts', 719 | params: [ 720 | { 721 | availableNetwork: [1, 1029], 722 | scopes: ['baseInfo', 'identity'], 723 | }, 724 | ], 725 | }) 726 | const { chainId, networkId, address: alreadyAuthedAddresses, code } = data 727 | console.log( 728 | 'DApp 获取到的授权结果', 729 | chainId, 730 | networkId, 731 | alreadyAuthedAddresses, 732 | code 733 | ) 734 | setState(data) 735 | getElement('initialized').innerHTML = 'initialized' 736 | getElement('chainId').innerHTML = chainId 737 | getElement('networkId').innerHTML = networkId 738 | 739 | if ( 740 | !alreadyAuthedAddresses || 741 | !alreadyAuthedAddresses.length || 742 | alreadyAuthedAddresses.length === 0 743 | ) { 744 | unAuthed() 745 | } else { 746 | authed(alreadyAuthedAddresses[0], code) 747 | } 748 | } catch (e) { 749 | unAuthed() 750 | console.error('try 到错误了', e) 751 | } 752 | 753 | provider.on('accountsChanged', (accounts) => { 754 | console.log('accountsChanged, accounts = ', accounts) 755 | if (!accounts || !accounts.length || accounts.length === 0) { 756 | return unAuthed() 757 | } 758 | authed(accounts[0]) 759 | }) 760 | 761 | provider.on('chainChanged', (chainId) => { 762 | console.log('chainChanged called', chainId) 763 | getElement('chainId').innerHTML = chainId 764 | }) 765 | 766 | connectButton.onclick = async () => { 767 | const data = await provider.request({ 768 | method: 'cfx_accounts', 769 | params: [ 770 | { 771 | availableNetwork: [1, 1029], 772 | scopes: ['baseInfo', 'identity'], 773 | phone: phoneInput.value, 774 | }, 775 | ], 776 | }) 777 | const { chainId, networkId, address: alreadyAuthedAddresses, code } = data 778 | console.log( 779 | 'DApp 获取到的授权结果', 780 | chainId, 781 | networkId, 782 | alreadyAuthedAddresses, 783 | code 784 | ) 785 | setState(data) 786 | getElement('initialized').innerHTML = 'initialized' 787 | getElement('chainId').innerHTML = chainId 788 | getElement('networkId').innerHTML = networkId 789 | 790 | if ( 791 | !alreadyAuthedAddresses || 792 | !alreadyAuthedAddresses.length || 793 | alreadyAuthedAddresses.length === 0 794 | ) { 795 | unAuthed() 796 | } else { 797 | authed(alreadyAuthedAddresses[0], code) 798 | } 799 | } 800 | 801 | DeauthorizeButton.onclick = () => { 802 | provider 803 | .request({ 804 | method: 'exit_accounts', 805 | }) 806 | .then(unAuthed) 807 | .catch(console.error) 808 | } 809 | logoutButton.onclick = () => { 810 | provider 811 | .request({ 812 | method: 'anyweb_logout', 813 | }) 814 | .then(unAuthed) 815 | .catch(console.error) 816 | } 817 | 818 | getCFXButton.onclick = async () => { 819 | try { 820 | const connectedAddress = address[0] 821 | const tx = { 822 | from: connectedAddress, 823 | to: confluxFaucetAddress, 824 | data: confluxFaucetContract.claimCfx().data, 825 | } 826 | console.log('getCFX tx', tx) 827 | provider 828 | .request({ method: 'cfx_sendTransaction', params: [tx] }) 829 | .then((result) => { 830 | getElement('get_cfx_result').innerHTML = result 831 | console.log('result', result) 832 | }) 833 | .catch((e) => { 834 | getElement('get_cfx_result').innerHTML = ` 835 | Code: ${e.code},\n 836 | Message: ${e.message},\n 837 | Data: ${JSON.stringify(e.data)}\n 838 | ` 839 | console.error('获取CFX失败', e) 840 | }) 841 | } catch (err) { 842 | console.log('err', err) 843 | } 844 | } 845 | gatewayTestButton.onclick = async () => { 846 | try { 847 | const connectedAddress = address[0] 848 | console.log('connectedAddress', connectedAddress) 849 | const payload = { 850 | from: connectedAddress, 851 | to: networkId === 1029 ? onlineAddress : dappAddress, 852 | data: dappContract.test('0x', '0x').data, 853 | abi: abi.filter( 854 | (item) => item.type === 'function' && item.name === 'test' 855 | )[0], 856 | } 857 | 858 | const gatewayPayload = { 859 | data: '123', 860 | data1: '456', 861 | } 862 | 863 | provider 864 | .request({ 865 | method: 'cfx_sendTransaction', 866 | params: [payload, gatewayPayload], 867 | }) 868 | .then((result) => { 869 | getElement('gateway_test_result').innerHTML = result 870 | console.log('result', result) 871 | }) 872 | .catch((e) => { 873 | getElement('gateway_test_result').innerHTML = ` 874 | Code: ${e.code},\n 875 | Message: ${e.message},\n 876 | Data: ${e.data}\n 877 | ` 878 | console.error('合约调用失败', { message: e.message, data: e.data }) 879 | }) 880 | } catch (err) { 881 | console.log('err', err) 882 | } 883 | } 884 | 885 | signButton.onclick = async () => { 886 | try { 887 | const from = address[0] 888 | console.log('connectedAddress', from) 889 | provider 890 | .request({ 891 | method: 'cfx_signTypedData', 892 | params: [from, JSON.stringify(msgParams)], 893 | }) 894 | .then((result) => { 895 | getElement('sign_result').innerHTML = JSON.stringify(result) 896 | console.log('result', result) 897 | }) 898 | .catch((e) => { 899 | getElement('sign_result').innerHTML = ` 900 | Code: ${e.code},\n 901 | Message: ${e.message},\n 902 | Data: ${e.data}\n 903 | ` 904 | console.error('签名失败', { message: e.message, data: e.data }) 905 | }) 906 | } catch (err) { 907 | console.log('err', err) 908 | } 909 | } 910 | 911 | personalSignButton.onclick = async () => { 912 | try { 913 | const from = address[0] 914 | console.log('connectedAddress', from) 915 | provider 916 | .request({ 917 | method: 'cfx_personalSign', 918 | params: [from, '0x123'], 919 | }) 920 | .then((result) => { 921 | getElement('personal_sign_result').innerHTML = JSON.stringify(result) 922 | console.log('result', result) 923 | }) 924 | .catch((e) => { 925 | getElement('personal_sign_result').innerHTML = ` 926 | Code: ${e.code},\n 927 | Message: ${e.message},\n 928 | Data: ${e.data}\n 929 | ` 930 | console.error('签名失败', { message: e.message, data: e.data }) 931 | }) 932 | } catch (err) { 933 | console.log('err', err) 934 | } 935 | } 936 | 937 | deployContract.onclick = async () => { 938 | try { 939 | const connectedAddress = address[0] 940 | 941 | const tx = { 942 | from: connectedAddress, 943 | data: exampleContract.constructor('Example', 18, 'EP', 10000).data, 944 | } 945 | provider 946 | .request({ method: 'cfx_sendTransaction', params: [tx] }) 947 | .then((result) => { 948 | getElement('deploy_contract_result').innerHTML = result 949 | console.log('result', result) 950 | }) 951 | } catch (err) { 952 | console.log('err', err) 953 | } 954 | } 955 | 956 | importAddressButton.onclick = async () => { 957 | if (importAddressInput.value.replace(/\s+/g, '') === '') { 958 | getElement('import_address_result').innerHTML = 'valid Params' 959 | return 960 | } 961 | const addressLength = importAddressInput.value.split(',').length 962 | const addressName = importAddressNameInput.value 963 | .split(',') 964 | .filter((name) => name !== '') 965 | const addressNamesLength = addressName.length 966 | console.log('addressNamesLength', addressNamesLength) 967 | if (addressNamesLength > 0 && addressNamesLength !== addressLength) { 968 | getElement('import_address_result').innerHTML = 969 | 'address length not equal to address name length' 970 | return 971 | } 972 | try { 973 | const tx = { 974 | address: importAddressInput.value.replace(/\s+/g, '').split(','), 975 | addressName: addressName, 976 | } 977 | provider 978 | .request({ method: 'anyweb_importAccount', params: [tx] }) 979 | .then((result) => { 980 | getElement('import_address_result').innerHTML = result 981 | console.log('result', result) 982 | }) 983 | } catch (err) { 984 | console.log('err', err) 985 | } 986 | } 987 | 988 | identifyButton.onclick = async () => { 989 | try { 990 | provider 991 | .request({ method: 'anyweb_identify', params: [] }) 992 | .then((result) => { 993 | getElement('identify_result').innerHTML = result 994 | console.log('result', result) 995 | }) 996 | } catch (err) { 997 | console.log('err', err) 998 | } 999 | } 1000 | 1001 | checkLoginButton.onclick = async () => { 1002 | try { 1003 | provider 1004 | .request({ method: 'anyweb_loginstate', params: [] }) 1005 | .then((result) => { 1006 | getElement('checklogin_result').innerHTML = result 1007 | console.log('result', result) 1008 | }) 1009 | } catch (err) { 1010 | console.log('err', err) 1011 | } 1012 | } 1013 | } 1014 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // collectCoverage: true, 3 | coverageDirectory: './coverage', 4 | coverageReporters: ['html'], 5 | 6 | testEnvironment: 'node', 7 | testRegex: 'test/.*test.js', 8 | preset: 'ts-jest', 9 | } 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@idealight-labs/anyweb-js-sdk", 3 | "description": "AnyWeb JavaScript Software Development Kit", 4 | "version": "1.3.6", 5 | "license": "LGPL-3.0", 6 | "author": "common@idealight.ltd", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/IdeaLightLabs/AnyWeb-JS-SDK.git" 10 | }, 11 | "keywords": [ 12 | "anyweb", 13 | "sdk" 14 | ], 15 | "main": "dist/src/index.js", 16 | "types": "dist/src/index.d.ts", 17 | "browser": "dist/src/index.js", 18 | "browserify-browser": { 19 | "secp256k1": "secp256k1/elliptic" 20 | }, 21 | "files": [ 22 | "dist", 23 | "src", 24 | "lib", 25 | "types", 26 | "anyweb-js-sdk.umd.min.js" 27 | ], 28 | "browserslit": "cover 99.5%", 29 | "dependencies": { 30 | "@commitlint/config-conventional": "^16.0.0", 31 | "@conflux-dev/conflux-address-js": "^1.3.12", 32 | "abi-util-lite": "^0.1.0", 33 | "big.js": "^5.2.2", 34 | "commander": "^8.0.0", 35 | "conventional-changelog-cli": "^2.2.2", 36 | "js-conflux-sdk": "^2.0.0", 37 | "keccak": "^2.0.0", 38 | "node-forge": "^1.2.1", 39 | "rlp": "^2.2.7", 40 | "scrypt-js": "^3.0.1", 41 | "secp256k1": "^3.7.1", 42 | "superagent": "^6.1.0", 43 | "typescript": "^4.5.5", 44 | "websocket": "^1.0.31" 45 | }, 46 | "devDependencies": { 47 | "@babel/core": "^7.8.4", 48 | "@babel/plugin-transform-runtime": "^7.8.3", 49 | "@babel/preset-env": "^7.8.4", 50 | "@babel/preset-typescript": "^7.16.7", 51 | "@babel/runtime": "^7.8.4", 52 | "@commitlint/cli": "^16.1.0", 53 | "@commitlint/config-angular": "^16.0.0", 54 | "@types/jest": "^27.4.0", 55 | "@types/node": "^14.0.23", 56 | "@types/node-forge": "^1.0.0", 57 | "@typescript-eslint/eslint-plugin": "^5.10.2", 58 | "@typescript-eslint/parser": "^5.10.2", 59 | "babel-plugin-lodash": "^3.3.4", 60 | "babelify": "^10.0.0", 61 | "browserify": "^16.5.1", 62 | "commitizen": "^4.2.4", 63 | "concurrently": "^5.1.0", 64 | "cz-conventional-changelog": "^3.3.0", 65 | "eslint": "^7.12.0", 66 | "eslint-config-airbnb-base": "^14.0.0", 67 | "eslint-config-prettier": "^8.3.0", 68 | "eslint-plugin-import": "^2.18.2", 69 | "eslint-plugin-prettier": "^4.0.0", 70 | "exorcist": "^1.0.1", 71 | "fs-extra": "^8.1.0", 72 | "husky": "^7.0.0", 73 | "jest": "^27.4.7", 74 | "jsbi": "^3.1.4", 75 | "jsdoc-to-markdown": "^7.1.0", 76 | "minify-stream": "^2.0.1", 77 | "mold-source-map": "^0.4.0", 78 | "prettier": "^2.5.1", 79 | "solc": "^0.6.10", 80 | "standard-version": "^9.3.2", 81 | "ts-jest": "^27.1.3", 82 | "tsify": "^5.0.4", 83 | "typedoc": "^0.22.11", 84 | "typedoc-plugin-markdown": "^3.11.12" 85 | }, 86 | "resolutions": { 87 | "tinyify/acorn-node/acorn": "7.1.1", 88 | "eslint/espree/acorn": "7.1.1", 89 | "tinyify/unassertify/unassert/acorn": "7.1.1", 90 | "**/minimist": "^1.2.3", 91 | "**/kind-of": "^6.0.3", 92 | "**/elliptic": "^6.5.3", 93 | "**/lodash": "^4.17.20", 94 | "**/babel-jest": "^26.6.0", 95 | "jest/jest-cli/jest-config/jest-environment-jsdom/jsdom/acorn-globals/acorn": "6.4.1" 96 | }, 97 | "scripts": { 98 | "lint": "eslint ./src ./test", 99 | "lint:fix": "eslint ./src ./test --fix", 100 | "build": "node scripts/build-frontend.js", 101 | "document": "typedoc --plugin typedoc-plugin-markdown --out docs/api/ src/index.ts", 102 | "prepublishOnly": "npm run build:lib && npm run build", 103 | "test": "jest --coverage", 104 | "build:lib": "tsc", 105 | "dev": "tsc --watch", 106 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1", 107 | "commit": "git cz", 108 | "release": "standard-version --release-as", 109 | "prepare": "husky install" 110 | }, 111 | "config": { 112 | "commitizen": { 113 | "path": "./node_modules/cz-conventional-changelog" 114 | } 115 | }, 116 | "bugs": { 117 | "url": "https://github.com/IdeaLightLabs/AnyWeb-JS-SDK/issues" 118 | }, 119 | "homepage": "https://github.com/IdeaLightLabs/AnyWeb-JS-SDK#readme", 120 | "directories": { 121 | "example": "example", 122 | "lib": "lib", 123 | "test": "test" 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /scripts/build-frontend.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const minify = require('minify-stream') 3 | const { mkdirpSync } = require('fs-extra') 4 | const browserify = require('browserify') 5 | const babelify = require('babelify') 6 | const fs = require('fs') 7 | const exorcist = require('exorcist') 8 | const mold = require('mold-source-map') 9 | const tsify = require('tsify') 10 | 11 | const browserifyOptions = { 12 | browserField: 'browserify-browser', 13 | entries: ['./src/index.ts'], 14 | debug: true, // gen inline sourcemap to extract with exorcist 15 | standalone: 'AnyWeb', // generate a umd file to load directly into browser 16 | } 17 | 18 | const OUTPUT_FILE_NAME = 'anyweb-js-sdk' 19 | 20 | mkdirpSync('dist') 21 | 22 | // use babel to remove unused lodash code 23 | // https://www.blazemeter.com/blog/the-correct-way-to-import-lodash-libraries-a-benchmark/ 24 | const babelTransform = babelify.configure({ 25 | presets: ['@babel/preset-env'], 26 | plugins: [ 27 | 'lodash', 28 | [ 29 | '@babel/plugin-transform-runtime', 30 | { 31 | regenerator: true, 32 | }, 33 | ], 34 | ], 35 | }) 36 | 37 | browserify(browserifyOptions) 38 | .plugin(tsify) 39 | .transform(babelTransform) 40 | .bundle() 41 | .pipe(minify()) 42 | .pipe(mold.transformSourcesRelativeTo(path.resolve(__dirname, '../'))) 43 | .pipe(exorcist(`./dist/${OUTPUT_FILE_NAME}.umd.min.js.map`)) 44 | .pipe(fs.createWriteStream(`./dist/${OUTPUT_FILE_NAME}.umd.min.js`)) 45 | -------------------------------------------------------------------------------- /scripts/document.mjs: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import { sep, resolve } from "path"; 3 | import { 4 | parseExportedFunctionsAsync, 5 | renderFunctionDataToMarkdown 6 | } from "generate-ts-docs"; 7 | import { exec } from "child_process"; 8 | 9 | const __dirname = resolve(); 10 | // function generateMarkdown(filters, apiName) { 11 | // const markdown = jsdocToMd(`${__dirname}/../lib`, { 12 | // filter: (filename) => { 13 | // console.log('FILTER', filename) 14 | // if (lodash.some(filters, (suffix) => filename.endsWith(suffix))) { 15 | // console.log(`File "${filename}" parsing...`) // eslint-disable-line no-console 16 | // return true 17 | // } 18 | // return false 19 | // }, 20 | // }) 21 | // 22 | // fs.writeFileSync(`${__dirname}/../docs/api/${apiName}.md`, `${markdown}`) 23 | // } 24 | async function generateMarkdown(files, apiName) { 25 | files = files.map( 26 | item => { 27 | return `${__dirname}/src${item}`; 28 | } 29 | ); 30 | await exec( 31 | `rm -ls ${__dirname}/docs/api/*.md | grep -v ${__dirname}/docs/api/README.txt`); 32 | await 33 | fs.writeFileSync(`${__dirname}/docs/api/${apiName}.md`, `${markdown}`); 34 | } 35 | 36 | const APIs = [ 37 | { 38 | name: "Index", 39 | files: [`${sep}index.ts`] 40 | }, 41 | { 42 | name: "Provider", 43 | files: [`${sep}provider.ts`] 44 | } 45 | ]; 46 | 47 | for (const API of APIs) { 48 | generateMarkdown(API.files, API.name); 49 | } 50 | -------------------------------------------------------------------------------- /scripts/jsdoc-to-md.js: -------------------------------------------------------------------------------- 1 | const jsdoc2md = require('jsdoc-to-markdown') 2 | const fs = require('fs') 3 | 4 | const DOC_FOLDER = './docs/api/' 5 | 6 | const files = [ 7 | { 8 | source: './src/rpc/txpool.js', 9 | name: 'txpool.md', 10 | }, 11 | { 12 | source: './src/rpc/pos.js', 13 | name: 'PoS.md', 14 | }, 15 | ] 16 | 17 | async function renderFile(fileMeta) { 18 | const result = await jsdoc2md.render({ files: fileMeta.source }) 19 | fs.writeFileSync(`${DOC_FOLDER}${fileMeta.name}`, result) 20 | } 21 | 22 | async function main() { 23 | for (const file of files) { 24 | await renderFile(file) 25 | } 26 | } 27 | 28 | main().catch(console.error) 29 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from './provider' 2 | 3 | module.exports = { 4 | Provider, 5 | } 6 | export { Provider } 7 | -------------------------------------------------------------------------------- /src/interface/provider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Littleor 3 | * @since 2022/2/4 4 | */ 5 | import { ConsoleLike } from '../utils/types' 6 | 7 | /** 8 | * Request Args 9 | */ 10 | export interface IRequestArguments { 11 | readonly method: string 12 | readonly params?: unknown[] 13 | readonly chainId?: number 14 | } 15 | 16 | export interface IBaseProviderOptions { 17 | logger?: ConsoleLike | null 18 | appId: string 19 | global?: boolean 20 | } 21 | 22 | /** 23 | * Base Provider 24 | */ 25 | export interface IProvider { 26 | /** 27 | * Request 28 | * @param args {IRequestArguments} Request Arguments: {method, params} 29 | * @returns {Promise} 30 | */ 31 | request(args: IRequestArguments): Promise 32 | 33 | /** 34 | * monitor information 35 | * @param type {string} monitor type 36 | * @param listener {Function} callback 37 | */ 38 | on(type: string, listener: (...args: any[]) => void): void 39 | } 40 | 41 | /** 42 | * @author Littleor 43 | * @since 2022/2/18 44 | */ 45 | 46 | export interface IAuthResult { 47 | chainId: number 48 | networkId: number 49 | address: string[] 50 | url: string 51 | code: string 52 | scopes: string[] 53 | } 54 | 55 | export interface IProviderRpcError extends Error { 56 | message: string 57 | code: number 58 | data?: unknown 59 | } 60 | 61 | export interface IProviderConnectInfo { 62 | readonly chainId: string 63 | } 64 | 65 | export interface IProviderMessage { 66 | readonly type: string 67 | readonly data: unknown 68 | } 69 | 70 | export type IMethodType = 71 | | 'account' 72 | | 'createContract' 73 | | 'callContract' 74 | | 'createTransaction' 75 | | 'importAccount' 76 | | 'exitAccounts' 77 | | 'signTypedData' 78 | | 'logout' 79 | | 'checkAuth' 80 | | 'checkLogin' 81 | | 'home' 82 | | 'unknownType' 83 | | 'identify' 84 | | 'checkIdentify' 85 | | 'personalSign' 86 | 87 | export interface IIframeOptions { 88 | appId: string 89 | params: string 90 | chainId: number 91 | scopes?: string[] 92 | waitResult?: boolean 93 | silence?: boolean 94 | } 95 | 96 | export interface IIframeData { 97 | type: 'event' | 'callback' | 'router' | 'default' 98 | data: unknown 99 | success?: boolean 100 | message?: string 101 | code: number 102 | } 103 | 104 | export interface IIframeEventData { 105 | type: 'changeNetwork' | 'changeChain' 106 | data: unknown 107 | } 108 | 109 | export type IRequestParams = 110 | | IRequestParamsAccounts 111 | | { payload: IPayload; gatewayPayload?: IGatewayPayload } 112 | | IPayload 113 | 114 | export interface IRequestParamsAccounts { 115 | scopes: string[] 116 | 117 | [key: string]: unknown 118 | } 119 | 120 | export interface IPayload { 121 | to: string 122 | 123 | [key: string]: unknown 124 | } 125 | 126 | export interface IGatewayPayload { 127 | [key: string]: unknown 128 | } 129 | -------------------------------------------------------------------------------- /src/provider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Littleor 3 | * @since 2022/2/2 4 | */ 5 | 6 | import { 7 | IAuthResult, 8 | IBaseProviderOptions, 9 | IIframeData, 10 | IMethodType, 11 | IProvider, 12 | IProviderConnectInfo, 13 | IProviderMessage, 14 | IProviderRpcError, 15 | IRequestArguments, 16 | } from './interface/provider' 17 | import { 18 | callIframe, 19 | createIframe, 20 | isObject, 21 | ProviderErrorCode, 22 | ProviderRpcError, 23 | } from './utils/common' 24 | import config from '../package.json' 25 | import { AddressType, getAddressType } from './utils/address' 26 | import { ConsoleLike } from './utils/types' 27 | 28 | /** 29 | * AnyWeb Provider 30 | * @class Provider 31 | * @author Littleor 32 | * @since 2020/2/2 33 | * @example 34 | * const provider = new Provider() 35 | */ 36 | export class Provider implements IProvider { 37 | logger: ConsoleLike | null = console 38 | public readonly appId!: string 39 | private chainId = 1 40 | private static instance: Provider 41 | public static ready = false 42 | appUrl 43 | 44 | events: { 45 | onConnect?: (connectInfo: IProviderConnectInfo) => void 46 | onDisconnect?: (error: IProviderRpcError) => void 47 | onChainChanged?: (chainId: string) => void 48 | onAccountsChanged?: (accounts: string[]) => void 49 | onMessage?: (message: IProviderMessage) => void 50 | onNetworkChanged?: (networkId: string) => void 51 | onReady?: () => void 52 | } = {} 53 | 54 | constructor( 55 | { logger = console, appId, global = false }: IBaseProviderOptions, 56 | appUrl = 'https://app.anyweb.cc/#/' 57 | ) { 58 | if (global) { 59 | appUrl = 'https://global.app.anyweb.cc/#/' 60 | } 61 | if (Provider.instance) { 62 | return Provider.instance 63 | } 64 | Provider.instance = this 65 | 66 | this.logger = logger 67 | this.appId = appId 68 | this.appUrl = appUrl 69 | 70 | // bind functions (to prevent consumers from making unbound calls) 71 | this.request = this.request.bind(this) 72 | this.call = this.call.bind(this) 73 | this.send = this.call.bind(this) 74 | this.enable = this.enable.bind(this) 75 | 76 | if (typeof window !== 'undefined') { 77 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 78 | // @ts-ignore 79 | window.anyweb = this 80 | } 81 | 82 | const messageHandler = (event: MessageEvent) => { 83 | if ( 84 | event.data && 85 | isObject(event.data) && 86 | 'type' in event.data && 87 | event.data.type === 'anyweb' 88 | ) { 89 | const IframeData = event.data.data as IIframeData 90 | if ( 91 | IframeData.type == 'event' && 92 | IframeData.data == 'ready' && 93 | IframeData.success 94 | ) { 95 | this.logger?.debug('[AnyWeb] SDK初始化完成') 96 | Provider.ready = true 97 | this.events.onReady && this.events.onReady() 98 | window.removeEventListener('message', messageHandler) 99 | } 100 | } 101 | } 102 | window.addEventListener('message', messageHandler) 103 | 104 | createIframe('pages/index/home', this.appUrl, this.logger) 105 | .then() 106 | .catch((e) => this.logger?.error('[AnyWeb] createIframe error', e)) 107 | } 108 | 109 | public static getInstance(params?: IBaseProviderOptions) { 110 | if (!Provider.instance) { 111 | if (params) { 112 | Provider.instance = new Provider(params) 113 | } else { 114 | throw new ProviderRpcError( 115 | ProviderErrorCode.SDKNotReady, 116 | 'Provider is not initialized' 117 | ) 118 | } 119 | } 120 | return Provider.instance 121 | } 122 | 123 | /** 124 | * Deprecated: use `request` instead 125 | * @param arg 126 | */ 127 | async send(...arg: any[]) { 128 | this.logger?.info('[AnyWeb] `send` is deprecated, use `request` instead') 129 | if (arg.length > 1) { 130 | return await this.request({ method: arg[0], params: arg[1] }) 131 | } 132 | throw new ProviderRpcError( 133 | ProviderErrorCode.ParamsError, 134 | 'Invalid arguments' 135 | ) 136 | } 137 | 138 | /** 139 | * Deprecated: use `request` instead 140 | * @param arg 141 | */ 142 | async call(...arg: any[]) { 143 | this.logger?.info( 144 | '[AnyWeb] `call` is deprecated, use `request` instead', 145 | arg 146 | ) 147 | if (arg.length > 1) { 148 | return await this.request({ method: arg[0], params: arg[1] }) 149 | } else { 150 | return this.enable() 151 | } 152 | } 153 | 154 | /** 155 | * Submits an RPC request 156 | * @param args {IRequestArguments} Request Arguments: {method, params} 157 | * @returns {Promise} 158 | * @example 159 | * const result = await provider.request({ method: 'cfx_sendTransaction', params}) 160 | */ 161 | async request(args: IRequestArguments): Promise { 162 | if (!args || typeof args !== 'object' || Array.isArray(args)) { 163 | throw new ProviderRpcError( 164 | ProviderErrorCode.ParamsError, 165 | 'Invalid request arguments' 166 | ) 167 | } 168 | const { method, params } = args 169 | if (!method || method.trim().length === 0) { 170 | throw new ProviderRpcError( 171 | ProviderErrorCode.ParamsError, 172 | 'Invalid request arguments: Method is required' 173 | ) 174 | } 175 | 176 | this.logger?.debug(`[AnyWeb] request ${method} with`, params) 177 | const result = await this.rawRequest(method, params) 178 | this.logger?.debug(`[AnyWeb] request(${method}):`, result) 179 | return result 180 | } 181 | 182 | /** 183 | * Deprecated: use `request` instead 184 | */ 185 | public async enable() { 186 | return await this.request({ 187 | method: 'cfx_requestAccounts', 188 | }) 189 | } 190 | 191 | /** 192 | * Submits an RPC request 193 | * @param method 194 | * @param params 195 | * @protected 196 | */ 197 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 198 | protected async rawRequest( 199 | method: string, 200 | params: any[] = [] 201 | ): Promise { 202 | if (!Provider.ready) { 203 | throw new ProviderRpcError( 204 | ProviderErrorCode.SDKNotReady, 205 | "Provider is not ready, please use on('ready', callback) to listen to ready event" 206 | ) 207 | } 208 | try { 209 | switch (method) { 210 | case 'cfx_requestAccounts': 211 | return this.rawRequest('cfx_accounts') 212 | case 'cfx_accounts': 213 | this.logger?.debug('[AnyWeb]', { params }) 214 | const scopes = params[0].scopes 215 | let result: IAuthResult 216 | try { 217 | result = (await callIframe( 218 | 'checkAuth', 219 | { 220 | appId: this.appId, 221 | params: params ? params[0] : {}, 222 | chainId: this.chainId, 223 | scopes: scopes, 224 | silence: true, 225 | }, 226 | this 227 | )) as IAuthResult 228 | this.logger?.debug('[AnyWeb]', 'silent auth result', result) 229 | } catch (e) { 230 | this.logger?.debug('[AnyWeb]', 'need to auth', e) 231 | result = (await callIframe( 232 | 'account', 233 | { 234 | appId: this.appId, 235 | params: params ? params[0] : {}, 236 | chainId: this.chainId, 237 | scopes: scopes, 238 | }, 239 | this 240 | )) as IAuthResult 241 | } 242 | 243 | result.scopes = scopes 244 | this.events.onAccountsChanged && 245 | this.events.onAccountsChanged(result.address) 246 | this.events.onChainChanged && 247 | this.events.onChainChanged(String(result.chainId)) 248 | this.events.onNetworkChanged && 249 | this.events.onNetworkChanged(String(result.networkId)) 250 | if (scopes.length > 0) { 251 | return { 252 | address: result.address, 253 | code: result.code, 254 | scopes: scopes, 255 | chainId: result.chainId, 256 | networkId: result.networkId, 257 | } 258 | } else { 259 | return false 260 | } 261 | case 'cfx_signTypedData': 262 | const from = params[0] 263 | const data = params[1] 264 | return await callIframe( 265 | 'signTypedData', 266 | { 267 | appId: this.appId, 268 | chainId: this.chainId, 269 | params: params 270 | ? JSON.stringify({ 271 | from, 272 | data, 273 | }) 274 | : '', 275 | }, 276 | this 277 | ) 278 | case 'cfx_personalSign': 279 | return await callIframe( 280 | 'personalSign', 281 | { 282 | appId: this.appId, 283 | chainId: this.chainId, 284 | params: params 285 | ? JSON.stringify({ 286 | from: params[0], 287 | message: params[1], 288 | }) 289 | : '', 290 | }, 291 | this 292 | ) 293 | case 'cfx_sendTransaction': 294 | let authType: IMethodType 295 | const payload = params[0] 296 | const to = payload.to 297 | if (to) { 298 | authType = 299 | getAddressType(to, this.logger) === AddressType.CONTRACT 300 | ? 'callContract' 301 | : 'createTransaction' 302 | } else { 303 | authType = 'createContract' 304 | } 305 | 306 | return await callIframe( 307 | authType, 308 | { 309 | appId: this.appId, 310 | chainId: this.chainId, 311 | params: params 312 | ? JSON.stringify({ 313 | payload: params[0], 314 | gatewayPayload: params[1], 315 | }) 316 | : '', 317 | }, 318 | this 319 | ) 320 | case 'anyweb_importAccount': 321 | return await callIframe( 322 | 'importAccount', 323 | { 324 | appId: this.appId, 325 | chainId: this.chainId, 326 | params: params ? params[0] : {}, 327 | }, 328 | this 329 | ) 330 | case 'anyweb_version': 331 | return config.version 332 | case 'anyweb_home': 333 | return await callIframe( 334 | 'home', 335 | { 336 | appId: this.appId, 337 | chainId: this.chainId, 338 | params: params ? JSON.stringify(params) : '', 339 | waitResult: false, 340 | }, 341 | this 342 | ) 343 | case 'exit_accounts': 344 | return this.rawRequest('anyweb_revoke', params) 345 | case 'anyweb_revoke': 346 | return await callIframe( 347 | 'exitAccounts', 348 | { 349 | appId: this.appId, 350 | chainId: this.chainId, 351 | params: params ? JSON.stringify(params) : '', 352 | silence: true, 353 | }, 354 | this 355 | ) 356 | case 'anyweb_identify': 357 | let identifyResult 358 | try { 359 | identifyResult = await callIframe( 360 | 'checkIdentify', 361 | { 362 | appId: this.appId, 363 | chainId: this.chainId, 364 | params: params ? JSON.stringify(params) : '', 365 | silence: true, 366 | }, 367 | this 368 | ) 369 | this.logger?.debug( 370 | '[AnyWeb]', 371 | 'Check identify result', 372 | identifyResult 373 | ) 374 | } catch (e) { 375 | this.logger?.debug('[AnyWeb]', 'need to identify', e) 376 | identifyResult = await callIframe( 377 | 'identify', 378 | { 379 | appId: this.appId, 380 | chainId: this.chainId, 381 | params: params ? JSON.stringify(params) : '', 382 | }, 383 | this 384 | ) 385 | } 386 | return identifyResult 387 | case 'anyweb_logout': 388 | // Logout the account of AnyWeb 389 | return await callIframe( 390 | 'logout', 391 | { 392 | appId: this.appId, 393 | chainId: this.chainId, 394 | params: params ? JSON.stringify(params) : '', 395 | silence: true, 396 | }, 397 | this 398 | ) 399 | case 'anyweb_loginstate': 400 | try { 401 | return await callIframe( 402 | 'checkLogin', 403 | { 404 | appId: this.appId, 405 | params: '', 406 | chainId: this.chainId, 407 | silence: true, 408 | }, 409 | this 410 | ) 411 | } catch (e) { 412 | this.logger?.debug('[AnyWeb]', 'need to login', e) 413 | return false 414 | } 415 | default: 416 | throw new ProviderRpcError( 417 | ProviderErrorCode.UnsupportedMethod, 418 | 'Unsupported Method: ' + method 419 | ) 420 | } 421 | } catch (e: any) { 422 | // const codeList = { 423 | // cfx_sendTransaction: ProviderErrorCode.SendTransactionError, 424 | // anyweb_importAccount: ProviderErrorCode.ImportAddressError, 425 | // } 426 | this.logger?.info(`Error when handler request '${method}'!`) 427 | throw new ProviderRpcError( 428 | ProviderErrorCode.RequestError, 429 | isObject(e) && 'message' in e ? e.message : e, 430 | isObject(e) && 'data' in e ? e.data : {} 431 | ) 432 | } 433 | } 434 | 435 | /** 436 | * Monitor information 437 | * @param type {string} Type of information 438 | * @param listener {Function} Event listener 439 | * @example 440 | * provider.on('connected', listener) 441 | */ 442 | on(type: string, listener: (...args: any[]) => void): void { 443 | this.logger?.debug('[AnyWeb] on', { 444 | type, 445 | listener, 446 | }) 447 | switch (type) { 448 | case 'connect': 449 | this.events.onConnect = listener 450 | break 451 | case 'disconnect': 452 | this.events.onDisconnect = listener 453 | break 454 | case 'chainChanged': 455 | this.events.onChainChanged = listener 456 | break 457 | case 'accountsChanged': 458 | this.events.onAccountsChanged = listener 459 | break 460 | case 'message': 461 | this.events.onMessage = listener 462 | break 463 | case 'networkChanged': 464 | this.events.onNetworkChanged = listener 465 | break 466 | case 'ready': 467 | this.events.onReady = listener 468 | break 469 | default: 470 | break 471 | } 472 | } 473 | } 474 | -------------------------------------------------------------------------------- /src/utils/address.ts: -------------------------------------------------------------------------------- 1 | import { decode } from '@conflux-dev/conflux-address-js' 2 | import { ConsoleLike } from './types' 3 | 4 | export enum AddressType { 5 | USER = 'user', 6 | CONTRACT = 'contract', 7 | BUILTIN = 'builtin', 8 | NULL = 'null', 9 | } 10 | 11 | /** 12 | * Get the type of an address. 13 | * @param address 14 | * @param logger 15 | */ 16 | export const getAddressType = ( 17 | address: string, 18 | logger: ConsoleLike | null = console 19 | ): AddressType => { 20 | const decodeResult = decode(address) 21 | logger?.debug('[AnyWeb] decodeResult', decodeResult) 22 | if (Object.keys(decodeResult).includes('type')) { 23 | return decodeResult.type as AddressType 24 | } else { 25 | return AddressType.USER 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/utils/common.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Littleor 3 | * @since 2022/2/11 4 | */ 5 | import * as forge from 'node-forge' 6 | import { 7 | IIframeData, 8 | IIframeEventData, 9 | IIframeOptions, 10 | IMethodType, 11 | IProviderRpcError, 12 | } from '../interface/provider' 13 | import { Provider } from '../provider' 14 | import { ConsoleLike } from './types' 15 | import config from '../../package.json' 16 | 17 | export const getFrameWidth = () => { 18 | if (window.innerHeight < 736) { 19 | return ((window.innerHeight - 18) * 9.0) / 16.0 20 | } else { 21 | return 414 22 | } 23 | } 24 | 25 | export const getFrameHeight = () => { 26 | if (window.innerHeight < 736) { 27 | return window.innerHeight - 18 28 | } else { 29 | return 736 30 | } 31 | } 32 | 33 | /** 34 | * Check the window width to decide whether to show in full screen 35 | */ 36 | export const isFullScreen = () => { 37 | return window.innerWidth < 500 38 | } 39 | 40 | /** 41 | * SHA512加密 42 | * @param str 43 | */ 44 | export function sha512(str: string) { 45 | const md = forge.md.sha512.create() 46 | md.update(str) 47 | return md.digest().toHex() 48 | } 49 | 50 | const setBodyNonScrollable = () => { 51 | document.body.style.overflow = 'hidden' 52 | const scrollTop = 53 | document.body.scrollTop || document.documentElement.scrollTop 54 | document.body.style.cssText += 55 | 'position:fixed;width:100%;top:-' + scrollTop + 'px;' 56 | document.addEventListener( 57 | 'touchmove', 58 | (e) => { 59 | e.stopPropagation() 60 | }, 61 | { passive: false } 62 | ) 63 | } 64 | 65 | const setBodyScrollable = () => { 66 | document.body.style.overflow = '' 67 | document.body.style.position = '' 68 | const top = document.body.style.top 69 | document.body.scrollTop = document.documentElement.scrollTop = -parseInt(top) 70 | document.body.style.top = '' 71 | 72 | document.removeEventListener('touchmove', (e) => { 73 | e.stopPropagation() 74 | }) 75 | } 76 | 77 | export const isObject = (obj: unknown) => { 78 | return Object.prototype.toString.call(obj) === '[object Object]' 79 | } 80 | 81 | const closeIframe = (root: HTMLDivElement, logger?: ConsoleLike) => { 82 | logger?.debug('[AnyWeb]', 'closeIframe', root.style) 83 | setBodyScrollable() 84 | root.style.visibility = 'hidden' 85 | } 86 | export const sendMessageToApp = ({ 87 | data, 88 | type, 89 | success = true, 90 | code = 0, 91 | }: IIframeData) => { 92 | const iframe: HTMLIFrameElement | null = document.getElementById( 93 | 'anyweb-iframe' 94 | ) as HTMLIFrameElement | null 95 | if (!iframe) { 96 | return 97 | } 98 | sendMessage(iframe.contentWindow, { data, type, success, code }) 99 | } 100 | 101 | export const sendMessage = ( 102 | localWindow: any, 103 | { data, type, success = true, code = 0, message }: IIframeData 104 | ) => { 105 | return ( 106 | localWindow && 107 | localWindow.postMessage( 108 | { 109 | data: { 110 | data, 111 | type, 112 | success, 113 | code, 114 | message, 115 | }, 116 | type: 'anyweb', 117 | }, 118 | '*' 119 | ) 120 | ) 121 | } 122 | 123 | export const createIframe = async ( 124 | url: string, 125 | appUrl: string, 126 | logger?: ConsoleLike | null 127 | ) => { 128 | logger?.debug('[AnyWeb] createIframe', url) 129 | const mask = document.createElement('div') 130 | const div = document.createElement('div') 131 | const iframe = document.createElement('iframe') 132 | const button = document.createElement('div') 133 | const style = document.createElement('style') 134 | style.innerHTML = ` 135 | .iframe::-webkit-scrollbar{ 136 | visibility: hidden; 137 | } 138 | .iframe-mask { 139 | position: fixed; 140 | top: 0; 141 | left: 0; 142 | width: 100%; 143 | height: 100%; 144 | background-color: rgba(247, 247, 247, 0.8); 145 | z-index: 99999; 146 | } 147 | .iframe-contain { 148 | position: fixed; 149 | z-index: 999999999; 150 | ${ 151 | isFullScreen() 152 | ? ` 153 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); 154 | border-radius: 15px;` 155 | : '' 156 | } 157 | 158 | width: ${isFullScreen() ? '100%' : `${getFrameWidth()}px`}; 159 | height: ${isFullScreen() ? '100%' : `${getFrameHeight()}px`}; 160 | transform: translate(-50%, -50%); 161 | top: 50%; 162 | left: 50%; 163 | } 164 | 165 | .iframe { 166 | border-radius: ${isFullScreen() ? '0' : '15px'}; 167 | height: 100%; 168 | width: 100%; 169 | z-index: 999999; 170 | overflow-x: hidden; 171 | } 172 | 173 | .iframe-contain-button { 174 | border-radius: 9px; 175 | width: 18px; 176 | height: 18px; 177 | z-index: 9999999; 178 | position: absolute; 179 | top: 36px; 180 | right: 36px; 181 | cursor: pointer; 182 | } 183 | 184 | .iframe-contain-button:before { 185 | position: absolute; 186 | content: ''; 187 | width: 2px; 188 | height: 24px; 189 | background: black; 190 | top: 50%; 191 | left: 50%; 192 | transform: translate(-50%, -50%) rotate(45deg); 193 | } 194 | 195 | .iframe-contain-button:after { 196 | content: ''; 197 | position: absolute; 198 | width: 2px; 199 | height: 24px; 200 | background: black; 201 | transform: translate(-50%, -50%) rotate(-45deg); 202 | top: 50%; 203 | left: 50%; 204 | }` 205 | mask.className = 'iframe-mask' 206 | div.className = 'iframe-contain' 207 | button.className = 'iframe-contain-button' 208 | iframe.className = 'iframe' 209 | 210 | iframe.id = 'anyweb-iframe' 211 | mask.id = 'anyweb-iframe-mask' 212 | 213 | document.body.appendChild(style) 214 | document.body.insertBefore(mask, document.body.firstElementChild) 215 | 216 | iframe.setAttribute('style', 'height: 100%; width: 100%;') 217 | iframe.setAttribute('src', `${appUrl}${url}`) 218 | iframe.setAttribute('frameborder', '0') 219 | iframe.setAttribute('scrolling', 'no') 220 | 221 | div.insertBefore(iframe, div.firstElementChild) 222 | !isFullScreen() && mask.insertBefore(button, mask.firstElementChild) 223 | mask.insertBefore(div, mask.firstElementChild) 224 | // Hide before call the method 225 | mask.style.visibility = 'hidden' 226 | // setBodyScrollable() 227 | 228 | button.onclick = () => { 229 | closeIframe(mask) 230 | window && 231 | sendMessage(window, { 232 | data: {}, 233 | type: 'callback', 234 | message: 'User canceled the operation', 235 | code: ProviderErrorCode.Unauthorized, 236 | success: false, 237 | }) 238 | } 239 | } 240 | 241 | export const getIframe = async ( 242 | method: IMethodType, 243 | appUrl: string, 244 | params: Record, 245 | onClose: () => void, 246 | silence = false, 247 | logger?: ConsoleLike 248 | ): Promise<() => void> => { 249 | if ( 250 | !( 251 | document.getElementById('anyweb-iframe-mask') && 252 | document.getElementById('anyweb-iframe') 253 | ) 254 | ) { 255 | logger?.warn('[AnyWeb] Something wrong with the iframe, recreating...') 256 | await createIframe('', appUrl) 257 | } 258 | sendMessageToApp({ 259 | type: 'event', 260 | data: { 261 | params: { ...params, version: config.version }, 262 | method: method, 263 | }, 264 | code: 0, 265 | }) 266 | const mask = document.getElementById('anyweb-iframe-mask') as HTMLDivElement 267 | if (!silence) { 268 | setTimeout(() => { 269 | mask.style.visibility = 'visible' 270 | setBodyNonScrollable() 271 | }, 300) 272 | } 273 | return () => { 274 | onClose() 275 | if (!silence) { 276 | closeIframe(mask) 277 | } 278 | } 279 | } 280 | 281 | export const callIframe = async ( 282 | method: IMethodType, 283 | { 284 | appId, 285 | params, 286 | chainId, 287 | scopes = [], 288 | waitResult = true, 289 | silence = false, 290 | }: IIframeOptions, 291 | provider: Provider 292 | ) => { 293 | if (waitResult) { 294 | return new Promise(async (resolve, reject) => { 295 | let callback: IIframeData | undefined = undefined 296 | const close = await getIframe( 297 | method, 298 | provider.appUrl!, 299 | { 300 | appId, 301 | authType: method, 302 | random: Math.floor(Math.random() * 1000), 303 | chainId, 304 | params, 305 | scopes, 306 | }, 307 | () => { 308 | if (timer) { 309 | clearTimeout(timer) 310 | } 311 | }, 312 | silence 313 | ) 314 | const timer = setTimeout(() => { 315 | close() 316 | reject({ 317 | code: ProviderErrorCode.SDKTimeOut, 318 | message: 'Timeout', 319 | data: {}, 320 | }) 321 | }, 10 * 60 * 1000) 322 | 323 | // Set Listeners 324 | window.addEventListener( 325 | 'message', 326 | function receiveMessageFromIframePage(event) { 327 | if ( 328 | event.data && 329 | isObject(event.data) && 330 | 'type' in event.data && 331 | event.data.type === 'anyweb' 332 | ) { 333 | provider.logger?.debug('[AnyWeb] SDK收到子页面信息: ', event.data) 334 | callback = event.data.data as IIframeData 335 | 336 | if (callback.type === 'callback') { 337 | window.removeEventListener( 338 | 'message', 339 | receiveMessageFromIframePage 340 | ) 341 | clearTimeout(timer) 342 | close() 343 | if (callback.success) { 344 | resolve(callback.data) 345 | } else { 346 | reject({ 347 | code: callback.code, 348 | message: callback.message as string, 349 | data: callback.data || {}, 350 | }) 351 | } 352 | } else if (callback.type === 'event') { 353 | const eventData = callback.data as IIframeEventData 354 | switch (eventData.type) { 355 | case 'changeNetwork': 356 | provider.events.onNetworkChanged && 357 | provider.events.onNetworkChanged(String(eventData.data)) 358 | break 359 | case 'changeChain': 360 | provider.events.onChainChanged && 361 | provider.events.onChainChanged(String(eventData.data)) 362 | break 363 | default: 364 | break 365 | } 366 | } 367 | } 368 | }, 369 | false 370 | ) 371 | }) 372 | } else { 373 | await getIframe( 374 | method, 375 | provider.appUrl!, 376 | { 377 | appId, 378 | authType: method, 379 | random: Math.floor(Math.random() * 1000), 380 | chainId, 381 | params, 382 | scopes, 383 | }, 384 | () => { 385 | return 386 | }, 387 | silence 388 | ) 389 | return 'ok' 390 | } 391 | } 392 | 393 | export const writeStorage = ( 394 | key: string, 395 | content: Record, 396 | expiresTime: number = 5 * 60 * 1000 397 | ) => { 398 | window.localStorage && 399 | window.localStorage.setItem( 400 | `anyweb_${key}`, 401 | JSON.stringify({ 402 | ...content, 403 | expires: expiresTime + new Date().getTime(), 404 | }) 405 | ) 406 | } 407 | 408 | export const isArrEqual = (arr1: T[], arr2: T[]) => { 409 | return arr1.length === arr2.length && arr1.every((ele) => arr2.includes(ele)) 410 | } 411 | 412 | export const isIncluded = (arr1: T[], arr2: T[]): boolean => { 413 | return arr1.length === new Set([...arr1, ...arr2]).size 414 | } 415 | 416 | export enum ProviderErrorCode { 417 | UserRejectedRequest = 4001, 418 | Unauthorized = 4100, 419 | UnsupportedMethod = 4200, 420 | Disconnected = 4900, 421 | ChainDisconnected = 4901, 422 | SDKNotReady = 5000, 423 | SDKTimeOut = 5001, 424 | ParamsError = 6000, 425 | RequestError = 7000, 426 | SendTransactionError = 7001, 427 | ImportAddressError = 7002, 428 | } 429 | 430 | export class ProviderRpcError extends Error implements IProviderRpcError { 431 | code: number 432 | data?: unknown 433 | 434 | constructor( 435 | code: ProviderErrorCode, 436 | message: string, 437 | data = {}, 438 | logger: ConsoleLike = console 439 | ) { 440 | super(message) 441 | logger.error( 442 | `[AnyWeb] Throw the error(${code}):`, 443 | '\n Message: ', 444 | message, 445 | '\n Data: ', 446 | data 447 | ) 448 | this.code = code 449 | this.name = ProviderErrorCode[code] 450 | this.data = data 451 | } 452 | } 453 | -------------------------------------------------------------------------------- /src/utils/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Littleor 3 | * @since 2022/2/4 4 | */ 5 | export type ConsoleLike = Pick< 6 | Console, 7 | 'log' | 'warn' | 'error' | 'debug' | 'info' | 'trace' 8 | > 9 | -------------------------------------------------------------------------------- /test/provider.test.js: -------------------------------------------------------------------------------- 1 | const { Provider } = require('../src/provider') 2 | 3 | test( 4 | 'Provider', 5 | async () => { 6 | const provider = new Provider({ 7 | logger: console, 8 | }) 9 | expect(provider.constructor.name).toEqual('Provider') 10 | 11 | await expect(provider.request({})).rejects.toThrow('Method is required') 12 | 13 | await expect(provider.request(1)).rejects.toThrow( 14 | 'Invalid request arguments' 15 | ) 16 | }, 17 | 60 * 1000 18 | ) 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "esModuleInterop": true, 14 | "module": "commonjs", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": false, 18 | "jsx": "preserve", 19 | "types": [], 20 | "outDir": "./dist", 21 | "declaration": true 22 | }, 23 | "include": [ 24 | "src" 25 | ], 26 | "exclude": [ 27 | "node_modules" 28 | ] 29 | } 30 | --------------------------------------------------------------------------------