API Reference

CLI Commands

process_pending_deposits

class polaris.management.commands.process_pending_deposits.Command[source]

This process handles all of the transaction submission logic for deposit transactions.

When this command is invoked, Polaris queries the database for transactions in the following scenarios and processes them accordingly.

A transaction is in the pending_user_transfer_start or pending_external status.

Polaris passes these transaction the poll_pending_deposits() integration function, and the anchor is expected to return Transaction objects whose funds have been received off-chain. Polaris then checks if each transaction is in one of the secenarios outlined below, and if not, submits the return transactions them to the Stellar network. See the poll_pending_deposits() integration function for more details.

A transaction’s destination account does not have a trustline to the requested asset.

Polaris checks if the trustline has been established. If it has, and the transaction’s source account doesn’t require multiple signatures, Polaris will submit the transaction to the Stellar Network.

A transaction’s source account requires multiple signatures before submission to the network.

In this case, pending_signatures is set to True and the anchor is expected to collect signatures, save the transaction envelope to envelope_xdr, and set pending_signatures back to False. Polaris will then query for these transactions and submit them to the Stellar network.

Optional arguments:

-h, --help

show this help message and exit

--loop

Continually restart command after a specified number of seconds.

--interval INTERVAL, -i INTERVAL

The number of seconds to wait before restarting command. Defaults to 10.

watch_transactions

class polaris.management.commands.watch_transactions.Command[source]

Streams transactions to the distribution_account of each Asset in the DB.

Note that this command assumes Stellar payments are made to one distribution account address per asset. Some third party custody service providers may not use this scheme, in which case the custody integration class should provide an alternative command for detecting incoming Stellar payments.

For every response from the server, attempts to find a matching transaction in the database and updates the transaction’s status to pending_anchor or pending_receiver depending on the protocol.

Then, the execute_outgoing_transactions process will query for transactions in those statuses and provide the anchor an integration function for executing the payment or withdrawal.

Optional arguments:

-h, --help

show this help message and exit

execute_outgoing_transactions

class polaris.management.commands.execute_outgoing_transactions.Command[source]

This process periodically queries for transactions that are ready to be executed off-chain and calls Polaris’ execute_outgoing_transaction() integration function for each one. Ready transactions are those in pending_receiver or pending_anchor statuses, among other conditions.

Anchors are expected to update the status to completed or pending_external if initiating the transfer was successful.

Optional arguments:

-h, --help

show this help message and exit

--loop

Continually restart command after a specified number of seconds.

--interval INTERVAL, -i INTERVAL

The number of seconds to wait before restarting command. Defaults to 30.

poll_outgoing_transactions

class polaris.management.commands.poll_outgoing_transactions.Command[source]

Polaris periodically queries for transactions in pending_external and passes them to the poll_outgoing_transactions().

The anchor is expected to update the transactions’ status to completed if the funds have been confirmed to be delivered.

Optional arguments:

-h, --help

show this help message and exit

--loop

Continually restart command after a specified number of seconds.

--interval INTERVAL, -i INTERVAL

The number of seconds to wait before restarting command. Defaults to 30.

testnet

class polaris.management.commands.testnet.Command[source]

The testnet command comes with the following commands:

issue allows users to create assets on the Stellar testnet network. When the test network resets, you’ll have to reissue your assets.

reset calls the functionality invoked by issue for each asset in the anchor’s database. Since the database does not store the issuing account’s secret key, the user must input each key as requested by the Polaris command. It also performs a couple other functions necessary to ensure your Polaris instance runs successfully after a testnet reset:

Moves all pending_trust transactions to error

This is done because all accounts have been cleared from the network. While its possible an account that required a trustline could be recreated and a trustline could be established, its unlikely. Polaris assumes a testnet reset makes in-progress transactions unrecoverable.

Updates the paging_token of latest transaction streamed for each anchored asset

watch_transactions streams transactions to and from each anchored asset’s distribution account. Specifically, it streams transactions starting with the most recently completed transaction’s paging_token on startup. When the testnet resets, the paging_token used for transactions prior to the reset are no longer valid. To fix this, Polaris updates the paging_token of the most recently completed transaction for each anchored asset to “now”.

Positional arguments:

reset
-h, --help

show this help message and exit

issue
-h, --help

show this help message and exit

--asset ASSET, -a ASSET

the code of the asset issued

--issuer-seed ISSUER_SEED, -i ISSUER_SEED

the issuer’s secret key

--distribution-seed DISTRIBUTION_SEED, -d DISTRIBUTION_SEED

the distribution account’s secret key

--client-seed CLIENT_SEED, -c CLIENT_SEED

the client account’s secret key

--issue-amount ISSUE_AMOUNT

the amount sent to distribution account. Also the limit for the trustline.

--client-amount CLIENT_AMOUNT

the amount sent to client account. Also the limit for the trustline.

add-asset allows users to add assets to the database:

add-asset
-h, --help

show this help message and exit

--asset ASSET, -a ASSET

the code of the asset issued

--issuer-public ISSUER_PUBLIC, -i ISSUER_PUBLIC

the issuer’s public key

--distribution-seed

DISTRIBUTION_SEED, -d DISTRIBUTION_SEED the distribution account’s secret key

--sep6-enabled

(Optional) flag to enable sep6 for this asset, defaults to false

--sep24-enabled

(Optional) flag to enable sep24 for this asset, defaults to false

--sep31-enabled

(Optional) flag to enable sep31 for this asset, defaults to false

--sep38-enabled

(Optional) flag to enable sep38 for this asset, defaults to false

--deposit-enabled

(Optional) flag to enable deposits for this asset, defaults to false

–withdrawal-enabled (Optional) flag to enable withdrawals for this asset, defaults to false –symbol (Optional) symbol for the asset, default to “$”

delete-asset allows users to delete assets from the database:

delete-asset
-h, --help

show this help message and exit

--asset ASSET, -a ASSET

the code of the asset to be deleted

--issuer-public ISSUER_PUBLIC, -i ISSUER_PUBLIC

the issuer’s public key

Forms

class polaris.integrations.TransactionForm(transaction, *args, **kwargs)[source]

A base class for collecting transaction information. Developers must define subclasses to collect additional information and apply additional validation.

This form assumes the amount collected is in units of a Stellar Asset. If the amount of an OffChainAsset must be collected, create a different form.

Note that Polaris’ base UI treats the amount field on this form and its subclasses differently than other forms. Specifically, Polaris automatically adds the asset’s symbol to the input field, adds a placeholder value of 0, makes the fee table visible (by default), and uses the amount entered to update the fee table on each change.

If you do not want the fee table to be displayed when this form class is rendered, set "show_fee_table" to False in the dict returned from content_for_template().

Fee calculation within the UI is done using the asset’s fixed and percentage fee values saved to the database. If those values are not present, Polaris makes calls to the anchor’s /fee endpoint and displays the response value to the user. If your /fee endpoint requires a type parameter, add a TransactionForm.type attribute to the form. Polaris will detect the attribute’s presence on the form and include it in /fee requests.

The amount field is validated with the clean_amount() function, which ensures the amount is within the bounds for the asset type.

Integrations

Fees

polaris.integrations.calculate_fee(fee_params, *_args, request=None, **_kwargs)[source]

Calculate the fee to be charged for the transaction described by fee_params.

Note that this endpoint only supports calculating fees expressed in units of a Stellar asset. If fees cannot be calculated using the fee_params passed, raise a ValueError for Polaris to return a 400 Bad Request to the client.

Replace this function with another by passing it to register_integrations() as described in Register Integrations if the fees charged for transactions is not calculated using the asset’s fee_fixed and fee_percent attributes.

If replaced, /info responses will no longer contain the fee_fixed and fee_percent attributes per-asset. This is because Polaris can no longer assume fees are determined using those attributes alone.

fee_params will always contain the following key-value pairs:

  • amount: Decimal

  • asset_code: str

  • operation: str

  • type: str

Each of these key-value pairs correspond to the associated parameter for the /fee endpoint. The Decimal returned will be used as the fee value in the response.

Return type

Decimal

Customers

class polaris.integrations.CustomerIntegration[source]
callback(token, request, params, *args, **kwargs)[source]

Save the URL provided in association with the user identified by the parameters sent in the request. The anchor is responsible for making POST requests containing the response body of a GET request to the saved URL whenever the SEP-12 status of the customer changes. Polaris does not manage an anchor’s customer data and therefore cannot make these requests.

Client applications may register callback URLs if the application does not have the ability to poll the GET /customer endopoint at any time, which requires SEP-10 authentication (and consequently the relevant account’s signature).

If the customer specified does not exist, raise an ObjectDoesNotExist. If the URL is provided is invalid in some way, raise a ValueError.

If this function is not implemented, Polaris will respond with a 501 Not Implemented.

Parameters
  • token (SEP10Token) – the SEP10Token object representing the authenticated session

  • request (Request) – a rest_framework.request.Request instance

  • params (Dict) – request parameters as described in SEP-12

Raises

ValueError or django.core.exceptions.ObjectDoesNotExist

delete(token, request, account, memo, memo_type, *args, **kwargs)[source]

