Glossary

Environment Variables

Some environment variables are required for all Polaris deployments, some are required for a specific set of SEPs, and others are optional.

Environment variables can be set within the environment itelf, in a .env file, or specified in your Django settings file.

A .env file must be within the directory specified by Django’s BASE_DIR setting or specified explitly using the POLARIS_ENV_PATH setting.

To set the variables in the project’s settings file, the variable name must be prepended with POLARIS_. Make sure not to put sensitive information in the project’s settings file, such as Stellar secret keys, encryption keys, etc.

ACTIVE_SEPS

Required.

A list of Stellar Ecosystem Proposals (SEPs) to run using Polaris. Polaris uses this list to configure various aspects of the deployment, such as the endpoint available and settings required.

Ex. ACTIVE_SEPS=sep-1,sep-10,sep-24

ADDITIVE_FEES_ENABLED

A boolean value indicating whether or not fee amounts returned from the registered fee function should be added to Transaction.amount_in, the amount the user should send to the anchor. Only used for SEP-24 transactions, specifically when a TransactionForm is submitted. If this functionality is desired for SEP-6 or SEP-31 transactions, the anchor can implement the logic themselves in the provided integration functions.

Defaults to False. By default, fees are subtracted from the amount initially specified by the client application or user.

Ex. ADDITIVE_FEES_ENABLED=1, ADDITIVE_FEES_ENABLED=True

CALLBACK_REQUEST_DOMAIN_DENYLIST

A list of home domains to check before accepting an on_change_callback parameter in SEP-6 and SEP-24 requests. This setting can be useful when a client is providing a callback URL that consistently reaches the CALLBACK_REQUEST_TIMEOUT limit, slowing down the rate at which transactions are processed. Requests containing denied callback URLs will not be rejected, but the URLs will not be saved to Transaction.on_change_callback and requests will not be made.

CALLBACK_REQUEST_TIMEOUT

An integer for the number of seconds to wait before canceling a server-side callback request to Transaction.on_change_callback if present. Only used for SEP-6 and SEP-24. Polaris makes server-side requests to Transaction.on_change_callback from CLI commands such as process_pending_deposits and execute_outgoing_transactions. Server-side callbacks requests are not made from the API server.

Defaults to 3 seconds.

Ex. CALLBACK_REQUEST_TIMEOUT=10

INTERACTIVE_JWT_EXPIRATION

An integer for the number of seconds a one-time-token used to authenticate the client with a SEP-24 interactive flow is valid for. This token (JWT) is distinct from the JWT returned by SEP-10, which should not be included in URLs.

Defaults to 30 seconds.

Ex. INTERACTIVE_JWT_EXPIRATION=180

LOCAL_MODE

A boolean value indicating if Polaris is in a local environment. Defaults to False. The value will be read from the environment using environ.Env.bool().

Ex. LOCAL_MODE=True, LOCAL_MODE=1

HORIZON_URI

A URL (protocol + hostname) for the Horizon instance Polaris should connect to.

Defaults to https://horizon-testnet.stellar.org.

Ex. HORIZON_URI=https://horizon.stellar.org

HOST_URL

Required.

The URL (protocol + hostname) that this Polaris instance will run on.

Ex. HOST_URL=https://testanchor.stellar.org, HOST_URL=http://localhost:8000

MAX_TRANSACTION_FEE_STROOPS

An integer limit for submitting Stellar transactions. Increasing this will increases the probability of the transaction being included in a ledger.

Defaults to the return value Python SDK’s Server().fetch_base_fee(), which is the most recent ledger’s base fee, usually 100.

Ex. MAX_TRANSACTION_FEE_STROOPS=300

SEP6_USE_MORE_INFO_URL

A boolean value indicating whether or not to provide the more_info_url response attribute in SEP-6 GET /transaction(s) responses and make the sep6/transaction/more_info endpoint available.

Defaults to False.

Ex. SEP6_USE_MORE_INFO_URL=1, SEP6_USE_MORE_INFO_URL=True

SEP10_CLIENT_ATTRIBUTION_REQUIRED

A boolean that if true, requires client applications to verify their identity by passing a domain in the challenge transaction request and signing the challenge with the SIGNING_KEY on that domain’s SEP-1 stellar.toml. See the SEP-10 section Verifying Client Application Identity for more information.

