๐Ÿš€
Stellar Kickstart
  • ๐Ÿ•๏ธWelcome to the SCF Kickstart Week
    • ๐Ÿ’ฐFunding Overview
    • โœ๏ธDear changemakers, visionaries, and problem solvers
    • โ„น๏ธTL;DR: How to Maximize Your SCF Kickstart Week Experience
  • ๐Ÿ“šFundamentals of Integrating with Stellar
    • ๐Ÿš€Stellar For
    • ๐Ÿ—๏ธBuilding with Stellar
    • ๐Ÿ”งTools
    • ๐Ÿ‘ทResources
      • Fundamental Concepts
        • โญIntroduction to the Stellar network
        • โ›“๏ธIntroduction to blockchain technology
        • ๐Ÿ’ตIntroduction to payments in Stellar
        • ๐Ÿง‘Accounts
      • Core Features & Mechanisms
        • ๐Ÿ”Assets: Powering Digital Value Exchange
        • Assets Issuance: Manage digital assets effortlessly on Stellar
        • ๐Ÿ’ธTransactions: At Stellar Core
        • ๐Ÿ‘ฎโ€โ™‚๏ธSignatures in Stellar: Who, how much and to what is authorized
      • Payments & Transactions
        • ๐Ÿ’ฐPayments: Simplifying Transactions with Stellar
        • โ›“๏ธPath Payments: Convert Assets at Minimal Cost
        • โ›ฝFee-Bump: How to pay for other people's transactions
      • Developer & Integration Tools
        • ๐Ÿ‘ฉโ€๐Ÿ”ฌStellar Laboratory: Stellar at hand for everyone
        • ๐ŸšชFaucet: Easy Access to Free Blockchain Assets
        • ๐ŸงฐStellar Wallets Kit: A kit to handle all Stellar Wallets at once with a simple API
        • โœ๏ธSimple Signer: A wallet aggregator and transaction signer
      • Advanced Development & Testing
        • ๐ŸงชHow to Create Integration Tests Using GitHub Actions and Stellar's Docker Image
  • ๐ŸŽจDesign Sprint
    • ๐ŸŒ…Introduction
    • 1๏ธโƒฃDay 1 - Validate your problem and define your MVP's Scope
    • 2๏ธโƒฃDay 2 - Build a prototype to validate with real users
    • 3๏ธโƒฃDay 3 - Define the technical architecture
    • 4๏ธโƒฃDay 4: Develop your Go To Market Strategy & Pitch Deck
    • 5๏ธโƒฃDay 5: Compile all the information
    • ๐Ÿ‘€Sample Completed Design Sprint
Powered by GitBook
On this page
  • What Are Wallets in Blockchain?
  • The Role of Blockchain Wallets
  • Why Blockchain Wallets Are Important
  • Why Stellar Developers Should Use Simple Signer?
  • Secure and User-Centric Authentication
  • What Is Simple Signer?
  • Implementing Simple Signer: Step-by-Step
  • 3. Build the Transaction
  • 4. The Sign Endpoint
  • 5. Submit the Transaction
  1. Fundamentals of Integrating with Stellar
  2. Resources
  3. Developer & Integration Tools

Simple Signer: A wallet aggregator and transaction signer

PreviousStellar Wallets Kit: A kit to handle all Stellar Wallets at once with a simple APINextAdvanced Development & Testing

Last updated 3 months ago

In this article, we'll explore Simple Signer, its role in Stellar application development, and how it facilitates secure wallet interactions. Weโ€™ll also look into what wallets are, why theyโ€™re important in blockchain, and how Simple Signer enhances user experience.

Before diving deeper into Simple Signer, letโ€™s take a step back and explore what blockchain wallets are and why they are important.

What Are Wallets in Blockchain?

The Role of Blockchain Wallets

A wallet in the blockchain ecosystem is a software tool that allows users to interact with the blockchain network, store digital assets, and sign transactions securely. Blockchain wallets do not "store" cryptocurrency in the traditional sense; instead, they store private keys that provide access to funds on the blockchain. The private key is essential for signing transactions and ensuring the security and authenticity of the userโ€™s interaction with the blockchain.

There are two types of wallets in the blockchain:

1. Hot Wallets โ€“ These are connected to the internet and offer the ability to send and receive assets instantly. Examples include browser-based wallets like MetaMask, and mobile apps like Trust Wallet.