Delete the record of the customer specified by account, memo, and memo_type. If such a record does not exist, raise a ObjectDoesNotExist exception for Polaris to return a 404 Not Found response.

Parameters
  • token (SEP10Token) – the SEP10Token object representing the authenticated session

  • request (Request) – a rest_framework.request.Request instance

  • account (str) – the stellar or muxed account associated with the customer

  • memo (Optional[str]) – the optional memo used to create the customer

  • memo_type (Optional[str]) – the optional type of the memo used to create to the customer

get(token, request, params, *args, **kwargs)[source]

Return a dictionary matching the response schema outlined in SEP-12 GET /customer based on the params passed.

Raise a ValueError if the parameters are invalid, or raise an ObjectDoesNotExist exception if the customer specified via the id parameter does not exist. An error response with the appropriate status will be sent using the message passed to the exception.

Parameters
  • token (SEP10Token) – the SEP10Token object representing the authenticated session

  • request (Request) – a rest_framework.request.Request instance

  • params (Dict) – request parameters as described in SEP-12

Return type

Dict

more_info_url(token, request, account, *args, memo=None, **kwargs)[source]

Return a URL the client can open in a browser to view the status of their account with the anchor. This URL will be returned in a SEP-6 Customer Information Status response. This is optional.

Parameters
  • token (SEP10Token) – the SEP10Token object representing the authenticated session

  • request (Request) – a rest_framework.request.Request instance

  • account (str) – the stellar or muxed account for the url to be returned

  • memo (Optional[int]) – the ID memo used to identify the user of the shared Stellar account

Return type

str

put(token, request, params, *args, **kwargs)[source]

Update or create a record of the customer information passed. This information can then later be queried for when a client requests a deposit or withdraw on behalf of the customer.

If the information passed in params is invalid in some way, raise a ValueError for Polaris to return a 400 Bad Request response to the client. The message contained in the exception will be passed as the error message in the response. If the request specified a customer id in the request body but a record with that ID doesn’t exist, raise a django.exceptions.ObjectDoesNotExist exception. Polaris will return a 404 response.

Return a customer ID that clients can use in future requests, such as a GET /customer request or a SEP-31 POST /transactions request. If the request included an id parameter, make sure the same id is returned.

If the required information is provided and the customer has Transaction objects in the pending_customer_info_update status, all such Transaction.status values should be updated to pending_receiver. Polaris will then call the execute_outgoing_transaction integration function for each updated transaction.

If the anchor requires verification of values passed in params, such as mobile_number or email_address, the anchor should initate the verification process in this function and ensure the next call to GET /customer contains the field requiring verification with a VERIFICATION_REQUIRED status. Unless the anchor expects users to verify the field value in some other manner, such as opening a confirmation link sent via email, client applications will eventually make a call to PUT /customer/verification to return the verification codes sent as a result of the initial call to PUT /customer.

Parameters
  • token (SEP10Token) – the SEP10Token object representing the authenticated session

  • request (Request) – a rest_framework.request.Request instance

  • params (Dict) – request parameters as described in SEP-12

Raises

ValueError or ObjectDoesNotExist

Return type

str

put_verification(token, request, account, params, *args, **kwargs)[source]

Validate the values, typically verification codes, passed in params for the customer identified by params["id"]. See the endpoint specification for more information on the request format.

Anchors may return fields from GET /customer requests with the VERIFICATION_REQUIRED status if the anchor requires the user to verify a SEP-9 field value provided in a previous call to PUT /customer. The most common field needing verification is mobile_number. This function will be called when the client passes the verification value back to the anchor.

If the validation values are correct, return a dictionary that is identical to what would be returned for a call to GET /customer.

If any of the validation values are incorrect, raise a ValueError and Polaris will raise a 400 Bad Request.

If the customer specified by params["id"] does not exist, or the authenticated account does not match Stellar account associated with the ID, raise an ObjectDoesNotExist exception. Polaris will return a 404 Not Found response.

If this function is not implemented, Polaris will respond with a 501 Not Implemented.

Parameters
  • token (SEP10Token) – the SEP10Token object representing the authenticated session

  • request (Request) – a rest_framework.request.Request instance

  • account (str) – the Stellar or muxed account authenticated via SEP-10

  • params (Dict) – the request body of the PUT /customer/verification call

Raises

ValueError, ObjectDoesNotExist, NotImplementedError

Return type

Dict

Deposits

class polaris.integrations.DepositIntegration[source]

The container class for deposit integration functions.

Subclasses must be registered with Polaris by passing it to polaris.integrations.register_integrations().

after_deposit(transaction, *args, **kwargs)[source]

Use this function to perform any post-processing of transaction after its been executed on the Stellar network. This could include actions such as updating other django models in your project or emailing users about completed deposits. Overriding this function is only required for anchors with multi-signature distribution accounts.

If the transacted asset’s distribution account requires multiple signatures, transaction.channel_account was created on Stellar when Polaris made a call to create_channel_account() and was used as the transaction-level source account when submitting to Stellar. This temporary account holds a minimum a XLM reserve balance that must be merged back to persistent account owned by the anchor. Generally, the destination account for the merge operation will be the same account that created and funded the channel account.

Parameters

transaction (Transaction) – a Transaction that was executed on the Stellar network

after_form_validation(request, form, transaction, *args, **kwargs)[source]

Use this function to process the data collected with form and to update the state of the interactive flow so that the next call to DepositIntegration.form_for_transaction() returns the next form to render to the user.

If you need to store some data to determine which form to return next when DepositIntegration.form_for_transaction is called, store this data in a model not used by Polaris.

If form is the last form to be served to the user, Polaris will update the transaction status to pending_user_transfer_start, indicating that the anchor is waiting for the user to deliver off-chain funds to the anchor. If the KYC information collected is still being verified, update the Transaction.status column to pending_anchor here. Make sure to save this change to the database before returning. In this case Polaris will detect the status change and will not update the status again. Polaris will wait until the anchor changes the transaction’s status to pending_user_transfer_start before including the transaction in calls to DepositIntegration.poll_pending_deposits().

If the user is requesting a deposit or withdrawal of a Stellar asset in exchange for different off-chain asset, such as requesting a deposit of USDC using fiat mexican pesos, the anchor must assign a Quote object to Transaction.quote before the end of the interactive flow. Polaris will check for a Quote object on the transaction and adjust the UI of the MORE_INFO template to display the exchange rate and other exchange-related information. Transaction.fee_asset also must be populated with the asset in which fees will be collected, formatted using SEP-38 Asset Identification Format.

Parameters
  • request (Request) – the rest_framework.request.Request object

  • form (Form) – the completed forms.Form submitted by the user

  • transaction (Transaction) – the Transaction database object

after_interactive_flow(request, transaction)[source]

Override this function to update the transaction or any related models with information collected during an external interactive flow.

This function will be called each time the external application makes a request to the GET /sep24/transactions/deposit/interactive endpoint. This gives anchors the freedom to update the transaction once at the end of the flow or multiple times throughout the flow.

The last time this function is called, the transaction’s status value must be updated to pending_user_transfer_start or pending_anchor, and the transaction’s amounts and fees must also be updated. This will signal to the wallet application that the interactive flow has complete and that the anchor is ready to proceed.

content_for_template(request, template, form=None, transaction=None, *args, **kwargs)[source]

Return a dictionary containing the Django template variables to be passed to the template rendered.

The anchor may also pass a special key, template_name, which should be a file path relative your Django app’s /templates directory. Polaris will render the template specified by this key to the user instead of the default templates defined below. Note that all of the Django template variables defined below will still be passed to the template specified.

Polaris will pass one of the following polaris.templates.Template values to indicate the default template Polaris will use.

Template.DEPOSIT

The template used for deposit flows

Template.WITHDRAW

The template used for withdraw flows

Template.MORE_INFO

The template used to show transaction details

The form parameter will always be None when template is Template.MORE_INFO since that page does not display form content.

If form is None and template_name is not Template.MORE_INFO, returning None will signal to Polaris that the anchor is done collecting information for the transaction. Returning content will signal to Polaris that the user needs to take some action before receiving the next form, such as confirming their email. In this case, make sure to return an appropriate guidance message or return a custom template_name.

Using this function, anchors pass key-value pairs to the template being rendered. Some of these key-value pairs are used by Polaris, but anchors are allowed and encouraged to extend Polaris’ templates and pass custom key-value pairs.

def content_for_template(template_name, form=None, transaction=None):
    ...
    return {
        "title": "Deposit Transaction Form",
        "guidance": "Please enter the amount you would like to deposit.",
        "show_fee_table": True,
        "symbol": "$",
        "icon_label": "Stellar Development Foundation",
        "icon_path": "images/company-icon.png",
        # custom field passed by the anchor
        "username": "John.Doe"
    }

Below are all the keys passed to the template rendered. If the dictionary returned has the same key, the default value Polaris uses will be overwritten.

For Template.DEPOSIT and Template.WITHDRAW:

form

The django.forms.Form instance returned from form_for_transaction().

post_url

The URL to make the POST request containing the form data to.

operation