Defaults to False.

Ex. SEP10_CLIENT_ATTRIBUTION_REQUIRED=True, SEP10_CLIENT_ATTRIBUTION_REQUIRED=1

SEP10_CLIENT_ATTRIBUTION_REQUEST_TIMEOUT

An integer for the number of seconds to wait before canceling a server-side request to the client_domain parameter specified in the request, if present. This request is made from the API server and therefore an unresponsive client_domain can slow down request processing.

Defaults to 3 seconds.

Ex. SEP10_CLIENT_ATTRIBUTION_REQUEST_TIMEOUT=10

SEP10_CLIENT_ATTRIBUTION_ALLOWLIST

A list of domains that the server will issue challenge transactions containing client_domain Manage Data operations for. If SEP10_CLIENT_ATTRIBUTION_REQUIRED is True, client applications must pass a client_domain parameter whose value matches one of the elements in this list, otherwise the request will be rejected. If SEP10_CLIENT_ATTRIBUTION_REQUIRED is False, Polaris will return a challenge transaction without the requested client_domain Manage Data operation.

Ex. SEP10_CLIENT_ATTRIBUTION_ALLOWLIST=approvedwallet1.com,approvedwallet2.com

SEP10_CLIENT_ATTRIBUTION_DENYLIST

A list of domains that the server will not issue challenge transactions containing client_domain Manage Data operations for. If SEP10_CLIENT_ATTRIBUTION_REQUIRED is True, client applications that pass a client_domain parameter value that matches one of the elements in this list will be rejected. If SEP10_CLIENT_ATTRIBUTION_REQUIRED is False, Polaris will return a challenge transaction without the requested client_domain Manage Data operation.

Ex. SEP10_CLIENT_ATTRIBUTION_DENYLIST=maliciousclient.com

SEP10_HOME_DOMAINS

A list of home domains (no protocol, only hostname) that Polaris should consider valid when verifying SEP-10 challenge transactions sent by clients. The first domain will be used to build SEP-10 challenge transactions if the client request does not contain a home_domain parameter. Polaris will reject client requests that contain a home_domain value not included in this list. The value will be read from the environment using environ.Env.list().

Defaults to a list containing the hostname of HOST_URL defined above if not specified.

Ex. SEP10_HOME_DOMAINS=testanchor.stellar.org,example.com

SERVER_JWT_KEY

Required for SEP-10.

A secret string used to sign the encoded SEP-10 JWT contents. This should not be checked into version control.

Ex. SERVER_JWT_KEY=supersecretstellarjwtsecret

SIGNING_SEED

Required for SEP-10.

A Stellar secret key used to sign challenge transactions before returning them to clients. This should not be checked into version control.

Ex. SIGNING_SEED=SAEJXYFZOQT6TYDAGXFH32KV6GLSMLCX2E2IOI3DXY7TO2O63WFCI5JD

STELLAR_NETWORK_PASSHRASE

The string identifying the Stellar network to use.

Defaults to Test SDF Network ; September 2015.

Ex. STELLAR_NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015"

Internationalization

Polaris currently supports English and Portuguese. Note that this feature depends on the GNU gettext library. This page assumes you understand how translations work in Django.

If you’d like to add support for another language, make a pull request to Polaris with the necessary translation files. If Polaris supports the language you wish to provide, make sure the text content rendered from your app supports translation to that language.

To enable this support, add the following to your settings.py:

from django.utils.translation import gettext_lazy as _

USE_I18N = True
USE_L10N = True
USE_THOUSAND_SEPARATOR = True
LANGUAGES = [("en", _("English")), ("pt", _("Portuguese"))]

Note that adding the LANGUAGE setting is required. Without this, Django assumes your application supports every language Django itself supports.

You must also add django.middleware.locale.LocaleMiddleware to your settings.MIDDLEWARE after SessionMiddleware:

MIDDLEWARE = [
    ...,
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    ...
]

Once your project is configured to support translations, compile the translation files:

python anchor/manage.py compilemessages

Finally, configure your browser to use the targeted language. You should then see the translated text.

Logging

You can add Polaris’ logger to your LOGGING configuration. For example:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        }
    },
    'loggers': {
        'myapp': {
            'handlers': ['console'],
            'propogate': True,
            'LEVEL': 'DEBUG'
        },
        'polaris': {
            'handlers': ['console'],
            'propagate': True,
            'LEVEL': 'INFO'
        },
    }
}

