├── .github └── workflows │ └── gh-pages.yml ├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── babel.config.js ├── docs ├── default-wallet.md ├── ethereum │ ├── _category_.json │ ├── builtin-chains.md │ ├── custom-chains.md │ ├── overview.md │ ├── provider-api │ │ ├── _category_.json │ │ ├── errors.md │ │ ├── events.md │ │ ├── methods.md │ │ └── properties.md │ ├── rpc-api │ │ ├── _category_.json │ │ ├── methods.md │ │ └── overview.md │ ├── use-cases │ │ ├── _category_.json │ │ ├── adding-custom-tokens.md │ │ ├── adding-evm-compatible-chains.md │ │ ├── connecting-your-site.md │ │ ├── local-development-environment.md │ │ ├── sending-transactions.md │ │ ├── signing-data.md │ │ └── switching-evm-compatible-chains.md │ └── wallet-detection.md ├── intro.md ├── provider-availability.md ├── provider-objects.md └── solana │ ├── _category_.json │ ├── overview.md │ └── provider-api │ ├── _category_.json │ ├── errors.md │ ├── events.md │ ├── methods.md │ ├── properties.md │ └── provider-detection.md ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── renovate.json ├── sidebars.js ├── src ├── components │ ├── AddChain.js │ ├── HomepageFeatures.js │ ├── HomepageFeatures.module.css │ └── connect.js ├── css │ └── custom.css └── pages │ ├── index.module.css │ └── markdown-page.md └── static ├── .nojekyll ├── CNAME └── img ├── brave128.png ├── brave32.png ├── docusaurus.png ├── favicon.png ├── logo.svg ├── tutorial ├── docsVersionDropdown.png └── localeDropdown.png ├── undraw_docusaurus_mountain.svg ├── undraw_docusaurus_react.svg └── undraw_docusaurus_tree.svg /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | build-publish: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: write 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ github.ref }} 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 19 | 20 | - name: Setup Node.js 18.x 21 | uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 22 | with: 23 | node-version: 18.x 24 | cache: npm 25 | 26 | - name: Install dependencies 27 | run: npm install 28 | 29 | - name: Audit dependencies 30 | if: ${{ github.actor != 'dependabot[bot]' && github.actor != 'renovate[bot]' }} 31 | run: npm audit 32 | 33 | - name: Build website 34 | run: npm run build 35 | 36 | - name: Deploy to GitHub Pages 37 | uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 38 | if: ${{ github.ref == 'refs/heads/main' }} 39 | with: 40 | github_token: ${{ secrets.GITHUB_TOKEN }} 41 | publish_dir: ./build 42 | user_name: brave-builds[bot] 43 | user_email: brave-builds@brave.com 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | build 107 | .docusaurus 108 | .DS_Store 109 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.singleQuote": true, 3 | "prettier.jsxSingleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | View the live Brave Wallet documentation site at https://wallet-docs.brave.com/ 4 | 5 | The Brave Wallet documentation website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 6 | 7 | ### Installation 8 | 9 | ``` 10 | $ npm install 11 | ``` 12 | 13 | ### Local Development 14 | 15 | ``` 16 | $ npm start 17 | ``` 18 | 19 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 20 | 21 | ### Build 22 | 23 | ``` 24 | $ npm run build 25 | ``` 26 | 27 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 28 | 29 | ### Deployment 30 | 31 | ``` 32 | $ GIT_USER= USE_SSH=true npm run deploy 33 | ``` 34 | 35 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 36 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/default-wallet.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Default Wallet setting 6 | 7 | We expose a setting in `brave://settings/wallet` to control how Brave makes the provider objects available (`window.ethereum` and `window.braveSolana` and its alias `window.solana`) 8 | 9 | Since extensions sometimes also provide these objects, this setting will help decide which wallet handles these objects. 10 | 11 | Here's a description of each setting: 12 | - `Extensions (Brave Wallet fallback)` - This is the default. Brave Wallet will expose `window.ethereum` and `window.braveSolana` but allow other extensions such as MetaMask to overwrite it. 13 | - `Brave Wallet` - Exposes `window.ethereum` and `window.braveSolana` and prevents sites and extensions from changing them. 14 | - `Extensions (no fallback)` - `window.ethereum` and `window.braveSolana` will not be provided by Brave Wallet at all. If you have enabled an extension such as MetaMask, it is free to use the provider object. 15 | - `Crypto Wallets (Deprecated)` - Gives access to the old deprecated wallet. This option is not compatible with other extensions such as MetaMask. 16 | 17 | After changing the default wallet, it is best to restart your browser. Why? 18 | - If you had Brave Wallet loaded, it won't be unloaded until the next restart. When Brave Wallet is loaded it will not work properly with other extensions trying to access `window.ethereum`. 19 | - Existing tabs (ones already opened) will not change to use the new wallet setting, you need a new tab or a browser restart. 20 | -------------------------------------------------------------------------------- /docs/ethereum/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Ethereum", 3 | "position": 5 4 | } 5 | -------------------------------------------------------------------------------- /docs/ethereum/builtin-chains.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Built-in chains 6 | 7 | Brave preloads the following EVM chains by default. Unless otherwise specified, 8 | the entries in the table are mainnet chains. 9 | 10 | | Chain ID | Name | Native currency | 11 | | ----------- | ---------------------------------- | --------------- | 12 | | 0x1 | Ethereum | ETH | 13 | | 0x89 | Polygon | MATIC | 14 | | 0x38 | BNB Smart Chain | BNB | 15 | | 0xa86a | Avalanche C-Chain | AVAX | 16 | | 0x4e454152 | Aurora | ETH | 17 | | 0xfa | Fantom | FTM | 18 | | 0xa | Optimism | ETH | 19 | | 0x13a | Filecoin (FEVM) | FIL | 20 | | 0x5 | Görli Testnet | ETH | 21 | | 0xaa36a7 | Sepolia Testnet | ETH | 22 | | 0x4cb2f | Filecoin (EVM) Calibration Testnet | tFIL | 23 | -------------------------------------------------------------------------------- /docs/ethereum/custom-chains.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | import AddChain from '../../src/components/AddChain' 6 | 7 | # Custom chains 8 | 9 | You can add custom networks by navigating to `brave://settings/wallet/networks` 10 | and clicking on the "Add" button. You can enter the network details manually or 11 | search through a list of networks sourced from [chainlist.org](https://chainlist.org). 12 | This list is updated on a daily basis and served through user data files of 13 | the browser. 14 | 15 | **Troubleshooting note:** Normally, a browser restart is enough to ensure that 16 | you're using the latest networks list, if not already the case. Alternatively, 17 | you can force-check for new updates by going to `brave://components` and 18 | clicking on "Check for update" under "Brave Wallet data files". 19 | 20 | You can also add custom chains through sites like [chainlist.org](https://chainlist.org). 21 | Examples of the UX for adding custom chains through external websites can be 22 | found below: 23 | 24 | | Chain ID | Name | Native currency | Decimals | Add | 25 | | ----------- | -------------------- | --------------- | -------- | ------ | 26 | | 0xa4b1 | Arbitrum One | AETH | 18 | 27 | | 0x2105 | Base | ETH | 18 | 28 | -------------------------------------------------------------------------------- /docs/ethereum/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: /ethereum 4 | --- 5 | 6 | # Overview 7 | 8 | Brave injects a `window.ethereum` provider object on secure sites [in these cases](/provider-availability). 9 | 10 | This object is defined by [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). 11 | 12 | The in-page provider will not be provided by Brave in private and Tor window. 13 | 14 | This object gives websites the ability to: 15 | - Make requests to an Ethereum node (or a compatible network) to read data from the blockchain 16 | - Request permission to view the addresses associated with one or more of the Ethereum accounts in the user's wallet 17 | - Ask the user (if given permission previously) to sign / submit a transaction 18 | - Ask the user (if given permission previously) to sign a message 19 | -------------------------------------------------------------------------------- /docs/ethereum/provider-api/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Ethereum Provider API", 3 | "position": 6 4 | } 5 | -------------------------------------------------------------------------------- /docs/ethereum/provider-api/errors.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Errors 6 | 7 | Provider errors come in the form of a `ProviderRpcError` object: 8 | 9 | ```ts 10 | interface ProviderRpcError extends Error { 11 | message: string; 12 | code: number; 13 | data?: unknown; 14 | } 15 | ``` 16 | 17 | For a full list of errors, see [EIP-1474](https://eips.ethereum.org/EIPS/eip-1474#error-codes). 18 | -------------------------------------------------------------------------------- /docs/ethereum/provider-api/events.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Events 6 | 7 | ## `connect` 8 | 9 | The Provider emits connect when it: 10 | 11 | - first connects to a chain after being initialized. 12 | - first connects to a chain, after the disconnect event was emitted. 13 | 14 | ```ts 15 | interface ProviderConnectInfo { 16 | readonly chainId: string; 17 | } 18 | ``` 19 | 20 | ```ts 21 | Provider.on('connect', listener: (connectInfo: ProviderConnectInfo) => void): Provider; 22 | ``` 23 | 24 | ## `disconnect` 25 | 26 | The Provider emits disconnect when it becomes disconnected from all chains. 27 | 28 | ```ts 29 | Provider.on('disconnect', listener: (error: ProviderRpcError) => void): Provider; 30 | ``` 31 | 32 | ## `chainChanged` 33 | 34 | The Provider emits chainChanged when connecting to a new chain. 35 | 36 | ```ts 37 | Provider.on('chainChanged', listener: (chainId: string) => void): Provider; 38 | ``` 39 | 40 | ## `accountsChanged` 41 | 42 | The Provider emits accountsChanged if the accounts returned from the Provider (eth_accounts) change. 43 | 44 | ```ts 45 | Provider.on('accountsChanged', listener: (accounts: string[]) => void): Provider; 46 | ``` 47 | 48 | ## `message` 49 | 50 | The `message` event is fired for `eth_subscribe` subscription results. 51 | 52 | Other types of events are possible in the future, so be sure to check the `type` property. 53 | 54 | The event will be emitted with an object argument of the following form: 55 | 56 | ```ts 57 | interface ProviderMessage { 58 | readonly type: string; 59 | readonly data: unknown; 60 | } 61 | ``` 62 | 63 | ## `close` (deprecated) 64 | 65 | Not yet implemented, but Brave may implement it. 66 | This event `close` is superseded by `disconnect`. 67 | 68 | :::danger Deprecated API 69 | 70 | This API is deprecated and not available in Brave Wallet. 71 | 72 | ::: 73 | 74 | 75 | ## `networkChanged` (deprecated) 76 | 77 | Not yet implemented, but Brave may implement it for webcompat reasons. 78 | 79 | The event `networkChanged` is superseded by `chainChanged`. 80 | 81 | :::danger Deprecated API 82 | 83 | This API is deprecated and not available in Brave Wallet. 84 | 85 | ::: 86 | -------------------------------------------------------------------------------- /docs/ethereum/provider-api/methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Methods 6 | 7 | ## `ethereum.request` 8 | 9 | `ethereum.request` is used to submit an RPC request to the remote EVM node. For some methods, the provider itself handles the response. 10 | 11 | ```ts 12 | interface RequestArguments { 13 | readonly method: string; 14 | readonly params?: readonly unknown[] | object; 15 | } 16 | 17 | Provider.request(args: RequestArguments): Promise; 18 | ``` 19 | 20 | The promise either resolves with a response object, or rejects with an [error](errors). 21 | 22 | ## `ethereum.isConnected` 23 | 24 | Returns true if the page is connected to the RPC networks and is able to make RPC requests. 25 | 26 | This method is not related to accounts and if an account has permission for the current page. For that you'd want to use `eth_accounts` to see if an account has permission or `eth_requestAccounts` to ask for permission if permission aren't currently granted. 27 | 28 | ```ts 29 | Provider.isConnected(): boolean; 30 | ``` 31 | 32 | ## `ethereum.enable` (deprecated) 33 | 34 | Allows a website to request permissions. 35 | 36 | This method is superseded by a `ethereum.request` with `eth_requestAccounts`. 37 | 38 | ```ts 39 | Provider.request({ method: 'eth_requestAccounts' }) 40 | ``` 41 | 42 | :::danger Deprecated API 43 | 44 | This API is deprecated but is available in Brave Wallet. 45 | 46 | ::: 47 | 48 | 49 | ## `ethereum.sendAsync` (deprecated) 50 | 51 | ```ts 52 | Provider.sendAsync(request: Object, callback: Function): void; 53 | ``` 54 | 55 | :::danger Deprecated API 56 | 57 | This API is deprecated but is available in Brave Wallet. 58 | This method is superseded by `ethereum.request`. 59 | 60 | ::: 61 | 62 | 63 | 64 | ## `ethereum.send` (deprecated) 65 | 66 | ```ts 67 | Provider.send(...args: unknown[]): unknown; 68 | ``` 69 | 70 | :::danger Deprecated API 71 | 72 | This API is deprecated but is available in Brave Wallet. 73 | This method is superseded by `ethereum.request`. 74 | 75 | ::: 76 | -------------------------------------------------------------------------------- /docs/ethereum/provider-api/properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Properties 6 | 7 | 8 | ## `ethereum.selectedAddress` (deprecated) 9 | 10 | The string address of the first allowed address or undefined if no account is currently allowed. Note that when the keyring is locked it is undefined. Since this property is deprecated, this property is provided for webcompat reasons only. 11 | 12 | :::danger Deprecated API 13 | 14 | This API is deprecated but is available in Brave Wallet. 15 | 16 | ::: 17 | 18 | ## `ethereum.chainId` (deprecated) 19 | 20 | The chain ID of the currently connected network. 21 | Since this property is deprecated, this property is provided for webcompat reasons only. 22 | 23 | :::danger Deprecated API 24 | 25 | This API is deprecated but is available in Brave Wallet. 26 | 27 | ::: 28 | 29 | ## `ethereum.networkVersion` (deprecated) 30 | 31 | A string of the chain ID in base 10. 32 | Since this property is deprecated, this property is provided for webcompat reasons only. 33 | 34 | :::danger Deprecated API 35 | 36 | This API is deprecated but is available in Brave Wallet. 37 | 38 | ::: 39 | 40 | ## `ethereum.isMetaMask` 41 | 42 | Even though there is no shared code with MetaMask, several dapps have become dependent on this property so `true` is returned for this value. -------------------------------------------------------------------------------- /docs/ethereum/rpc-api/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "RPC API", 3 | "position": 7 4 | } 5 | -------------------------------------------------------------------------------- /docs/ethereum/rpc-api/methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Methods 6 | 7 | ## `eth_sendTransaction` 8 | https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction 9 | 10 | ## `eth_signTransaction` 11 | https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction 12 | 13 | ## `eth_sendRawTransaction` 14 | https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction 15 | 16 | ## `eth_subscribe` 17 | 18 | Allows for a new subscription to be created. When a subscription is created, `message` events will be fired with new block information. 19 | 20 | Unlike the [documentation here](https://ethereum.org/en/developers/tutorials/using-websockets/#eth-subscribe), you can use `eth_subscribe` even with an HTTPS RPC URLs configured in Brave Wallet. 21 | Only `newHeads` is currently supported. 22 | 23 | https://ethereum.org/en/developers/tutorials/using-websockets/#eth-subscribe 24 | 25 | 26 | ## `eth_unsubscribe` 27 | 28 | Allows for a previous subscription to be removed. 29 | `message` events will stop being fired after a subscription is unsubscribed. 30 | 31 | https://ethereum.org/en/developers/tutorials/using-websockets/#eth-unsubscribe 32 | 33 | ## `wallet_addEthereumChain` 34 | 35 | `wallet_addEthereumChain` accepts a single object parameter, specified by the following TypeScript interface: 36 | 37 | ```ts 38 | interface AddEthereumChainParameter { 39 | chainId: string; 40 | blockExplorerUrls?: string[]; 41 | chainName?: string; 42 | iconUrls?: string[]; 43 | nativeCurrency?: { 44 | name: string; 45 | symbol: string; 46 | decimals: number; 47 | }; 48 | rpcUrls?: string[]; 49 | } 50 | ``` 51 | 52 | ## `wallet_switchEthereumChain` 53 | 54 | `wallet_switchEthereumChain` accepts a single object parameter, specified by the following TypeScript interface: 55 | 56 | ```ts 57 | interface SwitchEthereumChainParameter { 58 | chainId: string; 59 | } 60 | ``` 61 | 62 | 63 | ## `wallet_watchAsset` 64 | 65 | `wallet_watchAsset` accepts a single object parameter, specified by the following TypeScript interface: 66 | 67 | ```ts 68 | interface WatchAssetParameters { 69 | type: string; // The asset's interface, e.g. 'ERC20' 70 | options: { 71 | address: string; // The hexadecimal Ethereum address of the token contract 72 | symbol?: string; // A ticker symbol or shorthand, up to 5 alphanumerical characters 73 | decimals?: number; // The number of asset decimals 74 | image?: string; // A string url of the token logo 75 | }; 76 | } 77 | ``` 78 | 79 | ## `eth_getEncryptionPublicKey` (deprecated) 80 | 81 | Requests that the user shares their public encryption key. Returns a Promise that resolve to the public encryption key, or rejects if the user denied the request. 82 | 83 | The public key is computed from entropy associated with the specified user account, using the nacl (opens new window)implementation of the X25519_XSalsa20_Poly1305 algorithm. 84 | 85 | 86 | ### Example: 87 | 88 | #### Setup a new wallet: 89 | 90 | ``` 91 | Seed: 92 | home various adjust motion canvas stand combine gravity cluster behave despair dove 93 | 94 | Private key: 95 | 72d388592fb23300948c9eaf2dfaa60b8c3297903f2ea698d489d7c12116e2e6 96 | 97 | Address is: 98 | 0xB884707865B85990e6a140a12C3e5f5D24FE5736 99 | ``` 100 | 101 | 102 | #### Get the public key: 103 | 104 | ```js 105 | var x= await window.ethereum.request({method:'eth_getEncryptionPublicKey', params:['0xB884707865B85990e6a140a12C3e5f5D24FE5736']}) 106 | ``` 107 | 108 | Check the value of `x`: 109 | > 
`'eui9/fqCHT7aSUkKK9eooQFnOCD9COK9Mi1ZtOxIj2A='` 110 | 111 | 112 | #### Run these commands in a test directory:
 113 | 114 | ``` 115 | npm install @metamask/eth-sig-util 116 | npm install ethereumjs-util 117 | 118 | And then run this script:
 119 | ```js 120 | const ethUtil = require('ethereumjs-util'); 121 | const sigUtil = require('@metamask/eth-sig-util'); 122 | 123 | const encryptedMessage = ethUtil.bufferToHex( 124 | Buffer.from( 125 | JSON.stringify( 126 | sigUtil.encrypt({ 127 | publicKey: 'eui9/fqCHT7aSUkKK9eooQFnOCD9COK9Mi1ZtOxIj2A=', 128 | data: 'Ode to Anthony!', 129 | version: 'x25519-xsalsa20-poly1305', 130 | }) 131 | ), 132 | 'utf8' 133 | ) 134 | ); 135 | ``` 136 | 137 | #### In UI: 138 | 139 | If you then check the value of `encryptedMessage` you'll see: 140 | 141 | ``` 142 | '0x7b2276657273696f6e223a227832353531392d7873616c736132302d706f6c7931333035222c226e6f6e6365223a2232666f7254336e4350425279653944654d31515375574e385776475a5670584e222c22657068656d5075626c69634b6579223a226d6a67655235324a4347446c393333367551774e3239716b62595230574c4b4367696e42504446747958593d222c2263697068657274657874223a22653378704b703276476d70643965634f6a524a36786c7456723046656f2b506d2f432f67544d437944673d3d227d' 143 | ``` 144 | 145 | You can get back at the string with: 146 | 147 | ```js 148 | JSON.parse(Buffer.from('7b2276657273696f6e223a227832353531392d7873616c736132302d706f6c7931333035222c226e6f6e6365223a2232666f7254336e4350425279653944654d31515375574e385776475a5670584e222c22657068656d5075626c69634b6579223a226d6a67655235324a4347446c393333367551774e3239716b62595230574c4b4367696e42504446747958593d222c2263697068657274657874223a22653378704b703276476d70643965634f6a524a36786c7456723046656f2b506d2f432f67544d437944673d3d227d', 'hex')) 149 | ``` 150 | Which gives: 151 | ``` 152 | { 153 | version: 'x25519-xsalsa20-poly1305', 154 | nonce: '2forT3nCPBRye9DeM1QSuWN8WvGZVpXN', 155 | ephemPublicKey: 'mjgeR52JCGDl9336uQwN29qkbYR0WLKCginBPDFtyXY=', 156 | ciphertext: 'e3xpKp2vGmpd9ecOjRJ6xltVr0Feo+Pm/C/gTMCyDg==' 157 | } 158 | ``` 159 | 160 | #### Issuing the decrypt command 161 | 162 | Finally run the decrypt command with your encrypted string: 163 | 164 | ```js 165 | const encryptedMessage = '0x7b2276657273696f6e223a227832353531392d7873616c736132302d706f6c7931333035222c226e6f6e6365223a2232666f7254336e4350425279653944654d31515375574e385776475a5670584e222c22657068656d5075626c69634b6579223a226d6a67655235324a4347446c393333367551774e3239716b62595230574c4b4367696e42504446747958593d222c2263697068657274657874223a22653378704b703276476d70643965634f6a524a36786c7456723046656f2b506d2f432f67544d437944673d3d227d' 166 | ethereum 167 | .request({ 168 | method: 'eth_decrypt', 169 | params: [encryptedMessage, '0xB884707865B85990e6a140a12C3e5f5D24FE5736'] 170 | }) 171 | .then((decryptedMessage) => 172 | console.log('The decrypted message is:', decryptedMessage) 173 | ) 174 | .catch((error) => console.log(error.message)); 175 | ``` 176 | 177 | It will popup the UI to decrypt the message for the user. And if you press approve it will send it back to the Dapp. Check the JS console in dev tools to see. 178 | 179 | ## `eth_decrypt` (deprecated) 180 | 181 | This method requests that Brave Wallet decrypts the given encrypted message. 182 | 183 | Parameters: 184 | - A serialized JSON object which is base64 encoded and contains amongst other things the encrypted message and the seed 185 | - The ethereum account that can decrypt the message as the second. 186 | 187 | 188 | If the user doesn't approve, then the operation results in an error (user rejected). 189 | The user can peak at the data at any time to see what the encrypted blob contains before decrypting it to the dapp. 190 | The decrypted message is only returned to the Dapp if the decrypt request is approved. 191 | Since this is not trusted content, when decrypting the message, Brave will sanitize first, then parse the JSON object. 192 | 193 | The message must have been encrypted using the public encryption key of the given Ethereum address. See also `eth_getEncryptionPublicKey`. 194 | This method returns a Promise that resolves to the decrypted message, or rejects if the decryption attempt fails. 195 | -------------------------------------------------------------------------------- /docs/ethereum/rpc-api/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Overview 6 | -------------------------------------------------------------------------------- /docs/ethereum/use-cases/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Use cases", 3 | "position": 5 4 | } 5 | -------------------------------------------------------------------------------- /docs/ethereum/use-cases/adding-custom-tokens.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # Adding custom tokens 6 | 7 | [EIP-747](https://eips.ethereum.org/EIPS/eip-747) allows Dapps to request that a token be added. 8 | 9 | ```js 10 | async function addAsset() { 11 | return await ethereum.request({ 12 | method: 'wallet_watchAsset', 13 | params: { 14 | type: 'ERC20', 15 | options: { 16 | address: '0xb60e8dd61c5d32be8058bb8eb970870f07233155', 17 | symbol: 'FOO', 18 | decimals: 18, 19 | image: 'https://foo.io/token-image.svg', 20 | }, 21 | }, 22 | }) 23 | } 24 | console.log(await addAsset()) 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/ethereum/use-cases/adding-evm-compatible-chains.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Adding EVM compatible chains 6 | 7 | Websites can request that alternate chains be added by using the `wallet_addEthereumChain` method. 8 | 9 | ```js 10 | async function addEthereumChain() { 11 | const params = [{ 12 | chainId: '0x38', 13 | chainName: 'Binance1 Smart Chain', 14 | nativeCurrency: { 15 | name: 'BNB', 16 | symbol: 'BNB', 17 | decimals: 18 18 | }, 19 | rpcUrls: ['https://bsc-dataseed.binance.org/'], 20 | iconUrls: [], 21 | blockExplorerUrls: ['https://bscscan.com/'], 22 | }] 23 | return await window.ethereum.request({ method: 'wallet_addEthereumChain', params }) 24 | } 25 | console.log(await addEthereumChain()); 26 | ``` 27 | 28 | After a chain is added, a switch request is shown to the user to switch to the new chain. 29 | -------------------------------------------------------------------------------- /docs/ethereum/use-cases/connecting-your-site.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Connecting your site 6 | 7 | import Connect from '../../../src/components/connect' 8 | 9 | Websites can call: 10 | 11 | ```ts 12 | async function connectSite() { 13 | return await window.ethereum.request({ method: 'eth_requestAccounts' }) 14 | } 15 | console.log(await connectSite()) 16 | ``` 17 | 18 | 19 | 20 | to make a request for permissions to an account. 21 | 22 | # More info 23 | The user is asked to confirm which, if any, of the wallet's accounts should be visible to the website. 24 | For those allowed accounts, the website will be able to see the corresponding account address. 25 | 26 | The website will also be able to ask the user to approve (sign / send) transactions and to sign data. 27 | Signing transactions and messages require separate user confirmations after the initial account approval. 28 | 29 | Permissions can be revoked in `brave://settings/content/ethereum`. 30 | A user can also open up the wallet panel and disconnect a connected site when they are on that site. 31 | 32 | If a wallet is not yet setup and a page requests permissions, Brave opens `brave://wallet` for the user to setup the wallet. 33 | 34 | # Brave logos 35 | 36 | Download Brave logo package 37 | -------------------------------------------------------------------------------- /docs/ethereum/use-cases/local-development-environment.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Local development environment 6 | 7 | With [Ganache](https://trufflesuite.com/ganache/) you can quickly fire up a personal Ethereum blockchain which you can use to run tests, execute commands, and inspect state while controlling how the chain operates. 8 | 9 | [Truffle](https://trufflesuite.com/truffle/) can be used for smart contract management, testing, deployment and migrations 10 | -------------------------------------------------------------------------------- /docs/ethereum/use-cases/sending-transactions.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Sending transactions 6 | 7 | These requests will need to be approved by users in order to sign transactions. 8 | 9 | ## eth_sendTransaction 10 | 11 | Sites can request that a transaction be signed / sent by using the `eth_sendTransaction` method. 12 | 13 | 14 | ```js 15 | async function sendTransaction() { 16 | const accounts = await window.ethereum.request({ 17 | id: '191', 18 | method: 'eth_accounts', 19 | params: [], 20 | }) 21 | if (accounts.length === 0) { 22 | console.log('No accounts allowed') 23 | return 24 | } 25 | const from = accounts[0] 26 | const params = [{ 27 | from, 28 | // Change this to a different address 29 | to: from, 30 | value: '0x16345785D8A0000' 31 | // data: '0x...' 32 | // 33 | // Gas propeties are not needed, but if you specify them, 34 | // you can use either: 35 | // `maxPriorityFeePerGas` 36 | // `maxFeePerGas` 37 | // or 38 | // `gasPrice` 39 | }] 40 | 41 | return await window.ethereum.request({ 42 | method: 'eth_sendTransaction', 43 | params 44 | }) 45 | } 46 | console.log(await sendTransaction()) 47 | ``` 48 | 49 | For more information, see: https://eth.wiki/json-rpc/API#eth_sendtransaction 50 | 51 | ## eth_signTransaction and eth_sendRawTransaction 52 | 53 | Sites can request that a transaction be signed by `eth_signTransaction` method 54 | and send signed transaction later through `eth_sendRawTransaction` or other 55 | preferred methods. 56 | 57 | ```js 58 | async function signAndSendTransaction() { 59 | const accounts = await window.ethereum.request({ 60 | id: '191', 61 | method: 'eth_accounts', 62 | params: [], 63 | }) 64 | if (accounts.length === 0) { 65 | console.log('No accounts allowed') 66 | return 67 | } 68 | const from = accounts[0] 69 | const params = [{ 70 | from, 71 | // Change this to a different address 72 | to: from, 73 | value: '0x16345785D8A0000' 74 | // data: '0x...' 75 | // 76 | // Gas propeties are not needed, but if you specify them, 77 | // you can use either: 78 | // `maxPriorityFeePerGas` 79 | // `maxFeePerGas` 80 | // or 81 | // `gasPrice` 82 | }] 83 | 84 | const signedTransaction = await window.ethereum.request({ 85 | method: 'eth_signTransaction', 86 | params 87 | }) 88 | 89 | return await window.ethereum.request({ 90 | method: 'eth_sendRawTransaction, 91 | params: [ signedTransaction ] 92 | }) 93 | } 94 | console.log(await signAndSendTransaction()) 95 | ``` 96 | For more information, see: https://eth.wiki/json-rpc/API#eth_signtransaction 97 | and 98 | https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction 99 | -------------------------------------------------------------------------------- /docs/ethereum/use-cases/signing-data.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Signing data 6 | 7 | Signing data can be done with: 8 | 9 | - `eth_sign` 10 | - `personal_sign` 11 | - `signTypedData_v3` 12 | - `signTypedData_v4` 13 | 14 | Brave does not plan to implement: 15 | 16 | - `signTypedData` 17 | - `signTypedData_v1` (same as `signTypedData`) 18 | 19 | These methods are part of the same draft and are superseded. 20 | 21 | ## eth_sign 22 | 23 | The sign method computes a signature with: 24 | 25 | `sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))` 26 | 27 | The added prefix prevents malicious DApps from signing arbitrary data (e.g. transaction) and then using the signature to impersonate the victim. 28 | 29 | Note the address to sign with must be connected to the Dapp. If the wallet is locked it will ask to be unlocked first. 30 | 31 | ```js 32 | async function sign() { 33 | const accounts = await window.ethereum.request({ 34 | id: '191', 35 | method: 'eth_accounts', 36 | params: [], 37 | }) 38 | if (accounts.length === 0) { 39 | console.log('No accounts allowed') 40 | return 41 | } 42 | const from = accounts[0] 43 | // This hex is ascii for 'hello world' 44 | const message = '0x68656c6c6f20776f726c64' 45 | const params = [from, message] 46 | return await window.ethereum.request({ 47 | method: 'eth_sign', 48 | params 49 | }) 50 | } 51 | console.log(await sign()); 52 | ``` 53 | 54 | ## personal_sign 55 | 56 | The sign method computes a signature with: 57 | 58 | `sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))` 59 | 60 | The added prefix prevents malicious DApps from signing arbitrary data (e.g. transaction) and then using the signature to impersonate the victim. 61 | 62 | Note the address to sign with must be connected to the Dapp. If the wallet is locked it will ask to be unlocked first. 63 | 64 | MetaMask shipped this method with a bug that had the params in wrong order. For this reason MetaMask (and therefore Brave to be compatible) allows the params to be passed in the wrong order. If that is done, then Brave (as does MetaMask) tries to determine the correct ordering of the params based on trying to detect which one is an address. 65 | 66 | ```js 67 | async function personalSign() { 68 | const accounts = await window.ethereum.request({ 69 | id: '191', 70 | method: 'eth_accounts', 71 | params: [], 72 | }) 73 | if (accounts.length === 0) { 74 | console.log('No accounts allowed') 75 | return 76 | } 77 | const from = accounts[0] 78 | // This hex is ascii for 'hello world' 79 | const message = '0x68656c6c6f20776f726c64' 80 | const params = [message, from] 81 | return await window.ethereum.request({ 82 | method: 'personal_sign', 83 | params 84 | }) 85 | } 86 | console.log(await personalSign()); 87 | ``` 88 | 89 | ## signTypedData_v3 90 | 91 | ```js 92 | async function signTypedData_v3(method, messageInput) { 93 | const message = { 94 | "types":{ 95 | "EIP712Domain":[ 96 | {"name":"name","type":"string"}, 97 | {"name":"version","type":"string"}, 98 | {"name":"chainId","type":"uint256"}, 99 | {"name":"verifyingContract","type":"address"}], 100 | "Person":[ 101 | {"name":"name","type":"string"}, 102 | {"name":"wallet","type":"address"}], 103 | "Mail":[ 104 | {"name":"from","type":"Person"}, 105 | {"name":"to","type":"Person"}, 106 | {"name":"contents","type":"string"}]}, 107 | "primaryType":"Mail", 108 | "domain":{ 109 | "name":"Ether Mail", 110 | "version":"1", 111 | "chainId":1, 112 | "verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"}, 113 | "message":{ 114 | "from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"}, 115 | "to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"}, 116 | "contents":"Hello, Bob!" 117 | } 118 | } 119 | const accounts = await window.ethereum.request({ 120 | id: '191', 121 | method: 'eth_accounts', 122 | params: [], 123 | }) 124 | if (accounts.length === 0) { 125 | console.log('No accounts allowed') 126 | return 127 | } 128 | 129 | const from = accounts[0] 130 | const params = [from, JSON.stringify(message)] 131 | return await window.ethereum.request({ 132 | method: 'eth_signTypedData_v3', 133 | params 134 | }) 135 | } 136 | console.log(await signTypedData_v3()) 137 | ``` 138 | 139 | ## signTypedData_v4 140 | 141 | ```js 142 | async function signTypedData_v4(method, messageInput) { 143 | const message = { 144 | "types":{ 145 | "EIP712Domain":[ 146 | {"name":"name","type":"string"}, 147 | {"name":"version","type":"string"}, 148 | {"name":"chainId","type":"uint256"}, 149 | {"name":"verifyingContract","type":"address"}], 150 | "Person":[ 151 | {"name":"name","type":"string"}, 152 | {"name":"wallet","type":"address"}], 153 | "Mail":[ 154 | {"name":"from","type":"Person"}, 155 | {"name":"to","type":"Person[]"}, 156 | {"name":"contents","type":"string"}]}, 157 | "primaryType":"Mail", 158 | "domain":{ 159 | "name":"Ether Mail", 160 | "version":"1", 161 | "chainId":1, 162 | "verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"}, 163 | "message":{ 164 | "from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"}, 165 | "to": [ 166 | {"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"}, 167 | {"name":"Alice","wallet":"0xaAaAAAAaaAAAaaaAaaAaaaaAAaAaaaaAaAaaAAaA"}, 168 | ], 169 | "contents":"Hello, Bob & Alice!" 170 | } 171 | } 172 | const accounts = await window.ethereum.request({ 173 | id: '191', 174 | method: 'eth_accounts', 175 | params: [], 176 | }) 177 | if (accounts.length === 0) { 178 | console.log('No accounts allowed') 179 | return 180 | } 181 | const from = accounts[0] 182 | const params = [from, JSON.stringify(message)] 183 | return await window.ethereum.request({ 184 | method: 'eth_signTypedData_v4', 185 | params 186 | }) 187 | } 188 | console.log(await signTypedData_v4()); 189 | ``` 190 | -------------------------------------------------------------------------------- /docs/ethereum/use-cases/switching-evm-compatible-chains.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | --- 4 | 5 | # Switching to EVM compatible chains 6 | 7 | Websites can request that the browser changes to a different chain by using the `wallet_switchEthereumChain` method. 8 | 9 | ```js 10 | async function switchEthereumChain(chainId) { 11 | return await window.ethereum.request({ 12 | method: 'wallet_switchEthereumChain', 13 | params: [{ 14 | chainId 15 | }] 16 | }) 17 | } 18 | console.log(await switchEthereumChain('0x3')) 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/ethereum/wallet-detection.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Brave Wallet detection 6 | 7 | We recommend that Dapps use a Brave Wallet button and that they treat Brave Wallet like MetaMask. 8 | 9 | ## Compatibility with MetaMask 10 | 11 | Since Brave Wallet aims to be compatible with MetaMask's exposed API, we set `window.ethereum.isMetaMask` to `true`. 12 | 13 | ## Brave Wallet Provider injection & detection via library 14 | 15 | Check out these open-source libraries for off-the-shelf solutions 16 | 17 | - [Web3-Onboard](https://github.com/blocknative/web3-onboard) 18 | - [wagmi](https://github.com/tmm/wagmi) 19 | 20 | 21 | ## Synchronous detection 22 | 23 | ```js 24 | const isBraveWallet = window.ethereum.isBraveWallet 25 | console.log('Brave Wallet: ', isBraveWallet) 26 | ``` 27 | 28 | ## Asynchronous detection using `web3_clientVersion` 29 | 30 | ```js 31 | const isBraveWallet = await window.ethereum.request({ 32 | method: 'web3_clientVersion' 33 | }).then((clientVersion) => { 34 | return clientVersion.split('/')[0] === 'BraveWallet' 35 | }) 36 | console.log('Brave Wallet: ', isBraveWallet) 37 | ``` 38 | 39 | Or: 40 | 41 | ```js 42 | const isBraveWallet = await window.ethereum.request({ 43 | method: 'web3_clientVersion' 44 | }).then((clientVersion) => { 45 | return window.ethereum.isMetaMask && clientVersion.split('/')[0] !== 'MetaMask' 46 | }) 47 | console.log('Brave Wallet: ', isBraveWallet) 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: / 4 | --- 5 | 6 | # Intro 7 | 8 | Welcome to Brave Wallet's developer documentation. 9 | 10 | 11 | ## Resources 12 | 13 | - Brave Wallet is part of the [Brave Browser](https://brave.com/download/). 14 | - For questions please visit our [community site](https://community.brave.com/c/support-and-troubleshooting/wallet/131). 15 | - Follow Brave on [Twitter](https://twitter.com/brave) and [Facebook](https://www.facebook.com/BraveSoftware). 16 | - Post issues directly to the developers on Brave's [GitHub repo](https://github.com/brave/brave-browser/issues/new/choose). 17 | -------------------------------------------------------------------------------- /docs/provider-availability.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Restrictions for providers 6 | The provider objects (e.g. `window.ethereum` and `window.braveSolana`) are not provided in all contexts. 7 | 8 | Historically the web has had a notion of “powerful" APIs like geolocation and camera/microphone, which are subject to additional security restrictions. See for instance https://www.w3.org/TR/secure-contexts/. 9 | 10 | Because they allow websites to request access to user funds, new web3 APIs like `window.ethereum` and `window.braveSolana` are subject to the same restrictions as other powerful APIs like `geolocation` in Brave. 11 | As a rule of thumb, if a context is not allowed to request access to geolocation, `window.ethereum` and `window.braveSolana` are `undefined` in the same contexts. 12 | 13 | Provider objects are not accessible in private and Tor window. 14 | 15 | 16 | ## Restrictions for insecure contexts 17 | 18 | Only “secure origins" as defined in https://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features/#definitions have access to `window.ethereum` and `window.braveSolana`. 19 | This can be checked using `window.isSecureContext`, including inside iframes. 20 | Secure contexts include sites that are served from HTTPS but also HTTP `localhost`. 21 | 22 | ## Restrictions in iframes 23 | 24 | By default the provider objects are not exposed to 3p iframes. 25 | Brave exposes 2 new [feature policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Feature_Policy/Using_Feature_Policy) for Ethereum and Solana named `ethereum` and `solana` respectively. 26 | 27 | `window.ethereum` and `window.braveSolana` are blocked in an iframe if `window.isSecureContext` is `false` in that iframe. 28 | 29 | In addition: 30 | 31 | 1. If the iframe is third party to the top-level origin, it will be blocked UNLESS the iframe has the `allow="{solana/ethereum}"` attribute (where “solana" and “ethereum" values control the corresponding API permissions). 32 | 2. If the iframe is first party to the top-level origin AND the `sandbox` attribute is set on the iframe, it will be blocked UNLESS `sandbox="allow-same-origin"` is set. Note "allow-same-origin"` does nothing if the iframe is third-party. 33 | 3. For security-conscious users, we add a setting to block both `window.ethereum` and `window.solana` in ALL iframes, regardless of origin or attributes. This matches the default behavior on iOS. 34 | 35 | ### iOS 36 | Currently on iOS, `window.ethereum` and `window.braveSolana` are both undefined in all iframes. 37 | 38 | ## Example cases 39 | 40 | In all these cases, the `window.ethereum` or `window.braveSolana` request is coming from the innermost iframe. 41 | - Top level `http://a.com` -> blocked (insecure) 42 | - Top level `https://a.com` -> allowed 43 | - Top level `https://a.com` with `