Either deposit or withdraw.

asset

The polaris.models.Asset object of the Stellar asset being transacted.

use_fee_endpoint

A boolean indicating whether or not Polaris should use the GET /fee endpoint when calculating fees and rendering the amounts on the page.

org_logo_url

A URL for the default logo to render if the anchor has not specified their own via icon_path.

additive_fees_enabled

A boolean indicating whether or not to add fees to the amount entered in TransactionForm amount fields. False by default, meaning fees are subtracted from the amounts entered.

title

The browser tab’s title.

guidance

A text message displayed on the page that should help guide the user to take the appropriate action(s).

icon_label

The label for the image rendered on the page specified by "icon_path".

icon_path

The relative file path to the image you would like to use as the company icon in the UI. The file path should be relative to your Django app’s /static directory. If icon_path is not present, Polaris will use the image specified by your TOML integration function’s ORG_LOGO key. If neither are present, Polaris will use its default image. All images will be rendered in a 100 x 150px sized box as defined by the default stylesheet.

show_fee_table

A boolean for whether the fee table in the default template should be visible on the page rendered to the user. This table is hidden by default unless a TransactionForm is returned from form_for_transaction(), in which case the fee table will be displayed. If the anchor instructs Polaris to display the fee table but a TransactionForm is not present on the page, the anchor is responsible for updating the fee table with the appropriate values. This is useful when the anchor is collecting the amount of an off-chain asset, since TransactionForm assumes the amount collected is for an on-chain asset.

symbol

The character string that precedes the amounts shown on the fee table. It defaults to the Stellar Asset.symbol. Note that the symbol used in input fields must be passed separately using the field’s widget attributes.

For Template.MORE_INFO

tx_json

A JSON-serialized string matching the schema returned from GET /transaction

amount_in_asset

The string representation of the asset given to the anchor by the user, formatted using SEP-38 Asset Identification Format.

amount_out_asset

The string representation of the asset sent from the anchor to the user, formatted using SEP-38 Asset Identification Format.

amount_in

A string containing the amount to be displayed on the page as Amount Sent

amount_out

A string containing the amount to be displayed on the page as Amount Received

amount_fee

A string containing the amount to be displayed on the page as Fee

amount_in_symbol

Asset.symbol or OffChainAsset.symbol, depending on whether or not asset sent to the anchor is on or off chain. If Transaction.quote is null, the value will always match Asset.symbol.

amount_fee_symbol

Asset.symbol or OffChainAsset.symbol, depending on the value of Transaction.fee_asset. If Transaction.quote is null, the value will always be Asset.symbol.

amount_out_symbol

Asset.symbol or OffChainAsset.symbol, depending on whether or not asset sent by the anchor is on or off chain. If Transaction.quote is null, the value will always match Asset.symbol.

amount_in_significant_decimals

The number of decimals to display for amounts of Transaction.amount_in. Derived from Asset.significant_decimals or OffChainAsset.decimals. If Transaction.quote is null, the value will always match Asset.significant_decimals.

amount_fee_significant_decimals

The number of decimals to display for amounts of Transaction.amount_fee. Derived from Asset.significant_decimals or OffChainAsset.decimals, depending on the value of Transaction.fee_asset.

amount_out_significant_decimals

The number of decimals to display for amounts of Transaction.amount_out. Derived from Asset.significant_decimals or OffChainAsset.decimals. If Transaction.quote is null, the value will always match Asset.significant_decimals.

transaction

The polaris.models.Transaction object representing the transaction.

asset

The polaris.models.Asset object representing the asset.

offchain_asset

The OffChainAsset object used in the Transaction.quote, if present.

price

Transaction.quote.price, if present.

price_inversion

1 / Transaction.quote.price, if price is present. The default more_info.html template uses this number for displaying exchange rates when quotes are used.

price_inversion_significant_decimals

The number of decimals to display for exchange rates. Polaris calculates this to ensure the rate displayed is always correct.

exchange_amount

If Transaction.quote is not None, exchange_amount is the value of Transaction.amount_out expressed in units of Transaction.amount_in.

exchanged_amount

If Transaction.quote is not None, exchanged_amount is the value of Transaction.amount_in expressed in units of Transaction.amount_out.

Parameters
  • request (Request) – a rest_framework.request.Request instance

  • template (Template) – a polaris.templates.Template enum value for the template to be rendered in the response

  • form (Optional[Form]) – the form to be rendered in the template

  • transaction (Optional[Transaction]) – the transaction being processed

Return type

Optional[Dict]

create_channel_account(transaction, *args, **kwargs)[source]

Create a temporary, per-deposit-transaction-object Stellar account using a different Stellar account and save the secret key of the created account to transaction.channel_seed.

This channel account must only be used as the source account for transactions related to the Transaction object passed. It also must not be used to submit transactions by any service other than Polaris. If it is, the outstanding transactions will be invalidated due to bad sequence numbers.

If this integration function is called, the deposit payment represented by transaction requires multiple signatures in order to be successfully submitted to the Stellar network. The anchored asset’s distribution account may or may not be in that set of signatures required, depending on the configuration of the distribution account’s signers.

Once the transaction’s signatures have been collected and the updated XDR written to transaction.envelope_xdr, transaction.pending_signatures should be updated to False, which will cause the process_pending_deposits process to submit it to the network along with the other transactions deemed ready by the anchor.

If transaction.to_address doesn’t exist on Stellar and the transaction has a channel_account, transaction.channel_account will also be used to create and fund the destination account for the deposit payment to the user. So the channel account will be used for one or potentially two Stellar transactions.

Once the deposit payment has been made on Stellar, Polaris will call after_deposit(), which is where the anchor should merge the funds within transaction.channel_account back to a persistent Stellar account owned by the anchor. See after_deposit() for more information.

Parameters

transaction (Transaction) – An object representing the transaction that requires a channel account as it’s source.

form_for_transaction(request, transaction, post_data=None, amount=None, *args, **kwargs)[source]

This function should return the next form to render for the user given the state of the interactive flow.

For example, this function could return an instance of a TransactionForm subclass. Once the form is submitted, Polaris will detect the form used is a TransactionForm subclass and update transaction.amount_in with the amount specified in form.

If post_data is passed, it must be used to initialize the form returned so Polaris can validate the data submitted. If amount is passed, it can be used to pre-populate a TransactionForm amount field to improve the user experience.

def form_for_transaction(self, transaction, post_data = None, amount = None):
    if transaction.amount_in:
        return
    elif post_data:
        return TransactionForm(transaction, post_data)
    else:
        return TransactionForm(transaction, initial={"amount": amount})

After a form is submitted and validated, Polaris will call DepositIntegration.after_form_validation with the populated form and transaction. This is where developers should update their own state-tracking constructs or do any processing with the data submitted in the form.

Finally, Polaris will call this function again to check if there is another form that needs to be rendered to the user. If you are collecting KYC data, you can return a forms.Form with the fields you need.

This loop of submitting a form, validating & processing it, and checking for the next form will continue until this function returns None.

When that happens, Polaris will check if content_for_template() also returns None. If that is the case, Polaris assumes the anchor is finished collecting information and will update the Transaction status to pending_user_transfer_start.

If content_for_template() returns a dictionary, Polaris will serve a page without a form. Anchors should do this when the user needs to take some action in order to continue, such as confirming their email address. Once the user is confirmed, form_for_transaction() should return the next form.

Parameters
  • request (Request) – the rest_framework.request.Request object

  • transaction (Transaction) – the Transaction database object

  • post_data (Optional[QueryDict]) – the data sent in the POST request as a dictionary

  • amount (Optional[Decimal]) – a Decimal object the wallet may pass in the GET request. Use it to pre-populate your TransactionForm along with any SEP-9 parameters.

Return type

Optional[Form]

Returns

a dictionary containing various pieces of information to use when rendering the next page.

interactive_url(request, transaction, asset, amount, callback, lang, *args, **kwargs)[source]

Override this function to provide the wallet a non-Polaris endpoint to begin the interactive flow. If the amount or callback arguments are not None, make sure you include them in the URL returned.

Note that after_interactive_flow() should also be implemented if this function is implemented to ensure the status, amounts, fees, and any other relevant information is saved to the Transaction record once the interactive flow is complete.

Return type

Optional[str]

Returns

a URL to be used as the entry point for the interactive deposit flow

patch_transaction(token, request, params, transaction, *args, **kwargs)[source]

Currently only used for SEP-6 transactions.

The GET /info response contains a fields object that describes the custom fields an anchor requires in requests to the GET /deposit endpoint. If one or more of these fields were originally accepted but later discovered to be invalid in some way, an anchor can place the transaction in the pending_transaction_info_update status, save a JSON-serialized object describing the fields that need updating to Transaction.required_info_updates, and save a human-readable message to Transaction.required_info_message describing the reason the fields need to be updated. A client can make a request to GET /transactions to detect that updated information is needed.

This function is called when SEP-6 PATCH /transactions requests are made by the client to provide the updated values described in the Transaction.required_info_updates. Use the params passed in the request to update transaction or any related data.

