What is Polaris?¶
Polaris implements SEP-24 and is maintained by the Stellar Development Foundation (SDF). SEP-24 is a standard defined to make wallets and anchors interoperable, meaning any wallet can communicate with any anchor for the purpose of withdrawing or depositing assets into the stellar network.
Polaris is not a library or a framework; its an extendable django reusable-app. Like many django apps, it comes with fully-implemented endpoints, templates, and database models. The project is completely open source and available at the SDF’s github.
To use Polaris, developers must implement it’s provided integrations points. These integration points allow developers to inject their own business logic into the transaction processing flow, customize their stellar.toml, and more.
The SDF maintains a reference server running Polaris here, and its source code can be found under the repository’s example folder.
Installation and Configuration¶
First make sure you have
cd’ed into your django project’s main directory
and then run
pip install django-polaris
Add the following to
INSTALLED_APPS in settings.py. Any app that overrides
a static asset in Polaris should be listed before “polaris”. This ensures that
django will find your asset before the Polaris default.
INSTALLED_APPS = [ ..., "django.contrib.staticfiles", "corsheaders", "rest_framework", "sass_processor", "polaris", ]
Add Polaris’ PolarisSameSiteMiddleware,
CorsMiddleware to your
SessionMiddleware must be listed below
MIDDLEWARE = [ ..., 'polaris.middleware.PolarisSameSiteMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', ... ]
PROJECT_ROOT in your project’s settings.py. Polaris uses this to
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Add the following to your settings.py as well:
FORM_RENDERER = "django.forms.renderers.TemplatesSetting" STATIC_ROOT = os.path.join(BASE_DIR, "<your static root directory>") STATIC_URL = "<your static url path>" STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" STATICFILES_FINDERS = [ "django.contrib.staticfiles.finders.FileSystemFinder", "django.contrib.staticfiles.finders.AppDirectoriesFinder", "sass_processor.finders.CssFinder", ] SASS_PROCESSOR_ROOT = STATIC_ROOT DEFAULT_PAGE_SIZE = <your default page size>
This allows Polaris to override django’s default HTML widgets to provide a great UI out of the box. See the Static Files django page for more information.
Polaris uses environment variables that should be defined in the
environment or included in
DJANGO_SECRET_KEY="yoursupersecretkey" DJANGO_DEBUG=True ASSETS="USD" USD_DISTRIBUTION_ACCOUNT_SEED="" USD_ISSUER_ACCOUNT_ADDRESS="" STELLAR_NETWORK_PASSPHRASE="Test SDF Network ; September 2015" HORIZON_URI="https://horizon-testnet.stellar.org/" SERVER_JWT_KEY="yoursupersecretjwtkey" HOST_URL="https://example.com"
Polaris supports anchoring multiple assets on the Stellar network.
should be a comma-separated list of asset codes such as “USD”, “ETH”, or “MYCOIN”.
For every asset code listed, you should add a pair of variables for the distribution account’s private key and issuer account’s public key. Note that each pair of variable names should be prepended with the asset code. The SDF has built a small CLI tool for creating these accounts on testnet.
Python Code and Bash Commands¶
Add the Polaris endpoints in
import polaris.urls from django.urls import path, include urlpatterns = [ ..., path("", include(polaris.urls)), ]
python manage.py migrate
python manage.py compilescss
python manage.py collectstatic --no-input
The last step is to add an
Asset database object for every token you
intend to anchor. Get into your python shell, then run something like this:
from polaris.models import Asset Asset.objects.create( code="USD", issuer="<the issuer address>", significant_digits=2, deposit_fee_fixed=1, deposit_fee_percent=2, withdraw_fee_fixed=1, withdraw_fee_percent=2, deposit_min_amount=10, deposit_max_amount=10000, withdrawal_min_amount=10, withdrawal_min_amount=10000 )
See the Asset documentation for more information on the fields used.
At this point, you are now ready to run the Polaris anchor server!
Running the Service¶
Polaris is a multi-process application. The main process, the web server, implements SEP-24, but there are three other processes that perform necessary functions.
Polling Pending Deposits¶
When a user initiates a deposit transaction, the anchor must wait for the user to send the deposit amount to the anchor’s bank account. When this happens, the anchor should notice and deposit the same amount of the tokenized asset into the user’s stellar account.
Polaris provides the
poll_pending_deposits integration function for this
purpose, which will be run periodically via the
python manage.py poll_pending_deposits --loop --interval 10
This process will continue indefinitely, calling the associated integration function, sleeping for 10 seconds, and then calling it again.
Watching for Withdrawals¶
When a user initiates a withdrawal transaction, the anchor must wait for the
user to send the tokenized amount to the anchor’s stellar account. Polaris’
watch_transactions command line tool streams transactions from every
anchored asset’s distribution account and attempts to match every incoming
deposit with a pending withdrawal.
If it finds a match, it will update the transaction’s status and call
process_withdrawal integration function. Use this function to
connect to your banking rails and send the transaction amount to the user’s
Run the process like so:
python manage.py watch_transactions
Sometimes, a user will initiate a deposit to an account that does not exist yet,
or the user’s account won’t have a trustline to the asset’s issuer account. In
these cases, the transaction database object gets assigned the
check_trustlines is a command line tool that periodically checks if the
transactions with this status now have a trustline to the relevant asset. If one
does, Polaris will submit the transaction to the stellar network and call the
after_deposit integration function once its completed.
check_trustlines has the same arguments as
python manage.py check_trustlines --loop --interval 60
Running the Web Server¶
Polaris is an HTTPS-only server, so to run it locally you must have a self-signed SSL certificate and configure your browser to trust it.
Run this command to generate a self-signed certificate for localhost:
openssl req -x509 -out localhost.crt -keyout localhost.key \ -newkey rsa:2048 -nodes -sha256 \ -subj '/CN=localhost' -extensions EXT -config <( \ printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
Then, instead of using the usual
runserver command, Polaris comes with the
runsslserver command. Just add the app to your
INSTALLED_APPS = [ ..., "polaris", "sslserver" ]
Finally, run this commands:
python manage.py runsslserver --certificate <path to localhost.crt> --key <path to localhost.key>
At this point, you need to start implementing the integration points Polaris provides. Check out the Integrations section for more information.
To set up the development environment, fork the repository, then:
cd django-polaris docker-compose build docker-compose up
You should now have a minimal anchor server running on port 8000. When you make changes locally, the docker containers will restart with the updated code. Your browser may complain about the service using a self-signed certificate for HTTPS. You can resolve this by marking the certificate used by the service as trusted.
You can install the dependencies locally in a virtual environment:
pip install pipenv cd django-polaris pipenv install --dev pipenv run pytest -c polaris/pytest.ini
Or, you can simply run the tests from inside the docker container. However, this may be slower.
docker exec -it <image ID> pipenv run pytest
Submit a PR¶
After you’ve made your changes, push them to you a remote branch and make a Pull Request on the stellar/django-polaris master branch.