2. Cold Wallets โ€“ These are offline wallets that provide extra security by storing keys away from the internet, such as hardware wallets like Ledger or Trezor.

In Stellar, wallets play a crucial role because the network relies on them for creating and signing transactions. Without a proper wallet, a user would not be able to perform operations such as transferring funds or interacting with smart contracts.

Why Blockchain Wallets Are Important

1. Security: Wallets ensure the security of funds by using cryptographic keys (public and private keys). Without a private key, the user cannot access or control their digital assets.

2. Transaction Signing: For every transaction that a user wants to make (sending tokens, transferring assets), they must sign it with their private key to prove ownership.

3. Identity Management: Blockchain wallets also act as a decentralized identity system. When a user logs into a dApp or a blockchain-based service, their wallet functions as their identity, providing authentication and authorization.

Why Stellar Developers Should Use Simple Signer?

For developers building on the Stellar network, integrating wallet functionality can be complex. Historically, developers had to rely on libraries for different wallets, making it difficult to maintain a unified authentication and signing process across various user platforms. Simple Signer solves this problem by abstracting away the complexity and providing a consistent, easy-to-use interface for connecting and signing transactions with Stellar-supported wallets.

Secure and User-Centric Authentication

One of the most significant advantages of using Simple Signer is that it keeps private keys secure. The integration does not store or handle private keys directly; rather, the wallet remains in control of the private keys. This approach ensures that users retain full ownership of their assets and that developers are not exposed to the risks of handling private keys. Users are presented with a familiar wallet interface for signing transactions, making the process intuitive and reducing the risk of human error.

What Is Simple Signer?

Simple Signer is a Bigger tool that acts as a wrapper for some of the most commonly used wallets in the Stellar network. Its primary function is to simplify the process of connecting wallets to a website and handling the signing of transactions. It provides two main endpoints for developers: Connect and Sign

Implementing Simple Signer: Step-by-Step

Letโ€™s look at how to integrate Simple Signer into your Stellar-based web application:

1. Include Stellar in our Application

To get started, include the Stellar SDK in your HTML file or install it via npm or yarn if you're using a JavaScript framework.

<script src="https://cdnjs.cloudflare.com/ajax/libs/stellar-sdk/{version}/stellar-sdk.js"></script>

Or, if you're using npm:

npm install --save @stellar/stellar-sdk

or

yarn add @stellar/stellar-sdk

2. Implement the Connect Endpoint

The Connect endpoint is responsible for initiating a wallet connection. When users attempt to log into an application or authorize a transaction, Simple Signer will display a list of supported wallets that the user can choose from. Once a user selects their preferred wallet, Simple Signer returns the public key of the user along with the specific wallet they used to authenticate.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>Simple Signer - Connect Wallet Demo</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <script
            src="https://cdnjs.cloudflare.com/ajax/libs/stellar-sdk/{version}/stellar-sdk.min.js"
            integrity="sha512-EqNQsxKR6rZ5xKl29xXa+ez7xgtVSUpj9UDzZmTqoyF0wHbusLkrP8S7dOsKa9DmkoHbssoWUA4+n/0KYY1EAQ=="
            crossorigin="anonymous"
            referrerpolicy="no-referrer"
        ></script>
    </head>
    <body>
        <button onclick="openConnectWindow()">Connect</button>
        <script>
            const simpleSignerUrl = 'https://sign.bigger.systems';

            function openConnectWindow() {
                window.open(
                    `${simpleSignerUrl}/connect`,
                    'Connect_Window',
                    'width=360, height=450',
                );
            }

            function handleMessage(e) {
                // Reject messages that are not coming from simple signer (tailor this according to your needs)
                if (e.origin !== simpleSignerUrl) {
                    return;
                }
                const messageEvent = e.data;

                if (messageEvent.type === 'onConnect') {
                    const publicKey = messageEvent.message.publicKey;
                    // Validate the public key received. This is just good practice.
                    if (StellarSdk.Keypair.fromPublicKey(publicKey)) {
                        console.log('The public key is', publicKey);
                    }
                }
            }

            // see https://developer.mozilla.org/en-US/docs/Web/API/Window/message_event
            window.addEventListener('message', handleMessage);
        </script>
    </body>

This integration ensures that the user has complete control over their private keys and that their interaction with the Stellar network remains secure. The website or application using Simple Signer can then decide how to store or use the public key, depending on the applicationโ€™s business logic.