Polaris validates that every field listed in Transaction.required_info_updates is present in params but cannot validate the values. If a ValueError is raised, Polaris will return a 400 response containing the exception message in the body.

If no exception is raised, Polaris assumes the update was successful and will update the transaction’s status back to pending_anchor as well as clear the required_info_updates and required_info_message fields.

Parameters
  • token (SEP10Token) – the SEP10Token object representing the authenticated session

  • request (Request) – a rest_framwork.request.Request object

  • params (Dict) – The request parameters as described in the PATCH /transactions endpoint.

  • transaction (Transaction) – A Transaction object for which updated was provided.

process_sep6_request(token, request, params, transaction, *args, **kwargs)[source]

This function is called during requests made to the SEP-6 deposit and deposit-exchange endpoints. The params object will contain the parameters included in the request. Note that Polaris will only call this function for deposit-exchange requests if SEP-38 is added to Polaris’ ACTIVE_SEPS setting and the requested Stellar asset is enabled for SEP-38.

If a request to the the deposit-exchange endpoint is made, a Quote object will be assigned to the Transaction object passed.

Process these parameters and return one of the following responses outlined below as a dictionary. Save transaction to the DB if you plan to return a success response. If transaction is saved to the DB but a failure response is returned, Polaris will return a 500 error to the user.

If you’d like the user to send Transaction.amount_in plus the fee amount, add the amount charged as a fee to Transaction.amount_in and Transaction.amount_expected. here. While not required per SEP-6, it is encouraged to also populate Transaction.amount_fee and Transaction.amount_out here as well. If this function is called for a deposit-exchange request, Transaction.fee_asset should also be assigned. If not assigned here, these columns must be assigned before returning the transaction from RailsIntegration.poll_pending_deposits().

Note that the amount sent over the Stellar Network could differ from the amount specified in this API call, so fees and the amount delievered may have to be recalculated in RailsIntegration.poll_pending_deposits() for deposits and RailsIntegration.execute_outgoing_transaction() for withdrawals.

Polaris responds to requests with the standard status code according the SEP. However, if you would like to return a custom error code in the range of 400-599 you may raise an rest_framework.exceptions.APIException. For example, you could return a 503 status code by raising an APIException("service unavailable", status_code=503).

Deposit no additional information needed

The success response. Polaris creates most of the attributes described in this response. Simply return the ‘how’ and optionally ‘extra_info’ attributes. For example:

return {
    "how": "<your bank account address>",
    "extra_info": {
        "message": "Deposit the funds to the bank account specified in 'how'"
    }
}

Customer information needed

A failure response. Return the response as described in SEP.

return {
  "type": "non_interactive_customer_info_needed",
  "fields" : ["family_name", "given_name", "address", "tax_id"]
}

Customer Information Status

A failure response. Return the ‘type’ and ‘status’ attributes. If CustomerIntegration.more_info_url() is implemented, Polaris will include the ‘more_info_url’ attribute in the response as well.

return {
  "type": "customer_info_status",
  "status": "denied",
}
Parameters
  • token (SEP10Token) – the SEP10Token object representing the authenticated session

  • request (Request) – a rest_framwork.request.Request object

  • params (Dict) – the request parameters as described in /deposit

  • transaction (Transaction) – an unsaved Transaction object representing the transaction to be processed

Return type

Dict

save_sep9_fields(token, request, stellar_account, fields, language_code, muxed_account=None, account_memo=None, account_memo_type=None, *args, **kwargs)[source]

DEPRECATED: stellar_account, account_memo, account_memo_type, and muxed_account parameters. Use the token object passed instead.

Save the fields passed for the user identified by stellar_account to pre-populate the forms returned from form_for_transaction(). Note that this function is called before the transaction is created.

For example, you could save the user’s contact information with the model used for KYC information.

# Assuming you have a similar method and model
if token.muxed_account:
    user_key = token.muxed_account
elif token.memo:
    user_key = f"{token.account}:{token.memo}"
else:
    user_key = token.account
user = user_for_key(user_key)
user.phone_number = fields.get('mobile_number')
user.email = fields.get('email_address')
user.save()

Then when returning a form to collect KYC information, also return the values saved in this method relevant to that form.

# In your form_for_transaction() implementation
if token.muxed_account:
    user_key = token.muxed_account
elif token.memo:
    user_key = f"{token.account}:{token.memo}"
else:
    user_key = token.account
user = user_for_key(user_key)
form_args = {
    'phone_number': format_number(user.phone_number),
    'email': user.email_address
}
return KYCForm(initial=form_args),

If you’d like to validate the values passed in fields, you can perform any necessary checks and raise a ValueError in this function. Polaris will return the message of the exception in the response along with 400 HTTP status. The error message should be in the language specified by language_code if possible.

Stellar Info File (TOML)

polaris.integrations.get_stellar_toml(request, *args, **kwargs)[source]

Replace this function with another by passing it to register_integrations().

The dictionary returned will be merged with Polaris’ default attributes and serialized using the toml.dumps() function. The output will be rendered in the HTTP response.

The base attributes provided by Polaris are:

  • ACCOUNTS

  • VERSION

  • SIGNING_KEY

  • NETWORK_PASSPHRASE

  • WEB_AUTH_ENDPOINT

  • TRANSFER_SERVER

  • TRANSFER_SERVER_0024

  • KYC_SERVER

  • DIRECT_PAYMENT_SERVER

  • QUOTE_SERVER

The contents of the dictionary returned will overwrite the default matching key values.

Returns

a dictionary of SEP-1 attributes

SEP-6 Info

polaris.integrations.default_info_func(request, asset, lang, exchange, *args, **kwargs)[source]

Replace this function with another by passing it to register_integrations() as described in Register Integrations.

Return a dictionary containing the fields and types key-value pairs described in the SEP-6 /info response for the asset passed. Raise a ValueError() if lang is not supported. For example,

if asset.code == "USD":
    return {
        "fields": {
            "email_address" : {
                "description": "your email address for transaction status updates",
                "optional": True
            },
            "amount" : {
                "description": "amount in USD that you plan to deposit"
            },
            "type" : {
                "description": "type of deposit to make",
                "choices": ["SEPA", "SWIFT", "cash"]
            }
        },
        "types": {
            "bank_account": {
                "fields": {
                    "dest": {"description": "your bank account number" },
                    "dest_extra": { "description": "your routing number" },
                    "bank_branch": { "description": "address of your bank branch" },
                    "phone_number": { "description": "your phone number in case there's an issue" }
                }
            },
            "cash": {
                "fields": {
                    "dest": {
                        "description": "your email address. Your cashout PIN will be sent here.",
                        "optional": True
                    }
                }
            }
        }
    }
Parameters
  • request (Request) – a rest_framework.request.Request object

  • asset (Asset) – Asset object for which to return the fields and types key-value pairs

  • lang (Optional[str]) – the language code the client requested for the description values in the response

  • exchange (bool) – whether or not the info returned will be used for a deposit-exchange or withdraw-exchange response object. Only relevant if SEP-38 is enabled.

Return type

Dict

Rails

class polaris.integrations.RailsIntegration[source]

A container class for functions that access off-chain rails, such banking accounts or other crypto networks.

Register Integrations

polaris.integrations.register_integrations(deposit=None, withdrawal=None, sep31_receiver=None, rails=None, toml=None, fee=None, sep6_info=None, customer=None, custody=None, quote=None)[source]

Registers the integration classes and functions with Polaris

Call this function in your app’s Django AppConfig.ready() function:

from django.apps import AppConfig

class PolarisIntegrationApp(AppConfig):
    name = 'Polaris Integration'
    verbose_name = name

    def ready(self):
        from polaris.integrations import register_integrations
        from myapp.integrations import (
            MyDepositIntegration,
            MyWithdrawalIntegration,
            MyCustomerIntegration,
            MyQuoteIntegration,
            toml_integration,
            fee_integrations,
            info_integration
        )

        register_integrations(
            deposit=MyDepositIntegration(),
            withdrawal=MyWithdrawalIntegration(),
            customer=MyCustomerIntegration(),
            toml=toml_integration,
            sep6_info=info_integration,
            fee=fee_integration,
            quote=MyQuoteIntegration()
        )

Simply pass the integration classes or functions you use.

Parameters
  • deposit (Optional[DepositIntegration]) – the DepositIntegration subclass instance to be used by Polaris

  • withdrawal (Optional[WithdrawalIntegration]) – the WithdrawalIntegration subclass instance to be used by Polaris

  • sep31_receiver (Optional[SEP31ReceiverIntegration]) – the SEP31ReceiverIntegration subclass instance to be used by Polaris

  • rails (Optional[RailsIntegration]) – the RailsIntegration subclass instance to be used by Polaris

  • toml (Optional[Callable]) – a function that returns stellar.toml data as a dictionary

  • fee (Optional[Callable]) – a function that returns the fee that would be charged

  • sep6_info (Optional[Callable]) – a function that returns the /info fields or types values for an Asset

  • customer (Optional[CustomerIntegration]) – the CustomerIntegration subclass instance to be used by Polaris

  • custody (Optional[CustodyIntegration]) – the CustodyIntegration subclass instance to be used by Polaris

  • quote (Optional[QuoteIntegration]) – the QuoteIntegration subclass instance to be used by Polaris

