Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 117 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

v1.0

Loading...

Concepts

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Simple link / QR

Loading...

Loading...

Environments

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

JS/TS SDK

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Developer Education

If you want to learn more about the XRP Ledger first (concepts, transaction types, etc.) we have a great resource for you at https://learn.xumm.dev:

Getting started

Xaman allows developers and app users to "meet up".

While app users can simply use the Xaman application interact with the XRP Ledger with their accounts, balances and transactions, the true power of Xaman is unleashed through the platform available for developers.

This way users can interact with third party tools & platforms in the most secure and convenient way, while developers don't have to worry about wallet & key management.

Concept

XRP Ledger transactions are traditionally user initiated: users open their wallet, enter the destination, amount, etc. and then you submit a transaction. This is referred to as a Push Transaction.

In retail / e-commerce & third party interaction scenarios, the ideal flow is inverted: a Pull Transaction. The third party environment wants the user to sign a specific transaction, and a transaction to sign is offered to the user.

This is where the Xaman platform comes in. An XRP Ledger transaction template can be delivered to the end user through the Xaman platform. This is called a Sign Request.

Interaction

The most convenient way to interact with the Xaman platform is through the JavaScript/TypeScript SDK: . There are also some other SDKs available for Backend use in other languages:

Language
Maintenance
Package

The Xaman platform allows for easy integration in your application & workflow. Make sure to check the documentation for your environment:

Build on Xaman

You focus on building your cool app. We make sure your app & Xaman users can interact. Safely & smoothly.

Welcome to the Xaman Developer Docs! Xaman is a powerful platform designed to make your interaction with the XRP Ledger (XRPL) seamless. Whether you are an experienced developer or just getting started, Xaman offers a range of features, including xApps, payloads, transaction signing, and much more. This documentation will guide you through the essentials to get you up and running in no time.

While app users can simply use the Xaman app to manage their XRP ledger accounts, balances and transactions, the true power of Xaman can be experienced through the Xaman SDK, using our platform made available for developers.

Want to dive straight in? You're one click away from the

QR Scanning

QR scanning is an engaging way to have users interact with payloads, especially in physical mediums. It is simple, quick, and versatile.

Benefits of QR Scanning:

  • Use Cases: QR scanning is common in retail scenarios or multi-device interactions. It is perfect for physical interaction, Point-of-sale terminals, or when users interact across devices (desktop to mobile).

Mobile (iOS/Android)

Mobile payload delivery is essential for a seamless experience in mobile applications.

Payload delivery from your native iOS / Android app happens through "Deep Links".

Deep Linking allows your mobile app to communicate directly with the Xumm app, enabling users to interact with payloads effortlessly.

For a detailed guide on implementing mobile payload delivery through Deep Linking, please refer to the page.