3. Build the Transaction

The Sign endpoint is used for handling the signing of transactions. While Simple Signer handles wallet connection and transaction signing, it does not create the transaction itself. Developers are still required to build the transaction, which includes defining the operations and parameters (such as the amount, destination address, and asset type).

import { Server, BASE_FEE, Networks, Asset, Operation, Memo, TransactionBuilder } from 'stellar-sdk';
import TransactionBuilderError from '../errors/TransactionBuilderError';

const server = new Server(process.env.VITE_HORIZON_URL);

export async function buildTransaction(publicKey: string): Promise<string> {
    try {
        const sourceAccount = publicKey;
        const accountResponse = await server.loadAccount(sourceAccount);

        return new TransactionBuilder(accountResponse, {
            fee: BASE_FEE,
            networkPassphrase: Networks.TESTNET,
        })
            .addOperation(
                Operation.payment({
                    destination: process.env.VITE_DESTINATION_PUBLICKEY,
                    amount: '200',
                    asset: Asset.native(),
                }),
            )
            .addMemo(Memo.text('Tx test'))
            .setTimeout(0)
            .build()
            .toXDR();
    } catch (error) {
        throw new TransactionBuilderError();
    }
}

4. The Sign Endpoint

Once you generate the transaction you want the user to sign, you can present it using the /sign endpoint. Simple Signer will send a message back to your website with the signed transaction.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>Simple Signer - Sign Transaction Demo</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/stellar-sdk/{version}/stellar-sdk.min.js" integrity="sha512-EqNQsxKR6rZ5xKl29xXa+ez7xgtVSUpj9UDzZmTqoyF0wHbusLkrP8S7dOsKa9DmkoHbssoWUA4+n/0KYY1EAQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    </head>
    <body>
        <button onclick="openSignWindow(unsignedXdr)">Sign</button>
        <script>
            // This XDR may be constructed using the public key obtained from /connect, this is just an example.
            const unsignedXdr = 'AAAAAgAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAZAADGyCAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAAAAAAAAAvrwgAAAAAAAAAABAAAAAOGpdPW3p7zkOVQPIzk7OYnYo+a6NfyB6ADTbse8pIylAAAAAAAAAAAC+vCAAAAAAAAAAAEAAAAA4al09benvOQ5VA8jOTs5idij5ro1/IHoANNux7ykjKUAAAAAAAAAAAL68IAAAAAAAAAAAQAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAAAAAAAAAvrwgAAAAAAAAAAA';

            const simpleSignerUrl = 'https://sign.bigger.systems';

            async function openSignWindow(xdr) {
                const signWindow = window.open(
                    `${simpleSignerUrl}/sign/?xdr=${unsignedXdr}`,
                    'Sign_Window',
                    'width=360, height=700',
                );

                window.addEventListener('message', (e) => {
                    if (e.origin !== simpleSignerUrl) {
                        return;
                    } else if (signWindow && e.data.type === 'onReady') {
                        signWindow.postMessage(
                            { xdr, description, operationGroups },
                            simpleSignerUrl,
                        );
                    }
                });
                return signWindow;
            }

            async function handleMessage(e) {
                if (
                    e.origin !== simpleSignerUrl &&
                    e.data.type === 'onSign' &&
                    e.data.page === 'sign'
                ) {
                    const eventMessage = e.data;

                    const signedXdr = eventMessage.message.signedXDR;
                    // Validate the XDR, this is just good practice.
                    if (
                        StellarSdk.xdr.TransactionEnvelope.validateXDR(
                            signedXdr,
                            'base64',
                        )
                    ) {
                        const server = new StellarSdk.Server(
                            'https://horizon-testnet.stellar.org/',
                        ); //remember to update this to the correct value

                        // Construct the transaction from the signedXDR
                        // see https://stellar.github.io/js-stellar-sdk/TransactionBuilder.html#.fromXDR
                        const transaction = 
                            StellarSdk.TransactionBuilder.fromXDR(
                                signedXdr,
                                'Test SDF Network ; September 2015', //remember to update this to the correct value
                            );

                        try {
                            const transactionResult =
                                await server.submitTransaction(transaction);
                            console.log(transactionResult);
                        } catch (err) {
                            console.error(err);
                        }
                    }
                }
            }
            window.addEventListener('message', handleMessage);
        </script>
    </body>