Raises
  • ValueError – missing argument(s)

  • TypeError – arguments are not subclasses of DepositIntegration or Withdrawal

SEP-31 Transactions

class polaris.integrations.SEP31ReceiverIntegration[source]

The container class for SEP31 integrations

info(request, asset, lang=None, *args, **kwargs)[source]

Return a dictionary containing the "fields" and “sep12” objects as described in the info response for the given asset. Polaris will provide the rest of the fields documented in the info response.

Descriptions should be in the lang passed if supported.

return {
    "fields": {
        "transaction":{
           "routing_number":{
              "description": "routing number of the destination bank account"
           },
           "account_number":{
              "description": "bank account number of the destination"
           },
           "type":{
              "description": "type of deposit to make",
              "choices":[
                 "SEPA",
                 "SWIFT"
              ]
           }
        }
    },
    "sep12": {
        "sender": {
            "types": {
                "sep31-sender": {
                    "description": "the only SEP-12 type for SEP-31 sending customers"
                }
            }
        },
        "receiver": {
            "types": {
                "sep31-receiver-cash-pickup": {
                    "description": "recipients who will pick up cash at physical locations"
                },
                "sep31-receiver-bank-transfer": {
                    "description" : "recipients who would like to receive funds via direct bank transfer"
                }
            }
        }
    }
}
Parameters
  • request (Request) – the rest_framework.request.Request instance

  • asset (Asset) – the Asset object for the field values returned

  • lang (Optional[str]) – the ISO 639-1 language code of the user

Return type

Dict

process_patch_request(token, request, params, transaction, *args, **kwargs)[source]

Use the params passed in the request to update transaction or any related data.

Polaris validates that every field listed in Transaction.required_info_updates is present in params but cannot validate the values. If a ValueError is raised, Polaris will return a 400 response containing the exception message in the body.

If no exception is raised, Polaris assumes the update was successful and will update the transaction’s status back to pending_receiver as well as clear the required_info_updates and required_info_message fields.

Once the transaction enters the pending_receiver status, the execute_outgoing_transactions process will attempt to send the payment to the receiving user. See the RailsIntegration.execute_outgoing_transaction function for more information on the lifecycle of a transaction.

Parameters
  • token (SEP10Token) – The SEP10Token instance representing the authenticated session

  • request (Request) – the rest_framework.request.Request instance

  • params (Dict) – the request body of the PATCH /transaction request

  • transaction (Transaction) – the Transaction object that should be updated

process_post_request(token, request, params, transaction, *args, **kwargs)[source]

Use the params passed in the request to do any processing of the user and requested transaction necessary to facilitate the payment to the receiving user. If the arguments are valid, save transaction and link it to your other models. If the transaction is saved but an error response is returned Polaris will return a 500 response to the user.

If you’d like the user to send Transaction.amount_in plus the fee amount, add the amount charged as a fee to Transaction.amount_in and Transaction.amount_expected here.

While not required per SEP-31, it is encouraged to also populate Transaction.amount_fee, Transaction.fee_asset (if Transaction.quote is not None), and Transaction.amount_out here as well. Note that the amount sent over the Stellar Network could differ from the amount specified in this API call, so fees and the amount delievered may have to be recalculated in RailsIntegration.execute_outgoing_transaction().

Also note that if your anchor service supports SEP-38, Transaction.quote may be a firm or indicative Quote model instance representing the requested exchange of on and off-chain assets. If Quote.type == Quote.TYPE.indicative, it is not yet saved to the database and Polaris will save it if a success response is returned.

Polaris validates that the request includes all the required fields returned by SEP31ReceiverIntegration.info() but cannot validate the values. Return None if the params passed are valid, otherwise return one of the error dictionaries outlined below.

If the sender_id or receiver_id values are invalid or the information collected for these users is not sufficient to process this request, return a dictionary matching the customer-info-needed response schema.

return {
    "error": "customer_info_needed",
    "type": "sep31-large-amount-sender"
}

For example, the above response could be used if the anchor requires additional information on the sender when the amount is large. The type key specifies the appropriate type value the client should use for the sender’s SEP-12 GET /customer request, and is optional.

If some optional fields from info() are missing but needed for this transaction, return a dictionary matching the schema described in the transaction-info-needed response.

return {
    "error": "transaction_info_needed",
    "fields": {
        "transaction": {
            "sender_bank_account": {
                "description": (
                    "The bank account number used by the sender. "
                    "Only required for large transactions."
                ),
                "optional": True
            }
        }
    }
}

If some parameters passed are simply not acceptable, return a dictionary containing a single "error" key-value pair.

return {
    "error": "invalid 'sender_bank_account' format"
}
Parameters
  • token (SEP10Token) – The SEP10Token instance representing the authenticated session

  • request (Request) – The rest_framework.request.Request instance

  • params (Dict) – The parameters included in the /transaction request

  • transaction (Transaction) – the Transaction object representing the transaction being processed

Return type

Optional[Dict]

valid_sending_anchor(token, request, public_key, *args, **kwargs)[source]

Return True if public_key is a known anchor’s stellar account address, and False otherwise. This function ensures that only registered sending anchors can make requests to protected endpoints.

Parameters
  • token (SEP10Token) – The SEP10Token instance representing the authenticated session

  • request (Request) – the rest_framework.request.Request instance

  • public_key (str) – the public key of the sending anchor’s stellar account

Return type

bool

Withdrawals

class polaris.integrations.WithdrawalIntegration[source]

The container class for withdrawal integration functions

Subclasses must be registered with Polaris by passing it to polaris.integrations.register_integrations.

after_form_validation(request, form, transaction, *args, **kwargs)[source]

Same as DepositIntegration.after_form_validation, except transaction.to_address should be saved here when present in form.

Parameters
  • request (Request) – a rest_framework.request.Request instance

  • form (Form) – the completed forms.Form submitted by the user

  • transaction (Transaction) – the Transaction database object

after_interactive_flow(request, transaction)[source]

Same as DepositIntegration.after_interactive_flow

content_for_template(request, template, form=None, transaction=None, *args, **kwargs)[source]

Same as DepositIntegration.content_for_template.

Parameters
  • request (Request) – a rest_framework.request.Request instance

  • template (Template) – a polaris.templates.Template enum value for the template to be rendered in the response

  • form (Optional[Form]) – the form to be rendered in the template

  • transaction (Optional[Transaction]) – the transaction being processed

Return type

Optional[Dict]

form_for_transaction(request, transaction, post_data=None, amount=None, *args, **kwargs)[source]

Same as DepositIntegration.form_for_transaction

Parameters
  • request (Request) – a rest_framwork.request.Request object

  • transaction (Transaction) – the Transaction database object

  • post_data (Optional[QueryDict]) – the data included in the POST request body as a dictionary

  • amount (Optional[Decimal]) – a Decimal object the wallet may pass in the GET request. Use it to pre-populate your TransactionForm along with any SEP-9 parameters.

Return type

Optional[Form]

interactive_url(request, transaction, asset, amount, callback, lang, *args, **kwargs)[source]

Same as DepositIntegration.interactive_url

Return type

Optional[str]

Returns

a URL to be used as the entry point for the interactive withdrawal flow

patch_transaction(token, request, params, transaction, *args, **kwargs)[source]

Same as DepositIntegration.patch_transaction

process_sep6_request(token, request, params, transaction, *args, **kwargs)[source]

Same as DepositIntegration.process_sep6_request except for the case below. Specifically, the how attribute should not be included.

Withdraw no additional information needed

A success response. Polaris populates most of the attributes for this response. Simply return an ‘extra_info’ attribute if applicable:

{
    "extra_info": {
        "message": "Send the funds to the following stellar account including 'memo'"
    }
}

In addition to this response, you may also return the Customer information needed and Customer Information Status responses as described in DepositIntegration.process_sep6_request.

Return type

Dict

save_sep9_fields(token, request, stellar_account, fields, language_code, muxed_account=None, account_memo=None, account_memo_type=None, *args, **kwargs)[source]

Same as DepositIntegration.save_sep9_fields

Quotes

class polaris.integrations.QuoteIntegration[source]
get_price(token, request, sell_asset, buy_asset, buy_amount=None, sell_amount=None, sell_delivery_method=None, buy_delivery_method=None, country_code=None, *args, **kwargs)[source]

Return the price of one unit of buy_asset in terms of sell_asset. The price returned from this function is non-binding, meaning a Quote object will not be created and returned to the client as a result of this call.

Polaris will ensure that there is an ExchangePair database record for the sell_asset and buy_asset, that the specified sell_delivery_method or buy_delivery_method is supported by the off-chain asset, and that the anchor supports transacting the off-chain asset in the country_code, if specified.

Raise a ValueError if the parameters are invalid in some way. Because Polaris validates all the parameters passed, the only reason to raise this exception _should_ be because sell_amount or buy_amount is outside the minimum and maximum bounds for your service. Polaris will return a 400 Bad Request status code in this case.

