### Development Setup Source: https://github.com/airgap-it/beacon-sdk/blob/master/packages/beacon-sdk/README.md Set up the development environment for the Beacon SDK. This includes installing dependencies, building the project, and running tests. ```bash $ npm i $ npm run build $ npm run test ``` -------------------------------- ### Network Configuration Examples Source: https://context7.com/airgap-it/beacon-sdk/llms.txt Examples demonstrating how to initialize the DAppClient with different network configurations, including Mainnet, Ghostnet, and a custom local node. ```APIDOC ## NetworkType & Network Configuration The SDK supports all standard Tezos networks. The `network` option on `DAppClientOptions` (and on individual requests) controls which network the dApp operates on. ```typescript import { DAppClient, NetworkType, BeaconEvent } from '@airgap/beacon-sdk' // Available NetworkType values: // NetworkType.MAINNET // NetworkType.GHOSTNET // NetworkType.PARISNET // NetworkType.OXFORDNET // NetworkType.CUSTOM // Mainnet const mainnetClient = new DAppClient({ name: 'Mainnet DApp', network: { type: NetworkType.MAINNET } }) // Ghostnet (testnet) const ghostnetClient = new DAppClient({ name: 'Testnet DApp', network: { type: NetworkType.GHOSTNET } }) // Custom local node const customClient = new DAppClient({ name: 'Local DApp', network: { type: NetworkType.CUSTOM, name: 'Local Sandbox', rpcUrl: 'http://localhost:8732' } }) customClient.subscribeToEvent(BeaconEvent.ACTIVE_ACCOUNT_SET, (account) => { console.log('Connected on custom network:', account?.network) }) ``` ``` -------------------------------- ### Install Beacon SDK Source: https://github.com/airgap-it/beacon-sdk/blob/master/packages/beacon-sdk/README.md Install the Beacon SDK package using npm. ```bash npm i --save @airgap/beacon-sdk ``` -------------------------------- ### Example Wallet Integration Source: https://github.com/airgap-it/beacon-sdk/blob/master/packages/beacon-sdk/README.md Integrate the Beacon SDK into your wallet to handle incoming messages from dApps. This example shows how to initialize the WalletClient, establish a P2P connection, and handle a PermissionRequest. ```typescript const client = new WalletClient({ name: 'My Wallet' }) await client.init() // Establish P2P connection client .connect(async (message) => { // Example: Handle PermissionRequest. A wallet should handle all request types if (message.type === BeaconMessageType.PermissionRequest) { // Show a UI to the user where he can confirm sharing an account with the DApp const response: PermissionResponseInput = { type: BeaconMessageType.PermissionResponse, network: message.network, // Use the same network that the user requested scopes: [PermissionScope.OPERATION_REQUEST], // Ignore the scopes that have been requested and instead give only operation permissions id: message.id, publicKey: 'tezos public key' } // Send response back to DApp await client.respond(response) } }) .catch((error) => console.error('connect error', error)) ``` -------------------------------- ### Example DApp Integration Source: https://github.com/airgap-it/beacon-sdk/blob/master/packages/beacon-sdk/README.md Integrate the Beacon SDK into your dApp to request permissions from a user's wallet. This example shows how to initialize the DAppClient and request permissions. ```typescript const client = new DAppClient({ name: 'My Sample DApp' }) client .requestPermissions() // Send a permission request and automatically show UI to the user to select his favorite wallet .then((permissions) => { // Account that has been shared by the wallet console.log('got permissions', permissions) }) .catch((error) => console.log(error)) ``` -------------------------------- ### DApp Integration with Beacon SDK Source: https://github.com/airgap-it/beacon-sdk/blob/master/readme.md Integrate your dApp with the Beacon SDK to enable wallet connections. This example shows how to initialize the client, subscribe to account changes, and request permissions. ```typescript import { DAppClient, BeaconEvent } from '@airgap/beacon-sdk' const dAppClient = new DAppClient({ name: 'My Sample DApp' }) // Listen for all the active account changes dAppClient.subscribeToEvent(BeaconEvent.ACTIVE_ACCOUNT_SET, async (account) => { // An active account has been set, update the dApp UI console.log(`${BeaconEvent.ACTIVE_ACCOUNT_SET} triggered: `, account) }) try { console.log('Requesting permissions...') const permissions = await dAppClient.requestPermissions() console.log('Got permissions:', permissions.address) } catch (error) { console.error('Got error:', error) } ``` -------------------------------- ### Get Available Extensions Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3-sapling.html Retrieves a list of available Beacon extensions installed in the browser. The result is logged to the console. ```javascript document.getElementById('getExtensions').addEventListener('click', () => { beacon.availableTransports.availableExtensions.then((extensions) => { console.log(extensions) alert( `There are ${extensions.length} extensions installed. Check the console for more info.` ) }) }) ``` -------------------------------- ### Initialize and Connect WalletClient Source: https://context7.com/airgap-it/beacon-sdk/llms.txt Initializes the WalletClient with wallet details and starts listening for inbound dApp requests. Handles permission requests by showing an approval dialog and responding with granted scopes or an error. ```typescript import { WalletClient, BeaconMessageType, PermissionScope, BeaconResponseInputMessage } from '@airgap/beacon-sdk' const walletClient = new WalletClient({ name: 'My Tezos Wallet', iconUrl: 'https://my-wallet.example.com/icon.png', appUrl: 'https://my-wallet.example.com' }) // Initialize P2P connection (generates key pair, connects to matrix relay) await walletClient.init() // Start listening for inbound dApp requests walletClient .connect(async (message, connectionContext) => { console.log('Received request type:', message.type) console.log('From senderId:', message.senderId) console.log('Via transport:', connectionContext.origin) if (message.type === BeaconMessageType.PermissionRequest) { // Show user: dApp name + requested scopes const dAppName = message.appMetadata.name const requestedScopes = message.scopes const userApproved = await showApprovalDialog(dAppName, requestedScopes) if (userApproved) { const response: BeaconResponseInputMessage = { type: BeaconMessageType.PermissionResponse, id: message.id, network: message.network, scopes: [PermissionScope.OPERATION_REQUEST, PermissionScope.SIGN], publicKey: 'edpk...' } await walletClient.respond(response) } else { const errorResponse: BeaconResponseInputMessage = { type: BeaconMessageType.Error, id: message.id, errorType: 'ABORTED_ERROR' } await walletClient.respond(errorResponse) } } }) .catch((error) => console.error('WalletClient connect error:', error)) async function showApprovalDialog(dAppName: string, scopes: string[]): Promise { // Wallet UI implementation return true } ``` -------------------------------- ### WalletClient Constructor & Initialization Source: https://context7.com/airgap-it/beacon-sdk/llms.txt Initializes the WalletClient to connect to the P2P matrix network and start listening for dApp requests. It requires configuration options like name, iconUrl, and appUrl. ```APIDOC ## WalletClient — Constructor & Initialization `WalletClient` is used inside Tezos wallet implementations. It connects to the P2P matrix network and exposes a `connect` method that fires a callback for every inbound dApp request. ```typescript import { WalletClient, BeaconMessageType, PermissionScope, BeaconResponseInputMessage } from '@airgap/beacon-sdk' const walletClient = new WalletClient({ name: 'My Tezos Wallet', iconUrl: 'https://my-wallet.example.com/icon.png', appUrl: 'https://my-wallet.example.com' }) // Initialize P2P connection (generates key pair, connects to matrix relay) await walletClient.init() // Start listening for inbound dApp requests walletClient .connect(async (message, connectionContext) => { console.log('Received request type:', message.type) console.log('From senderId:', message.senderId) console.log('Via transport:', connectionContext.origin) if (message.type === BeaconMessageType.PermissionRequest) { // Show user: dApp name + requested scopes const dAppName = message.appMetadata.name const requestedScopes = message.scopes const userApproved = await showApprovalDialog(dAppName, requestedScopes) if (userApproved) { const response: BeaconResponseInputMessage = { type: BeaconMessageType.PermissionResponse, id: message.id, network: message.network, scopes: [PermissionScope.OPERATION_REQUEST, PermissionScope.SIGN], publicKey: 'edpk...' } await walletClient.respond(response) } else { const errorResponse: BeaconResponseInputMessage = { type: BeaconMessageType.Error, id: message.id, errorType: 'ABORTED_ERROR' } await walletClient.respond(errorResponse) } } }) .catch((error) => console.error('WalletClient connect error:', error)) async function showApprovalDialog(dAppName: string, scopes: string[]): Promise { // Wallet UI implementation return true } ``` ``` -------------------------------- ### Initialize DAppClient and Add Tezos Blockchain Support Source: https://github.com/airgap-it/beacon-sdk/blob/master/packages/beacon-blockchain-tezos/README.md Instantiate a DAppClient and add Tezos blockchain support by creating a TezosBlockchain instance and adding it to the client. Ensure you have the necessary packages installed. ```javascript import { DAppClient } from '@airga/beacon-dapp' import { TezosBlockchain } from '@airga/beacon-blockchain-tezos' const client = new DAppClient({ name: 'Example DApp', }) const tezosBlockchain = new TezosBlockchain() client.addBlockchain(tezosBlockchain) ``` -------------------------------- ### Send Contract Call Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp.html Initiates a contract call to set a color on a specific contract. This example demonstrates calling a contract with parameters and includes error handling for potential failures. ```javascript const sendContractCall = () => { return client.getActiveAccount().then(async (activeAccount) => { const TZ_BUTTON_COLORS_CONTRACT = 'KT1GSdrLzGAorWKoe2z7qV3P5Df6Vmo7neZt' const tokenId = '925' try { const result = await client.requestOperation({ operationDetails: [ { kind: beacon.TezosOperationType.TRANSACTION, amount: '0', destination: TZ_BUTTON_COLORS_CONTRACT, parameters: { entrypoint: 'set_color', value: { int: tokenId } } } ] }) console.log(result) } catch (error) { console.log(`The contract call failed and the following error was returned:`, error) } }) } ``` -------------------------------- ### Get Available Extensions Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3.html Retrieves a list of available Beacon extensions. The result is logged to the console and an alert shows the count. ```javascript document.getElementById('getExtensions').addEventListener('click', () => { beacon.availableTransports.availableExtensions.then((extensions) => { console.log(extensions) alert( `There are ${extensions.length} extensions installed. Check the console for more info.` ) }) }) ``` -------------------------------- ### Sign Raw Payload Event Listener Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3-sapling.html Attaches a 'click' event listener to a button that initiates a request to sign a raw payload. This example is incomplete and requires further implementation for the payload. ```javascript document.getElementById('signPayloadRaw').addEventListener('click', async () => { const signature = await client.requestSignPayload({ payload: '0' ``` -------------------------------- ### Initialize Beacon Wallet Client Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/wallet-v3.html Initiate a new Beacon WalletClient instance. Configure with a name and optionally specify matrix nodes. ```javascript const client = new beacon.WalletClient({ name: 'Example Wallet' // Name of the DApp // matrixNodes: ['beacon-dendrite-node-1.crystal.papers.tech'] // matrixNodes: ['beacon-node-0.papers.tech:8448'] // matrixNodes: ['beacon.tztip.me'] }) ``` -------------------------------- ### Get Stored Accounts Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3-sapling.html Fetches all accounts that have been previously authorized by the user. The count is displayed in an alert. ```javascript document.getElementById('getAccounts').addEventListener('click', () => { client.getAccounts().then((accounts) => { console.log(accounts) alert(`There are ${accounts.length} accounts stored. Check the console for more info.`) }) }) ``` -------------------------------- ### Show and Hide UI Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3-sapling.html Demonstrates showing the Beacon UI's prepare screen and then hiding it after a 2-second delay. ```javascript document.getElementById('showPrepareAndHide').addEventListener('click', () => { client.showPrepare() setTimeout(() => { client.hideUI() }, 2000) }) ``` -------------------------------- ### Initialize DAppClient with Configuration Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp.html Initialize the DAppClient with essential configuration options, including the DApp name, optional disclaimer, WalletConnect project ID, and network settings. This is the primary step to connect your DApp to Beacon. ```javascript const client = beacon.getDAppClientInstance({ name: 'Example DApp', // Name of the DApp, disclaimerText: 'This is an optional disclaimer.', appUrl: 'http://localhost:8080', errorMessages: { KT1RPW5kTX6WFxg8JK34rGEU24gqEEudyfvz: { NOT_OWNER: 'You are not the owner of this token.' } }, walletConnectOptions: { projectId: '97f804b46f0db632c52af0556586a5f3', relayUrl: 'wss://relay.walletconnect.com' }, matrixNodes: { [beacon.Regions.EUROPE_WEST]: [ 'beacon-node-1.diamond.papers.tech', 'beacon-node-1.sky.papers.tech', 'beacon-node-2.sky.papers.tech', 'beacon-node-1.hope.papers.tech', 'beacon-node-1.hope-2.papers.tech', 'beacon-node-1.hope-3.papers.tech', 'beacon-node-1.hope-4.papers.tech', 'beacon-node-1.hope-5.papers.tech', 'beacon-node-1.octez.io', 'beacon-node-2.octez.io', 'beacon-node-3.octez.io', 'beacon-node-4.octez.io', 'beacon-node-5.octez.io', 'beacon-node-6.octez.io', 'beacon-node-7.octez.io', 'beacon-node-8.octez.io' ], [beacon.Regions.NORTH_AMERICA_EAST]: [] }, featuredWallets: ['kukai', 'metamask', 'airgap'], network: { type: beacon.NetworkType.GHOSTNET }, enableMetrics: true // matrixNodes: ['test.papers.tech', 'test2.papers.tech', 'matrix.papers.tech'] // matrixNodes: ['beacon-node-0.papers.tech:8448'] // matrixNodes: ['matrix.papers.tech'] // matrixNodes: ['beacon.tztip.me'] }) ``` -------------------------------- ### Send Notification Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp.html Sends a notification to the connected wallet. This example shows how to send a simple message with a title. ```javascript document.getElementById('sendNotification').addEventListener('click', () => { client .sendNotification('Beacon Test', 'Message', '', 'xtz') .then((res) => console.log('Notification Response', res)) }) ``` -------------------------------- ### Send Transaction Request Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp.html Sends a transaction request to the connected wallet. This example demonstrates toggling a status value. ```javascript client.requestOperation({ request: { beaconId: 'YOUR_BEACON_ID', network: { type: 'custom', rpcUrl: 'YOUR_RPC_URL' }, appMetadata: { name: 'My DApp' }, command: 'request_operation', payload: { Michelson: '{\"prim\": \"Unit\"}' } }, eventHandlers: { // Handle response from the wallet response: (res) => { console.log('Operation Response:', res) } } }).then((response) => console.log(response)).catch((error) => console.log(error)) ``` -------------------------------- ### Initialize Beacon Wallet Client Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/wallet-v3-sapling.html Instantiate a new WalletClient for your DApp. Provide a name for your wallet. Optional matrix nodes can be specified for custom network configurations. ```javascript const client = new beacon.WalletClient({ name: 'Example Wallet' // Name of the DApp // matrixNodes: ['beacon-dendrite-node-1.crystal.papers.tech'] // matrixNodes: ['beacon-node-0.papers.tech:8448'] // matrixNodes: ['beacon.tztip.me'] }) ``` -------------------------------- ### Get Stored Accounts Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp.html Adds an event listener to a button to retrieve and log all stored accounts. Displays an alert with the count of accounts. ```javascript document.getElementById('getAccounts').addEventListener('click', () => { client.getAccounts().then((accounts) => { console.log(accounts) alert( `There are ${accounts.length} accounts stored. Check the console for more info. `) }) }) ``` -------------------------------- ### Initiate WalletClient Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/abstracted-account.html Initializes the WalletClient for a wallet application, configuring it with a name and local storage for persistence. ```javascript const client = new beacon.WalletClient({ name: 'Example Wallet', // Name of the DApp storage: new beacon.LocalStorage('WALLET') }) ``` -------------------------------- ### Send Tez to Self Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3.html Requests a transfer of 1 tez to the active account's own address. This example demonstrates a basic transfer operation. ```javascript const sendToSelf = () => { return client.getActiveAccount().then((activeAccount) => { client .request({ blockchainIdentifier: 'substrate', type: 'blockchain_request', blockchainData: { type: 'transfer_request', scope: 'transfer', sourceAddress: activeAccount.address, amount: '1', recipient: activeAccount.address, network: { genesisHash: 'xxx' }, mode: 'return' } }) .then((response) => { console.log('response', response) }) }) } ``` -------------------------------- ### Get Available Extensions Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp.html Adds an event listener to a button to retrieve and log available Beacon extensions. Displays an alert with the count of extensions. ```javascript document.getElementById('getExtensions').addEventListener('click', () => { beacon.availableTransports.availableExtensions.then((extensions) => { console.log(extensions) alert( `There are ${extensions.length} extensions installed. Check the console for more info.` ) }) }) ``` -------------------------------- ### Handle Beacon Client Connection and Messages Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/wallet-v3.html Initializes the Beacon client and sets up a listener to handle incoming messages. Includes logic for PermissionRequest for version 3 and older. ```javascript client.init().then(() => { console.log('init') client .connect(async (message) => { setStatus('Handling request...') console.log('message', message) if (message.version === '3') { // Example: Handle PermissionRequest. A wallet should handle all request types if (message.message.type === beacon.BeaconMessageType.PermissionRequest) { if (message.message.blockchainIdentifier !== 'substrate') { throw new Error('Only KSM supported') } console.log('SUBSTRATE MESSAGE') // Show a UI to the user where he can confirm sharing an account with the DApp const response = { id: message.id, type: beacon.BeaconMessageType.PermissionResponse, blockchainData: { appMetadata: { name: 'Example Wallet' }, scopes: [0], accounts: [ { network: { genesisHash: 'xxx' }, addressPrefix: 0, publicKey: '3b92229274683b338cf8b040cf91ac0f8e19e410f06eda5537ef077e718e0024' // should we add a curve type here? } ] } } // Let's wait a little to make it more natural (to test the UI on the dApp side) await new Promise((resolve) => setTimeout(resolve, 1000)) // Send response back to DApp client.respond(response) } else { console.error('Only permission requests are supported in this demo') console.error('Received: ', message) const response = { type: beacon.BeaconMessageType.Error, id: message.id, errorType: beacon.BeaconErrorType.ABORTED_ERROR } client.respond(response) } } else { // Example: Handle PermissionRequest. A wallet should handle all request types if (message.type === beacon.BeaconMessageType.PermissionRequest) { // Show a UI to the user where he can confirm sharing an account with the DApp const response = { type: beacon.BeaconMessageType.PermissionResponse, network: message.network, // Use the same network that the user requested scopes: [ beacon.PermissionScope.OPERATION_REQUEST, beacon.PermissionScope.ENCRYPT ], // Ignore the scopes that have been requested and instead give only operation permissions id: message.id, publicKey: '3b92229274683b338cf8b040cf91ac0f8e19e410f06eda5537ef077e718e0024' } // Let's wait a little to make it more natural (to test the UI on the dApp side) await new Promise((resolve) => setTimeout(resolve, 1000)) // Send response back to DApp client.respond(response) } else { console.error('Only permission requests are supported in this demo') console.error('Received: ', message) const response = { type: beacon.BeaconMessageType.Error, id: message.id, errorType: beacon.BeaconErrorType.ABORTED_ERROR } client.respond(response) } } setStatus('') }) .catch((error) => console.error('connect error', error)) }) ``` -------------------------------- ### Connect and Handle Beacon Messages Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/wallet.html Initializes the client and sets up a listener for incoming Beacon messages. It specifically handles PermissionRequest messages by responding with granted permissions. ```javascript client.init().then(() => { console.log('init') client .connect(async (message) => { setStatus('Handling request...') console.log('message', message) // Example: Handle PermissionRequest. A wallet should handle all request types if (message.type === beacon.BeaconMessageType.PermissionRequest) { // Show a UI to the user where he can confirm sharing an account with the DApp // const URL = 'https://beacon-notification-oracle.dev.gke.papers.tech' const publicKey = '3b92229274683b338cf8b040cf91ac0f8e19e410f06eda5537ef077e718e0026' // const res = await client.registerPush( // 'https://webhook.site/37e64204-3058-41ea-b681-9466ec70a892', // TODO: Replace this with your own webhook // publicKey, // 'xtz', // Math.random().toString(), // URL // ) // console.log('res', res) const response = { type: beacon.BeaconMessageType.PermissionResponse, network: message.network, // Use the same network that the user requested scopes: [ beacon.PermissionScope.OPERATION_REQUEST, beacon.PermissionScope.NOTIFICATION, beacon.PermissionScope.ENCRYPT, beacon.PermissionScope.SIGN ], // Ignore the scopes that have been requested and instead give only operation permissions id: message.id, publicKey: publicKey // notification: { // version: 1, // apiUrl: URL, // token: res.accessToken // } } // Let's wait a little to make it more natural (to test the UI on the dApp side) await new Promise((resolve) => setTimeout(resolve, 1000)) // Send response back to DApp client.respond(response) } else { console.error('Only permission requests are supported in this demo') console.error('Received: ', message) const response = { type: beacon.BeaconMessageType.Error, id: message.id, errorType: beacon.BeaconErrorType.ABORTED_ERROR } client.respond(response) } setStatus('') }) .catch((error) => console.error('connect error', error)) }) ``` -------------------------------- ### DAppClient Constructor & Initialization Source: https://context7.com/airgap-it/beacon-sdk/llms.txt Initializes the DAppClient, which is the entry point for dApp integrations. It manages wallet connections and request/response cycles. Subscribing to BeaconEvent.ACTIVE_ACCOUNT_SET is required. ```APIDOC ## DAppClient — Constructor & Initialization `DAppClient` is the entry point for dApp integrations. It accepts a `DAppClientOptions` object and manages wallet connections, transport selection, and all request/response cycles. The `subscribeToEvent` call for `ACTIVE_ACCOUNT_SET` is **required** to properly track the active wallet account. ```typescript import { DAppClient, NetworkType, ColorMode, BeaconEvent, Regions } from '@airgap/beacon-sdk' const client = new DAppClient({ name: 'My Tezos DApp', description: 'A sample Tezos DApp', appUrl: 'https://my-dapp.example.com', iconUrl: 'https://my-dapp.example.com/icon.png', network: { type: NetworkType.MAINNET }, colorMode: ColorMode.LIGHT, disclaimerText: 'Use at your own risk.', walletConnectOptions: { projectId: 'YOUR_WALLETCONNECT_PROJECT_ID' // from https://cloud.walletconnect.com }, matrixNodes: { [Regions.EUROPE_WEST]: ['beacon-node-1.diamond.papers.tech'], [Regions.NORTH_AMERICA_EAST]: [] }, featuredWallets: ['kukai', 'airgap', 'temple'], errorMessages: { KT1SomeContract: { 101: 'Insufficient balance', NOT_OWNER: 'You are not the owner of this token.' } }, disableDefaultEvents: false // set true to fully replace all default UI }) // REQUIRED: subscribe before any requests client.subscribeToEvent(BeaconEvent.ACTIVE_ACCOUNT_SET, (account) => { if (account) { console.log('Wallet connected:', account.address, 'on', account.network.type) } else { console.log('Wallet disconnected') } }) ``` ``` -------------------------------- ### Send Tezos Transfer to Self Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3-sapling.html Initiates a Tezos transfer operation to send 1 mutez to the currently active account. This example demonstrates a direct blockchain request for a transfer. ```javascript const sendToSelf = () => { return client.getActiveAccount().then((activeAccount) => { client .request({ blockchainIdentifier: 'substrate', type: 'blockchain_request', blockchainData: { type: 'transfer_request', scope: 'transfer', sourceAddress: activeAccount.address, amount: '1', recipient: activeAccount.address, network: {}, mode: 'return' } }) .then((response) => { console.log('response', response) }) }) } ``` -------------------------------- ### Initialize WalletClient and Handle Messages Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/abstracted-account.html Initializes the WalletClient and sets up a connection handler to process incoming messages from DApps, including permission requests and proof-of-event challenges. ```javascript client.init().then(() => { console.log('init') client .connect(async (message) => { setStatus('Handling request...') console.log('message', message) // Example: Handle PermissionRequest. A wallet should handle all request types if (message.type === beacon.BeaconMessageType.PermissionRequest) { // Show a UI to the user where he can confirm sharing an account with the DApp const response = { type: beacon.BeaconMessageType.PermissionResponse, network: message.network, // Use the same network that the user requested scopes: message.scopes, // Ignore the scopes that have been requested and instead give only operation permissions id: message.id, address: ABSTRACTED_ACCOUNT_ADDRESS, publicKey: '', walletType: 'abstracted_account', verificationType: 'proof_of_event' // notification: { // version: 1, // apiUrl: URL, // token: res.accessToken // } } // Let's wait a little to make it more natural (to test the UI on the dApp side) await new Promise((resolve) => setTimeout(resolve, 1000)) // Send response back to DApp client.respond(response) } else if (message.type === beacon.BeaconMessageType.ProofOfEventChallengeRequest) { const isAccepted = window.confirm( 'Do you want to accept the Proof Of Event Challenge ?' ) challengeData.challenge_id = message.dAppChallengeId challengeData.payload = message.payload client .respond({ ...message, type: beacon.BeaconMessageType.ProofOfEventChallengeResponse, isAccepted }) .then(() => { if (!isAccepted) return const btn = document.getElementById('signChallenge') btn.style.opacity = 1 btn.disabled = false }) } else { console.error('Only permission requests are supported in this demo') console.error('Received: ', message) const response = { type: beacon.BeaconMessageType.Error, id: message.id, errorType: beacon.BeaconErrorType.ABORTED_ERROR } client.respond(response) } setStatus('') }) .catch((error) => console.error('connect error', er) ) }) ``` -------------------------------- ### Initialize DAppClient with WalletConnect Options Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3-sapling.html Initializes the DAppClient with essential configuration including name, disclaimer, app URL, and WalletConnect options. Ensure you have a valid projectId and relayUrl for WalletConnect. ```javascript const client = new beacon.DAppClient({ name: 'Example dApp', // Name of the dApp, disclaimerText: 'This is an optional disclaimer.', appUrl: 'http://localhost:8080', walletConnectOptions: { projectId: '97f804b46f0db632c52af0556586a5f3', relayUrl: 'wss://relay.walletconnect.com' } // preferredNetwork: beacon.NetworkType.DELPHINET // matrixNodes: ['test.papers.tech', 'test2.papers.tech', 'matrix.papers.tech'] // matrixNodes: ['beacon-node-0.papers.tech:8448'] // matrixNodes: ['matrix.papers.tech'] // matrixNodes: ['beacon.tztip.me'] }) ``` -------------------------------- ### Initialize DAppClient and Open Toast Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/iframes/basic-toast.html Initializes the DAppClient and makes the openToast function available. It then sets up a function to display a basic toast with a configurable body, state, and timer. The toast is shown on page load and at regular intervals. ```javascript window.beaconSdkDebugEnabled = true const client = new beacon.DAppClient({ name: 'Basic Toast Example' }) const { openToast } = beacon window.showBasicToast = function() { const config = { body: 'This is a basic toast notification', state: 'finished', timer: 5000 } openToast(config) } window.addEventListener('load', () => { setTimeout(window.showBasicToast, 500) setInterval(window.showBasicToast, 5000) }) ``` -------------------------------- ### Instantiate DAppClient in dApp Source: https://github.com/airgap-it/beacon-sdk/blob/master/packages/beacon-dapp/README.md Use this package on your dApp to instantiate a DAppClient object and communicate with wallets. Ensure you have the necessary imports. ```javascript import { DAppClient } from '@airgap/beacon-dapp' const dAppClient = new DAppClient({ name: "Beacon Docs" }); ``` -------------------------------- ### Manage Active Account: Get, Set, Clear Source: https://context7.com/airgap-it/beacon-sdk/llms.txt Manage the active wallet account using `getActiveAccount`, `setActiveAccount`, and `clearActiveAccount`. `getActiveAccount` checks connection state on page load, while `clearActiveAccount` performs a full disconnect. ```typescript import { DAppClient, NetworkType, BeaconEvent } from '@airgap/beacon-sdk' const client = new DAppClient({ name: 'My DApp', network: { type: NetworkType.MAINNET } }) client.subscribeToEvent(BeaconEvent.ACTIVE_ACCOUNT_SET, (account) => { console.log('Account changed:', account?.address) }) // Check if already connected on page load const activeAccount = await client.getActiveAccount() if (activeAccount) { console.log('Already connected:', activeAccount.address) console.log('Network:', activeAccount.network.type) console.log('Transport:', activeAccount.origin.type) // 'extension' | 'p2p' | 'walletconnect' console.log('Scopes:', activeAccount.scopes) console.log('Connected at:', new Date(activeAccount.connectedAt)) } else { console.log('Not connected, requesting permissions...') await client.requestPermissions() } // Disconnect await client.clearActiveAccount() console.log('Disconnected.') ``` -------------------------------- ### Initialize DAppClient and add SubstrateBlockchain Source: https://github.com/airgap-it/beacon-sdk/blob/master/packages/beacon-blockchain-substrate/README.md Instantiate a DAppClient and add the SubstrateBlockchain to enable communication with Substrate-based networks. ```typescript import { DAppClient } from '@airga/beacon-dapp' import { SubstrateBlockchain } from '@airga/beacon-blockchain-substrate' const client = new DAppClient({ name: 'Example DApp', }) const substrateBlockchain = new SubstrateBlockchain() client.addBlockchain(substrateBlockchain) ``` -------------------------------- ### Get Singleton DAppClient Instance Source: https://context7.com/airgap-it/beacon-sdk/llms.txt A convenience function that returns a shared DAppClient singleton. Subsequent calls return the same instance, preventing multiple instances from being created. Useful for ensuring a single point of interaction with the Beacon network for a dApp. ```typescript import { getDAppClientInstance, NetworkType, BeaconEvent } from '@airgap/beacon-sdk' // First call creates the instance const client = getDAppClientInstance({ name: 'My DApp', network: { type: NetworkType.MAINNET } }) // Subsequent calls return the same instance regardless of options passed const sameClient = getDAppClientInstance({ name: 'Different Name' }) console.log(client === sameClient) // true client.subscribeToEvent(BeaconEvent.ACTIVE_ACCOUNT_SET, (account) => { console.log('Account:', account?.address) }) const permissions = await client.requestPermissions() console.log('Address:', permissions.address) ``` -------------------------------- ### Initialize Beacon Client and Handle Messages Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/wallet-v3-sapling.html Initializes the Beacon client and sets up a listener for incoming messages. It handles different message versions and types, specifically focusing on PermissionRequest. ```javascript client.init().then(() => { console.log('init') client .connect(async (message) => { setStatus('Handling request...') console.log('message', message) if (message.version === '3') { // Example: Handle PermissionRequest. A wallet should handle all request types if (message.message.type === beacon.BeaconMessageType.PermissionRequest) { if (message.message.blockchainIdentifier !== 'substrate') { throw new Error('Only KSM supported') } console.log('SUBSTRATE MESSAGE') // Show a UI to the user where he can confirm sharing an account with the DApp const response = { id: message.id, type: beacon.BeaconMessageType.PermissionResponse, blockchainData: { appMetadata: { name: 'Example Wallet' }, scopes: [0], accounts: [ { network: { genesisHash: 'xxx' }, addressPrefix: 0, publicKey: '3b92229274683b338cf8b040cf91ac0f8e19e410f06eda5537ef077e718e0024' // should we add a curve type here? } ] } } // Let's wait a little to make it more natural (to test the UI on the dApp side) await new Promise((resolve) => setTimeout(resolve, 1000)) // Send response back to DApp client.respond(response) } else { console.error('Only permission requests are supported in this demo') console.error('Received: ', message) const response = { type: beacon.BeaconMessageType.Error, id: message.id, errorType: beacon.BeaconErrorType.ABORTED\_ERROR } client.respond(response) } } else { // Example: Handle PermissionRequest. A wallet should handle all request types if (message.type === beacon.BeaconMessageType.PermissionRequest) { // Show a UI to the user where he can confirm sharing an account with the DApp const response = { type: beacon.BeaconMessageType.PermissionResponse, network: message.network, // Use the same network that the user requested scopes: [ beacon.PermissionScope.OPERATION\_REQUEST, beacon.PermissionScope.ENCRYPT ], // Ignore the scopes that have been requested and instead give only operation permissions id: message.id, publicKey: '3b92229274683b338cf8b040cf91ac0f8e19e410f06eda5537ef077e718e0024' } // Let's wait a little to make it more natural (to test the UI on the dApp side) await new Promise((resolve) => setTimeout(resolve, 1000)) // Send response back to DApp client.respond(response) } else { console.error('Only permission requests are supported in this demo') console.error('Received: ', message) const response = { type: beacon.BeaconMessageType.Error, id: message.id, errorType: beacon.BeaconErrorType.ABORTED\_ERROR } client.respond(response) } } setStatus('') }) .catch((error) => console.error('connect error', error)) }) ``` -------------------------------- ### Register for Push Notifications with WalletClient Source: https://context7.com/airgap-it/beacon-sdk/llms.txt A two-step process to register the wallet for push notifications. First, get a challenge to sign, then sign it and register with the notification backend. Requires a notification backend URL, account public key, and device ID. ```typescript import { WalletClient } from '@airgap/beacon-sdk' const walletClient = new WalletClient({ name: 'My Wallet' }) await walletClient.init() const NOTIFICATION_BACKEND_URL = 'https://push.my-wallet.example.com' const accountPublicKey = 'edpkUGx...' const deviceId = 'fcm-device-token-or-apns-token' const protocolIdentifier = 'tezos' // Step 1: Get a challenge payload to sign const { challenge, payloadToSign } = await walletClient.getRegisterPushChallenge( NOTIFICATION_BACKEND_URL, accountPublicKey ) // Step 2: Sign the payload with the wallet's account key (outside SDK) const signature = await walletSignPayload(payloadToSign) // => 'edsig...' // Step 3: Register with the oracle and store the push token const pushToken = await walletClient.registerPush( challenge, signature, NOTIFICATION_BACKEND_URL, accountPublicKey, protocolIdentifier, deviceId ) console.log('Push registered. Access token:', pushToken.accessToken) // pushToken: { publicKey, backendUrl, accessToken, managementToken } async function walletSignPayload(payload: string): Promise { return 'edsig...' // actual signing implementation } ``` -------------------------------- ### Initialize DAppClient and Show Wallet Toast Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/iframes/wallet-toast.html Enables debug mode, initializes the DAppClient, and defines a function to open a customizable wallet toast. The toast is configured with a message, state, timer, wallet information, and actions. This function is made available to the parent window. ```javascript beacon.DAppClient.beaconSdkDebugEnabled = true const client = new beacon.DAppClient({ name: 'Wallet Toast Example' }) const { openToast } = beacon // Make the function available to the parent window window.showWalletToast = function () { const config = { body: '{{wallet}} has granted permission', state: 'finished', timer: 5000, walletInfo: { name: 'Temple Wallet', icon: '../../assets/logos/ios-temple.png' }, actions: [ { text: 'Address', actionText: 'tz1abc...xyz', isBold: true }, { text: 'Network', actionText: 'Mainnet' } ] } openToast(config) } ``` -------------------------------- ### Initialize Beacon DAppClient Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/ui-testing.html Instantiate a DAppClient for interacting with Beacon. Ensure this is done before using other Beacon SDK features. ```javascript const client = new beacon.DAppClient({ name: 'UI Components Example' }) ``` -------------------------------- ### Initialize Beacon SDK Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/dapp-v3-sapling.html Initializes the Beacon SDK and requests permissions from the user. This method should be called directly after the page loads. ```javascript document.getElementById('externalInit').addEventListener('click', () => { console.log('This method has to be called directly after page load to reproduce the error') client.init().then(() => { console.log('init done') client.requestPermissions().then((permissions) => { console.log('permissions', permissions) if (callback) { callback(permissions) } updateActiveAccount() }) }) }) ``` -------------------------------- ### Initialize Beacon Wallet Client Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/wallet.html Initialize the Beacon WalletClient with a name for your DApp. Optional matrixNodes can be configured for specific network connections. ```javascript const client = new beacon.WalletClient({ name: 'Example Wallet' // Name of the DApp // matrixNodes: { // [beacon.Regions.EUROPE_WEST]: [ // 'beacon-node-1.diamond.papers.tech', // 'beacon-node-1.sky.papers.tech', // 'beacon-node-2.sky.papers.tech', // 'beacon-node-1.hope.papers.tech', // 'beacon-node-1.hope-2.papers.tech', // 'beacon-node-1.hope-3.papers.tech', // 'beacon-node-1.hope-4.papers.tech', // 'beacon-node-1.hope-5.papers.tech' // ], // [beacon.Regions.NORTH_AMERICA_EAST]: [] // } // matrixNodes: ['beacon-node-0.papers.tech:8448'] // matrixNodes: ['beacon.tztip.me'] }) ``` -------------------------------- ### Initiate DAppClient with Abstracted Account Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/abstracted-account.html Initializes the DAppClient for a DApp, configuring it to use an abstracted account with specific WalletConnect options and local storage. ```javascript const dappClient = beacon.getDAppClientInstance({ name: 'Example DApp', // Name of the DApp, disclaimerText: 'This is an optional disclaimer.', appUrl: 'http://localhost:8080', walletConnectOptions: { projectId: '97f804b46f0db632c52af0556586a5f3', relayUrl: 'wss://relay.walletconnect.com' }, storage: new beacon.LocalStorage('DAPP'), preferredNetwork: beacon.NetworkType.GHOSTNET }) ``` -------------------------------- ### Initialize WalletConnect SignClient Source: https://github.com/airgap-it/beacon-sdk/blob/master/examples/wallet-wc.html Initializes the WalletConnect SignClient with project ID and metadata. It also sets up event listeners for session proposals, requests, and deletions. Ensure the SignClient is available in the window scope. ```javascript let signClient = null const projectId = '97f804b46f0db632c52af0556586a5f3' // ← your WalletConnect Project ID // Mock Tezos wallet data let walletData = { address: 'tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb', publicKey: 'edpkvGfYw3LyB1UcCahKQk4rF2tvbMUk8GFiTuMjL75uGXrpvKXhjn', privateKey: 'edsktesttesttesttesttesttesttesttesttesttesttestte', network: { type: 'ghostnet', name: 'Tezos Ghostnet', rpcUrl: 'https://ghostnet.api.tez.ie' } } const setStatus = (status) => { document.getElementById('status').innerText = status ? 'Status: ' + status : 'Status: Ready' } const updateSessionList = () => { if (!signClient) return const sessions = signClient.session.getAll() const sessionList = document.getElementById('session-list') if (sessions.length === 0) { sessionList.innerHTML = '
No active sessions
' } else { sessionList.innerHTML = sessions .map( (session) => `
Session: ${session.topic.substring(0, 8)}... | Peer: ${session.peer.metadata.name}
` ) .join('') } } // Initialize WalletConnect SignClient const initializeWalletConnect = async () => { try { setStatus('Initializing WalletConnect...') const SignClientClass = window.SignClient || window.WalletConnect?.SignClient || window.WalletConnectSignClient?.SignClient || window ['@walletconnect/sign-client']?.SignClient if (!SignClientClass) { throw new Error( 'SignClient not found. Available: ' + Object.keys(window) .filter((key) => key.toLowerCase().includes('wallet')) .join(', ') ) } signClient = await SignClientClass.init({ projectId: projectId, metadata: { name: 'Example Tezos Wallet', description: 'WalletConnect Tezos Example Wallet', url: window.location.origin, icons: [ 'https://assets.website-files.com/61748e1c1c733a4ca33f1dd5/618d5e5faa4beaefd41b7fc8_tezos_symbol_blue.svg', ], }, }) setStatus('Ready') signClient.on('session_proposal', onSessionProposal) signClient.on('session_request', onSessionRequest) signClient.on('session_delete', onSessionDelete) signClient.on('session_expire', onSessionExpire) updateSessionList() } catch (error) { console.error('Failed to initialize WalletConnect:', error) setStatus('Failed to initialize') } } ```