You may want to configure the LEVEL of the Polaris logger differently depending on whether you’re running the service locally or in production. One way to do this by reading a POLARIS_LOG_LEVEL variable, or something similar, from the project’s environment.

Multisignature Assets

Background and Definitions

In the broader Stellar context, a multisignature account has more than one Stellar public key listed in it’s signers list. In an effort not to rephrase good documentation, a good quote from our Stellar dev documentation is:

In two cases, a transaction may need more than one signature. If the transaction has operations that affect more than one account, it will need authorization from every account in question. A transaction will also need additional signatures if the account associated with the transaction has multiple public keys.

This optional feature adds security but also complexity to an anchor’s application logic.

Multisignature Assets in Polaris

In the context of Polaris, multisignature assets refer to anchored assets that use distribution accounts that require multiple signatures in order to be successfully submitted to the Stellar network. Specifically, Polaris defines multisignatures assets as those whose distribution account’s medium threshold is not met by the master key’s weight.

Anchors can optionally configure each of their assets’ distribution accounts to require more than one (or many) signatures from valid signers in order to improve security around the flow of outgoing payments. The signers for each asset’s distribution account may or may not include the account’s public key as a master signer on the account by reducing it’s weight to zero.

Thresholds, signers, and more are configured on a Stellar account using the Set Options operation.

Note that anchors that issue their own assets may configure the issuing account to require multiple signatures as well. However, this is outside the scope of Polaris’ multisignature asset support.

Channel Accounts

A channel account as defined by the documentation,

[is] simply another Stellar account that is used not to send the funds but as the “source” account of the transaction. Remember transactions in Stellar each have a source account that can be different than the accounts being effected by the operations in the transaction. The source account of the transaction pays the fee and consumes a sequence number [and is not affected in any other way.]

Using channel accounts for transactions that need multiple signatures allows for a good deal of flexibility in terms of how signatures are collected for a transaction, but the reason why they are necessary is best explained by walking through what the process would look like without channel accounts.

  1. A client application makes a POST /deposit request and creates a transaction record

  2. The client application sends the funds to be deposited to the anchor’s off-chain account

  3. The anchor detects the received funds

  4. The anchor uses the current sequence number of the asset’s distribution account to create a transaction envelope in their database

  5. The anchor collects the necessary signatures on the transaction envelope

  6. Meanwhile, the distribution account submits another transaction to the Stellar Network

  7. When all signatures have been collected, the envelope XDR is submitted to the network

  8. The transaction fails with a 400 HTTP status code

This is due to the fact that the sequence number used for the transaction in step 3 is less than the current sequence number on the account as a direct result of step 4. Remember, when a Stellar account submits a transaction, the source account’s sequence number must be greater than the last sequence number used for that account.

Therefore, when a sequence number is used in an envelope to be submitted later, the sequence number in the envelope is likely less than the sequence number on the account when the anchor eventually gets around to submitting the transaction. This will cause the transaction to fail.

All this context is necessary to state the following:

Polaris uses channel accounts created by the anchor the source accounts on transactions using multisig distribution accounts as the source of funds so that transaction envelopes can be serialized, signed, and submitted on any schedule.

Using channel accounts, Polaris supports the following process for multisignature transactions:

  1. A client application makes a POST /deposit request and creates a transaction record

  2. The client application sends the funds to be deposited to the anchor’s off-chain account

  3. The anchor detects the received funds

  4. Polaris detects that the transaction requires more than one signature

  5. Polaris calls create_channel_account() for the transaction record

  6. The anchor funds a Stellar account using another Stellar account that doesn’t require multiple signatures

  7. Polaris uses the channel account as the transaction’s source account when building and saving the envelope XDR

  8. The anchor collects signatures on the transaction and updates it as ‘ready for submission’

  9. Polaris retrieves multisig transactions ready to be submitted in process_pending_deposits and submits them

  10. Multisig transactions succeed assuming it has proper signatures

  11. Polaris calls after_deposit(), in which the anchor can optionally merge the channel account back into another distribution account.