Raise a RuntimeError if you cannot return prices for the provided sell_asset and buy_asset for any reason. For example, the service used by the anchor to source exchange prices could be down. Polaris will return a 503 Server Unavailable status code in this case.

Parameters
  • token (SEP10Token) – The SEP10Token object representing the authenticated session

  • request (Request) – The rest_framework.Request object representing the request

  • sell_asset (Union[Asset, OffChainAsset]) – The asset the client would like to sell for buy_assets

  • sell_amount (Optional[Decimal]) – The amount the client would like to sell of sell_asset

  • buy_asset (Union[Asset, OffChainAsset]) – The asset the client would like to buy using sell_asset

  • buy_amount (Optional[Decimal]) – The amount the client would like to purchase of buy_asset

  • sell_delivery_method (Optional[DeliveryMethod]) – The method the client would like to use to deliver funds to the anchor.

  • buy_delivery_method (Optional[DeliveryMethod]) – The method the client would like to use to receive or collect funds from the anchor.

  • country_code (Optional[str]) – The ISO 3166-1 alpha-3 code of the user’s current address

Return type

Decimal

get_prices(token, request, sell_asset, sell_amount, buy_assets, sell_delivery_method=None, buy_delivery_method=None, country_code=None, *args, **kwargs)[source]

Return a list of prices in the order of the buy_assets provided. Each price should be the value of one unit of the buy_asset in terms of sell_asset. The prices returned from this function are non-binding, meaning a Quote object will not be created and returned to the client as a result of this call.

The buy_assets list passed are the assets that have an ExchangePair database record with the sell_asset. Polaris will also ensure all buy_assets support the buy_delivery_method and country_code if specified by the client.

Polaris will also ensure that the sell_delivery_method is supported for sell_asset.

Raise a ValueError if the parameters are invalid in some way. Because Polaris validates all the parameters passed, the only reason to raise this exception _should_ be because the sell_amount is outside the minimum and maximum bounds for your service. Polaris will return a 400 Bad Request status code in this case.

Raise a RuntimeError if you cannot return prices for the provided sell_asset and buy_assets for any reason. For example, the service used by the anchor to source exchange prices could be down. Polaris will return a 503 Server Unavailable status code in this case.

Parameters
  • token (SEP10Token) – The SEP10Token object representing the authenticated session

  • request (Request) – The rest_framework.Request object representing the request

  • sell_asset (Union[Asset, OffChainAsset]) – The asset the client would like to sell for buy_assets

  • buy_assets (List[Union[Asset, OffChainAsset]]) – The assets the client would like to buy using sell_asset

  • sell_amount (Decimal) – The amount the client would like to sell of sell_asset

  • sell_delivery_method (Optional[DeliveryMethod]) – The method the client would like to use to deliver funds to the anchor.

  • buy_delivery_method (Optional[DeliveryMethod]) – The method the client would like to use to receive or collect funds from the anchor.

  • country_code (Optional[str]) – The ISO 3166-1 alpha-3 code of the user’s current address

Return type

List[Decimal]

post_quote(token, request, quote, *args, **kwargs)[source]

Assign Quote.price and Quote.expire_at`` on the quote passed and return it. The anchor will be expected to honor the price set when the quote is used in a Transaction. Note that the Quote object passed is not yet saved to the database when this function is called. If no exception is raised, Polaris will calculate the amount of the asset not specified in the request using the price assigned and save the returned quote to the database. However, the anchor is free to save the quote to the database in this function if necessary.

Polaris will ensure that there is an ExchangePair database record for the sell_asset and buy_asset, that the specified sell_delivery_method or buy_delivery_method is supported by the off-chain asset, and that the anchor supports transacting the off-chain asset in the country_code, if specified.

Raise a ValueError if the parameters are invalid in some way. Because Polaris validates all the parameters passed, the only reason to raise this exception _should_ be because sell_amount or buy_amount is outside the minimum and maximum bounds for your service OR the requested expires_at value is not acceptable to the anchor. Polaris will return a 400 Bad Request status code in this case.

Raise a RuntimeError if you cannot return prices for the provided sell_asset and buy_asset for any reason. For example, the service used by the anchor to source exchange prices could be down. Polaris will return a 503 Server Unavailable status code in this case.

Parameters
  • token (SEP10Token) – The SEP10Token object representing the authenticated session

  • request (Request) – The rest_framework.Request object representing the request

  • quote (Quote) – The Quote object representing the exchange rate to be offered

Return type

Quote

Custody

class polaris.integrations.CustodyIntegration[source]

The base class for supporting third party custody service providers.

property account_creation_supported: bool

Return True if the custody service provider supports funding Stellar accounts not custodied by the provider, False otherwise.

Return type

bool

property claimable_balances_supported: bool

Return True if the custody service provider supports sending deposit payments in the form of claimable balances, False otherwise.

Return type

bool

create_destination_account(transaction)[source]

Submit a transaction using the anchor’s custody service provider to fund the Stellar account address saved to Transaction.to_address and return the hash of the transaction once it is included in a ledger

If self.account_creation_supported is False Polaris will never call this method. However, Polaris will instead check if destination accounts exist when a request for deposit is made and will return a 422 Unprocessable Entity response if it does not.

It is highly recommended to support creating destination accounts.

Handling Non-Success Cases

Raise a TransactionSubmissionPending exception if the call(s) made to initiate the transaction submission process did not result in the immediate inclusion of the transaction in a ledger. Polaris will simply call this function again with the same transaction parameters unless a SIGINT or SIGTERM signal has been sent to the process, in which case Polaris will save Transaction.submission_status as SubmissionStatus.PENDING and exit. When the process starts up, Polaris will retrieve the currently pending transaction from the database and pass it to this function again.

Raise a TransactionSubmissionBlocked exception if the transaction is not yet ready to be submitted. A transaction may be blocked for a number of reasons excluding Polaris’ default checks for account and trustline existence. Polaris will update Transaction.submission_status to SubmissionStatus.BLOCKED and expected the anchor to update this field to SubmissionStatus.UNBLOCKED once Polaris should attempt submission again.

Parameters

transaction (Transaction) – the transaction for which the destination account must be funded

Return type

str

get_distribution_account(asset)[source]

Return the Stellar account used to receive payments of asset. This method is a replacement for the Asset.distribution_account property which is derived from the Asset.distribution_seed database column.

This means that the same distribution account should always be returned for the same asset. Do not implement this method if your custody service provider does not support using the same Stellar account for all incoming payments of an asset. Some custody service providers provide a Stellar account and memo to use as the destination of an incoming payment on a per-transaction basis, with no guaranteed consistency for the Stellar account provided.

The watch_transactions command assumes this method is implemented. If this method is not implemented, another appraoch to detecting and matching incoming payments must be used.

Parameters

asset (Asset) – the asset sent in payments to the returned Stellar account

Return type

str

get_receiving_account_and_memo(request, transaction)[source]

Return the Stellar account that the client should use as the destination of the payment transaction and the string representation of the memo the client should attach to the transaction. Polaris will save these to transaction and return them in API responses when necessary.

This method is only called once for a given transaction.

The memo returned _must_ be unique to the transaction, since the anchor is expected to match the database record represented by transaction with the on-chain transaction submitted.

This function differs from get_distribution_account() by allowing the anchor to return any Stellar account that can be used to receive a payment. This is ideal when the account used is determined by a custody service provider that does not guarantee that the account provided will be the account provided for future transactions.

Parameters
  • request (Request) – the request that initiated the call to this function

  • transaction (Transaction) – the transaction that will be processed when a payment using the account and memo returned is received

Return type

Tuple[str, str]

submit_deposit_transaction(transaction, has_trustline=True)[source]

Submit the transaction to the Stellar network using the anchor’s custody service provider and return the hash of the transaction once it is included in a ledger

Claimable Balances

If self.claimable_balances_supported is True, Polaris may call this method when the destination account does not yet have a trustline to Transaction.asset. In this case, the anchor should send the deposit as a claimable balance instead of a payment or path payment. Use the has_trustline parameter to determine which operations to use.

If self.claimable_balances_supported is False, this method will only be called when the destination account exists and has a trustline to Transaction.asset.

Handling Non-Success Cases

Raise a TransactionSubmissionPending exception if the call(s) made to initiate the transaction submission process did not result in the immediate inclusion of the transaction in a ledger. Polaris will simply call this function again with the same transaction parameters unless a SIGINT or SIGTERM signal has been sent to the process, in which case Polaris will save Transaction.submission_status as SubmissionStatus.PENDING and exit. When the process starts up, Polaris will retrieve the currently pending transaction from the database and pass it to this function again.

Raise a TransactionSubmissionBlocked exception if the transaction is not yet ready to be submitted. A transaction may be blocked for a number of reasons excluding Polaris’ default checks for account and trustline existence. Polaris will update Transaction.submission_status to SubmissionStatus.BLOCKED and expected the anchor to update this field to SubmissionStatus.UNBLOCKED once Polaris should attempt submission again.

Parameters
  • transaction (Transaction) – the Transaction object representing the Stellar transaction that should be submitted to the network

  • has_trustline (bool) – whether or not the destination account has a trustline for the requested asset

