{"id":24054666,"url":"https://github.com/cardinal-cryptography/signer-integration-example","last_synced_at":"2026-06-10T18:32:12.257Z","repository":{"id":197258688,"uuid":"652538180","full_name":"Cardinal-Cryptography/signer-integration-example","owner":"Cardinal-Cryptography","description":"Extensive README and simple app to showcase Signer integration","archived":false,"fork":false,"pushed_at":"2023-10-27T11:36:13.000Z","size":249,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-26T10:46:27.549Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cardinal-Cryptography.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-12T09:21:09.000Z","updated_at":"2023-09-29T14:59:42.000Z","dependencies_parsed_at":"2025-02-26T10:45:33.583Z","dependency_job_id":"313cab21-fa26-4e87-9ce7-a0466597b053","html_url":"https://github.com/Cardinal-Cryptography/signer-integration-example","commit_stats":null,"previous_names":["cardinal-cryptography/signer-integration-example"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Cardinal-Cryptography/signer-integration-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fsigner-integration-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fsigner-integration-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fsigner-integration-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fsigner-integration-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cardinal-Cryptography","download_url":"https://codeload.github.com/Cardinal-Cryptography/signer-integration-example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fsigner-integration-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34165482,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-09T03:49:18.890Z","updated_at":"2026-06-10T18:32:12.240Z","avatar_url":"https://github.com/Cardinal-Cryptography.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Aleph Zero Signer integration example\n\n## Intro\n\nIn this tutorial we are creating a simple webapp integrated with the Aleph Zero Signer. Our app will:\n\n- import and display accounts from the Signer;\n- sign a simple transfer transaction using those accounts.\n\n## Requirements\n\n- [Aleph Zero Signer](https://alephzero.org/signer)\n  - [Install on Google Chrome, Brave, MS Edge and Opera](https://chrome.google.com/webstore/detail/aleph-zero-signer/opbinaebpmphpefcimknblieddamhmol)\n  - [Install on Firefox](https://addons.mozilla.org/en-US/firefox/addon/aleph-zero-signer/)\n- `node` 14.18+ or 16+ (required to use `vite` with `react`: your dependencies may vary if you choose to use a different framework).\n\n## Create project\n\nWe're using [`vite`](https://vitejs.dev/) to set up the React project. Run:\n\n```bash\nnpm create vite@latest signer-integration -- --template react-ts\n```\n\nYou will then be able to start the dev server like this:\n\n```bash\ncd signer-integration\nnpm install\nnpm run dev\n```\n\n## Install dependency\n\nAleph Zero Signer exposes the polkadot.{js} dapp extension library API. You can check out their docs [here](https://polkadot.js.org/docs/extension/).\n\n```bash\nnpm install @polkadot/extension-dapp\n```\n\n## Check if Signer is injected\n\nFirst, let's make sure Signer was successfully injected into our website.\n\nIf Signer (or any other extension supporting this API) is available, it is added to the `window.injectedWeb3` object.\n\nYou can test that by running this example:\n\n```bash\nnpm run dev\n```\n\nand, using your browser's developer console, inspect the `window.injectedWeb3` object to see if Signer is registered.\n\n![Connect pop-up screenshot][inspect-injected-web3]\n\nCommon pitfalls/troubleshooting\n\n- Signer extension wasn't successfully installed\n- Signer is disabled\n- Make sure your site is served from localhost, 127.0.0.1, or over https:// - Signer isn't injected on other sites served over http://.\n\n## Connect to Signer\n\nNow we are going to enable injected extensions (the API can handle more than one extension at a time, but in our case it's just the Signer). We will be using `web3Enable` - a util function from `@polkadot/extension-dapp`. It enables the connection and returns a list of all injected extensions.\n\nWe're going to call this method in the `onClick` handler of the 'Connect account' button:\n\n```jsx\nimport { web3Enable } from \"@polkadot/extension-dapp\";\n\ntype InjectedExtension = Awaited\u003cReturnType\u003ctypeof web3Enable\u003e\u003e[number];\n\nconst [extensions, setExtensions] = useState\u003cInjectedExtension[]\u003e([]);\n\nconst loadAccountsFromExtensions = async () =\u003e {\n  // extension-dapp API: connect to extensions; returns list of injected extensions\n  const injectedExtensions = await web3Enable(APP_NAME);\n\n  setExtensions(injectedExtensions);\n};\n\n\u003cbutton onClick={loadAccountsFromExtensions}\u003e\n  Connect to extensions\n\u003c/button\u003e\n```\n\n`APP_NAME` is a string - a name of the app that's trying to connect. This is how your app is going to be represented inside the Signer.\n\nImportant! You have to call `web3Enable` before any other utility functions.\n\nNow, after clicking the button and going through the `Your privacy is protected` screen, you should see one of these pop-ups:\n\n![Connect pop-up screenshot][no-accounts]\n![Connect pop-up screenshot][connect-app-screenshot]\n\nAdd an account to Signer if you haven't already and make sure you select the checkbox next to it when connecting. Connecting an account means it's going to be available to a website - we'll be able to get account information and initiate signing transactions.\n\nYou can change connected accounts by going to:\n`settings (top left corner) \u003e Trusted apps \u003e \u003cYour app\u003e`\n\n## Loading accounts\n\nNow we can use `web3Accounts` helper function to get all the accounts provided by the Signer:\n\n```jsx\nimport { web3Accounts } from \"@polkadot/extension-dapp\";\n\ntype InjectedAccountWithMeta = Awaited\u003cReturnType\u003ctypeof web3Accounts\u003e\u003e[number];\n\nconst [accounts, setAccounts] = useState\u003cInjectedAccountWithMeta[]\u003e([]);\n\n// extension-dapp API: get accounts from extensions filtered by name\nconst accounts = await web3Accounts(\n  { extensions: [\"aleph-zero-signer\"] }\n);\n\nsetAccounts(accounts);\n\n\u003carticle\u003e\n  \u003ch2\u003eSigner accounts\u003c/h2\u003e\n  \u003cul\u003e\n    {accounts.map(({ address, meta: { name } }) =\u003e (\n      \u003cli key={address}\u003e\n        \u003cstrong\u003e{name || \"\u003cunknown\u003e\"}\u003c/strong\u003e {address}\n      \u003c/li\u003e\n    ))}\n  \u003c/ul\u003e\n\u003c/article\u003e\n```\n\nAbove, we're filtering to get only the accounts from the Signer, but you might choose to include all accounts.\n\n## Transaction: prepare accounts\n\nSince we are going to make transactions on the Aleph Zero Testnet, we are going to need two accounts and some funds (TZERO).\nCreate a second account in the Signer. Accounts have associated networks and we want both our accounts to have the Aleph Zero Testnet selected. You can either select it in the account creator or change it later in the settings.\n\nWe should be able to filter the accounts over selected network. To that end, `web3Accounts` has a `genesisHash` param available and for the Aleph Zero Testnet we want:\n\n```js\n// extension-dapp API: get accounts from extensions filtered by name and chain\nconst accounts = await web3Accounts({\n  extensions: [\"aleph-zero-signer\"],\n  genesisHash:\n    \"0x05d5279c52c484cc80396535a316add7d47b1c5b9e0398dd1f584149341460c5\",\n});\n```\n\n### Getting the funds\n\nWith the accounts ready, we need to set them up with some TZERO (the Aleph Zero Testnet currency). In order to do so, copy first account address and paste it in the address field in the Testnet [Faucet](https://faucet.test.azero.dev/). You'll need to solve a captcha and the system will transfer some TZERO to your account. You can check your accounts' balances e.g. in https://test.azero.dev/#/accounts (which, incidentally, is also an example of a Signer integration).\n\n## Transaction: set up the API\n\nTo create a transaction we are going to be using the `@polkadot/api` library - [docs](https://polkadot.js.org/docs/api/).\n\n```bash\nnpm install @polkadot/api\n```\n\nWe'll need to set it up and initialize it using the Aleph Zero Testnet websocket:\n\n```js\nimport { ApiPromise, WsProvider } from \"@polkadot/api\";\n\nconst ALEPH_ZERO_TESTNET_WS_PROVIDER = new WsProvider(\n  \"wss://ws.test.azero.dev\"\n);\n\nconst API_PROMISE = ApiPromise.create({\n  provider: ALEPH_ZERO_TESTNET_WS_PROVIDER,\n});\n\nconst [api, setApi] = useState\u003cApiPromise\u003e();\n\nuseEffect(() =\u003e {\n  API_PROMISE.then(setApi);\n}, []);\n```\n\n## Transaction: sign a transaction\n\nNext, we are going to sign a simple transfer transaction.\nFor the sake of simplicity we are going to transfer `50 TZERO` from the first account to the second one.\n\nNote that we're using the big number implementation from `@polkadot/util` to make sure we don't exceed JavaScript's safe integer range.\n\n```bash\nnpm install @polkadot/util\n```\n\nThe balance on chain is kept in pico TZERO (10\u003csup\u003e-12\u003c/sup\u003e), so we need to adjust the transferred value. Instead of hardcoding the units here, we can get this information from the `api`.\n\n```jsx\nimport { web3FromAddress } from \"@polkadot/extension-dapp\";\nimport { BN } from \"@polkadot/util\";\n\nconst makeTransfer = async () =\u003e {\n  const [first, second] = accounts;\n\n  // extension-dapp API: get address's injector\n  const firstAddressInjector = await web3FromAddress(first.address);\n\n  const transferAmount = new BN(50);\n  const unitAdjustment = new BN(10).pow(new BN(api.registry.chainDecimals[0]));\n  const finalAmount = transferAmount.mul(unitAdjustment);\n\n  await (api.tx.balances.transferAllowDeath || api.tx.balances.transfer)(\n    second.address,\n    finalAmount\n  ).signAndSend(first.address, { signer: firstAddressInjector.signer });\n};\n\n\u003cbutton onClick={makeTransfer}\u003eMake transfer\u003c/button\u003e;\n```\n\nAfter clicking the button you should see the Signer pop-up:\n\n![Connect pop-up screenshot][transfer-authorization]\n\nLastly, you can confirm and check your accounts' balances in https://test.azero.dev/#/accounts.\n\nImportant! Just because the transaction Promise doesn't throw an exception, it doesn't mean it succeeded - see https://polkadot.js.org/docs/api/cookbook/tx/#how-do-i-get-the-decoded-enum-for-an-extrinsicfailed-event.\n\n## Closing remarks\n\nWe hope you've enjoyed this tutorial, and now you know how to smoothly integrate your app with the Signer.\n\nFor other tutorials, head over to [alephzero.org/developers](https://alephzero.org/developers)\n\nIf you need any other help, make sure to join our [Discord](https://discord.gg/alephzero)!\n\n[no-accounts]: ./screenshots/no-accounts.png\n[connect-app-screenshot]: ./screenshots/connect-app-screen.png\n[inspect-injected-web3]: ./screenshots/inspect-injected-web3.png\n[transfer-authorization]: ./screenshots/transfer-authorization.png\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcardinal-cryptography%2Fsigner-integration-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcardinal-cryptography%2Fsigner-integration-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcardinal-cryptography%2Fsigner-integration-example/lists"}