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
orpending_external
status. Polaris passes these transaction the
poll_pending_deposits()
integration function, and the anchor is expected to returnTransaction
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 thepoll_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 toTrue
and the anchor is expected to collect signatures, save the transaction envelope toenvelope_xdr
, and setpending_signatures
back toFalse
. 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.
- A transaction is in the
watch_transactions
- class polaris.management.commands.watch_transactions.Command[source]
Streams transactions to the
distribution_account
of eachAsset
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
orpending_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 inpending_receiver
orpending_anchor
statuses, among other conditions.Anchors are expected to update the
status
tocompleted
orpending_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 thepoll_outgoing_transactions()
.The anchor is expected to update the transactions’
status
tocompleted
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 two subcommands,
issue
andreset
.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 byissue
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’spaging_token
on startup. When the testnet resets, thepaging_token
used for transactions prior to the reset are no longer valid. To fix this, Polaris updates thepaging_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.
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 anOffChainAsset
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"
toFalse
in the dict returned fromcontent_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 theclean_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’sfee_fixed
andfee_percent
attributes.If replaced, /info responses will no longer contain the
fee_fixed
andfee_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 aValueError
.If this function is not implemented, Polaris will respond with a 501 Not Implemented.
- Parameters
token (
SEP10Token
) – theSEP10Token
object representing the authenticated sessionrequest (
Request
) – arest_framework.request.Request
instanceparams (
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
) – theSEP10Token
object representing the authenticated sessionrequest (
Request
) – arest_framework.request.Request
instanceaccount (
str
) – the stellar or muxed account associated with the customermemo (
Optional
[str
]) – the optional memo used to create the customermemo_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 theid
parameter does not exist. An error response with the appropriate status will be sent using the message passed to the exception.- Parameters
token (
SEP10Token
) – theSEP10Token
object representing the authenticated sessionrequest (
Request
) – arest_framework.request.Request
instanceparams (
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
) – theSEP10Token
object representing the authenticated sessionrequest (
Request
) – arest_framework.request.Request
instanceaccount (
str
) – the stellar or muxed account for the url to be returnedmemo (
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 adjango.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 thepending_customer_info_update
status, all suchTransaction.status
values should be updated topending_receiver
. Polaris will then call theexecute_outgoing_transaction
integration function for each updated transaction.If the anchor requires verification of values passed in params, such as
mobile_number
oremail_address
, the anchor should initate the verification process in this function and ensure the next call toGET /customer
contains the field requiring verification with aVERIFICATION_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 toPUT /customer/verification
to return the verification codes sent as a result of the initial call toPUT /customer
.- Parameters
token (
SEP10Token
) – theSEP10Token
object representing the authenticated sessionrequest (
Request
) – arest_framework.request.Request
instanceparams (
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 theVERIFICATION_REQUIRED
status if the anchor requires the user to verify a SEP-9 field value provided in a previous call toPUT /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 authenticatedaccount
does not match Stellar account associated with the ID, raise anObjectDoesNotExist
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
) – theSEP10Token
object representing the authenticated sessionrequest (
Request
) – arest_framework.request.Request
instanceaccount (
str
) – the Stellar or muxed account authenticated via SEP-10params (
Dict
) – the request body of thePUT /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 tocreate_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
) – aTransaction
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 theTransaction.status
column topending_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 topending_user_transfer_start
before including the transaction in calls toDepositIntegration.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 toTransaction.quote
before the end of the interactive flow. Polaris will check for aQuote
object on the transaction and adjust the UI of theMORE_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
) – therest_framework.request.Request
objectform (
Form
) – the completedforms.Form
submitted by the usertransaction (
Transaction
) – theTransaction
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 topending_user_transfer_start
orpending_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 isTemplate.MORE_INFO
since that page does not display form content.If form is
None
and template_name is notTemplate.MORE_INFO
, returningNone
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
andTemplate.WITHDRAW
:form
The
django.forms.Form
instance returned fromform_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 fromform_for_transaction()
, in which case the fee table will be displayed. If the anchor instructs Polaris to display the fee table but aTransactionForm
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, sinceTransactionForm
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
orOffChainAsset.symbol
, depending on whether or not asset sent to the anchor is on or off chain. IfTransaction.quote
is null, the value will always matchAsset.symbol
.amount_fee_symbol
Asset.symbol
orOffChainAsset.symbol
, depending on the value ofTransaction.fee_asset
. IfTransaction.quote
is null, the value will always beAsset.symbol
.amount_out_symbol
Asset.symbol
orOffChainAsset.symbol
, depending on whether or not asset sent by the anchor is on or off chain. IfTransaction.quote
is null, the value will always matchAsset.symbol
.amount_in_significant_decimals
The number of decimals to display for amounts of
Transaction.amount_in
. Derived fromAsset.significant_decimals
orOffChainAsset.decimals
. IfTransaction.quote
is null, the value will always matchAsset.significant_decimals
.amount_fee_significant_decimals
The number of decimals to display for amounts of
Transaction.amount_fee
. Derived fromAsset.significant_decimals
orOffChainAsset.decimals
, depending on the value ofTransaction.fee_asset
.amount_out_significant_decimals
The number of decimals to display for amounts of
Transaction.amount_out
. Derived fromAsset.significant_decimals
orOffChainAsset.decimals
. IfTransaction.quote
is null, the value will always matchAsset.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 theTransaction.quote
, if present.price
Transaction.quote.price
, if present.price_inversion
1 / Transaction.quote.price
, ifprice
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 notNone
,exchange_amount
is the value ofTransaction.amount_out
expressed in units ofTransaction.amount_in
.exchanged_amount
If
Transaction.quote
is notNone
,exchanged_amount
is the value ofTransaction.amount_in
expressed in units ofTransaction.amount_out
.- Parameters
request (
Request
) – arest_framework.request.Request
instancetemplate (
Template
) – apolaris.templates.Template
enum value for the template to be rendered in the responseform (
Optional
[Form
]) – the form to be rendered in the templatetransaction (
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 toFalse
, which will cause theprocess_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 achannel_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 withintransaction.channel_account
back to a persistent Stellar account owned by the anchor. Seeafter_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 aTransactionForm
subclass and updatetransaction.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 returnsNone
. If that is the case, Polaris assumes the anchor is finished collecting information and will update the Transaction status topending_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
) – therest_framework.request.Request
objecttransaction (
Transaction
) – theTransaction
database objectpost_data (
Optional
[QueryDict
]) – the data sent in the POST request as a dictionaryamount (
Optional
[Decimal
]) – aDecimal
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, *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 theTransaction
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 toTransaction.required_info_updates
, and save a human-readable message toTransaction.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 aValueError
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 therequired_info_updates
andrequired_info_message
fields.- Parameters
token (
SEP10Token
) – theSEP10Token
object representing the authenticated sessionrequest (
Request
) – arest_framwork.request.Request
objectparams (
Dict
) – The request parameters as described in the PATCH /transactions endpoint.transaction (
Transaction
) – ATransaction
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 theTransaction
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 toTransaction.amount_in
andTransaction.amount_expected
. here. While not required per SEP-6, it is encouraged to also populateTransaction.amount_fee
andTransaction.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 fromRailsIntegration.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 andRailsIntegration.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 anAPIException("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'" } }
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"] }
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
) – theSEP10Token
object representing the authenticated sessionrequest (
Request
) – arest_framwork.request.Request
objectparams (
Dict
) – the request parameters as described in /deposittransaction (
Transaction
) – an unsavedTransaction
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
) – arest_framework.request.Request
objectasset (
Asset
) –Asset
object for which to return the fields and types key-value pairslang (
Optional
[str
]) – the language code the client requested for the description values in the responseexchange (
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
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
]) – theDepositIntegration
subclass instance to be used by Polariswithdrawal (
Optional
[WithdrawalIntegration
]) – theWithdrawalIntegration
subclass instance to be used by Polarissep31_receiver (
Optional
[SEP31ReceiverIntegration
]) – theSEP31ReceiverIntegration
subclass instance to be used by Polarisrails (
Optional
[RailsIntegration
]) – theRailsIntegration
subclass instance to be used by Polaristoml (
Optional
[Callable
]) – a function that returns stellar.toml data as a dictionaryfee (
Optional
[Callable
]) – a function that returns the fee that would be chargedsep6_info (
Optional
[Callable
]) – a function that returns the /info fields or types values for an Assetcustomer (
Optional
[CustomerIntegration
]) – theCustomerIntegration
subclass instance to be used by Polariscustody (
Optional
[CustodyIntegration
]) – theCustodyIntegration
subclass instance to be used by Polarisquote (
Optional
[QuoteIntegration
]) – theQuoteIntegration
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
) – therest_framework.request.Request
instanceasset (
Asset
) – theAsset
object for the field values returnedlang (
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 aValueError
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 therequired_info_updates
andrequired_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 theRailsIntegration.execute_outgoing_transaction
function for more information on the lifecycle of a transaction.- Parameters
token (
SEP10Token
) – TheSEP10Token
instance representing the authenticated sessionrequest (
Request
) – therest_framework.request.Request
instanceparams (
Dict
) – the request body of the PATCH /transaction requesttransaction (
Transaction
) – theTransaction
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 toTransaction.amount_in
andTransaction.amount_expected
here.While not required per SEP-31, it is encouraged to also populate
Transaction.amount_fee
,Transaction.fee_asset
(ifTransaction.quote
is notNone
), andTransaction.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 inRailsIntegration.execute_outgoing_transaction()
.Also note that if your anchor service supports SEP-38,
Transaction.quote
may be a firm or indicativeQuote
model instance representing the requested exchange of on and off-chain assets. IfQuote.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. ReturnNone
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
) – TheSEP10Token
instance representing the authenticated sessionrequest (
Request
) – Therest_framework.request.Request
instanceparams (
Dict
) – The parameters included in the /transaction requesttransaction (
Transaction
) – theTransaction
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, andFalse
otherwise. This function ensures that only registered sending anchors can make requests to protected endpoints.- Parameters
token (
SEP10Token
) – TheSEP10Token
instance representing the authenticated sessionrequest (
Request
) – therest_framework.request.Request
instancepublic_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
) – arest_framework.request.Request
instanceform (
Form
) – the completedforms.Form
submitted by the usertransaction (
Transaction
) – theTransaction
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
) – arest_framework.request.Request
instancetemplate (
Template
) – apolaris.templates.Template
enum value for the template to be rendered in the responseform (
Optional
[Form
]) – the form to be rendered in the templatetransaction (
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
) – arest_framwork.request.Request
objecttransaction (
Transaction
) – theTransaction
database objectpost_data (
Optional
[QueryDict
]) – the data included in the POST request body as a dictionaryamount (
Optional
[Decimal
]) – aDecimal
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, *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, thehow
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
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
) – TheSEP10Token
object representing the authenticated sessionrequest (
Request
) – Therest_framework.Request
object representing the requestsell_asset (
Union
[Asset
,OffChainAsset
]) – The asset the client would like to sell for buy_assetssell_amount (
Optional
[Decimal
]) – The amount the client would like to sell of sell_assetbuy_asset (
Union
[Asset
,OffChainAsset
]) – The asset the client would like to buy using sell_assetbuy_amount (
Optional
[Decimal
]) – The amount the client would like to purchase of buy_assetsell_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
) – TheSEP10Token
object representing the authenticated sessionrequest (
Request
) – Therest_framework.Request
object representing the requestsell_asset (
Union
[Asset
,OffChainAsset
]) – The asset the client would like to sell for buy_assetsbuy_assets (
List
[Union
[Asset
,OffChainAsset
]]) – The assets the client would like to buy using sell_assetsell_amount (
Decimal
) – The amount the client would like to sell of sell_assetsell_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 aTransaction
. Note that theQuote
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
) – TheSEP10Token
object representing the authenticated sessionrequest (
Request
) – Therest_framework.Request
object representing the requestquote (
Quote
) – TheQuote
object representing the exchange rate to be offered
- Return type
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 ledgerIf
self.account_creation_supported
isFalse
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 saveTransaction.submission_status
asSubmissionStatus.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 updateTransaction.submission_status
toSubmissionStatus.BLOCKED
and expected the anchor to update this field toSubmissionStatus.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 theAsset.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 functiontransaction (
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
isTrue
, Polaris may call this method when the destination account does not yet have a trustline toTransaction.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
isFalse
, this method will only be called when the destination account exists and has a trustline toTransaction.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 saveTransaction.submission_status
asSubmissionStatus.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 updateTransaction.submission_status
toSubmissionStatus.BLOCKED
and expected the anchor to update this field toSubmissionStatus.UNBLOCKED
once Polaris should attempt submission again.- Parameters
transaction (
Transaction
) – theTransaction
object representing the Stellar transaction that should be submitted to the networkhas_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 frombase.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.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.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.
- 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
ifclaimable_balance_supported
isFalse
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 andTransaction.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 andQuote.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.