</html>

Once the transaction is built, Simple Signer will present the user with a sign-in prompt, where the user is asked to confirm the transaction. After the user signs the transaction, Simple Signer will return the signed transaction data (in XDR format), which can then be submitted to the Stellar network for processing.

You may choose to pass the unsigned transaction XDR to Simple Signer either via URL or via postMessage.

Via URL:

const unsignedXdr = AAAAAgAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAZAADGyCAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAAAAAAAAAvrwgAAAAAAAAAABAAAAAOGpdPW3p7zkOVQPIzk7OYnYo+a6NfyB6ADTbse8pIylAAAAAAAAAAAC+vCAAAAAAAAAAAEAAAAA4al09benvOQ5VA8jOTs5idij5ro1/IHoANNux7ykjKUAAAAAAAAAAAL68IAAAAAAAAAAAQAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAAAAAAAAAvrwgAAAAAAAAAAA';
const signWindow = window.open(
    `https://sign.bigger.systems/sign/?xdr=${unsignedXdr}`,
    'Sign_Window',
    'width=360, height=700',
);

Via PostMessage:

const unsignedXdr = 'AAAAAgAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAZAADGyCAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAAAAAAAAAvrwgAAAAAAAAAABAAAAAOGpdPW3p7zkOVQPIzk7OYnYo+a6NfyB6ADTbse8pIylAAAAAAAAAAAC+vCAAAAAAAAAAAEAAAAA4al09benvOQ5VA8jOTs5idij5ro1/IHoANNux7ykjKUAAAAAAAAAAAL68IAAAAAAAAAAAQAAAADhqXT1t6e85DlUDyM5OzmJ2KPmujX8gegA027HvKSMpQAAAAAAAAAAAvrwgAAAAAAAAAAA';
const simpleSignerUrl = 'https://sign.bigger.systems';
const signWindow = window.open(
    `${simpleSignerUrl}/sign`,
    'Sign_Window',
    'width=360, height=700',
);

window.addEventListener('message', (e) => {
    if (
        e.origin !== simpleSignerUrl &&
        e.data.type === 'onReady' &&
        e.data.page === 'sign'
    ) {
        signWindow.postMessage({ xdr: unsignedXdr }, simpleSignerUrl);
    }
});

It is important to note that Simple Signer only handles signing transactions and connecting wallets. The actual submission of transactions to the Stellar network is the responsibility of the application. Simple Signer does not interact directly with the Stellar blockchain but ensures that transactions are securely signed and ready for submission.

Once the user signs the transaction, you will receive the signed transaction in XDR format, which can then be submitted to the Stellar network.

5. Submit the Transaction

                        try {
                            const transactionResult = await server.submitTransaction(transaction);
                            console.log(transactionResult);
                        } catch (err) {
                            console.error(err);
                        }

Conclusion

Simple Signer is a powerful tool for Stellar developers looking to simplify wallet connections and transaction signing. By abstracting the complexity of interacting with different wallets, Simple Signer provides an easy-to-use, secure, and flexible solution for managing blockchain interactions. Developers can focus on building robust applications while leaving the intricate details of wallet connectivity and signing to Simple Signer.

With Simple Signer, Stellar developers can ensure a seamless, secure user experience while supporting multiple wallet types. This allows users to maintain control over their private keys and sign transactions with confidence, further reinforcing the core principles of decentralization in the blockchain ecosystem. Whether you're building a payment system, a cross-border remittance app, or a dApp on Stellar, integrating Simple Signer should be a key part of your development workflow.

Resources:

Simple Signer simplifies the process by offering two main endpointsโ€”Connect and Signโ€”and it supports various popular wallets in the Stellar ecosystem such as , , , , and . Developers can leverage Simple Signer to avoid writing custom integrations for each wallet, which saves time and reduces the chances of bugs.

has some advantages over the URL method which are covered in the Sign API section.

Finally, once the transaction is signed, you can submit it to the Stellar network using the appropriate Stellar SDK (e.g., ).

-

-

๐Ÿ“š
๐Ÿ‘ท
โœ๏ธ
Lobstr
xBull
Freighter
Albedo
Rabet
WalletConnect
Post Message
@stellar/stellar-sdk
Simple Signer - GitHub Repository
Simple Signer - Integration Example