Currently, multisignature asset support is only relevant in the context of SEP-6 and 24 deposit transactions. Withdraw transaction flows don’t involve the anchor making any Stellar transaction using an asset’s distribution account, and SEP-31 outbound payments are not yet supported in Polaris.

Rate Limiting

It is highly encouraged to employ a rate limiting strategy when running Polaris to ensure the service remains available for all client applications. Many endpoints retrieve and create database records on each request, and some endpoints make outgoing web requests to Horizon or a client application’s callback endpoint.

Rate limiting can be particularly important for SEP-6 or SEP-24 deposit requests because the anchor is expected to poll their off-chain rails to detect if any of the funds from pending transactions initiated in these requests have arrived in the anchor’s account, which can be a resource-intensive process.

Rate limiting can be deployed using a number of strategies that often depend on the anchor’s deployment infrastructure. Optionally, the anchor could also implement a rate limiting policy using Django custom middleware support.

Shared Stellar Accounts

Shared accounts, sometimes called pooled or omnibus accounts, are Stellar accounts that hold the funds of multiple users and are managed by a service provider. These service providers can be cryptocurrency exchanges, wallet applications, remittance companies, or other businesses.

In the Stellar ecosystem today, users of these services are often assigned a Stellar Memo that the service provider uses internally to identify and track users’ balances held within the shared account. These user memos can also be attached to Stellar transactions containing payment operations as a way of specifying the user identified by the attached memo as the source or beneficiary of the payment.

Muxed Accounts

Using memos to identify users of shared accounts has several drawbacks. Users may forget to include their memo ID when making a payment to or from another account, and applications may not know to interpret transaction memos as user IDs, since memos are often used for other purposes as well.

For this reason, Stellar Core introduced Muxed Account support in Protocol 13. Literally speaking, muxed accounts are Stellar accounts encoded with an ID memo (a 64-bit integer). For example, the Stellar account GDUI2XWUZLWZQJV3Q4T6DMDMQD75WSVBJWCQ7GFD4TMB6G22TQK4ZPSU combined with the integer 12345 creates the muxed account MDUI2XWUZLWZQJV3Q4T6DMDMQD75WSVBJWCQ7GFD4TMB6G22TQK4YAAAAAAAAABQHHOWI.

Muxed accounts can be used as source and destination addresses within Stellar transactions. This removes the need to use transaction memo values as user IDs, provides applications a clear indication that the sender or recipient is a user of a shared account, and improves the user’s experience when transacting on Stellar in general.

SEP Support for Shared Accounts

Support for shared accounts has been added to the Stellar Ecosystem Protocols. In each protocol, shared accounts can be identified using either one of the approached outlined above (using memos or muxed accounts). Polaris and it’s integration functions have been adapted to provide the necessary support for each of these approaches.

SEP 10 Support

SEP-10 allows wallet or client applications to either specify a memo in addition to the Stellar account being authenticated or a muxed account. As a result, the challenge transaction and authentication token will also include this information, which allows services consuming the token to restrict access provided to information relevant to the particular user of the shared account.

See the SEP10Token documentation for more information on how anchors can determine which address format was used when authenticating.

SEP 12 Support

SEP-12 allows customers to be registered using either a memo in addition to the Stellar account or a muxed account. If the SEP-10 token used to authenticate contains a memo or muxed account when making a SEP-12 request, it must match the memo or muxed account used to originally create the customer.

Note

Anchors must design the data models used to store user information in a way that allows users to be specified using a memo or muxed account.

SEP 6 & 24 Support

Polaris’ Transaction model has three columns that are used to identify the user that initiated the transaction: stellar_account, muxed_account, and account_memo. These values are assigned directly from information extracted from the SEP-10 JWT used when requesting the transaction.

Additionally, Transaction.to_address and Transaction.from_address may be muxed account addresses. Polaris will properly submit deposit transactions and detect incoming withdrawal payment transaction using the muxed account if present.

SEP 31 Support

SEP-31 is unique in the sense that the owners of the Stellar accounts used to send and receive Stellar payments are service providers, not end-users. This means that the use of muxed accounts or user memos in payment transactions are unnecessary.

However, SEP-31 relies on SEP-12 for registering customers involved in a transaction. The SEP-10 JWT created for SEP-31 sender applications will not include memo or muxed account information, but these applications will use memos in SEP-12 requests for registering customers.