Multi-Device Scenarios: In cases like desktop to mobile, users can scan the QR code on the desktop screen with their mobile device. Typically, there's no need for a return URL as the desktop browser can pick up the results.

  • How It Works: Generate a QR code for the payload using Xumm. Users scan this QR code with the Xumm app to access and interact with the payload.

  • User Perspective:

    For end users, QR scanning is intuitive and engaging. They scan the QR code with their mobile device and are immediately taken to the payload in the Xumm app. This method is particularly effective in retail environments or when users operate across multiple devices.

    Deep Linking

    Deep Linking

    Deep linking in Xumm enables developers to provide a seamless user experience by swiftly guiding users to interact with payloads.

    Deep Links are a well known flow to allow users to automatically launch and open another app in a specific state. Xumm allows for a Deep Link workflow, where your application (browser based or native) can trigger Xumm to open and immediately show your sign request.

    Benefits of Deep Linking:

    • When to Use: Opt for deep linking when you want to minimize user steps and create a fluid transition between your app and Xumm.

    • Device Compatibility: Deep linking works when the origin (your app or browser) and Xumm are on the same device (iOS/Android).

    • Link Creation: Generate a deep link that opens Xumm with the payload ready for interaction, making interactions more seamless while keeping users engaged.

    • Return URL: Set a return URL in the payload to redirect users back to your app or browser post-interaction, maintaining a smooth flow.

    Note for Web Origins:

    For web origins, users return to the default browser, not necessarily the original tab. In order to make this smooth, handle session restoration to ensure continuity.

    User Perspective:

    For end users, deep linking is a breeze. They tap a link, interact with the payload in Xumm, and return to your app effortlessly.

    PaymentChannelAuthorize

    To authorize a Payment Channel, an off ledger "receipt" must be signed. This is implemented in Xaman through a 'Pseudo Transaction' with TransactionType `PaymentChannelAuthorize`.

    PaymentChannelAuthorize is normally a 'Command' or locally signed object. Implemented in Xumm as a TransactionType (which it actually isn't, also: the resulting signed blob can never be submitted to an XRPL node as is). For more information, see: https://xrpl.org/use-payment-channels.html

    Sample PayChan transactions (gist):

    https://gist.github.com/WietseWind/c7b6addfd9b8cb465894209cc9073c47

    Note: the PaymentChannelAuthorize transaction type is useful when you want to authorize a payment channel without submitting a transaction to the XRPL.

    Limitations

    Special Transaction Types

    In Xaman, you can use all XRPL transaction types when sending a JSON transaction payload. However, some special transaction types are unique to Xaman, or require some extra info to use them.

    SignInBatch (multiple inner signers)PaymentChannelAuthorize

    Xumm.off(event, fn)

    See on(xAppEvent, fn)

    Examples / User stories

    Xumm.helpers { … }

    SDK (syntax)

    Developers can use the Xumm SDK to easily interact with the Xumm platform. This section contains the technical documentation for the Javascript/TypeScript API (objects, methods, arguments).

    Signature verification

    Signature verification is crucial for ensuring the integrity and authenticity of the data received. It involves verifying that the data was sent by Xumm and has not been tampered with.

    If you want to make sure a WebHook received by your platform has been sent by the Xumm platform, verify the signature the platform sends in an HTTP header.

    Every WebHook call contains a signature to verify the authenticity. It sends an HMAC using your application secret as a key. Sample verification in NodeJS:

    import crypto from 'crypto'
    
    // Xumm App secret (Xumm developer console)
    const secret = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
    
    const timestamp = req.headers?.['x-xumm-request-timestamp'] || ''
    const json = req.body
    
    const hmac = crypto.createHmac('sha1', secret.replace('-', ''))
      .update(timestamp + JSON.stringify(json))
      .digest('hex')
    
    console.log(hmac, hmac === req.headers?.['x-xumm-request-signature'])

    getRates( … )

    Get aggregated exchange rates vs. XRP for most fiat & crypto assets.

    The getRates method allows you to get the exchange rates for an XRP <> requested pair. The source information is aggregated from several data providers.

    const rate = await Sdk.getRates('BTC');

    Example response

    {
    	"USD": 1,
    	"XRP": 0.52069,
    	"__meta": {
    		"currency": {
    			"en": "US Dollar",
    			"code": "USD",
    			"symbol": "$",
    			"isoDecimals": 4
    		}
    	}
    }
    Ways to interact

    The Xaman SDK can be used to interact with Xaman users. An example can be a "sign request", where the user is asked to sign a transaction, identification (sign in) or a user interface presented in Xaman (xApp).

    What are you going to build? Read more about specific user & developer flows:

    Packages

    The Xaman SDK offers a ready to use Javascript & Typescript SDK for all frontend and backend projects. With only minor differences depending on the environment you are using the SDK in, the SDK is the most convenient way to interact with Xaman users & the Xaman ecosystem.

    If you are not working in a Javascript/Typescript environment and prefer to build your own backend implementation, you can use our API (endpoint) documentation or use one of our SDKs for Python (PyPI), PHP (Packagist) or C# (NuGet)

    Language
    Maintenance
    Package

    Typescript / Javascript

    XRPL Labs ⭐

    /

    Python

    Community

    C# (.NET)

    Community

    PHP

    Community

    Examples / User stories

    Typescript / Javascript

    XRPL Labs ⭐

    / CDN

    Python

    Community

    C# (.NET)

    Community

    PHP

    Community

    https://github.com/XRPL-Labs/Developer-Help-Center/blob/main/concepts/broken-reference/README.md
    🌎Browser ("Web3")
    📱xApps ("dApps")
    📂Backend (SDK / API)
    🎛️Native Apps

    Terminology

    Essential terms and concepts to help you better understand and utilize the powerful features of the Xaman Wallet platform.

    Xaman

    The self custodial wallet application for iOS and Android developed by XRPL Labs. The app can be used by end users to manage their XRP Ledger account(s) and interact with the "Xaman Platform" (see below) through "Sign Requests" (see below).

    Xumm

    The previous name of Xaman, Xaman is formerly known as Xumm (and has rebranded). Some references in these docs may still point to our old name.

    Xumm Platform

    The platform your application and the Xaman app (iOS/Android) interact with. For developers, the platform offers the ability to send "Sign Requests" (see below) to the platform's "API" (see below). The Sign Request can then be interacted with by Xaman app users.

    Xaman API

    The endpoints providing features to developers & integrated applications. The API endpoint reference can be found here: but a more convenient way to interact with the Xaman Platform is through our SDK's (packages):

    Developer Console

    The Developer Console is where you can get your credentials (API Key & secret) and configure your Xaman platform integration. You can find the Xaman Developer Console at

    Documentation

    This website:

    Payload Delivery

    Payload delivery in Xumm is a crucial step in the transaction lifecycle. It involves delivering the payload to the user for signing.

    What is a Payload?

    In Xumm, a payload is a sign request sent by applications or developers to users for interaction. Users review the payload and decide to reject or accept by signing.

    Delivery Methods

    Xumm offers various payload delivery methods:

    • Deep Linking: Open the Xumm app with the payload already loaded.

    • QR Code Scanning: Users scan a QR code to access the payload.

    • Push Notifications: Send payloads as push notifications.

    Status Updates

    After delivering a payload, tracking its status is vital to know whether the user has interacted with it. Xumm provides mechanisms for obtaining notifications and results of payload interactions. You can learn more about this in the section.

    Moving Forward

    Now that you have an overview of what payload delivery entails in Xumm, you can delve into the specifics of each delivery method.

    Status updates

    Xumm's Payload status updates bridge the gap between your application and the end user by providing real-time feedback on payload interactions.

    Overview

    When users interact with payloads, Xumm provides real-time status updates and results (e.g., rejected, signed with signature). These updates allow you to make your application user interface reflect the status of the interaction with the user, and return sign request results to your application.

    Real-Time Status Updates

    • Keep track of user interactions with the payload.

    • Update the UI to reflect statuses like "opened" or "signed".

    • They provide status but not the final resolved data (for security reasons, resolved data like signatures can only be separately fetched from the Xumm platform).

    Websocket Usage

    • Receive real-time updates in your front-end and back-end.

    • Frontend: Keep the user informed about the status.

    • Backend: Determine when you can fetch final results.

    • This ensures responsiveness and keeps the end-user informed.

    Fetching End Results

    • Webhook: Once the payload is resolved, a Webhook can be sent to your platform for backend processing. For more on WebHooks, see .

    • API/SDK: Alternatively, fetch the payload end results using the Xumm API or SDK for more control and flexibility.

    Status Updates for End users

    Understanding the end user's workflow/experience is vital. The real-time status updates and Webhooks are not just technical tools but communication channels between your application and the user.

    By effectively using these features, you ensure an engaging and informed experience for the user.

    Rate limits

    To prevent excessive load on our platform, the Xumm platform applies rate limits. The limits depend on the type of consumer (regular API, SDK, JWT) and endpoint(s).

    On average, the Xumm platform allows API consumers to make between 60~200 calls per minute. These numbers depend on the load on the platform and the use of the API consumer.

    Some endpoints have lower limits, e.g.:

    • POST a Payload (sign request) on average allows for sending 30 payloads per minute

    • Fetching TXs (no need to use our platform, best use a native XRPL WebSocket connection): 60 requests per minute

    • KYC status: 600 calls per minute

    • Account metadata: 120 calls per minute

    To make sure you are not hitting the API limits, every call to our API returns two response headers:

    • X-RateLimit-Limit (e.g.: 30)

    • X-RateLimit-Remaining

    These numbers are not guarantees: they are averages and can be adjusted by our platform on the fly, based on your overall API call behaviour & end user interaction(s).

    Raising API limits

    If there are good reasons to assign elevated API limits, we're happy to have a discussion to hear about the reasons how your application consumes the Xumm API, and why your application needs higher limits. Please .

    API limits will only be raised if:

    • Your app does not use polling techniques: to retrieve the status of a payload, use the websocket we provide for status updates (or the createAndSubscribe / subscribe method provided by the SDK: / ). Backend applications can also use a webhook: .

    • (If your app is an xApp) - Your app respects the xApp \

    API Call (polling)

    Polling, or repeated API calls, is a common method to fetch updates. However, in Xumm, it's not the recommended approach due to rate limits.

    Instead of polling, consider these efficient alternatives:

    • Webhooks: Once a payload is resolved, Xumm can send a WebHook to your platform, eliminating the need for constant polling. Learn more: Webhooks.

    • Websocket Subscription: Use Websocket to receive live status updates. Learn more: Websocket.

    Excessive polling can lead to your application being temporarily rate limited, disrupting your service. If your application has been rate limited, you will receive a notification email later the same day on the e-mail address entered in the application details in the .

    Sample POS lifecycle

    Transaction types

    Xumm supports a wide range of transaction types to cater to various use cases on the XRPL. Here's what you need to know:

    • Standard Transaction Types: Xumm accepts all mainnet XRPL transaction types.

      • Exception: Transaction types for non-voted in amendments may be unavailable

      • Payment Channel signature types (non-transaction, receipt) are not yet supported (to be added in Xumm 2.5.0)

    • Pseudo-Transaction Types: One pseudo-transaction type: SignIn -

    • Limited Transaction Types:: Some transaction types, such as setting a Regular Key or setting a Signer List (multisign), require special permission for user security reasons:

      • Setting a Regular Key

      • Setting a Signer List (multisign)

    Test Tools

    Trying to get your OAuth2 / OpenID integration to work? There are a couple of tools to help you test things.

    Payloads (sign requests)

    Xumm Payloads: creating, delivering, and utilizing incomplete XRP Ledger transactions as a Sign Request to end users.

    The difference between XRP Ledger Transaction JSON and a Xumm Payload is that the XRP Ledger JSON needs to be complete and signed locally, while a Xumm Payload can contain an incomplete transaction.

    The incomplete transaction, referred to as a Transaction Template, can be delivered to Xumm users allowing end users to view the Payload in the form of a "Sign Request": a transaction to sign and submit, or reject.

    Xumm will then add the missing fields like the signer account, network Fee, Account Sequence, based on the context the user provides.

    Xumm Payloads use the exact same syntax as the XRP Ledger JSON transaction format.

    To easily test a payload, you can enter the Transaction JSON template on this page and try to create a payload:

    Workflow

    Xumm's workflow is designed to streamline the process of transaction signing and interaction with the XRP Ledger.

    Here's a step-by-step guide to understanding and implementing Xumm's workflow in your application:

    1. Create a Payload: Start by using Xumm's API to create a payload. A payload is essentially a transaction template containing all the details for the transaction you want the User to sign.

    2. Deliver the Payload to the User: Once the payload is created, you need to deliver it to the User for signing. Xumm offers multiple delivery options, including push notifications, QR codes, and deep links. Choose the method that best suits your application.

    Lifecycle

    Xumm's transaction lifecycle is a sequence of steps that ensures secure and efficient transaction processing on the XRP Ledger.

    Here's a comprehensive guide to understanding and implementing Xumm's transaction lifecycle:

    1. Transaction Template

    Start by composing the transaction you want to be signed in JSON format, as per the . You can include all except "Account" and "Sequence", which will be automatically filled by Xumm.

    Therefore, any JSON value you'd use to sign and send to an XRPL node can be sent to the Xumm SDK/API, with the (signing) account fields being added/filled being the only major difference.

    CORS (Browser)

    CORS (Cross-Origin Resource Sharing) is a security feature that restricts a web page from accessing resources from another domain. Xumm allows for CORS calls to JWT endpoints.

    CORS (Cross-Origin Resource Sharing) is a mechanism that allows a web page from one origin (domain) to access resources from another origin. In other words, it is a security feature implemented by web browsers that restricts a web page from making requests to a different domain than the one that served the web page.

    The Xumm API endpoints allow cross origin requests: we want your web application to be able to make calls to the Xumm platform using the credential (JWT) you have received when a user logged in.

    If you are building a integration, CORS is irrelevant.

    If you are building something in the browser (a web application), the most convenient way to interact with the Xumm platform is through the Javascript/TypeScript SDK: .

    Networks

    The Xumm API/SDK is designed to be network-independent, providing flexibility for developers and end users. This means that the end user determines the network on which transactions occur.

    However, a payload can include a forced network identifier to specify a particular network. When a user signs a payload, the result includes information about the network the user was on when signing, allowing developers to track and manage transactions across different networks.

    If your payload contains a NetworkID, it is only valid for the given network. Xumm will ask a user to switch to the given network (starting Xumm 2.6.0)

    Desktop browser

    For web applications accessed through desktop browsers, Xumm provides an optimized delivery method.

    This includes options like QR code scanning and deep linking, adapted for larger screens.

    • If you can't already identify the user, refer to the

    • If you have already identified the user and obtained a user_token, refer to the

    Develop & Test

    When building xApps, there are some tools to make building & sharing your xApp easier.

    While developing your xApp, you may want to easily test & debug your web application. You may even benefit from live reaload during development. You can expose your local development environment with a tool like or and configure your public URL as your xApp URL.

    You can get access to the remote browser console using the techniques explained in the article.

    If you want to share your xApp with a small group of testers or team members, you can ask them for their Xumm Device Identifier (Xumm - Settings - Advanced). You can add up to 10 Device Identifiers as xApp testers, so they can open your sandboxed xApp.

    Warning! If you have multiple xApps (e.g. a live version & a test version, pointing to your development URL) please make sure to use the right API Key, otherwise your app can't communicate with the Xumm backend. Also note things like

    TrustSet Link/QR

    If you simply want to offer users a static link / QR code to sign a specific XRPL transaction, you can craft a link (to be offered directly or as contents of a QR code) for users to click / scan.

    Offering a direct link / QR code to a payload does not come with the advantages of creating a of getting live feedback & webhooks based on the user's engagement.

    The advantage of a simple Sign Link / QR is that you can craft the link / QR once, and it will be available for all users without further code implementations.

    Simple Sign Link/QR is available for the following transaction type(s)

    • TrustSet (adding a Trust Line, a.k.a. adding a Token)

    Payload Return URL

    After a user signs a payload, a user can return to a URL (your website / app).

    The Return URL (return_url) determines where the user is sent when the payload is signed. If none is given, the user will simply be displayed Close button in Xumm. Otherwise, the user will be presented a button which launches the Return URL.

    Warning! iOS and Android do not allow the user to return to the browser tab they came from (if your flow starts in a browser). Make sure you restore state based on the payload / session / custom identifier or custom metadata assigned to the payload.

    SignIn

    The `SignIn` payload is a "Pseudo transaction type": an off ledger transaction specific to Xaman, which can be used to identify a user and obtain a token to push sign requests to the end user.

    Note that the SignIn transaction type is already embedded in the Xaman SDK and OAuth flows. You only need the SignIn transaction type if you are manually building your own integrations (e.g. API integrations:)

    The SignIn transaction type is Xaman specific, signature only, can never be submitted. When sending a JSON transaction payload, you can use all XRPL transaction types, including a Xumm-specific "pseudo transaction type": SignIn.

    The payload for a SignIn transaction can look like this:

    Payment Request Link

    To route users to a simple payment request, all you need to use is a URL / QR containing that URL, crafted with the right parameters.

    To offer users a direct payment link, you can send them straight to a URL (deeplink) or QR containing that same URL. The URL already contains destination, network, currency & other parameters.

    Note: Payment Requests will request for the given asset to be delivered to the given destination account. The Xaman user will be offered an interface where they can choose to send any asset they own that can satisfy delivering the requested amount. This means that if you verify the transaction recieved, you must take into account that the transaction can contain an asset sent by the user that differs from the asset delivered to you.

    Tx Explorer(s)

    To easily link to transaction explorers, you can link to the Xumm explorer launchpad and allow users to pick their preferred explorer.

    Don't keep a list of explorer links youself: you can easily rely on our explorer launchpad URL.

    When using TX Hash

    The network param can be mainnet, xahau and any other key from the rails endpoint

    getTransaction( … )

    Fetch an XRPL transaction & metadata. Please don't use this method unless absolutely necessary: please set up your own connection to an XRPL node to fetch this information.

    The getTransaction method allows you to get the transaction outcome (mainnet) live from the XRP ledger, as fetched for you by the XUMM backend.

    Note: it's best to retrieve these results yourself instead of relying on the XUMM platform to get live XRPL transaction information! You can use the package to do this:

    Returns:

    getRails()

    Fetch the available (known) networks and network parameters.

    The getRails method allows you to get the network information for all networks known to Xumm.

    Returns:

    getNftokenDetail( … )

    Get NFT Token details. Only available in JWT context. Please fetch your NFT info from other NFT data sources if possible.

    This method is only available when using the SDK in a JWT context!

    The getNftokenDetail method allows you to get basic XLS20 token information as fetched/parsed/cached for you by the XUMM backend.

    Note: it's best to retrieve these results yourself instead of relying on the XUMM platform to get live XRPL transaction information!

    Returns:

    Sign Requests (payloads)

    A sign request in Xumm is a prompt to approve a transaction or action on the XRP Ledger. This page will show you how you can create a Sign Request, and how you can deliver the request to the end user.

    getHookHashes()

    Get the meta information for all known Hooks. Object returned contains Hook hash as key, meta as value.

    Sdk.getHookHashes()

    The getHookHashes allows you to get all meta information for all Hooks known to Xumm.

    Returns:

    ping()

    Contact the Xumm platform to check for connectivity and valid auth.

    The ping method allows you to verify API access (valid credentials) and returns some info on your XUMM APP:

    Returns :

    close({ … })

    Close the xApp

    Parameters

    The refreshEvents param. is optional. If passed (and true) the Event list will be forcefully refreshed (updated) when the xApp closes. This can be useful if the xApp closes programatically after e.g. resolving (cancelling) or signing a Sign Request.

    navigate({ … })

    Navigate to another xApp (by identifier)

    Warning! This command is permissioned. To use it in your xApp, please contact Xumm, explain the user flow & use case and share your API key so we can discuss granting your xApp this permission.

    Parameters

    scanQr()

    Scan a QR code

    Syntax

    Response

    Returns an event: qr

    openSignRequest({ … })

    Open a Sign Request (payload) created with Xumm.payload.create

    Parameters

    Syntax

    share({ … })

    Use the OS Share-dialog to share text or a URL

    Parameters

    Syntax

    openBrowser({ … })

    Open an external URL in the OS default browser

    Calling the openBrowser method will trigger a dialog for the end user to confirm leaving Xumm & opening a browser page. Only under certain conditions this confirmation dialog can be waived on a per xApp, per developer basis.

    Parameters

    User Interaction: The User will interact with the payload through the Xumm app. They have the option to either sign or reject the transaction.

  • Retrieve the Result: After the User has interacted with the payload, your application needs to retrieve the result Status updates. This can be done by fetching the result from Xumm's API. The result will indicate whether the User signed or rejected the transaction.

  • Interact with the XRP Ledger: If the User signed the transaction, your application can now interact with the XRP Ledger to finalize the transaction. This involves submitting the signed transaction to the XRP Ledger and handling any responses or confirmations.

  • Provide Feedback to the User: Finally, provide appropriate Feedback based on the transaction's outcome. This could be a confirmation message for a successful transaction or an error message if something went wrong.

  • By following these steps, you can effectively integrate Xumm's workflow into your application and leverage its features for secure and streamlined transactions on the XRP Ledger.

    Key Points:
    1. Network Independence: The Xumm API/SDK operates independently of the network, giving the end user the freedom to choose their preferred network in the Xumm app.

    2. Network Information in Results: The results of a signed payload include information about the network the user was on at the time of signing.

    3. Forced Network Identifier: A user can be on any network while signing. You must check for the expected result in the Payload results. Alternatively, you can include a forced network identifier in a payload to specify a particular network.

    4. Network Information in OTT Data: xApp OTT data also includes network information, providing additional resources for developers to manage transactions.

    5. User Experience: The choice of the network result in loss of goods or funds: imagine getting paid on Testnet, while delivering actual sold goods expecting a mainnet payment. It's important to consider this in your application development process.

    Example URLs

    A simple payment on Xahau for 2 XAH (native asset) to the rwietse... account:

    https://xaman.app/detect/request:rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ?amount=2&network=XAHAU

    A payment on the XRP Ledger for 2 $RLUSD to the rwietse... account: https://xaman.app/detect/request:rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ?amount=2&network=XRPL&dt=123&issuer=rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De&currency=524C555344000000000000000000000000000000

    Variants (universal)

    If the user does not have Xaman installed, the above links will automatically fall back to a regular webpage showing the payment request information & download links to Xaman. If you however want to craft a link / QR that is not Xaman specific, you can use a protocol prefix which can be claimed by any XRPL supporting app in the ecosystem. The downside is that if one does not have a supporting app installed, there is no graceful fallback webpage.

    Instead of prefixing with https://xaman.app/detect/request you can prefix with the xrpl:// protocol handler:

    xrpl://rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ?amount=2&network=XRPL&dt=123&issuer=rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De&currency=524C555344000000000000000000000000000000&invoiceid=0CAFEBABE000DEADBEEF000CAFEBABE000DEADBEEF000CAFEBABE000DEADBEEF

    Parameters

    • amount - The amount in native asset or issued currency to request - can be omitted, the user can then enter the amount

    • network - The network the transaction should be sent on, can be XRPL or XAHAU, can be omitted, defaults to XRPL

    • dt - The Destination Tag to send to - can be omitted

    • invoiceid - The InvoiceID to send, must be formatted in HEX according to the InvoiceID length specifications (64 hex chars) - usually omitted

    • issuer - The issuing account, only required combined with currency for requests in issued currencies

    • currency - The currency code, must be in three-char ALPHA notation or HEX notation for issued currencies with asset codes > 3 char length. Only required in combination with issuer for payments in issued assets.

    App Developers

    For App/Platform developers, there's an easy JS lib. to decode strings & parse them into normalised objects to support payment requests (and other ecosystem data formats):

    https://www.npmjs.com/package/xumm-string-decode

    Status updates
    Webhooks
    https://github.com/XRPL-Labs/Developer-Help-Center/blob/main/js-ts-sdk/sdk-syntax/xumm.payload
    (e.g. 21)

    These headers return the results of the current requests allowed per minute, and the amount remaining in the current (sliding) minute.

    contact Xumm Support
    createAndSubscribe( … )
    createAndSubscribe( … )
    Webhooks
    Requirements
    Xumm Developer Console
    User identification payloads

    API Documentation

    API endpoint reference: https://xumm.readme.io/reference

    Sign Request

    When you send a call to the Xumm Platform to ask a user to sign a transaction, you are creating a "Sign Request". You are delivering a "Payload" (see below) to the Xumm platform, containing the transaction template you would like the user to sign & possibly some options. You obtain a unique UUID (identifier) to the Sign Request to get real time status updates, Webhooks upon status change & when signed: the on ledger Transaction Hash and signed transaction.

    Payload

    The Payload (JSON formatted) is part of a Sign Request. It contains the Transaction Template to offer to the end user to sign. The Payload matches the formatting, fields & properties of native XRP Ledger transactions, except for the fact that some fields (like Fee, Account, Sequence) can be omitted as Xaman can add these for you.

    xApp

    An xApp is a Web App (HTML, JS, CSS) that can be opened inside Xaman by users, straight from and in Xaman. See xApps ("dApps")

    Frontend

    When referred to Frontend, we refer to your frontend: the HTML/JS/CSS application you are building, where you are integrating Xaman as xApps ("dApps")or Browser ("Web3") application.

    Backend

    When referred to Backend, we refer to your backend application. If you are building an xApp or Web3 (Browser) app, you may not have and may not need your own backend. If you are building a backend integration (e.g. headless application, backend for your own Frontend application), please see Backend (SDK / API)

    SDK

    The most convenient way to interact with the Xaman Platform is through our SDK's (packages): https://docs.xumm.dev/#packages

    JWT

    JSON Web Token: the authorization bearer as provided by Xaman when using the xApps ("dApps") or Browser ("Web3") flow. Valid for 24h, bound to the Xum App user, you can call the Xaman platform to create Sign Requests & more.

    OTT

    "One Time Token", specific to xApps. Automatically handled for you when using our Javascript/Typescript SDK.

    https://xumm.readme.io/reference
    https://docs.xumm.dev/#packages
    https://apps.xumm.dev
    https://docs.xumm.dev
    All fields and values in the JSON transaction template sent to the Xumm SDK/API are passed on as-is, except for the following:
    1. Account: If this field is part of the transaction template, it will be completely ignored, as the Account will be automatically filled based on the account the end user uses to sign the transaction with in the Xumm app.

    2. Sequence: Based on the account used to sign by the end user in the Xumm app, the Sequence will be automatically filled by Xumm.

    3. LastLedgerSequence: If a valid ledger index is entered in the LastLedgerSequence field, it will be passed on unchanged to the Xumm app. However, if a value < 32570 is entered, the Xumm app will automatically calculate the {current ledger index} + the given amount of ledgers, where {current ledger index} is based on the most recent closed ledger index at the moment the end user taps the button to accept & sign the sign request.

    2. Payload Options

    Configure Payload Options: Configure the payload options to customize the transaction request. Refer to the Payload Options Documentation for detailed information on the available options.

    3. User Token (Optional)

    If you are using a backend flow, you can optionally include a user token. This token is specific to the user and can be used for personalized transactions.

    4. Submit the Payload

    Submit the payload to Xumm through the Xumm SDK or API. You can also use alternative language SDKs for this step. This initiates the transaction signing process.

    5. Handle Client Interaction

    The client, a mobile app, xApp, or desktop application, will interact with the payload. Implement logic to handle this interaction and guide the user through the signing process.

    6. Resolve the Transaction

    The user will either sign or reject the transaction. Your application should be ready to handle both outcomes and take appropriate action.

    7. Retrieve Payload Results

    After resolution, retrieve the payload results to understand the outcome of the transaction. You can use WebHooks, and WebSockets or verify through the SDK/API.

    8. On-Ledger Verification

    Finally, verify the transaction on the XRP Ledger. You can use libraries like xrpl-client or verify-xrpl-signature for on-ledger verification. Ensure to check for delivered_amount and other relevant fields.

    Understanding and implementing Xumm's transaction lifecycle is crucial for creating secure and efficient transactions on the XRP Ledger through the Xumm platform.

    XRPL transaction format specification at xrpl.org
    common fields

    If you are using the Javascript/TypeScript SDK (https://github.com/XRPL-Labs/Developer-Help-Center/blob/main/environments/browser-web3/broken-reference/README.md) the SDK will automatically make sure you are calling the right CORS enabled endpoints when a user signed in through the SDK.

    If you are building your own, custom implementation, you will have to make sure you are calling the JWT routes: only our JWT (JSON Web Token) routes allow for cross origin calls, and serve the right headers to allow your browser to do so.

    Backend (SDK / API)
    https://github.com/XRPL-Labs/Developer-Help-Center/blob/main/environments/browser-web3/broken-reference/README.md
    QR Scanning
    Push
    Browser
    xApp
    Backend

    Xumm.xapp { … }

    Your application crafts the XRPL transaction template. The difference between a regular XRPL JSON transaction and a Xumm transaction template is that you can leave out some fields (or leave them blank) as the Xumm app on the device of the end user will fill them automatically.

    Your application backend will send the transaction template to the Xumm API / SDK. Your application will receive a unique Payload ID that contains your Sign Request.

    Typical fields Xumm provides:

    • Fee will be automatically filled with the appropriate network fee, but when set in the Payload, Xumm will respect your provided fee.

    • Sequence will be automatically filled with the Account sequence of the account interacting with your payload.

    • Account will be automatically filled with the account interacting with your payload.

    https://xumm.dev/signing-tool
    are API Key & user bound.

    When you want to develop in your local browser instead of in Xumm, please see the "OTT Replay" section in the Development & Debugging article.

    We are currently working on a Desktop xApp Development Application so you can develop & test locally 🎉 (Work in progress, more good things are coming)

    https://ngrok.io
    https://localtunnel.me
    Development & Debugging
    https://github.com/XRPL-Labs/Developer-Help-Center/blob/main/js-ts-sdk/sdk-syntax/xumm.userstore
    const rails = await Sdk.getRails();
    <Rails>
    const txInfo = await Sdk.getNftokenDetail(tokenId);
    <NftokenDetail>
    const hookHashes = await Sdk.getHookHashes();
    <HookHashes>
    const pong = await Sdk.ping();
    {
      quota: {},
      application: {
        uuidv4: '00000000-1111-2222-3333-aaaaaaaaaaaa',
        name: 'My XUMM APP',
        webhookurl: '',
        disabled: 0
      },
      call: { uuidv4: 'bbbbbbbb-cccc-dddd-eeee-111111111111' }
    }
    <ApplicationDetails>
    . Use
    to subscribe to the return data.
    xumm.xapp.scanQr()
    xumm.xapp.on('qr', data => {
        console.log('QR', data)
    })
    on(xAppEvent, fn)
    Response

    Returns an event: payload. Use on(xAppEvent, fn) to subscribe to the return data.

    { uuid: '...' }
    xumm.payload.create({
      TransactionType: 'Payment',
      Destination: 'rfHn6cB5mmqZ6fHZ4fdemCDSxqLTijgMwo',
      Amount: String(1)
    }).then(payload => {
      xumm.xapp.openSignRequest(payload)
    })
    { text: 'Some text to share' }
    xumm.xapp.share({ text: 'Some text to share' })

    verifyUserTokens([ … ])

    Verify a user token (or multiple), to see if the token is still valid (not expired, not revoked) and can be used to deliver sign requests to user(s)

    The verifyUserTokens (or single token: verifyUserToken) method allows you to verify one or more User Tokens obtained from previous sign requests. This allows you to detect if you will be able to push your next Sign Request to specific users.

    const someToken = '691d5ae8-968b-44c8-8835-f25da1214f35')
    
    const tokenValidity = Sdk.verifyUserTokens([
      someToken,
      'b12b59a8-83c8-4bc0-8acb-1d1d743871f1',
      '51313be2-5887-4ae8-9fda-765775a59e51'
    ])
    
    if ((await Sdk.verifyUserToken(someToken).active) {
      // Push, use `user_token` in payload
    } else {
      // QR or Redirect (deeplink) flow
    }

    Returns: Promise<UserTokenValidity[]> or Promise

    Xumm.ping()

    Can be used to check connectivity / JWT (credential) validity & to obtain basic information about the calling credentials.

    Sample response

    {
      "pong": true,
      "auth": {
        "quota": {},
        "application": {
          "uuidv4": "8525e32b-1bd0-4839-af2f-f794874a80b0",
          "name": "Some App",
          "webhookurl": "https://webhook.site/3e5dee90-a654-4e34-8112-c4391247a8ee",
          "disabled": 0
        },
        "call": {
          "uuidv4": "4b97cf7a-1837-471f-baed-2ebebcf5adb4"
        }
      }
    }

    When a payload is created using the Xumm SDK in an xApp flow, the return URL is ignoded as the user will return to the xApp post signing, where an SDK event will be triggered.

    Replacement variables

    You can add the following replacement tags in your Return URL. They will be replaced with the appropriate values by Xumm.

    • {id} will be replaced with the xumm payload UUID.

    • {cid} will be replaced with the optional custom payload identifier.

    • {txid} will be replaced with the signed transaction hash.

    • {txblob} will be replaced with the signed transaction HEX blob.

    Routing / origin logic

    If both the app and web return URL values are present, and if they are identical, the XUMM platform will execute logic to see if the user is coming from a browser tab (local device or remote, e.g. desktop browser). If so, and if the origin browser window is still active, only the origin browser window will redirect, and the app won't. Else (if the browser window is not active anymore) XUMM will redirect to the return URL.

    This behaviour prevents a double redirect (both on mobile and on desktop / browser window).

    Sample payload body

    After the user signs your SignIn request, the server-to-server call (to your configured Webhook location) will receive the signed transaction containing the signed transaction HEX blob.

    You can verify the signature using the verify-xrpl-signature package: https://github.com/XRPL-Labs/verify-xrpl-signature

    Note: The SignIn transaction type is particularly useful when you want to authenticate a user without performing any transaction on the XRPL.

    Backend (SDK / API)
    {
      "txjson": {
        "TransactionType": "SignIn"
      }
    }
    - also available in our SDK:

    When using CTID

    CTID is a more efficient way to link to transactions, as they contain the ledger index, transaction index in that ledger and the NetworkID.

    More info: https://xrpl.org/ctid.html

    https://xumm.app/explorer/{network}/{txhash}
    https://xumm.app/explorer/{ctid}
    https://xumm.app/api/v1/platform/rails
    getRails()
    Syntax
    { refreshEvents: true }
    xumm.xapp.close({ refreshEvents: true })
    The provided value of the xApp property should be a valid xApp identifier.

    Syntax

    { xApp: '...' }
    Support
    xumm.xapp.navigate({ xApp: 'xumm.support' })
    Syntax
    { url: '...' }
    xumm.xapp.openBrowser({ url: 'https://wietse.com' })
    {
      "txjson": {
        "TransactionType": "..."
      },
      "options": {
        "return_url": {
          "app": "https://...",
          "web": "https://..."
        }
      }
    }
    Crafting the link / QR contents

    Example QR:

    Payloads (sign requests)
    const tx = {
      TransactionType: 'TrustSet',
      Flags: 131072,
      LimitAmount: {
        currency: 'XAH',
        issuer: 'rswh1fvyLqHizBS2awu1vs6QcmwTBd9qiv',
        value: '100000000',
      }
    }
    
    const str = JSON.stringify(tx)
    const hex = Buffer.from(str, 'utf-8').toString('hex')
    
    console.log(`https://xaman.app/detect/${hex}`)

    Client side web apps "Web3"

    xApps: your web app in Xaman

    Backend integrations

    Xaman as Identity Provider

    CDN
    Cover
    Cover
    Cover
    Cover
    const txInfo = await Sdk.getTransaction(txHash);
    xrpl-txdata
    <XrplTransaction>

    Push

    Delivering Sign Requests using a push notification can be a very convenient way for end users to interact with your application: they don't even have to scan a QR code.

    xApps ("dApps") and Browser ("Web3") are signed in with user context, so payloads created in those environments will automatically be pushed to the signed-in user.

    This means if you're using the xApp / Browser (Web3) flow, you do not have to specify the user_token as the payloads created from the xApp / Browser (Web3) flow are automatically pushed to the signed-in user.

    If you are building a backend integration, the flow is slightly different.

    Backend

    If your application features user sign-in (to identify your user) and you obtained a user_token from a previously signed payload from this specific user, you can add the user_token to the next payload to deliver the payload through a push notification.

    The first interaction (to obtain the user_token) will always involve either: showing a QR code for the user to scan with the Xumm app or a deep link to the Xumm app to sign a payload.

    A payload containing a user token looks like this:

    After posting the payload the Xumm SDK/API, the response will confirm push notification delivery:

    User token expiration

    The issued user token expires 30 days after the last successfully signed payload of your application by the Xumm user using the same issued user token. If there's a good reason for your application to have longer living user tokens, please contact Xumm Support and explain your use case.

    Obtaining the `user_token`

    From a webhook

    After the end user resolves the sign request by signing, the configured application Webhook URL will receive a JSON body per POST request containing the accessToken section:

    From a resolved Payload

    When you get the payload results, the application.issued_user_token contains the user token.

    xApps

    xApps are custom applications that run within the Xumm environment. As a developer working with xApps, delivering payloads is crucial for a seamless user experience.

    Delivering Payloads within xApps

    Delivering payloads within xApps is about efficiency and user experience. Since the user is already engaged with your xApp inside Xumm, delivering the payload directly within the xApp streamlines the process. This minimizes context switching for the user and keeps them focused on the task at hand.

    How to Deliver Payloads within xApps

    1. Create a Payload: First, you need to create a payload with the transaction details. This payload is essentially a sign request you want the user to interact with. See:

    2. Use Xumm SDK: To deliver the payload within your xApp, use the Xumm SDK. The SDK provides functions allowing you to seamlessly integrate the payload within your xApp. See:

    3. Once integrated, the payload will be displayed to the user within your xApp. The user can then review and interact with the payload without leaving the xApp.

    Xaman SDK (Intro)

    Developers can use the Xaman SDK to easily integrate with the Xaman platform. This allows for easy & secure end user interaction. With your application & the XRP Ledger.

    JavaScript/TypeScript

    NPM

    The Xaman Javascript/TypeScript SDK can be found on npm:

    CDN

    The latest version of the Xumm SDK is always available at:

    Please note the CDN URL is heavily cached (edge and headers, so client side). If you are expecting a new version of the SDK to load, consider cleaning local cache and adding a random (e.g. your build hash) as a URL Query param to the URL to force URL uniqueness.

    Code samples

    See

    Warning (legacy packages)

    Previously there were three different packages:

    • xumm-sdkfor backend interaction

    Development & Debugging

    Debugging your xApp is tricky: it runs on your phone. How to access the logs?

    The easiest way to debug your xApps is by using our xApp Developer App for desktop (Mac, Windows, Linux): xAppBuilder 🏗️

    Some things that may help debugging your xApp:

    Remote JS Console

    Using you can drop one line (script) in your page's <head> and get realtime access to the remote console (bi-directional).

    Replay OTT's

    If you open your own xApp using the device you added in the Xumm Developer Console as debug device (using the Device Identifier), the OTT (one time token) can be replayed when visiting from the same IP address.

    Note: Replaying OTT's only works if you force your browser to identify with the user agent xumm/xapp. In the Chrome Developer Console, on the Network tab, click the "Radio antenna signal" icon and uncheck "Use browser default" next to User agent.

    • Make sure your device (Xumm - Settings - Advanced) is whitelisted as Debug Identifier in the Xumm Developer Console

    • Make sure your phone and computer are visiting from the same public IP address (e.g. by having them both on the same WiFi and internet connection

    • Obtain your OTT in the xApp: it's the value of the xAppToken query parameter. Your xApp is being called with https://your-url/?xAppToken=...

    You will now see your xApp in your browser.

    Use your local dev URL as xApp URL

    Use a tool like ngrok () or localtunnel.me () to temporarily publish your local development URL to a publicly available URL you can use to access your xApp during live debug/development.

    Protocol specific checks

    The XRP Ledger Protocol has several protocol-related things to check in your app/implementation to make the experience for end users better. Please take these things into account:

    User identification payloads

    When building your own backend integration, you can request a user to sign a Sign Request with a "SignIn" transaction type. This is a pseudo transaction type allowing a user to confirm their r-address

    A SignIn transaction will never be submitted to the XRP ledger, as it is an invalid transaction type (XUMM specific pseudo transaction type).

    A sign SignIn sign request can be as simple as this:

    {
      "txjson": {
        "TransactionType": "SignIn"
      }
    }

    All Xumm payload options are valid for a SignIn transaction.

    After the user signs your SignIn request, the server to server call (to your configured Webhook location) will receive the signed transaction containing the signed transaction HEX blob.

    Response

    When the user signs the Sign Request, you will get a signed transaction (that has never been submitted to the XRP Ledger).

    You can now get the account address and some basic public account information from the payload details, and assign this information to your own local dataset, like a session.

    Verify the signature

    If you want to you can run your own signature verification on the signed SignIn pseudo transaction our platform returns to you. Of course the Xumm platform also verified the signature for you. Would you like to check yourself as well, we have created this package

    Your own backend (Auth)

    Xumm xApps yield a JWT that can be used to make subsequent calls from the user context to the Xumm API's. You can also use this JWT for your own backend.

    If you want to identify a Xumm xApp user with your own backend, you can rely on the xApp JWT's issued by Xumm: the secret used to sign the JWT is your own Xumm application secret (HMAC, HS256).

    This makes it really convenient to obtain three things at once, making calls to your own backend with an Autorization: Bearer {The Xumm JWT} header:

    1. You obtain basic user information, like the r-address and network the user is connected to, as this information is encoded in the JWT.

    2. You can verify the authenticity of the JWT, as it is signed with your own Xumm API Secret.

    3. You can make calls from the user context to the Xumm backend with this JWT (for as long as it is valid: 24h).

    Every time when a user opens your xApp, a new JWT is issued, valid for 24h.

    Please note: if you are using the OAuth2 flow instead of an xApp to obtain your JWT, you can verify the OAuth2 issued RS256 JWT using the certificate info publised as per OpenID specifications:

    How to validate a JWT

    When using the JWT for authorization, you need to validate it before you can make sure that the user is who they say they are. This is a brief explanation in how to verify the JWT using a npm package called and the bearer provided by the Xumm SDK.

    You can obtain the JWT associated with the OTT by initiating the Xumm SDK:

    Then get the bearer by awaiting the environment:

    This bearer is the JWT. You must check if the JWT is valid.

    First, run:

    After this, use the code underneath to verify the JWT. You'll need the xApp API Secret to sign the JWT and check it's validity.

    This xApp API Secret is found in the developer console at .

    get( … )

    To get payload details, status and if resolved & signed: results (transaction, transaction hash, etc.) you can get() a payload.

    Note! Please don't use polling! The XUMM API offers Webhooks (configure your Webhook endpoint in the Developer Console) or use a subscription to receive live payload updates (for non-SDK users: Webhooks).

    You can get() a payload by:

    • Payload UUID

      const payload = await Sdk.payload.get("aaaaaaaa-bbbb-cccc-dddd-1234567890ab");
    • Passing a created Payload object (see: Sdk.payload.create)

    If a payload can't be fetched (eg. doesn't exist), null will be returned, unless a second param (boolean) is provided to get the SDK to throw an Error in case a payload can't be retrieved:

    Object

    cancel( … )

    To cancel a payload, provide a payload UUID (string), a <XummPayload> (by performing a Sdk.payload.get() first) or a <CreatedPayload> (by using the response of a Sdk.payload.create() call). By cancelling an existing payload, the payload will be marked as expired and can no longer be opened by users.

    Please note: if a user already opened the payload in XUMM APP, the payload cannot be cancelled: the user may still be resolving the payload in the XUMM App, and should have a chance to complete that process.

    A response (generic API types here) looks like:

    {
      result: {
        cancelled: boolean;
        reason: XummCancelReason;
      }
      meta: XummPayloadMeta;
      custom_meta: XummCustomMeta;
    }

    Object

    selectDestination({ … })

    Open the Destination Picker: select/find/scan (QR) an XRPL destination account by r-address, slug or PayString

    Parameters

    If you want to request the destination address only, skipping the "Destination Tag" required check & input, you can provide the ignoreDestinationTag param. If not provided (or false) Xumm will chech if the destination account requires a Destination Tag and ask the user to input one.

    { ignoreDestinationTag: boolean }

    The ignoreDestinationTag feature is available in Xumm 2.5.0 and higher.

    Syntax

    Response

    Returns an event: destination. Use to subscribe to the return data.

    Verify Payload signature

    You can fetch the corresponding payload to verify the signature, to make sure it's signed by the account you expected to sign the payload.

    xumm.payload?.get('some-payload-uuid').then(payloadResult => { /**/ })

    If you want the actual blob and signature for the user signed in with the Xumm OAuth2 flow:

    1. Get the JWT contents

    2. Get the payload from the JWT (that's the Sign In payload)

    3. Get that payload with the SDK

    4. Check the payload data, the response.hex property holds the signed TX Blob

    Now you can verify the signature using the xrpl-verify-signature package, or using any native method capable of verifying XRP Ledger signatures:

    CORS (xApp)

    CORS restricts access to resources on different domains to ensure privacy and security, allowing website owners to control access. As xApps run inside Xumm, allowing CORS is required for xApps.

    Troubleshooting

    If an xApp integration doesn't allow for running commands, and the console shows messages like "Couldn't connect to host", problems are a result of the same cause: CORS issues.

    • The SDK can't reach Xumm (the app), so:

    • "Could not contact Xumm host" error appears, and:

    • For example: the openSignRequest trigger doesn't fire, the Sign Request doesn't open, and:

    • Xumm keeps on trying, and is stalling the init. to see if the host can be reached - yielding "Attempt n » Retry" console messages (just to make sure it isn't a timing issue).

    Find the cause

    Check the following things:

    1. Are you getting this messages from your frontend console, or backend (node?)

    2. Do you have CORS setup correctly? (Allow iframe loading, allow CORS (origin: *)

    3. Does your app run over http (instead of https with a valid certificate?)

    While #3 and #4 should be valid, we've seen some Android phones where this prevented the integration from working. We use ngrok to work around the local http and non standard port development issues.

    \

    Backend

    A sign request in Xumm is a prompt to approve a transaction or action on the XRP Ledger. This page will show you how you can create a Sign Request, and how you can deliver the request to the end user.

    When creating Sign Requests from a backend environment, the Xumm SDK is called with your API Key & Secret. A payload can be opened by any user. A user will not get notified about a payload, unless if they interacted with the payload through a deeplink or scanning the Payload QR code.

    If you want to deliver backend created Sign Requests to a user & the user is identified by your application, you have to provide a user_token to the payload. The user_token can be obtained after the user interacted with your application & signed a payload. See: Push

    For more information about the object contents to be used for Payloads & the return URL replacement variables, see:

    To decide where the user is sent after signing the payload, please read:

    xAppBuilder 🏗️

    Introducing xAppBuilder, an advanced tool specifically designed to streamline the creation and debugging process of xApps for Xumm.

    Seamless xApp Emulation

    This is where xAppBuilder shines - it seamlessly emulates your xApp directly on your local development environment.

    What does this mean for you? Instant, real-time feedback on your code modifications. Every tweak you save in your IDE, you can immediately see its effect on the emulated xApp.

    xAppBuilder transforms these challenges into a smooth, manageable process.

    Simplified OTT Replay

    One Time Tokens (OTTs) and replay tokens can often present challenges, particularly for those new to xApp development.

    xAppBuilder assists in addressing this issue by offering an automatic fetching feature for OTT and Replay OTT, reducing development time and allowing developers to concentrate more on enhancing the functionality of their xApp.

    Real-Time Debugging

    Debugging becomes a breeze with xAppBuilder. How? With live console logs of your xApp, spotting and fixing bugs is a more efficient process.

    These real-time logs help you to monitor and understand your xApp's performance and behavior better.

    Get Started with xAppBuilder

    Ready to level up your xApp development process? xAppBuilder is now live for Linux on the , , and . Check out the demo video and download the tool today!

    For more about xApps and Xumm, visit our . Here's to smoother, faster, and more efficient xApp development. Happy building, developers! 🏗️ 🛠️

    Xumm.environment { … }

    Information

    • ott

    • jwt

    • openid

    • bearer

    Promises (state)

    • ready

    • retrieving

    • success

    Authorization & Credentials

    How to authorize when communicating with the Xumm platform depends on your workflow.

    Authorization

    Backend

    When communicating with the Xumm platform from your backend environment, you will need a

    Websocket

    Websockets provide real-time payload updates

    All payloads get assigned a payload-specific Websocket URL. You can connect to this socket from the client side of your application to receive live status updates (if the user opens the payload on their device and the user resolves the payload).

    The pushed information contains minimal information; it is meant to trigger your application to fetch more information from your application's backend.

    If a payload doesn't exist, the Websocket connection will receive an {"message":"..."} update, and the socket will be closed. If the payload has expired, the connection will receive a {"expired":true"} message.

    If the payload exists and did not expire, the connection will start with a message containing the remaining seconds until expiration: {"expires_in_seconds":51}. This message will be sent every 15 seconds for keepalive reasons. If the connection is still active when the payload expires, a {"expired":true"} message will be sent. The connection will be kept alive, leaving it up to the client to disconnect.

    Webhooks

    Webhooks are HTTP callbacks that allow you to receive notifications when a Payload (Sign Request) has been resolved (rejected or signed).

    Webhooks are essential for asynchronous communication and can trigger specific actions in your application based on events in Xumm.

    If you entered a valid Webhook URL in your Application Settings at the Xumm, your application would receive an HTTP POST containing a JSON body with limited details for the given payload.

    Please note a Webhook will not contain the entire payload: to get the entire payload, you should GET the payload using an SDK/API call.

    A sample webhook looks like this:

    Backend (SDK / API)

    Use your API key and secret obtained from the Xumm Developer Console & off you go. Using our SDK's, or building your own integration on top of our well documented APIs.

    Backend integration intro here...

    Sample code

    Native Apps

    When building a native app (iOS / Android / React Native / Capacitor / ...) you can leverage "Sign In with Xumm" and offloading transaction signing to Xumm as well. This uses application deep links.

    The process to integrate Sign In with Xumm and transaction signing by Xumm with your own native app is actually quite similar to either the flow: it uses OAuth2 (PKCE or Implicit flow) or the flow.

    Combined with "Deep Links", your application sending off the user to Xumm will happen with a simple app-redirect. After the user interacted with your sign request, Xumm will return the user to the Return URL: the URL you added to your sign request payload to be opened post-signing.

    If your application registers a Deep Link URL as well, and you pass that URL to Xumm as the payload Return URL, the user will be redirected back to your app. To match state, you can add information to the Deep Link URL Xumm sends the user to.

    xAppBuilder FAQ

    Frequently Asked Questions

    Q: I do not see my xApp in the xAppBuilder. What should I do?

    A: Ensure your Device ID has been entered in the Debug Device ID section.

    • Step 1: Retrieve your Device ID from Xumm by going to Xumm -> Settings -> Advanced -> Device ID (double tap to copy it).

    • Step 2: Visit , select your application, navigate to the xApp section, and paste the Device ID you copied in Step 1 into the Debug Device ID section.

    Connecting localhost to xAppBuilder

    With xAppBuilder, you can now conveniently connect your localhost for an efficient and real-time development experience. This video provides an overview of connecting your localhost.

    Step 1: Create Your xApp

    Begin by opening your preferred code editor (in this case, we are using VS Code). Establish a project folder, and within this, create an index.html file. Type some text between the body tag.

    Next, install the Live Server extension for VS Code.

    Then, initiate the Live Server by clicking the 'Go Live' button/link located in the bottom right corner of VS Code. Take note of the port number that is displayed.

    Step 2: Make Your Website or Web Service Globally Accessible

    In your terminal, execute the command npm install -g localtunnel. If you encounter a permission error, use sudo npm install -g localtunnel.

    Following this, run lt --port 5500, making sure to replace '5500' with the port number noted in Step 1.

    create( … )

    To create a payload, a txjson XRPL transaction can be provided. Alternatively, a transaction formatted as HEX blob (string) can be provided in a txblob property.

    Example contents of a payload

    getKycStatus( … )

    Get the KYC status for users, based on a user_token issued by a successful sign request.

    The getKycStatus return the KYC status of a user based on a user_token, issued after the user signed a Sign Request (from your app) before (see Payloads - Intro).

    If a user token specified is invalid, revoked, expired, etc. the method will always return NONE, just like when a user didn't go through KYC. You cannot distinct a non-KYC'd user from an invalid token.

    Alternatively, KYC status can be retrieved for an XPRL account address: the address selected in XUMM when the session KYC was initiated by.

    ... or using an account address:

    Returns .

    Notes on KYC information

    Xumm UI interaction

    Using the Xumm SDK in xApps, you can trigger native Xumm interaction & receive events from Xumm in your xApp.

    xApps are WebApps. They are opened in Xumm for a great user experience. They add value (tooling, wizards) for end users, using Sign Requests to help users perform tasks on the XRPL.

    To add value for end users, your xApp will most likely implement some of the features Xumm offers natively in your xApp. E.g. open the QR scanner, Account Destination Picker, or start a Sign Request flow. Then to receive the response from these native Xumm flows in your xApp (WebApp).

    Your xApp can trigger specific actions in Xumm:

    These actions can be sent form your xApp (frontend Javascript) context, and will trigger functionality native to the Xumm app:

    • Open a Sign Request

    subscribe( … )

    • Returning non-void in the callback function passed to the Sdk.payload.subscribe() method

    • Manually calling <PayloadSubscription>.resolve() on the object returned by the Sdk.payload.subscribe() method

    The subscription will be closed by either:

    Push permission

    Two types of Push:

    1. Payload (Sign Request Push). Any application can send Sign Requests with a push notification after the user interacted with the app at least once.

      1. Backend integration: the Webhook & Payload get will contain a user token after the user decided to interact by signing a payload.

    Style guide

    When building xApps, it makes a lot of sense to stick to the design (colour palette, font, etc.) as used by Xumm to offer the best user experience to xApp users.

    Font family

    The main application uses the font-family: proxima-nova, sans-serif. Only when using this font for your (web) xApp to be embedded in XUMM, use this stylesheet:

    When offering your application anywhere else than as embedded (web) xApp, check your licensing needs and requirements for the use of Proxima Nova.

    tx({ … })

    Open the Transaction Details panel

    Parameters

    Syntax

    Simple Sign Request

    See this code in action:

    Xaman Developer EducationXaman Developer Education
    Does your app run over https on a non standard (non TCP 443) port?
  • Some web server configurations don't allow CORS to work on a subdomain. Try running on a FQDN

  • retrieved
    xApp & Browser (Web3) integrations obtain a user token after xApp open / Sign In.\

    - A user token is valid for 30 days (default, can be extended on a per app basis if good reasons are provided). Every time the user interacts with the app again, the 30 day cycle will reset. - When creating a new payload (sign request), the user token can be specified in the payload, after which the user will receive a push notification, and the sign request will present itself in the Event List of the user. - Users can revoke the user token validity in Xumm (Settings - 3rd party apps - Revoke) - A user token is user & app bound, meaning the same user token can only be used by the API credentials it was originally extended to.

  • Custom xApp push events. Custom xApp push events are permissioned.

    1. Notification with link to xApp

    2. Notification with link to xApp & Event in Event list with link to xApp

  • Handle Status Updates: Implement logic to handle status updates. This includes whether the user signed or rejected the payload. Xumm SDK provides functions that allow you to receive status updates and take appropriate actions based on the user's response, see: on(xAppEvent, fn)

    Sign Requests (payloads)
    openSignRequest({ … })

    Now open your public xApp URL with /force appended, and include the xApp Token. E.g. if your xApp launch URL is: https://xumm.app/detect/xapp:sandbox.abcd1234 ... You open (in your browser): https://xumm.app/detect/xapp:sandbox.abcd1234/force?xAppToken=...

    https://remotejs.com
    https://ngrok.io
    https://localtunnel.me
    Snapcraft Store
    Mac App Store
    Windows Store
    Developer Center
    import { Xumm } from "xumm";
    
    const xumm = new Xumm("some-api-key", "some-secret-key");
    
    (async () => {
      console.log("pong", await xumm.ping());
    
      const transaction = { TransactionType: 'SignIn' };
      console.log("payload", await xumm.payload?.create(transaction)) 
    })()
    const { Xumm } = require('xumm')
    
    const xumm = new Xumm('apikey', 'apisecret')
    
    xumm.ping().then(pong => console.log(pong))
    
    const transaction = { TransactionType: "SignIn" }
    xumm.payload?.create(transaction).then(payload => console.log(payload))
    npm version
    ownerwnerCount = accountInfo.account_data.OwnerCount
    reserveBase = serverInfo.info.validated_ledger.reserve_base_native || serverInfo.info.validated_ledger.reserve_base_xrp
    reserveInc = serverInfo.info.validated_ledger.reserve_inc_native || serverInfo.info.validated_ledger.reserve_inc_xrp
    https://www.npmjs.com/package/xrpl-client
    https://xrpl.org/subscribe.html
    https://oauth2.xumm.app/certs
    jsonwebtoken
    https://apps.xumm.dev
    const newPayload: XummTypes.CreatePayload = {txjson: {...}}
    const created: XummTypes.CreatedPayload = await Sdk.payload.create(newPayload)
    const payload: XummTypes.XummPayload = await Sdk.payload.get(created)
    await Sdk.payload.get("aaaaaaaa-bbbb-cccc-dddd-1234567890ab", true)
    async Sdk.payload.cancel (
      payload: string | XummPayload | CreatedPayload,
      returnErrors: boolean = false
    ): Promise<DeletedPayload | null>
    xumm.xapp.selectDestination({ ignoreDestinationTag: false })
    xumm.xapp.on('destination', data => {
        console.log('Destination', data.destination)
    })
    on(xAppEvent, fn)
    import { Xumm } from "xumm"
    
    const xumm = new Xumm("some-api-key", "some-secret-key")
    
    const payload = await xumm.payload?.create({
      user_token: "xxxxxxxxxx",
      txjson: {
        TransactionType: "SignIn"
      },
      options: {
        return_url: {
          app: "https://sample.test/?...",
          web: "https://sample.test/?id={id}"
        },
        force_network: "MAINNET"
      },
      custom_meta: {
        identifier: "123123",
        instruction: "Please sign this to..."
      }
    })) 
    https://xumm.readme.io/reference/post-payload
    Payload Return URL
    If a user token (userToken.user_token) is issued and you plan on payload delivery using push notifications in the future, your application could/should store the token. See Push

    Use the payloadResponse.payload_uuidv4 to confirm and get payload outcome using an SDK/API call.

    Expected result / retry

    If your backend does not respond within 15 seconds, or responds with a non 200 HTTP status code, the Xumm platform will retry the webhook four more times (bringing the max. total attempts at five).

    The first retry will take place after 10 seconds. The next after 60 seconds. Then two more retries will take place at a 600 second (10 minute) interval.

    Safety

    If you want to make sure the Webhook your application received came from the Xumm platform, there are two things you can do:

    1. Send a GET for the payload to get the full payload using the SDK/API to the Xumm platform: get( … )

    2. Verify the signature we send in a HTTP Header when we deliver the Webhook: Signature verification\

    Xumm Developer Console

    Once an account has successfully completed the XUMM KYC flow, the KYC flag will be applied to the account even if the identity document used to KYC expired. The flag shows that the account was once KYC'd by a real person with a real identity document.

  • Please note that the KYC flag provided by XUMM can't be seen as a "all good, let's go ahead" flag: it should be used as one of the data points to determine if an account can be trusted. There are situations where the KYC flag is still true, but an account can no longer be trusted. Eg. when account keys are compromised and the account is now controlled by a 3rd party. While unlikely, depending on the level of trust required for your application you may want to mitigate against these kinds of fraud.

  • const kycStatus = await Sdk.getKycStatus(
      "00000000-0000-0000-0000-000000000000"
    );
    const kycStatus = await Sdk.getKycStatus("rwu1dgaUq8DCj3ZLFXzRbc1Aco5xLykMMQ");
    <keyof PossibleKycStatuses>
    Requirement(s)
    • The given account must be imported in Xumm

    • Xumm must be on the network the transaction is present on

    {
      account: '...',
      tx: 'HASH...',
      network?: 'MAINNET|TESTNET|XAHAU|...',
    }
    xumm.xapp.tx({
      account: 'rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ',
      tx: '250DC3E83946EFE965DE36B3F9AE8608CD7ED793657BDEC5B794B665B2DCBC0E',
      network: 'MAINNET',
    })
    Take a look at the API Docs for more information about payloads object contents and possible replacement variables for the Return URLs.

    The response of a Sdk.payload.create() operation, looks like this:

    The next.always URL is the URL to send the end user to, to scan a QR code or automatically open the XUMM app (if on mobile). If a user_token has been provided as part of the payload data provided to Sdk.payload.create(), you can see if the payload has been pushed to the end user. A button "didn't receive a push notification" could then take the user to the next.no_push_msg_received URL. The

    Alternatively user routing / instruction flows can be custom built using the QR information provided in the refs object, and a subscription for live status updates (opened, signed, etc.) using a WebSocket client can be setup by connecting to the refs.websocket_status URL. Please note: this SDK already offers subscriptions. There's no need to setup your own WebSocket client: createAndSubscribe( … )

    Object

    async Sdk.payload.create (
      payload: CreatePayload,
      returnErrors: boolean = false
    ): Promise<CreatedPayload | null>

    Open the QR scanner to retrieve a scanned value

  • Open the Account Destination Picker

  • etc.

  • To prevent showing a double loader (first the Xumm xApp loader, then your xApp's loader while hydrating / booting) you can enable the "Xumm Loader Screen" option in the Xumm Developer Console (xApp tab). See ready()

    Your xApp can also receive events (data) from Xumm:

    Certain actions in Xumm will trigger an event so your xApp can retrieve data or act based on the event (details below):

    • Payload resolved

    • QR Code scanner opened/closed

    • Destination picker: closed / destination picked

    Example code

    Trigger actions

    For all Xumm UI (interface) actions / worfklows you can trigger, see the SDK documentation: https://github.com/XRPL-Labs/Developer-Help-Center/blob/main/js-ts-sdk/sdk-syntax/xumm.xapp

    Receive events

    For all events emitted in your xApp (like the async follow up data of an xApp UI action triggered), see the xApp event handler: on(xAppEvent, fn)

    Status updates can be processed by providing a
    callback function
    to the
    Sdk.payload.subscribe()
    method. Alternatively, the (by the
    Sdk.payload.subscribe()
    method) returned raw websocket can be used to listen for WebSocket
    onmessage
    events.

    More information about the status update events & sample event data: Status updates

    • The payload is opened by a XUMM App user (webpage)

    • The payload is opened by a XUMM App user (in the app)

    • Payload expiration updates (remaining time in seconds)

    • The payload was resolved by rejecting

    • The payload was resolved by accepting (signing)

    To subscribe to live payload status updates, the XUMM SDK can setup a WebSocket connection and monitor live status events. Emitted events include:

    Payload subscriptions: live updates

    If a callback function is not provided, the subscription will stay active until the <PayloadSubscription>.resolve() method is called manually, eg. based on handling <PayloadSubscription>.websocket.onmessage events.

    When a callback function is provided, for every payload specific event the callback function will be called with <SubscriptionCallbackParams>.

    The <SubscriptionCallbackParams>.data property contains parsed JSON containing event information.

    Either by calling <SubscriptionCallbackParams>.resolve() or by returning a non-void value in the callback function the subscription will be ended, and the <PayloadSubscription>.resolved promise will resolve with the value returned or passed to the <SubscriptionCallbackParams>.resolve() method.

    Resolving (by returning non-void in the callback or calling resolve() manually) closes the WebSocket client the XUMM SDK sets up 'under the hood'.

    The <PayloadSubscription> object looks like this:

    Object

    {
      "user_token": "c5bc4ccc-28fa-4080-b702-0d3aac97b993",
      "txjson": { ... }
    }
    {
      "uuid": "<some-uuid>",
      ...
      "pushed": true
    }
    {
      "meta": { ... },
      "payloadResponse": { ... },
      "userToken": {
        "user_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
        ...
      }
    }
    {
      "meta": { ... },
      "application": {
        "issued_user_token": "e5fff0d0-698d-425d-bdcf-3156e744282d",
        ...
      },
      ...
    }
    const xumm = new Xumm(apiKey, xAppToken)
    const bearer = await xumm.environment.bearer
    npm install jsonwebtoken
    const jwt = require('jsonwebtoken')
    
    const apiKey = '' // Your Xumm API key here
    const apiSecret = '' // Your Xumm API secret (BACKEND ONLY!)
    const bearer = await xumm.environment.bearer
    
    try {
      // If decoded comes back as an object, the JWT is valid.
      // Otherwise, the catch block is activated
      const decoded = jwt.verify(bearer, apiSecret);
    
      // For extra security, check if the decoded JWT contains
      // the client_id of your xApp, e.g. the API Key from the developer console  
      if(decoded.client_id === apiKey) {
        // JWT is valid and signed for this client (client_id matched)
      } else {
        // Valid JWT, but for another client? There's something
        // wrong with an otherwise valid JWT.
      }
    } catch (error) {
      // Handle your error here and inform the user that their access is denied.
    }
    async Sdk.payload.get (
      payload: string | CreatedPayload,
      returnErrors: boolean = false
    ): Promise<XummPayload | null>
    {
      "meta": {
        "url": "<your-webhook-endpoint>",
        "application_uuidv4": "<some-uuid>",
        "payload_uuidv4": "<some-uuid>",
        "opened_by_deeplink": true
      },
      "custom_meta": {
        "identifier": "some_identifier_1337",
        "blob": {},
        "instruction": "Hey ❤️ ..."
      },
      "payloadResponse": {
        "payload_uuidv4": "<some-uuid>",
        "reference_call_uuidv4": "<some-uuid>",
        "signed": true,
        "user_token": true,
        "return_url": {
          "app": "<your-url>",
          "web": "<your-url>"
        },
        "txid": "<some-tx-hash>"
      },
      "userToken": {
        "user_token": "<some-token>",
        "token_issued": 1635000000,
        "token_expiration": 1637500000
      }
    }
    {
      txjson: {
        TransactionType: "Payment",
        Destination: "r...",
        Amount: "1000000"
      },
      options: {
        return_url: {
          app: "https://sample.test/?...",
          web: "https://sample.test/?id={id}"
        },
        force_network: "MAINNET"
      },
      custom_meta: {
        identifier: "123123",
        instruction: "Please sign this to..."
      }
    }
    {
      "uuid": "1289e9ae-7d5d-4d5f-b89c-18633112ce09",
      "next": {
        "always": "https://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09",
        "no_push_msg_received": "https://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09/qr"
      },
      "refs": {
        "qr_png": "https://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09_q.png",
        "qr_matrix": "https://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09_q.json",
        "qr_uri_quality_opts": ["m", "q", "h"],
        "websocket_status": "wss://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09"
      },
      "pushed": true
    }
    <html lang="en">
      <body>
        <div id="destinationname">...</div>
        <input id="destinationaddress" value="" placeholder="Destination address" />
        <button onclick="xumm.xapp.selectDestination()">Pick destination account</button>
    
        <script src="https://xumm.app/assets/cdn/xumm.min.js"></script>
        <script>
          var xumm = new Xumm('your-api-key')
    
          xumm.xapp.on('destination', data => {
            if (data.destination.address) {
              document.getElementById('destinationname').innerText = data.destination.name
              document.getElementById('destinationaddress').value = data.destination.address
            } else {
              console.log('No destination selected', data.reason)
            }
          })
        </script>
      </body>
    </html>
    {
      payload: XummPayload,
      resolved: Promise<unknown> | undefined
      resolve: (resolveData?: unknown) => void
      websocket: WebSocket
    }
    async Sdk.payload.subscribe (
      payload: string | XummPayload | CreatedPayload,
      callback?: onPayloadEvent
    ): Promise<PayloadSubscription>
    xumm-xapp-sdk
    for xApp frontend interaction
  • xumm-oauth2-pkce for browser / "Web3" interaction

  • All three packages above have been replaced by the xumm package, which allows for easier (unified) interaction with the three aforementioned topics.

    Examples / User stories
    API Key
    and
    API Secret
    . They can be obtained from our
    , and are to be passed in the x-api-key and x-api-secret headers to our platform.

    Frontend (browser, client side)

    Frontend (browser, client side) implementations Browser ("Web3") can use our Javascript/Typescript SDK, in which case the entire authorization is abstracted away. Under the hood, the user will go through an OAuth2-flow and a JWT (JSON Web Token) is obtained from our platform. This token is valid for 24 hours and user context bound.

    If you are building your own frontend implementation, any OAuth2 (Implicit and PKCE flows both supported) client will do. See Identity (OAuth2, OpenID)

    Never use an API Secret obtained from the Developer Dashboard in a frontend environment! Anyone in possession of your API Secret (x-api-secret) can create payloads (Sign Requests) on behalf of your application. If abused, this can immensely damage the reputation of your application.

    xApp

    xApps xApps ("dApps") are loaded with several URL Query Paramters added, one of which is the xAppToken parameter. This parameter contains what we refer to as the "OTT", the "One Time Token". This token can be resolved by your application to a JSON response containing:

    • user context information

    • a JWT, JSON Web Token, allowing you to make subsequent calls to our platform

    If you use our Javascript/Typescript SDK, this entire authorization flow is abstracted away by our SDK; the SDK (in the xApp, client side) will automatically resolve the xApp Token ("OTT") and use the JWT to make subsequent calls to our platform.

    Native application

    Any OAuth2 (Implicit and PKCE flows both supported) client will do. Your application Native Apps can redirect the user to our platform (to be redirected to the Xumm app) to sign in after which the client will be redirected back to your application (if your application supports deep links). You will obtain a JWT (JSON Web Token) to communicate to our platform from the user context. See:Identity (OAuth2, OpenID)

    Credentials

    Backend
    PKCE / JWT
    xApps

    Also known as

    "Server side"

    "Sign in with Xumm"

    "dApps", "web apps" embedded in Xumm

    Credentials

    API Key & Secret

    JWT (SDK handles this for you)

    JWT (SDK handles this for you)

    Credential source

    Obtained from the

    Obtained after end user logs in (SDK does this for you)

    Developer Dashboard

    Expiration

    The expiration should be handled as an OPEN/SCAN BEFORE, not a RESOLVE BEFORE. If the end user opens the payload (from the push notification, deep link, or QR scanning) but it didn't resolve before expiration, they will not receive a notification and will still be able to resolve it as if the payload hadn't expired.

    When the user resolves after the expiration moment, the webhook and callback will handle the response as they would when the payload wasn't expired.

    Websocket Events

    Websocket events to expect

    Event
    JSON

    Connected

    {"message":"Welcome <payload-uuid>"}

    After connecting and every 15 seconds while the connection is alive, a negative value means the transaction expired that many seconds ago

    {"expires_in_seconds":54}

    When the user received the payload, eg. push notification, deeplink or QR scan

    {"opened":true}

    When the Xumm SDK/API fetched the payload details

    {"devapp_fetched":true}

    When the user starts the signing routine

    {"pre_signed":true}

    When the submission to a node starts

    {"dispatched":true}

    WARNING! Do not just rely on a `signed: true` indication! If you receive a websocket message with `signed: true` indication, always fetch the payload to confirm that all payment details are as expected.

    Sample

    The Websocket payload resolve message looks like:

    The payload information the Websocket connection delivers does not contain the entire payload object. It should be considered a trigger to GET the entire payload using an SDK/API call: get( … )

    Integration

    Sign In & obtain JWT

    If you just want to authorize/identify a user with his/her r-address, the OAuth2 "Identify" flow suffices: you send off the user to a Sign In URL with a return URL and the user will return to your application with a JWT (JSON Web Token) you can use to call the Xumm API to get the user identification information (r-address). For more information, see Identity (OAuth2, OpenID).

    If you are building a native app and you want to easily allow users to sign in with Xumm, you can use the OAuth2 Implicit flow like this:

    1. Register an app at https://apps.xumm.dev and get the (public) API Key

    2. Register a deeplink or deeplink protocol for your app, e.g. yourapp://signin

    3. Add your deeplink / protocol URL to the Xumm Developer Console as a valid Return URL.

    4. Redirect your user to: https://oauth2.xumm.app/auth?client_id={apikey} &redirect_uri=yourapp://signin &response_type=token

    5. Now, when the user signed in, Xumm redirects the user to your app, to the redirect_uri, with URL Query Parameters appended containing a JWT in the access_token field.

    6. You can now use (you can construct the Xumm() with this JWT.

    Sign In & Sign Requests

    If you also want to send Sign Requests to users & you don't want the user to re-authorize the JWT every 24h, you can generate Sign Requests yourself, in which case the flow you will use is the Backend (SDK / API)flow. You craft your Sign In Payload: User identification payloads yourself, obtain a User Token after which you can generate user bound sign requests.

    This workflow requires a backend on your end, where our application communicates to your backend to generate the Sign Requests. You need a backend for this, as you do not want to expose your Xumm API keys in your compiled application.

    Please do not include your Xumm API Secret in your native app build. Native apps can be decompiled and you do not want your API Secret to be abused by third parties.

    Browser ("Web3")
    Backend (SDK / API)
    If you are not the owner of the xApp, you will need to ask the owner to input your Device ID in the Guest Device IDs section.

    Q: Why are some of my xApps shown in gray at the end of the xApp list in xAppBuilder?

    A: These xApps are ones you have not actively used, and their session has expired. To start a new session, open the xApp in Xumm and quit. Next, click on the "Refetch" link in xAppBuilder. This should fetch the active session of your xApp into xAppBuilder.

    Q: How can I open the xApp on xAppBuilder with a different context / r-address?

    A: Start by opening the xApp in Xumm with the different context / r-address, which will create a new session for the new context / r-address. Then return to xAppBuilder and click on the "Refetch" link. The new context / r-address should now be listed in the context dropdown menu.

    Q: How do I exit / close the xAppBuilder?

    A: On MacOS, hover over the top left corner to find the close, minimize, and maximize buttons. On Windows and Linux, click on the x symbol in the top right corner.

    For Mac users, you can also use Shift + Click on the tray icon to exit.

    Switching Network

    Q: How can I access my xApp from a different network within xAppBuilder?

    A: First, switch to your desired network in Xumm. Next, open the relevant xApp within Xumm — this action generates the OTT for replay. Following this, click on the 'Refetch' button(top left corner) in xAppBuilder and open the xApp in xAppBuilder.

    It's important to note that xAppBuilder doesn't connect to any specific network by itself. The connection relies on the most recent OTT of your xApp. For instance, if you last accessed your xApp on the Testnet and subsequently open it in xAppBuilder, it will connect to the Testnet.

    If the network hasn't switched, ensure that you're accessing the xApp within xAppBuilder using the same account (raddress) as the one you recently used in Xumm OR maybe you forgot to click on the 'Refetch' button.

    Verify Network in xAppBuilder\

    Location of the URL after switching networks

    \

    Xumm Developer Console

    The terminal will output a unique URL. Copy this, and open it in your browser. Here, submit your IP address (if you are unsure of your IP, a quick Google search of 'whatsmyip' will provide it).

    For further information about this package, you can refer to the official Localtunnel documentation.

    Step 3: Set Up Your Xumm Developer Console Account

    Navigate to the Xumm Developer Console and create an xApp account.

    Paste the URL acquired in Step 2 into the 'WebApp URL' section. In the 'Debug Device ID' section, enter your device ID (which can be found by navigating through Xumm -> settings -> advanced -> Device ID).

    Step 4: Access Your xApp on xAppBuilder

    Open xAppBuilder and scan the provided QR code using Xumm. Afterward, click on the xApp within xAppBuilder.

    Now, when you make and save changes to your code in the VS code editor, these changes will be reflected in xAppBuilder, allowing for real-time modifications and testing.

    Colours

    Starting XUMM version 1.1 four colour palettes are available. The colour the app is running in will be passed to the xApp in the style parameter, see the xapp/ott/:token documentation (applies to the SDK as well).

    Used colour palette codes:

    • LIGHT

    • DARK

    • MOONLIGHT

    • ROYAL

    Your xApp launch URL will receive a GET parameter (query param) named xAppStyle containing the colour palette name as active on the client device. If your xApp URL is eg.:

    ... the URL opened will be:

    Standard CSS stylesheets

    The four available themes are shipped as Bootstrap (version 4.5) rolled stylesheets, ready to use. You can include a Bootstrap 4.5 stylesheet by pointing to:

    The {theme} element should be replaced by the theme name in lower case notation.

    SPA / Front-end app only

    To load the right stylesheet dynamically in an environment without a backend, consider using this script in your <head>:

    Colours

    xumm.on("success", async () => {
      const { payload_uuidv4 } = await xumm.environment.jwt
      const payloadResult = await xumm.payload?.get(payload_uuidv4)
      console.log(payloadResult)
    })
    import { Xumm } from "xumm"
    
    const Sdk = new Xumm(process.env.XUMM_KEY, process.env.XUMM_SECRET)
    const pong = await Sdk?.ping()
    const payload = await Sdk.payload?.create({
      custom_meta: {
        instruction: "Sign request from " + pong?.application.name,
      },
      txjson: {
        TransactionType: "SignIn",
      },
    })
    
    console.log(payload)
    npm version
    python version
    NuGet version
    npm version
    python version
    NuGet version

    Implementation checklist

    This article presents a concise implementation checklist for developers using Xumm. By following these steps, you can ensure a smooth and secure integration whilst optimizing the user experience.

    1. Fetch Payload Results: Trigger your application to fetch payload results after receiving a Webhook callback.

    2. Inspect Payload Output: Confirm meta.resolved and meta.signed are both true in the payload output.

    3. Identify Dispatched Node Type: Ensure response.dispatched_nodetype is "MAINNET" for real payments.

    4. Validate Transaction ID: Validate the response.txid value on the ledger.

    5. Examine Delivered Amount: Confirm the meta.delivered_amount equals the expected payment amount.

    6. Use xrpl-txdata Package: Establish a connection to the XRP Ledger, fetch the transaction by hash, and cross-verify transaction details with the XRPL ledger.

    1. Network Independence: Use the Xumm API/SDK, which operates independently of the network, to allow users the freedom of network choice.

    2. Network Information: Ensure the results of a signed payload include the network the user was on during the signing.

    3. Forced Network Identifier: Check for the expected result in the Payload results or specify a particular network using a forced network identifier in a payload.

    1. Secure Your Webhooks: Implement appropriate security measures.

    2. Verify Payloads: Authenticate received payloads.

    3. Error Handling: Develop robust error management mechanisms.

    1. xApp Creation & Audit: Anyone can create sandbox xApps, but public release requires an audit by XRPL Labs for user safety, compliance, and value addition.

    2. User Experience: xApps must be self-explanatory, prevent dangerous mistakes, and provide a unique experience tailored to Xumm users.

    3. Technical & Styling Standards: xApps must meet Xumm's technical guidelines and respect or have unique styling.

    xApp

    A sign request in Xumm is a prompt to approve a transaction or action on the XRP Ledger. This page will show you how you can create a Sign Request, and how you can deliver the request to the end user.

    xApps are natively aware of the end user context, so a Sign Request payload can easily be served with the xumm.xapp.openSignRequest method: openSignRequest({ … })

    For more information about the object contents to be used for Payloads & the return URL replacement variables, see: https://xumm.readme.io/reference/post-payload

    <html lang="en">
      <head>
        <script src="https://xumm.app/assets/cdn/xumm.min.js"></script>
      </head>
      <body>
        <pre id=
    

    When a payload (Sign Request) has been created and opened in your xApp, you probably want to be informed if the payload has been signed or rejected, then to check the payload results and act on the results. You can do so by subscribing to the payload event, see:

    Browser ("Web3")

    Building a web app? Running as a client side SPA (single page webapp) or server side rendered? React Native / VueJS / VanillaJS / etc.: you can integrate with the Xumm ecosystem using our SDK.

    The Xumm SDK can run fully client side: either as part of your compiled web app or using plain HTML and Javascript using our ready to use browserified version.

    Using the Xumm SDK, you can easily add "Sign in with Xumm" capabilities to your web app. You don't even need a backend. You get the full "Web3" experience (sign in with a blockchain account) with our "Web2" compatible stack (see: Identity (OAuth2, OpenID) / Native Apps).

    Make sure to add the return URL (also known as redirect URL) in the Xumm Developer Console on the application home page in the "Origin/Redirect URIs (one per line)" field.

    Capabilities

    Using the Xumm SDK in your web project, you get:

    • Sign in with a QR code for when loaded on a desktop

    • Deeplink (redirect to Xumm, back to your web app) on mobile

    • Basic user information: XRP Ledger account address, icon (hashicon or even avatar), connected chain (mainnet, testnet, ..) & some basic information about the end user's environment (currency, language, ...)

    Sample code

    Please note the xumm.authorize() and xumm.logout() methods:

    More links

    For the SDK documentation (objects, methods), see the SDK section: . For a simple demo of the Xumm SDK in a React Native environment, check this sample repository:

    createAndSubscribe( … )

    The <PayloadAndSubscription> object is basically a <PayloadSubscription> object with the created payload results in the created property:

    All information that applies on Sdk.payload.create() and Sdk.payload.subscribe() applies. create( … ) / subscribe( … ). For the contents of a Payload, see the API Docs for more information about payloads object contents. Differences are:

    1. The input for a Sdk.payload.createAndSubscribe() call isn't a payload UUID / existing payload, but a payload to create.

    2. The response object also contains (<PayloadAndSubscription>.created) the response obtained when creating the payload.

    Example code

    Object

    Xumm.user { … }

    Returns information about the signed in user (in case of xApp or Web3 flow).

    This method only applies to the xApp & Web3 (browser) flow. Backend flows (using API Key & API Secret) have no user context.

    The following properties are part of the user object. Every property is a Promise that is resolved when the user is signed in.

    • account - r-address

    • picture - Profile picture or Hashicon URL

    • name - Account name (if present) - e.g. Xumm Pro account name

    • domain - Domain name (if present) for account

    • source - Information source (e.g. a specific explorer)

    • networkType - Enum, e.g. MAINNET, TESTNET, ... the user is connected to

    • networkEndpoint - WebSocket endpoint to connect to the network

    • blocked - If the account is on a blacklist (e.g. because of scams)

    • kycApproved - If the account owner went through opt in KYC with Xumm

    • proSubscription - If the account has a Xumm Pro subscription

    • profile - Xumm Pro Profile slug (URL)

    • token - User Token for future sign request Push delivery

    The token field contains a user_token; this token is specific to both the application (SDK) credentials and the end user. It grants you access to asynchronously send notifications to the end user (for 30 days, unless granted long living tokens).

    When your application creates a payload for the end user to sign using the SDK session (or JWT), a user will always receive a push notification.

    If you want to asynchronously create a payload on your backend using the flow, you can include this token in the user_token field of the payload.

    ready()

    When using the native Xumm loader screen for your xApp (until your xApp is ready, fully hydrated, booted, etc.) you call this method to remove the Xumm loading screen.

    This feature is available in Xumm 2.5.0 and higher.

    To prevent showing a double loader (first the Xumm xApp loader, then your xApp's loader while hydrating / booting) you have to enable the "Xumm loader till SDK ready() is called" option in the Xumm Developer Console (xApp tab). The xApp will then show the Xumm native loader, until your application calls the ready() method on the Xumm SDK.

    Syntax

    First your app loads, fetches, etc. Then you have all the information you need to render & show your app, and you call:

    Exception flows

    1. The xApp doesn't load, to be able to debug the app needs to be displayed (e.g. reverse proxy 502 error or some other app error, preventing the SDK's ready() call being made). With Xumm in Developer Mode, the Xumm loading screen shows a 'Proceed to xApp' button at the Xumm loader screen, below the spinner. This way you can dismiss the Xumm loader and view the underlying problem.

    2. The xApp takes very long to load or doesn't load at all: users are confronted with a long wait. If the ready() method in the Xumm SDK isn't called within ~6 seconds a label + button is made visible: "xApp is slow to respond..." [Contact Developer]. This button then opens the Support URL for the xApp as entered in the Developer Console.

    xApps ("dApps")

    Build your own web app to live in-app, inside Xumm for all Xumm users. Build an xApp. Use your favourite tools & frameworks for the client side code (HTML, CSS, JS, etc.

    xApps are web apps. They are offered to users as integrated apps, opened in Xumm for a great user experience. They add value (tools, apps, wizards, ...) for end users. They receive context information when opened, and can interact with some of the native Xumm features & users through Sign Requests.

    Please read carefully:

    Secure Payment Verification

    Once a payment has been sent and the payload resolved on Xumm, some checks are performed to ensure secure payment verification. This document walks you through verifying a payment transaction on Xumm.

    Payload Completion and Verification

    After a payload completes its lifecycle, which includes creation, user interaction, transaction signing, and transaction submission to the XRP Ledger by Xumm, your application will receive (if configured) a Webhook callback.

    This callback should trigger your application to fetch the payload results. It is highly advisable to fetch the payload results again on your "thank you" or "return" page in case you did not persist the payload results after receiving a Webhook.

    Xumm.payload { … }

    Payloads are the primary reason for the XUMM API (thus this SDK) to exist.

    An XRPL transaction "template" can be posted to the XUMM API. Your transaction tample to sign (so: your "sign request") will be persisted at the XUMM API backend. We now call it a a Payload. XUMM app user(s) can open the Payload (sign request) by scanning a QR code, opening deeplink or receiving push notification and resolve (reject or sign) on their own device.

    A payload can contain an XRPL transaction template. Some properties may be omitted, as they will be added by the XUMM app when a user signs a transaction. A simple payload may look like this:

    As you can see the payload looks like a regular XRPL transaction, wrapped in an txjson object, omitting the mandatory Account, Fee and Sequence properties. They will be added containing the correct values when the payload is signed by an app user.

    getHookHash( … )

    Get meta information for a known Hook, by specifying the Hook Hash (64 hex chars)

    Sdk.getHookHash(hookHash: string)

    The getHookHash method allows you to get meta information for a specific Hook hash (64 hex chars)

    Returns:

    getCuratedAssets()

    Get the curated assets (shortlist in Xumm) for Trust Lines

    The getCuratedAssets method allows you to get the list of trusted issuers and IOU's. This is the same list used to populate the "Add Asset" button at the XUMM home screan.

    Returns :

    OpenID Connect Debuggeroidcdebugger.com
    https://xaman.app/assets/cdn/xumm.min.js
    {
      "payload_uuidv4": "<some-uuid>",
      "reference_call_uuidv4": "<some-uuid>",
      "return_url":{
        "app": "<some-url>",
        "web": "<some-url>",
      },
      "signed": true,
      "opened_by_deeplink": false,
      "user_token": true,
      "custom_meta":{
        "identifier": "<some-identifier>",
        "blob": {},
        "instruction": "<some-instruction>"
      },
      "txid": "<some-tx-hash>"
    }
    https://my.app.local/some/app
    https://my.app.local/some/app?xAppStyle={THEME}
    <link rel="stylesheet" href="https://use.typekit.net/vtt7ckl.css">
    https://xumm.app/assets/themes/xapp/xumm-{theme}/bootstrap.min.css
    <script>
      var theme = ((new URLSearchParams(document.location.href))
                   .get('xAppStyle') || 'light').toLowerCase()
      var link = document.createElement('link')
      link.href = 'https://xumm.app/assets/themes/xapp/xumm-'
        + theme + '/bootstrap.min.css'
      link.type = 'text/css'
      link.rel = 'stylesheet'
      document.getElementsByTagName('head')[0].appendChild(link)
    </script>
    const { Xumm } = require("xumm")
    
    const Sdk = new Xumm(process.env.XUMM_KEY, process.env.XUMM_SECRET)
    Sdk.ping().then(pong => {
      Sdk.payload.create({
        custom_meta: {
          instruction: "Sign request from " + pong.application.name,
        },
        txjson: {
          TransactionType: "SignIn",
        }
      }).then(payload => {
        // Done
        console.log(payload)
      })
    })
    const Sdk = new Xumm('some-api-key')
    
    Sdk.authorize()
    
    Sdk.on("ready", () => {
      Sdk.ping().then(pong => {
        Sdk.payload.create({
          custom_meta: {
            instruction: "Sign request from " + pong.application.name,
          },
          txjson: {
            TransactionType: "SignIn",
          }
        }).then(payload => {
          // Done
          console.log(payload)
        })
      })
    })
    const payload = await xumm.payload?.create({
      txjson: {
        TransactionType: "Payment",
        Destination: "r...",
        Amount: "1000000"
      },
      options: {
        return_url: {
          app: "https://sample.test/?...",
          web: "https://sample.test/?id={id}"
        },
        force_network: "MAINNET"
      },
      custom_meta: {
        identifier: "123123",
        instruction: "Please sign this to..."
      }
    })
    
    xumm.xapp?.openSignRequest(payload)

    When the payload is resolved

    {"payload_uuidv4": "...", [...] } With: signed: true/false

    When the payload is expired

    {"expired":true}

    JS/TS class
    OTT Data: Utilize xApp OTT data, including network information, to better manage transactions.
  • When linking to Transaction Details using a Transaction Explorer, consider using our helper tooling: Tx Explorer(s)

  • Transparency & Support: Developers cannot be anonymous and must provide a clear support workflow, terms & conditions, and a privacy statement.
    Networks
    Signature verification
    XRPL.org documentation
    Requirements
    Push
    Backend (SDK / API)

    Automatically obtained through a "One Time Token" (SDK does this for you)

    Can send sign request push notifications

    After the user signs their first Sign Request by you through deeplink / QR with a then obtained "User Token"

    ✅ Yes

    ✅ Yes

    User identified with credentials?

    No, "SignIn" payload (Sign Request) required first.

    ✅ Yes

    ✅ Yes

    Usable in backend environments?

    ✅ Yes

    Yes (but frontend obtained)

    Yes (but frontend (xApp) obtained)

    Usable in frontend (browser) environments?

    ❌ No

    ✅ Yes

    ✅ No

    CORS ready?

    ❌ No

    Yes (JWT endpoints, SDK handles this for you)

    Yes (JWT endpoints, SDK handles this for you)

    Usable in native app environments?

    ❌ No

    Yes (but OAuth2 sign in flow required)

    ❌ No

    Credential validity & authenticity can be offline verified?

    ❌ No

    Yes, the JWT: using the OAuth2 certs information (RS256).

    Yes, the JWT (HS256):Your own backend (Auth)

    Xumm Developer Dashboard
    Screensshot of the location of the URL for switching networks in xApp Builder
    https://www.npmjs.com/package/verify-xrpl-signaturewww.npmjs.com
    https://www.npmjs.com/package/verify-xrpl-signaturewww.npmjs.com
    "payload"
    >...</
    pre
    >
    <script>
    var xumm = new Xumm('your-api-key')
    xumm.on('payload', event => {
    document.getElementById('payload').innerHTML = JSON.stringify(event, null, 2)
    })
    xumm.payload
    .create({
    txjson: {
    TransactionType: "Payment",
    Destination: "r...",
    Amount: "1000000"
    },
    options: {
    return_url: {
    app: "https://sample.test/?...",
    web: "https://sample.test/?id={id}"
    },
    force_network: "MAINNET"
    },
    custom_meta: {
    identifier: "123123",
    instruction: "Please sign this to..."
    }
    })
    .then(payload => {
    document.getElementById('payload').innerHTML = JSON.stringify(payload, null, 2)
    xumm.xapp.openSignRequest(payload)
    })
    </script>
    </body>
    </html>
    Xumm.on(event, fn)
    An access token (JSON Web Token "JWT") valid for 24h, to actively send (push) Sign Requests (transactions for the end user to sign)
    SDK (syntax)
    https://github.com/XRPL-Labs/XummSDK-React-Demo
    xumm.xapp.ready()

    Optionally (besides txjson) a payload can contain these properties (TS definition):

    • options to define payload options like a return URL, expiration, etc.

    • custom_meta to add metadata, user insruction, your own unique ID, ...

    • user_token to push the payload to a user (after obtaining a user specific token)

    A more complex payload could look like this. A reference for payload options & custom meta can be found in: Payloads (sign requests)

    Instead of providing a txjson transaction, a transaction formatted as HEX blob (string) can be provided in a txblob property.

    {
      txjson: {
        TransactionType : 'Payment',
        Destination : 'rwiETSee2wMz3SBnAG8hkMsCgvGy9LWbZ1',
        Amount: '1337'
      }
    }
    const hookInfo = await Sdk.getHookHash('64hexchars');
    <HookHash>
    const curatedAssets = await Sdk.getCuratedAssets();
    {
      curatedAssets: {
        issuers: [ 'Bitstamp', 'GateHub' ],
        currencies: [ 'USD', 'BTC', 'EUR', 'ETH' ],
        details: {
          Bitstamp: [Object],
          GateHub: [Object]
        }
      }
    }
    <CuratedAssetsResponse>
    Permissions

    xApps have extra special permissions, allowing the xApp (web app) to interact with some of the native Xumm features:

    • They receive context (user account selected in Xumm when opened, Xumm theme, input params, account type (eg. Tangem / ...)

    • They can trigger overlay Sign Requests and receive callback info

    • They can trigger the QR scanner and receive scanned QR data

    Opening xApps

    xApps can be opened (triggered) in lots of ways:

    • In the Xumm shortlist (we feature some apps, they get replaced by frequently used apps by the user)

    • From the xApp directory

    • By opening a deeplink (browser / from within another app)

    • By scanning a QR code

    To prevent showing a double loader (first the Xumm xApp loader, then your xApp's loader while hydrating / booting) you can enable the "Xumm Loader Screen" option in the Xumm Developer Console (xApp tab). See ready()

    Advanced ways to open xApps

    • By attaching an xApp memo to an XRPL TX (so the Event list will show there's an xApp attached to the TX)

    • Using push notifications

    • From the Event list, as an xApp session pushed to a Xumm user

    xApp example use cases

    • Trading interface (offloads signing to Xumm)

    • Admission ticket checking

    • NFT marketplaces / viewers

    • Issuing tokens, checking tokens

    • Tools: setting up accounts, crafting advanced transactions, escrows, etc.

    • Exchange deposit / withdraw integrations

    Sample code

    Requirements
    xumm.on('payload', data => {
      if (data?.uuid) {
        xumm.payload.get(data.uuid).then(payload => {
          // Payload contains the full paylaod data
        })
      }
    })
    xumm.on('payload', data => {
      if (data?.uuid) {
        const payload = await xumm.payload.get(data.uuid)
        // Payload contains the full paylaod data
      }
    })
    <html lang="en">
      <body>
        <h1 id="accountaddress">...</h1>
        <button id="signinbutton" onclick="xumm.authorize()">Login</button>
        <button id="logoutbutton" onclick="xumm.logout()">Logout</button>
            
        <script src="https://xumm.app/assets/cdn/xumm.min.js"></script>
        <script>
          var xumm = new Xumm('your-api-key')
          
          xumm.on("ready", () => console.log("Ready (e.g. hide loading state of page)"))
          
          // We rely on promises in the `success` event: fired again if a user
          // logs out and logs back in again (resets all promises)
          xumm.on("success", async () => {
            xumm.user.account.then(account => {
              document.getElementById('accountaddress').innerText = account
            })
          })
    
          xumm.on("logout", async () => {
            document.getElementById('accountaddress').innerText = '...'
          })
        </script>
      </body>
    </html>
    xumm.payload.createAndSubscribe({
      TransactionType: 'Payment',
      Destination: 'rfHn6cB5mmqZ6fHZ4fdemCDSxqLTijgMwo',
      Amount: String(1000000) // one million drops, 1 XRP
    }, eventMessage => {
      if (Object.keys(eventMessage.data).indexOf('opened') > -1) {
        // Update the UI? The payload was opened.
      }
      if (Object.keys(eventMessage.data).indexOf('signed') > -1) {
        // The `signed` property is present, true (signed) / false (rejected)
        return eventMessage
      }
    })
      .then(({ created, resolved }) => {
        console.log('Payload URL:', created.next.always)
        console.log('Payload QR:', created.refs.qr_png)
    
        return resolved // Return payload promise for the next `then`
      })
      .then(payload => console.log('Payload resolved', payload))
      // This is where you can do `xumm.payload.get(...)` to fetch details
    async Sdk.payload.createAndSubscribe (
        payload: CreatePayload,
        callback?: onPayloadEvent
      ): Promise<PayloadAndSubscription>
    <html lang="en">
      <body>
        <h1 id="accountaddress">...</h1>
            
        <script src="https://xumm.app/assets/cdn/xumm.min.js"></script>
        <script>
          var xumm = new Xumm('your-api-key')
          
          xumm.on("ready", () => console.log("Ready (e.g. hide loading state of xApp)"))
      
          // Account can't change (like Web3 logout/login) so we can rely on the promise
          xumm.user.account.then(account => {
            document.getElementById('accountaddress').innerText = account
          })
        </script>
      </body>
    </html>
    Verifying Payment Transactions

    Here are the steps to verify that you have indeed received a payment:

    1. Check Payload Output: Verify if the Payload output contains meta.resolved. This value should be true. Otherwise, the payload is still pending or has been abandoned by the user. Also, check if the Payload output contains meta.signed. This value should be true, indicating that the user signed the transaction.

    2. Check Response Dispatched Node Type: Verify the response.dispatched_nodetype value. If you are expecting a real payment, this value should contain MAINNET. If it doesn't, you might be accepting a TESTNET payment!

    3. Check Transaction ID: The response.txid value is the on-ledger transaction hash. You must verify this transaction on the ledger. Note that it may take around 4 seconds for a ledger to close and slightly longer for the ledger and transaction info to propagate. You may want to repeat async/delay fetching this info if you don't get a result at first or if your result contains a validated: false value.

    4. ⚠️ Check Delivered Amount: After fetching the transaction details, check the meta.delivered_amount value to see if the amount of XRP (in drops, one million drops = one XRP) equals the expected amount to be paid. This is a crucial step in the verification process.

    Fetching Transaction Details

    You can fetch transaction details using the XRPL Transaction Data fetcher or the JSON RPC (HTTP POST) method at https://xrplcluster.com.

    Utilizing (flow+code) the xrpl-txdata Package (JS/TS) for Transaction Verification

    After sending a Sign Request (payload) to Xumm, you receive a response with the signed transaction hash (Webhook: payloadResponse.txid, WebSocket: txid).

    You're in luck if you immediately check this transaction hash on the XRP Ledger, and it's already in a validated ledger. However, if the transaction hasn't been included in a closed ledger, you might encounter a "Not Found" error, while if you had checked a few seconds later, you'd have found the transaction.

    To streamline this process, use the xrpl-txdata NPM package (JS/TS). This package simplifies:

    1. Establishing a redundant (multi-node, failover) and reliable (auto-timeout, auto-retry) connection to the XRP Ledger

    2. Fetching a transaction by hash

    3. Optionally, monitoring the XRP Ledger (all closed ledgers, all the transactions in those ledgers) and waiting for a specified time (seconds).

    Once your transaction is found, the package returns the transaction outcome and validated balance changes.

    Here's how to use it in JavaScript:

    Good Practice: Cross-verify with the XRPL

    It is always a good practice to cross-verify with the XRPL for absolute certainty. Using the tx method, you can fetch transaction details directly from the XRPL ledger.

    More information on how to do this can be found in the XRPL Transaction Documentation.

    Xumm.on(event, fn)

    Events fired by the SDK per environment. For the order of events, see the section per environment after the table with events.

    Event
    Environment
    Meaning

    retrieved

    xApp, Web3 (browser)

    A valid signed in Xumm SDK session has been retrieved.

    success

    xApp, Web3 (browser)

    A user is succesfully identified and signed in

    ready

    xApp, Web3 (browser)

    The SDK is ready (final state) so your application can render

    Event order

    The following order of events can be expected per environment.

    Note about the ready vs the success event: The ready event fires if the SDK state is ready for the rendering of your application. This does not have to mean the SDK is signed in: it just means the SDK is ready. If you want to know a user

    xApp (always auto-signed in)

    1. retrieved - xApps always auto-resolve

    2. success- all information is populated to SDK properties (Promises)

    3. ready - ready to render your application with the correct Xumm SDK state

    Web3 (browser) - Signed out & then signing in

    1. retrieving - but the user is signed out

    2. ready - ready to render your application with the correct Xumm SDK state, but the user must still log in

    3. The user signs in

    Web3 (browser) - Already signed in

    1. retrieving - existing session information is being fetched & verified

    2. success - all information is populated to SDK properties (Promises)

    3. retrieved - you are dealing with an already signed in user

    Identity (OAuth2, OpenID)

    The Xumm platform can act as the OAuth2 provider. The Xumm platform supports the OAuth2 / OpenID Connect flow. Authenticate and identify end users using their self custodial XRPL accounts.

    All credentials created in the Xumm Developer Console () will work with the OAuth2 / OpenID Connect flow.

    OAuth2 flows

    OAuth 2.0 Debuggeroauthdebugger.com
    https://codesandbox.io/p/sandbox/xumm-sdk-6gm4du?file=/src/index.tscodesandbox.io
    const {TxData} = require('xrpl-txdata')
    
    const TxHash = '8F3CE0481EF31A1BE44AD7D744D286B0F440780CD0056951948F93A803D47F8B'
    
    const VerifyTx = new TxData([
      'wss://xrplcluster.com',
      'wss://xrpl.link',
      // Or:
      // 'wss://testnet.xrpl-labs.com'
    ], {
      OverallTimeoutMs: 6000,
      EndpointTimeoutMs: 1500,
      // If using testnet, see above:
      // AllowNoFullHistory: true
    })
    
    // Specify the transaction hash to verify and the # of seconds
    // to wait & monitor the XRPL if not found initially.
    VerifyTx.getOne(TxHash, 20)
      .then(tx => {
        console.log(`Got the TX, details:`, tx)
      })

    success - all information is populated to SDK properties (Promises)

    ready - ready to render your application with the correct Xumm SDK state

    retrieving

    Web3 (browser)

    The SDK is trying to retrieve & verify an existing session

    logout

    Web3 (browser)

    The SDK is going to destroy a pending signed in session

    loggedout

    Web3 (browser)

    The SDK destroyed a signed in session, a user can login again.

    error

    Web3 (browser)

    An error occurred, see the browser console for more information

    qr

    xApp (user event)

    The QR code scan dialog in Xumm has been closed (dismissed or a QR code has been scanned) From: scanQr()

    payload

    xApp (user event)

    A Sign Request (payload) has been resolved (cancelled / signed / ...) From: openSignRequest({ … })

    destination

    xApp (user event)

    The "Destination Picker" dialog in Xumm has been closed (dismissed or a destination has been selected) From: selectDestination({ … })

    networkswitch

    xApp (user event)

    The user switched the selected network in Xumm while present in the xApp, while your xApp settings (Xumm Developer Console) indicate the xApp shouldn't reload but receive an event. network contains getRails()key.

    https://www.npmjs.com/package/xummwww.npmjs.com
    Logo
    The Xumm OAuth2 / OpenID Connect provider supports the
    authorization code
    flow and the
    implicit flow
    .

    The PKCE flow (which is the new & more secure industry standard and replaces the Implicit flow) is also available.

    All supported OAuth2 flows have their own use cases, advantages and caveats. The right one depends on your project & audience.

    Authorization code
    PKCE
    Implicit

    Backend

    Frontend

    Frontend

    API Key + Secret

    API Key

    API Key

    Custom implementation, custom sessions / token persistence if needed.

    Xumm SDK handles user sign in & session retrieval

    Xumm SDK handles user sign in & session retrieval

    As secure as your own implementation

    Secure (Man in the Middle attack not possible)

    Credentials & Redirect URLs

    To use the Xumm Platform as OAuth2 / OpenID Connect provider, one or more valid OAuth2 redirect URI's must be whitelisted in the Xumm Developer Console, on an application level.

    The same API Key and API Secret the Xumm Developer Console offers to be used calling our API's and using our SDK's can be used as OAuth2 client id and secret.

    Obtained credential (bearer)

    The Xumm platform returns a Bearer token (JWT) with limited validity. The token can not be refreshed: after expiration a new user sign in is mandatory to obtain a new JWT token.

    When using the Xumm SDK (TypeScript & Javascript) all OAuth2/JWT interaction, authorisation & implementation will be abstracted away, which is by far the easiest way to interact with the Xumm platform.

    Building your own integration, or using a standard OAuth2 consumer? All JWT tokens obtained through from a Xumm OAuth2 flow can be used with the JWT API endpoints (from a user locked context). The way to interact with the JWT endpoints is similar to the JWT flow for xApps, except the JWT is obtained through the OAuth2 flow instead of inside the xApp.

    All JWTs the obtained by a successful user sign in are valid for one day (24h)

    Auth URL

    Special parameters

    • force_network allows you to specify a network the payload will have to be signed on. Sample values are MAINNET TESTNET XAHAU XAHAUTESTNET, etc.

    • signers allows you to specify one or more forced signers, by r-address, seperated by a comma (if multiple are to be provided where the user can choose from, providing they have signing capabilities for the account(s))

    Sample Auth URL using the above params:

    OAuth2 & OpenID Connect endpoints

    Endpoint type
    Path (URL linked)

    Authorization

    https://oauth2.xumm.app/

    Token

    https://oauth2.xumm.app/

    Userinfo

    https://oauth2.xumm.app/

    JWKS

    https://oauth2.xumm.app/

    OpenID Connect Metadata

    https://oauth2.xumm.app/

    All other JWT compatible Xumm API's

    See our API docs:

    https://apps.xumm.dev

    Requirements

    xApps are WebApps, embedded in Xumm for a great user experience. They add value (tooling, wizards) for end users, using Sign Requests and their Web UI to help users perform tasks on the XRPL and beyond.

    • Anyone can create sandbox xApp

    • Only you can use your own sandbox xApp from a specific Xumm installation you can whitelist after activating xApp features.

    • The fact that you got a sandbox xApp is not to be presented anywhere as an endorsement (e.g. in communication like on social media, etc.))

    • To build an xApp, you need to have experience with Frontend Web Development as xApps are WebApps (loaded in Xumm)

    • xApps need to add value to a significant share of the Xumm user base

    • xApps need to be self explanatory to have clear instructions for end users

    • xApps need to be designed in a way where users can not make dangerous mistakes: users need to be protected

    • xApps developers can not be anonymous (accountability)

    • Promotion of speculation, pushing users towards buying tokens is not allowed (see: user protection)

    • Activating xApp features and building a sandbox xApp does NOT guarantee your xApp will be going live in the future. To take your xApp live, it will be audited by XRPL Labs. The rules above apply, security & usability will be tested. If you want to have more certainty in advance, please .

    All xApps

    • The xApp should be self explanatory, or do a good job explaining to the users what the xApp offers in the very first screen the xApp shows

    • xApps can not be designed in a way where it it completely unclear to end users if they are using a third party developed xApp or a XRPL Labs maintained component

    • xApps must not be a regular website/webapp fitted in an xApp: the user experience must be to seme degree tailored to users in Xumm, and must have relevance for Xumm users

    Technical

    • All links to external sites / window opens must be replaced by a openBrowser call on the Xumm SDK: so that users won't reach another website through navigating in the xApp

    • Reliable user-bound storage is available not through cookies / localStorage, but through the Xumm userstore:

    • No polling should be used: to retrieve the status of a payload, use the websocket we provide for status updates (or the createAndSubscribe

    Accessibility

    • Simple accessible navigation

    • Clear icons:

    • Reduce clutter: Keep minimum content on screen

    • Use accessible fonts

    Accessibility Tools:

    • Contrast checker link 1:

    • Contrast checker link 2:

    • Iconset:

    Styling

    • xApps should either have their own colour scheme (dark/light mode independent) or respect the Xumm colour schemes: . The end user styling will be passed to the xApp using the xAppStyle query parameter.

    • The xApp <html> and <body> tag must have a transparent background color right upon page load, so the xApp doesn't 'flicker' white while loading, until styling has been applied (rendered by the browser).

    Sandboxed xApps

    • Full access, no restrictions, but only for the developer and max. 10 testers (whitelisted by Device UUID in the Xumm Developer Console)

    Link (QR/Deeplink) only xApps

    • The xApp should look appealing

    • The xApp should respect different Xumm user screen sizes

    • The xApp should be well crafted: it should be clear what the xApp will do, and it should do what the xApp promised to do

    • The xApp should have a clear Support workflow & offer terms & conditions & a privacy statement

    Public (listed) xApps

    • The xApp should not be a "launchpad" to something that could be perfectly located at a website: if there is no actual Xumm wallet/XRPL interaction where the integration with Xumm adds value, it should be a website, not an xApp

    • Offer value (features people will appreciate/need) for a large part of the XRPL / Xumm user base

    • The frontend source code must either be open source, shared (under NDA) with XRPL Labs for review or a third party security audit (code & dependencies + dependency update procedures) acceptable by XRPL Labs has to be provided.

    Browser

    A sign request in Xumm is a prompt to approve a transaction or action on the XRP Ledger. This page will show you how you can create a Sign Request, and how you can deliver the request to the end user.

    When working with Xumm sign in & payloads in the browser, there are two flows to consider. Your application should deal with both flows.

    • User is on mobile, Xumm is installed

    • User is on desktop, Xumm is on their phone

    Mobile

    When a user visits on their smartphone with Xumm installed, your application can "deeplink" straight into Xumm, where a Sign Request will be opened.

    • If your application can persist state, you can use a return URL to get your user to return to your web app.

    • If you need the user to return to the launching webpage, do not provide a return URL to the payload, so the user is forced to go back to the launching browser.

    To make sure the user is expecting Xumm to open, the best user experience would be to ask the user to open Xumm (with a button), alternatively allowing them to use a button to just show the QR code, so the Sign Request can be opened on another device.

    For more information about the object contents to be used for Payloads & the return URL replacement variables, see:

    Warning: most mobile browsers / operating systems will only allow deeplinks to trigger an application (so: the payload URL to trigger opening Xumm) if the button resulting in the trigger is user invoked.

    Meaning there must always be a direct user onclick/ontap event resulting in the routine opening the payload URL being opened will deeplink.

    Desktop

    On the desktop, a user may or may not receive a push notification. The user can scan a QR code as fallback. The ideal implementation:

    1. Checks if the pushed property of the created payload

      1. If false the user is displayed the payload QR code to scan with their phone.

        1. Using the method the application receives real time updates about end user interaction. The application can update to reflect the interaction the user has with the Sign Request on their phone (

    OAuth ToolsOAuth Tools by Curity

    Batch (multiple inner signers)

    The Batch feature allows multiple transactions to be packaged together and executed as a single atomic transaction. Create and submit a batch of up to 8 transactions that succeed or fail atomically.

    The Batch transaction type can be submitted through the Xaman API as any regular Sign Request (payload). It requires:

    • TransactionType "Batch"

    • Flags as integer, with one of the processing methods allowed for a Batch transaction:

    https://oauth2.xumm.app/auth
      ?client_id=47fdfcb7-8362-47fe-9a89-a2efc55e86d5
      &redirect_uri=https://dev.wietse.com
      &response_type=token
      &force_network=MAINNET
      &signers=rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ,rTeLeproT3BVgjWoYrDYpKbBLXPaVMkge

    Secure (but Man in the Middle attack possible)

    You deal with the mobile return flow state persistence. You will have to make sure you restore your session to cover sessions where user return in another browser.

    Only works on mobile when users leave and return from & to the same browser. E.g. when starting off in a Twitter embedded browser frame & returning to the native OS browser, the sign in will fail.

    Works on mobile even when users start in one browser and get redirected to another browser (e.g. the OS native browser). Basically always works.

    You deal with the desktop sign in flow (redirect / popup / ...)

    Xumm SDK (TypeScript/Javascript) will trigger a pop up & handle sign state & events.

    Xumm SDK (TypeScript/Javascript) will trigger a pop up & handle sign state & events.

    auth
    token
    userinfo
    certs
    .well-known/openid-configuration
    reference/oauth2-jwt
    Logo
    "opened": true
    ).
  • If true the user is displayed a message that the Sign Request has been delivered to their phone. A button with a label like "I did not receive the Push Notification" is displayed, which takes users to the QR flow.

  • https://xumm.readme.io/reference/post-payload
    createAndSubscribe( … )
    xumm.payload.create({
      txjson: {
        TransactionType: "Payment",
        Destination: "r...",
        Amount: "1000000"
      },
      options: {
        return_url: {
          app: "https://sample.test/?...",
          web: "https://sample.test/?id={id}"
        },
        force_network: "MAINNET"
      },
      custom_meta: {
        identifier: "123123",
        instruction: "Please sign this to..."
      }
    }).then(payload => {
      // Redirect directly to payload.next.always, or (preferable)
      var btn = document.getElementById('launchXummBtn')
      btn.setAttribute('href', payload.next.always)
    })

    ALLORNOTHING (tfAllOrNothing), Flag integer value: 65536

  • ONLYONE (tfOnlyOne), Flag integer value: 131072

  • UNTILFAILURE (tfUntilFailure), Flag integer value: 262144

  • INDEPENDENT (tfIndependent), Flag integer value: 524288

  • RawTransactions containing the inner transactions of the batch. Note that every single inner transaction needs to:

    • Have Fee at a string containing the value "0"

    • Have SigningPubkey as empty string ""

    • Have the Flags field contain the flag indicating it is an inner Batch transaction: 1073741824

  • Multiple 'inner' signers

    One of the amazing features of Batch is the ability to atomically have multiple parties interact. Combined with ALLORNOTHING on the upper Batch, this allows for fully atomic transactions between multiple parties, where either every participant gets what they agreed to, or none of them do.

    To use this feature, every individual party involved in the inner 'RawTransactions' need to provide a signature for the entire batch, then to be combined in the parent Batch. At this point any account (even one not participating in the inner Batch transactions) can bundle and submit, as the combined inner batch participant's transactions will satisfy the signing requirements.

    Normally, the Batch transaction would require a formatted object with signers and signatures to be added to the Batch transaction in the BatchSigners field, as per XRPL's Batch specification.

    To make it easier to deal with multiple inner signers, when using the Xaman SDK / API you can gather individual signer's transactions and then combine using only the Payload UUID's (or signed transaction blobs), at which point Xaman will 'unfurl' the information to craft a valid Batch transaction with multiple signers.

    The workflow woud be as follows:

    1. Multiple participants in `RawTransactions`

    Craft the Batch transaction with the RawTransactions containing all transactions to be approved (signed) by different participants. At this stage the r-addresses for the individual transactions must already be known (see: SignIn). The overall Batch may look like below.

    At this stage the upper Batch Transaction can have the Sequence/Ticket , Fee, and Account fields omitted. They don't have to be known yet, as they can be added later when the inner transactions are signed and any account can submit the bundle.

    2. Gather individual inner transaction sigatures

    As can be seen in the proposed JSON transaction above, two signers will need to approve the transaction:

    • rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ

    • r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4

    Each participant can now be presented with the Batch to be approved, where the signer is pre-filled, and thus enforced. The payload will have to be created with submit: false as we don't want to try to submit, we just want to get a signature from the Batch participant.

    This means if someone with Xaman installed without the specific account present with signing permissions, Xaman will reject the sign request.

    Payload (sign request):

    The same routine has then to be walked through for other signers.

    3. Combine the inner transaction signatures and submit the Batch

    Every Sign Request in the previous steps (per signer) is assigned an uuid. Gather those who are signed succesfully by the inner Batch transactions participants, to be combined (bundled) later to submit the Batch transaction. Now a specific signer is not required and submit can be true .

    Note! While the official Batch spec requires a full signer object to be present in the BatchSigners field, Xaman accepts three different notations:

    1. Conform native XRPL implementation: BatchSigners formatted object, containing an STArray with multiple signer pubkeys + their signature

    2. Xaman specific (more convenient): the signed TX blob (as string) - this works for TX blobs signed by Xaman, or by any other XRPL signing implementation.

    3. Xaman specific (most convenient): the signed Payload UUID - this works only if all signers are Xaman users.

    const paload = await xumm.payload.create({
      txjson: {
        TransactionType: "Payment",
        Destination: "r...",
        Amount: "1000000"
      },
      options: {
        return_url: {
          app: "https://sample.test/?...",
          web: "https://sample.test/?id={id}"
        },
        force_network: "MAINNET"
      },
      custom_meta: {
        identifier: "123123",
        instruction: "Please sign this to..."
      }
    })
    
    // Now assigin the link to a button or redirect the user straight away to:
    // payload.next.always
    xumm.payload.createAndSubscribe({
      TransactionType: 'Payment',
      Destination: 'rfHn6cB5mmqZ6fHZ4fdemCDSxqLTijgMwo',
      Amount: String(1000000) // one million drops, 1 XRP
    }, eventMessage => {
      if ('opened' in eventMessage.data) {
        // Update the UI? The payload was opened.
      }
      if ('signed' in eventMessage.data) {
        // The `signed` property is present, true (signed) / false (rejected)
        return eventMessage
      }
    })
      .then(({ created, resolved }) => {
        console.log('Payload URL:', created.next.always)
        console.log('Payload QR:', created.refs.qr_png)
    
        return resolved // Return payload promise for the next `then`
      })
      .then(payload => console.log('Payload resolved', payload))
      // This is where you can do `xumm.payload.get(...)` to fetch details
    const { created, resolved } = await xumm.payload.createAndSubscribe({
      TransactionType: 'Payment',
      Destination: 'rfHn6cB5mmqZ6fHZ4fdemCDSxqLTijgMwo',
      Amount: String(1000000) // one million drops, 1 XRP
    }, eventMessage => {
      if ('opened' in eventMessage.data) {
        // Update the UI? The payload was opened.
      }
      if ('signed' in eventMessage.data) {
        // The `signed` property is present, true (signed) / false (rejected)
        return eventMessage
      }
    })
    
    console.log('Payload URL:', created.next.always)
    console.log('Payload QR:', created.refs.qr_png)
    
    const payload = await resolved
    
    console.log('Resolved', payload)
    {
        "TransactionType": "Batch",
        "Flags": 65536,
        "Fee": "1337",
        "RawTransactions": [
          {
            "RawTransaction": {
              "TransactionType": "Payment",
              "Account": "rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ",
              "Destination": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
              "Amount": "100",
              "Sequence": 36969,
              "Fee": "0",
              "Flags": 1073741824,
              "SigningPubKey": ""
            }
          },
          {
            "RawTransaction": {
              "TransactionType": "CredentialCreate",
              "Expiration": 889004799,
              "Account": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
              "Subject": "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ",
              "URI": "CAFEBABE",
              "CredentialType": "4B5943CAFEBABE",
              "Sequence": 36971,
              "Flags": 1073741824,
              "Fee": "0",
              "SigningPubKey": ""
            }
          }
        ]
    }
    {
      "options": {
        "submit": false,
        "signer": "rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ"
      },
      "txjson": {
        "TransactionType": "Batch",
        "Flags": 65536,
        "Fee": "1337",
        "RawTransactions": [
          {
            "RawTransaction": {
              "TransactionType": "Payment",
              "Account": "rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ",
              "Destination": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
              "Amount": "100",
              "Sequence": 36969,
              "Fee": "0",
              "Flags": 1073741824,
              "SigningPubKey": ""
            }
          },
          {
            "RawTransaction": {
              "TransactionType": "CredentialCreate",
              "Expiration": 889004799,
              "Account": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
              "Subject": "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ",
              "URI": "CAFEBABE",
              "CredentialType": "4B5943CAFEBABE",
              "Sequence": 36971,
              "Flags": 1073741824,
              "Fee": "0",
              "SigningPubKey": ""
            }
          }
        ]
      }
    }
    {
      "options": {
        "submit": true
      },
      "txjson": {
        "TransactionType": "Batch",
        "Flags": 65536,
        "Fee": "1337",
        "BatchSigners": [
          "82a46463-c8e7-4f5f-9a9e-4cc8a5b332b9",
          "15dce664-a040-40ca-8de7-fdf3cc337055"
        ],
        "RawTransactions": [
          {
            "RawTransaction": {
              "TransactionType": "Payment",
              "Account": "rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ",
              "Destination": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
              "Amount": "100",
              "Sequence": 36969,
              "Fee": "0",
              "Flags": 1073741824,
              "SigningPubKey": ""
            }
          },
          {
            "RawTransaction": {
              "TransactionType": "CredentialCreate",
              "Expiration": 889004799,
              "Account": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
              "Subject": "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ",
              "URI": "CAFEBABE",
              "CredentialType": "4B5943CAFEBABE",
              "Sequence": 36971,
              "Flags": 1073741824,
              "Fee": "0",
              "SigningPubKey": ""
            }
          }
        ]
      }
    }
    xApps must not be in violation with Apple and Google App Store / Play Store requirements. For example, unlocking features based on NFTs owned is not allowed.
    /
    subscribe
    method provided by the SDK:
    /
    ). Backend applications can also use a webhook:
    .

    Use minimal of 16pt font for standard body text

  • Test on different devices:

  • Manage information on a logical level

  • Consistency in design

  • Use a 40x40px target area for touch controls

  • Good (horizontal) alignment:

  • Distinction between primary and secondary Buttons:

  • Clear error text:

  • Appropriate color contrast:

  • No slang or bad grammar. Use proper English.

  • Human like language:

  • Breaking up content:

  • reach out
    Xumm UI interaction
    https://github.com/XRPL-Labs/Developer-Help-Center/blob/main/js-ts-sdk/sdk-syntax/xumm.userstore
    https://accessibleweb.com/color-contrast-checker
    https://contrastchecker.com/
    https://feathericons.com/
    Style guide
    createAndSubscribe( … )
    createAndSubscribe( … )
    Webhooks
    npm version
    GitHub Actions NodeJS status
    Logo
    Logo
    CDNJS Browserified Minified
    CDNJS Browserified
    Logo
    Packagist PHP version
    Packagist PHP version