Return type

str

Middleware

class polaris.middleware.TimezoneMiddleware(get_response)[source]

Adapted from the Django documentation on timezones. It checks for a "timezone" key stored in the request session and uses it when rendering content returned in the response.

Polaris includes a timezone.js script that detects the users’ UTC offset and sends it to the server, which stores a timezone with that offset in the user’s session. This script is automatically loaded if using a template that inherits from base.html.

However, there is a limitation with this approach. For users’s without exising sessions, which are identified using a browser cookie, Polaris cannot detect the user’s timezone prior to rendering the first page of content. This means that dates and times shown to on the first page to a new user will be in the default timezone specified in your project’s settings.

That is why Django’s documentation recommends that you simply ask the user what timezone they would like to use instead of attempting to detect it automatically. If this approach is taken, simply save the specified timezone in the user’s session under the "timezone" key after adding this middleware.

Miscellaneous

class polaris.sep10.token.SEP10Token(jwt)[source]

An object representing the authenticated session of the client.

This object will be passed to every integration function that is called within the a request containing the JWT in the Authorization header.

property account: str

The Stellar account (G…) authenticated. Note that a muxed account could have been authenticated, in which case Token.muxed_account should be used.

Return type

str

property client_domain: Optional[str]

A nonstandard JWT claim containing the client’s home domain, included if the challenge transaction contained a client_domain ManageData operation

Return type

Optional[str]

property expires_at: datetime

The expiration time on or after which the JWT will not accepted for processing, RFC7519, Section 4.1.4 — represented as a UTC datetime object

Return type

datetime

property issued_at: datetime

The time at which the JWT was issued RFC7519, Section 4.1.6 - represented as a UTC datetime object

Return type

datetime

property issuer: str

The principal that issued a token, RFC7519, Section 4.1.1 — a Uniform Resource Identifier (URI) for the issuer (https://example.com or https://example.com/G…)

Return type

str

property memo: Optional[int]

The memo included with the payload’s sub value, if present

Return type

Optional[int]

property muxed_account: Optional[str]

The M-address specified in the payload’s sub value, if present

Return type

Optional[str]

property payload: dict

The decoded contents of the JWT string

Return type

dict

Models

Asset

class polaris.models.Asset[source]

Asset(id, created, modified, code, issuer, significant_decimals, deposit_enabled, deposit_fee_fixed, deposit_fee_percent, deposit_min_amount, deposit_max_amount, withdrawal_enabled, withdrawal_fee_fixed, withdrawal_fee_percent, withdrawal_min_amount, withdrawal_max_amount, send_fee_fixed, send_fee_percent, send_min_amount, send_max_amount, distribution_seed, sep24_enabled, sep6_enabled, sep31_enabled, sep38_enabled, symbol)

property asset_identification_format

SEP-38 asset identification format

code

The asset code as defined on the Stellar network.

deposit_enabled

True if deposit for this asset is supported.

deposit_fee_fixed

Optional fixed (base) fee for deposit. In units of the deposited asset. This is in addition to any fee_percent. Omit if there is no fee or the fee schedule is complex.

deposit_fee_percent

Optional percentage fee for deposit. In percentage points. This is in addition to any fee_fixed. Omit if there is no fee or the fee schedule is complex.

deposit_max_amount

Optional maximum amount. No limit if not specified.

deposit_min_amount

Optional minimum amount. No limit if not specified.

property distribution_account

The Stellar public key derived from Asset.distribution_seed

distribution_seed

The distribution stellar account secret key. The value is stored in the database using Fernet symmetric encryption, and only decrypted when in the Asset object is in memory.

issuer

The issuing Stellar account address.

send_fee_fixed

Optional fixed (base) fee for sending this asset in units of this asset. This is in addition to any send_fee_percent. If null, fee_fixed will not be displayed in SEP31 /info response.

send_fee_percent

Optional percentage fee for sending this asset in percentage points. This is in addition to any send_fee_fixed. If null, fee_percent will not be displayed in SEP31 /info response.

send_max_amount

Optional maximum amount. No limit if not specified.

send_min_amount

Optional minimum amount. No limit if not specified.

sep24_enabled

True if this asset is transferable via SEP-24

sep31_enabled

True if this asset is transferable via SEP-31

sep38_enabled

True if this asset is exchangeable via SEP-38

sep6_enabled

True if this asset is transferable via SEP-6

significant_decimals

The number of decimal places Polaris should save when collecting input amounts

symbol

The symbol used in HTML pages when displaying amounts of this asset

withdrawal_enabled

True if withdrawal for this asset is supported.

withdrawal_fee_fixed

Optional fixed (base) fee for withdraw. In units of the withdrawn asset. This is in addition to any fee_percent.

withdrawal_fee_percent

Optional percentage fee for withdraw in percentage points. This is in addition to any fee_fixed.

withdrawal_max_amount

Optional maximum amount. No limit if not specified.

withdrawal_min_amount

Optional minimum amount. No limit if not specified.

Delivery Method

class polaris.models.DeliveryMethod[source]

Delivery methods are the supported means of payment from the user to the anchor and from the anchor to the user. For example, an anchor may have retail stores that accept cash drop-off and pick-up, or only accept debit or credit card payments. The method used by the anchor to collect or deliver funds to the user may affect the rate or fees charged for facilitating the transaction.

TYPE = <class 'model_utils.choices.Choices'>

The types of delivery methods.

description

The human-readable description of the deliver method, to be used in SEP-38 response bodies.

name

The name of the delivery method, to be used in SEP-38 request and response bodies.

type

The type of delivery method. Sell methods describe how a client can deliver funds to the anchor. Buy methods describe how a client can receive or collect funds from the anchor.

Exchange Pair

class polaris.models.ExchangePair[source]

Exchange pairs consist of an off-chain and on-chain asset that can be exchanged. Specifically, one of these assets can be sold by the client (sell_asset) and the other is bought by the client (buy_asset). ExchangePairs cannot consist of two off-chain assets or two on-chain assets. Note that two exchange pair objects must be created if each asset can be bought or sold for the other.

buy_asset

The asset the client can purchase with sell_asset using SEP-38’s Asset Identification Format.

sell_asset

The asset the client can provide in exchange for buy_asset using SEP-38’s Asset Identification Format.

Off-Chain Asset

class polaris.models.OffChainAsset[source]

Off-chain assets represent the asset being exchanged with the Stellar asset. Each off-chain asset has a set of delivery methods by which the user can provide funds to the anchor and by which the anchor can deliver funds to the user.

country_codes

A comma-separated list of ISO 3166-1 alpha-3 codes of the countries where the anchor supports delivery of this asset.

delivery_methods

The list of delivery methods support for collecting and receiving this asset

identifier

The identifier of the off-chain asset as defined by SEP-38’s Asset Identification Format.

scheme

The scheme of the off-chain asset as defined by SEP-38’s Asset Identification Format.

significant_decimals

The number of decimal places Polaris should preserve when collecting & calculating amounts.

symbol

The symbol to use when displaying amounts of this asset

Transaction

class polaris.models.Transaction[source]

Transaction(id, paging_token, stellar_account, muxed_account, account_memo, asset, quote, kind, submission_status, status, status_eta, status_message, stellar_transaction_id, external_transaction_id, amount_in, amount_expected, amount_out, amount_fee, fee_asset, queue, queued_at, started_at, completed_at, from_address, to_address, required_info_updates, required_info_message, memo, memo_type, receiving_anchor_account, refunded, protocol, pending_signatures, envelope_xdr, channel_seed, claimable_balance_supported, claimable_balance_id, more_info_url, on_change_callback, pending_execution_attempt, client_domain)

KIND = <class 'model_utils.choices.Choices'>

Choices object for the kind of transaction

MEMO_TYPES = <class 'model_utils.choices.Choices'>

Type for the memo. Can be either hash, id, or text

PROTOCOL = <class 'model_utils.choices.Choices'>

Values for protocol column

SUBMISSION_STATUS = <class 'model_utils.choices.Choices'>

Submission Statuses

  • not_ready

    used until a transaction is returned from RailsIntegration.poll_pending_deposits() and determined by check_account to be ready for submission to the Stellar Network

  • ready

    used when the transaction has been processed by the check_account task and verified that the transaction is ready to be submitted to the Stellar Network

  • processing

    used when Polaris is submitting the transaction to Stellar. Note that up to two transactions could be submitted for this Transaction object, one for creating the account if it doesn’t exist, and the other for sending the deposit payment.

  • pending

    used when the transaction has been passed to CustodyIntegration.create_destination_account() or CustodyIntegration.submit_deposit_transaction() but a TransactionSubmissionPending exception was raised in the most-recent invocation, and a SIGINT or SIGTERM was sent, preventing Polaris from submitting again.

  • pending_trust

    used when the transaction destination account does not yet have a trustline

  • blocked

    used when the transaction has been passed to CustodyIntegration.create_destination_account() or CustodyIntegration.submit_deposit_transaction() but a TransactionSubmissionBlocked exception was raised in the most-recent invocation. Polaris will simply move to the next transaction.

  • unblocked

    Similar to READY, but indicates that the transaction was previously blocked.

  • completed

    used when a transaction has been successfully submitted to the Stellar network

  • failed

    used when a transaction has been passed to CustodyIntegration.submit_deposit_transaction() but a TransactionSubmissionFailed exception was raised

account_memo

The ID (64-bit integer) memo identifying the user of the shared Stellar account authenticated via SEP-10 that initiated this transaction. If this column value is not null, Transaction.muxed_account will be null.

amount_expected

Amount the client specified would be sent to the anchor at the start of a transaction. Note that Transaction.amount_in can differ from this field after funds have been received. Until then, the fields will match. This field makes it possible to check if the amount sent to the anchor matches the amount the client initially specified in an API request or form.

amount_fee

Amount of fee charged by anchor.

amount_in

Amount received by anchor at start of transaction as a string with up to 7 decimals. Excludes any fees charged before the anchor received the funds.

amount_out

Amount sent by anchor to user at end of transaction as a string with up to 7 decimals. Excludes amount converted to XLM to fund account and any external fees.

asset

The Django foreign key to the associated Asset

channel_seed

A keypair of the account used when sending SEP-6 or SEP-24 deposit transactions to Transaction.to_address, if present. This is only used for transactions requiring signatures Polaris cannot add itself.

claimable_balance_id

The ID of the claimable balance used to send funds to the user. This column will be None if claimable_balance_supported is False or if the transaction has not yet been submitted to the Stellar network.

claimable_balance_supported

claimable_balance_supported is a boolean to indicate if the wallet supports the SEP24 requirements for handeling claimable balance deposits.

client_domain

The hostname of the client application that requested this transaction on behalf of the user. The SIGNING_KEY on https://client_domain/.well-known/stellar.toml signed the challenge transaction used to obtain the authentication token necessary to request this transaction, effectively allowing requests including the authentication token to be attributed to it.

completed_at

Completion date and time of transaction. Assigned null for in-progress transactions.

envelope_xdr

The base64-encoded XDR blob that can be deserialized to inspect and sign the encoded transaction.

external_transaction_id

(optional) ID of transaction on external network that either started the deposit or completed the withdrawal.

fee_asset

The string representing the asset in which the fee is charged. The string must be formatted using SEP-38’s Asset Identification Format, and is only necessary for transactions using different on and off-chain assets.

from_address

Sent from address, perhaps BTC, IBAN, or bank account.

id

Unique, anchor-generated id for the deposit/withdrawal.

kind

The character field for the available KIND choices.

memo

(optional) Value of memo to attach to transaction, for hash this should be base64-encoded.

memo_type

(optional) Type of memo that anchor should attach to the Stellar payment transaction, one of text, id or hash.

property message

Human readable explanation of transaction status

more_info_url

A URL that is opened by wallets after the interactive flow is complete. It can include banking information for users to start deposits, the status of the transaction, or any other information the user might need to know about the transaction.

muxed_account

The muxed (M…) account authenticated via SEP-10 that initiated this transaction. If this column value is not null, Transaction.stellar_account is derived from this value and Transaction.account_memo will be null.

on_change_callback

A URL that the anchor should POST a JSON message to when the status property of the transaction created as a result of this request changes.

paging_token

The token to be used as a cursor for querying before or after this transaction

pending_execution_attempt

An internal column used to ensure transactions are not retrieved from the database and executed by different processes running the same command, specifically process_pending_deposits and execute_outgoing_transactions.

pending_signatures

Boolean for whether or not non-Polaris signatures are needed for this transaction’s envelope.

protocol

Either ‘sep6’, ‘sep24’, or ‘sep31’

queue

The queue that this transaction is currently in

queued_at

The time when this transaction was queued

receiving_anchor_account

Stellar account to send payment or withdrawal funds to

refunded

True if the transaction was refunded, false otherwise.

required_info_message

(SEP31) (optional) A human readable message indicating any errors that require updated information from the sender

required_info_updates

(SEP31) (optional) A set of fields that require an update from the sender, in the same format as described in /info.

started_at

Start date and time of transaction.

status

Choices field for processing status of deposit, withdrawal, & send.

SEP-6 & SEP-24 Statuses:

  • completed

    deposit/withdrawal fully completed

  • pending_external

    deposit/withdrawal has been submitted to external network, but is not yet confirmed. This is the status when waiting on Bitcoin or other external crypto network to complete a transaction, or when waiting on a bank transfer.

  • pending_anchor

    deposit/withdrawal is being processed internally by anchor.

  • pending_stellar

    deposit/withdrawal operation has been submitted to Stellar network, but is not yet confirmed.

  • pending_trust

    the user must add a trust-line for the asset for the deposit to complete.

  • pending_user

    the user must take additional action before the deposit / withdrawal can complete.

  • pending_user_transfer_start

    the user has not yet initiated their transfer to the anchor. This is the necessary first step in any deposit or withdrawal flow.

  • incomplete

    there is not yet enough information for this transaction to be initiated. Perhaps the user has not yet entered necessary info in an interactive flow.

  • no_market

    could not complete deposit because no satisfactory asset/XLM market was available to create the account.

  • too_small

    deposit/withdrawal size less than min_amount.

  • too_large

    deposit/withdrawal size exceeded max_amount.

  • error

    catch-all for any error not enumerated above.

SEP-31 Statuses:

  • pending_sender

    awaiting payment to be initiated by sending anchor.

  • pending_stellar

    transaction has been submitted to Stellar network, but is not yet confirmed.

  • pending_transaction_info_update

    transaction details must be updated to successfully execute transaction off-chain

  • pending_customer_info_update

    customer (SEP-12) information must be updated to facilitate transactions

  • pending_receiver

    payment is being processed by the receiving anchor.

  • pending_external

    payment has been submitted to external network, but is not yet confirmed.

  • completed

    deposit/withdrawal fully completed.

  • error

    catch-all for any error not enumerated above.

status_eta

(optional) Estimated number of seconds until a status change is expected.

status_message

A message stored in association to the current status for debugging

stellar_account

The Stellar (G…) account authenticated via SEP-10 that initiated this transaction. Note that if Transaction.muxed_account is not null, this column’s value is derived from the muxed account.

stellar_transaction_id

transaction_id on Stellar network of the transfer that either completed the deposit or started the withdrawal.

to_address

Sent to address (perhaps BTC, IBAN, or bank account in the case of a withdrawal or send, Stellar or muxed address in the case of a deposit).

Quote

class polaris.models.Quote[source]

Quote objects represent either firm or indicative quotes requested by the client application and provided by the anchor. Quote objects will be assigned to the Transaction.quote column by Polaris when requested via a SEP-6 or SEP-31 request. Anchors must create their own Quote objects when facilitating a SEP-24 transaction.

TYPE = <class 'model_utils.choices.Choices'>

Choices for type.

account_memo

The ID (64-bit integer) memo identifying the user of the shared Stellar account authenticated via SEP-10 when this Quote was created. If this column value is not null, Quote.muxed_account will be null.

buy_amount

The amount of buy_asset the client would like to purchase with sell_asset.

buy_asset

The asset the client would like to receive for some amount of sell_asset.

buy_delivery_method

One of the name values specified by the buy_delivery_methods array.

country_code

The ISO 3166-1 alpha-3 code of the user’s current address.

expires_at

The expiration time of the quote. Null if type is Quote.TYPE.indicative.

id

The unique ID for the quote.

muxed_account

The muxed (M…) account authenticated via SEP-10 when this Quote was created. If this column value is not null, Quote.stellar_account is derived from this value and Quote.account_memo will be null.

price

The price offered by the anchor for one unit of buy_asset in terms of sell_asset.

requested_expire_after

The requested expiration date from the client.

sell_amount

The amount of sell_asset the client would exchange for buy_asset.

sell_asset

The asset the client would like to sell. Ex. USDC:G…, iso4217:ARS

sell_delivery_method

One of the name values specified by the sell_delivery_methods array.

stellar_account

The Stellar (G…) account authenticated via SEP-10 when this Quote was created. Note that if Quote.muxed_account is not null, this column’s value is derived from the muxed account.

type

The type of quote. Firm quotes have a non-null price and expiration, indicative quotes may have a null price and expiration.

Exceptions

While Polaris does have some custom exceptions defined below, most of the exceptions used in Polaris are built-in exceptions such as ValueError. For example, Polaris expects anchors to raise a ValueError from DepositIntegration.save_sep9_fields() if any of the SEP-9 KYC fields passed are not valid.

However, this approach is not ideal for reasons outlined in a GitHub issue on the Polaris repository.

Starting with Polaris 3.0, all exceptions expected to be raised from integration functions will be defined here.

exception polaris.exceptions.TransactionSubmissionError[source]

Bases: Exception

exception polaris.exceptions.TransactionSubmissionPending[source]

Bases: TransactionSubmissionError

exception polaris.exceptions.TransactionSubmissionBlocked[source]

Bases: TransactionSubmissionError

exception polaris.exceptions.TransactionSubmissionFailed[source]

Bases: TransactionSubmissionError