diff --git a/docs/anchoring-assets/anchor-platform/sep6/_category_.json b/docs/anchoring-assets/anchor-platform/sep6/_category_.json new file mode 100644 index 000000000..da6dc71ce --- /dev/null +++ b/docs/anchoring-assets/anchor-platform/sep6/_category_.json @@ -0,0 +1,7 @@ +{ + "position": 65, + "label": "Programmatic Deposits and Withdrawals", + "link": { + "type": "generated-index" + } +} \ No newline at end of file diff --git a/docs/anchoring-assets/anchor-platform/sep6/configuration.mdx b/docs/anchoring-assets/anchor-platform/sep6/configuration.mdx new file mode 100644 index 000000000..ddd57759e --- /dev/null +++ b/docs/anchoring-assets/anchor-platform/sep6/configuration.mdx @@ -0,0 +1,127 @@ +--- +title: "Configuration" +sidebar_position: 20 +--- + +import { CodeExample } from "@site/src/components/CodeExample"; + +## Modify a Stellar Info File + +Next, let's modify the `stellar.toml` file created [earlier][sep1-ap]. Wallets need to know that SEP-6 functionality is supported by your business, and they also need to know all the currencies you support. + + + +```toml +# dev.stellar.toml +ACCOUNTS = ["add your public keys for your distribution accounts here"] +SIGNING_KEY = "add your signing key here" +NETWORK_PASSPHRASE = "Test SDF Network ; September 2015" + +TRANSFER_SERVER = "http://localhost:8080/sep6" +WEB_AUTH_ENDPOINT = "http://localhost:8080/auth" + +# Add support for USDC +[[CURRENCIES]] +code = "USDC" +issuer = "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5" +status = "test" +is_asset_anchored = false +desc = "USD Coin issued by Circle" + +[DOCUMENTATION] +ORG_NAME = "Your organization" +ORG_URL = "Your website" +ORG_DESCRIPTION = "A description of your organization" +``` + + + +Note that you will need to create another file for your production deployment that uses the public network's passphrase, your production service URLs, your Mainnet distribution accounts and signing key, as well as the Mainnet issuing accounts of the assets your service utilizes. + +## Enable Programmatic Deposits & Withdrawals + +Now you're ready to enable programmatic deposits and withdrawals using the SEP-6 API. Specify the following in your `dev.assets.yaml` file, and change the values depending on your use case. This example asset file enables support for Circle's USDC and a fiat USD to deposit from and withdraw to. + + + +```yaml +assets: + - schema: stellar + code: USDC + issuer: GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5 + distribution_account: GBLSAHONJRODSFTLOV225NZR4LHICH63RIFQTQN37L5CRTR2IMQ5UEK7 + significant_decimals: 2 + sep6_enabled: true + deposit: + enabled: true + methods: + - SEPA + - SWIFT + - cash + withdraw: + enabled: true + methods: + - bank_account + - cash + - schema: iso4217 + code: USD + significant_decimals: 2 +``` + + + +The information provided for the `assets` value closely maps to the information that will be exposed to the wallet application using the [`GET /info`][sep-6] SEP-6 endpoint. The Anchor Platform also uses this information to validate requests made to your service. + +## Test With the Demo Wallet + +Wallets should now be able to discover, authenticate, and initiate transactions with your service! Your project and source files should now look something like this. + + + +``` +├── dev.env +├── docker-compose.yaml +├── config +│ ├── dev.assets.yaml +│ ├── dev.stellar.toml +``` + + + +Your environment should now look like the following. + + + +```bash +# dev.env +ASSETS_TYPE=file +ASSETS_VALUE=/home/dev.assets.yaml + +SEP1_ENABLED=true +SEP1_TOML_TYPE=file +SEP1_TOML_VALUE=/home/dev.stellar.toml + +SEP10_ENABLED=true +SEP10_HOME_DOMAIN=localhost:8080 +SECRET_SEP10_SIGNING_SEED="a Stellar private key" +SECRET_SEP10_JWT_SECRET="a secret encryption key" +``` + + + +To test this out, go to the [Stellar Demo Wallet][stellar-demo-wallet]. + +Initiate a deposit transaction by doing the following: + +- Create a new keypair +- Click the "Add Asset" button and enter + - the code of the Stellar asset on your `stellar.toml` file + - your home domain, `localhost:8080` +- Select the dropdown and click "SEP-6 Deposit", then click "Start" + +The demo wallet should be able to find your `stellar.toml` file, authenticate using the Stellar keypair you just created, and initiate a transaction. + +[sep-1]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +[sep-6]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0006.md +[sep1-ap]: /docs/category/stellar-info-file +[stellar-demo-wallet]: https://demo-wallet.stellar.org/ diff --git a/docs/anchoring-assets/anchor-platform/sep6/index.mdx b/docs/anchoring-assets/anchor-platform/sep6/index.mdx new file mode 100644 index 000000000..660790b9e --- /dev/null +++ b/docs/anchoring-assets/anchor-platform/sep6/index.mdx @@ -0,0 +1,33 @@ +--- +title: "Getting Started" +sidebar_position: 10 +--- + +This guide will walk you through configuring and integration with the Anchor Platform for the purpose of build an on & off-ramp service compatible with [SEP-6][sep-6], the ecosystem's standardized protocol for programmatic deposit and withdrawals. + +By leveraging the Anchor Platform's support for SEP-6, businesses make their own on & off-ramp service available as an in-app experience through Stellar-based applications such as wallets and exchanges, extending their reach and connecting with users through the applications they already use. + +Before continuing with this section, make sure that you have already [installed][installation-ap] the Anchor Platform, and configured necessary features, required by SEP-6: [SEP-1 (Stellar Info File)][sep1-ap] and [SEP-10 (Stellar Authentication)][sep10-ap]. + +## The Basic User Experience + +The complete customer experience for a deposit or withdrawal using SEP-6 is as follows: + +1. The customer opens the SEP-6 wallet application of their choice +2. The customer selects an asset to deposit and the wallet finds an anchor (clients could also choose the specific anchor) +3. Once the wallet authenticates with the anchor, the customer begins entering their KYC and transaction information requested by the anchor +4. The wallet provides instructions, and the customer deposits real fiat currency with the anchor (e.g. makes a bank transfer) +5. Once the wallet receives the deposit, the customer receives the tokenized asset on the Stellar network from the anchor's distribution account + +The customer can then use the digital asset on the Stellar network for remittance, payments, trading, store of value, or another use case not listed here. At some later date, the customer could decide to withdraw their assets from the Stellar network, which would look something like this: + +1. The customer opens their wallet application +2. The customer selects the asset for withdrawal and wallet finds the anchor +3. After authenticating with the anchor, the customer can enter their transaction information and any additional KYC information that wasn't already collected +4. After asking for customer approval, the wallet sends the specified amount of the customer's asset balance to the anchor's distribution account on Stellar +5. Once the anchor receives the payment, the customer receives the withdrawn funds via bank transfer + +[sep-6]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0006.md +[installation-ap]: /docs/anchoring-assets/anchor-platform/getting_started +[sep1-ap]: /docs/category/stellar-info-file +[sep10-ap]: /docs/category/stellar-authentication diff --git a/docs/anchoring-assets/anchor-platform/sep6/integration.mdx b/docs/anchoring-assets/anchor-platform/sep6/integration.mdx new file mode 100644 index 000000000..44cc15ecb --- /dev/null +++ b/docs/anchoring-assets/anchor-platform/sep6/integration.mdx @@ -0,0 +1,1058 @@ +--- +title: "Integration" +sidebar_position: 30 +--- + +import { CodeExample } from "@site/src/components/CodeExample"; +import { AttributeTable } from "@site/src/components/AttributeTable"; + +One of the main points of interaction with the Anchor Platform is notifying the Platform about events related to transactions. + +In general, you will want to provide updates for the following events. + +- Your business requires the user to submit KYC information to process a transaction +- Your business updated the in/out/fee amounts for a transaction +- Your business is ready to receive funds from the user +- Your business has received funds from the user +- Your business has sent funds to the user +- Your business has a processed a refund for the user's transaction +- Your business experienced an unexpected error + +This is done by making JSON-RPC requests to the Platform API's endpoint. JSON-RPC requests allow you to update the status of the transaction. To move the transaction to a specific status, it's necessary to make a corresponding JSON-RPC request and pass data that is required by the RPC method. + +The Anchor Platform JSON-RPC API is designed to notify the platform about changes in the status of the transaction. Given that, the API will be called every time a user or the anchor takes any action that progresses the transaction status in the flow. + +You can find out more about transaction flow and statuses in the [SEP-6 protocol document][sep-6]. + +[sep-6]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0006.md + +## Securing Platform API + +:::caution + +By default, the Platform API's endpoints such as `GET /transactions` and `GET /transactions/:id` are not protected, and are accessible by anyone who has access to the server, including wallet applications. + +::: + +:::info + +It's recommended to keep Platform server accessible only from the private network. However, you may want to add additional layer of protection via securing the API. + +::: + +### Using API Key + +To enable API key authentication, modify your `dev.env` file: + + + +```bash +# dev.env +PLATFORM_SERVER_AUTH_TYPE=api_key +# Will be used as API key +SECRET_PLATFORM_API_AUTH_SECRET="your API key that business server will use" +``` + + + +After it's enabled, all requests must contain a valid `X-Api-Key` header, set to the configured API key. + +### Using JWT + +To enable JWT authentication, modify your `dev.env` file: + + + +```bash +# dev.env +PLATFORM_SERVER_AUTH_TYPE=jwt +SECRET_PLATFORM_API_AUTH_SECRET="your encryption key shared with your business server" +``` + + + +After it's enabled, all requests must contain a valid `Authorization` header. The JWT provided must have the `jti` and `exp` fields representing a valid transaction and token expiration time, respectively. + +## Making JSON-RPC Requests + +Before making JSON-RPC requests, let's first create a template for making a request to the Anchor Platform. + + + +```bash +# call-json-rpc.sh +#!/usr/bin/env bash + +curl localhost:8085 \ + -X POST \ + -H 'Content-Type: application/json' \ + --data "@$1" +``` + + + +This small script will make a JSON-RPC request to the Anchor Platform hosted on the default port (8085). JSON transaction data stored in the provided file will be used as body (requests must be an array). + +### JSON-RPC Request + +The Request object must contain the following attributes: + + + +- ATTRIBUTE + - DATA TYPE + - DESCRIPTION +- jsonrpc + - string + - A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0" +- method + - string + - A String containing the name of the method to be invoked. List of available methods you can see in [JSON-RPC Methods][json-rpc-methods] +- params + - object + - A Structured value that holds the parameter values, corresponding to method call, to be used during the invocation of the method +- id + - string + - An identifier established by the client. The Server will reply with the same value in the Response object + + + +:::tip + +It's possible to provide multiple updates in a single JSON-RPC request (by placing multiple JSON-RPC request objects). When an update is done in this way, all updates will be done sequentially. + +Most importantly, each JSON-RPC request is atomic. If one update fails, all previous updates WILL be applied and all subsequent updates WILL be processed and applied as well. + +::: + +### JSON-RPC Response + +The Response is expressed as a single JSON Object, with the following attributes: + + + +- ATTRIBUTE + - DATA TYPE + - DESCRIPTION +- jsonrpc + - string + - A String specifying the version of the JSON-RPC protocol. It's set to "2.0" +- result + - object + - A Structured value that holds the updated transaction details +- id + - string + - An identifier sent by the client +- error + - object + - A Structured value that holds the error details + - id + - string + - Unique id of the transaction for which an error occurred + - code + - number + - A number that indicates the error type that occurred. Please see a list of [error codes](#error-codes) below + - message + - string + - A String providing a short description of the error + - data + - string + - A primitive or structured value that contains additional information about the error + + + +### Error Codes + +
+ +| Error code | Meaning | +| :--------- | :------------------------------------------- | +| -32600 | The JSON sent is not a valid Request object | +| -32601 | The method does not exist / is not available | +| -32602 | Invalid method parameter(s) | +| -32603 | Internal JSON-RPC error | + +
+ +:::tip + +We will also reference a `$transaction_id` variable. This is an identification of transaction that is being returned from the Anchor Platform on an withdrawal or deposit start request. You can obtain the transaction ID by connecting the test wallet to your local Anchor Platform instance. + +::: + +## Updating Deposit (Exchange) Transaction Via JSON-RPC + +SEP-6 deposit flow diagram defines sequences/rules of the transaction's status transition and a set of JSON-RPC method that should be called to change that status. You can't define the status you want to set for a specific transaction in your requests. Each JSON-RPC method defines data structures that it expects in request. If request doesn't contain a required attributes, the Anchor Platform will return and error and won't change status of the transaction. + +[![sep6 deposit flow](/assets/sep6-deposit-flow-diagram.png)](/assets/sep6-deposit-flow-diagram.png) + +:::tip + +Statuses in green are mandatory and define the shortest way. + +Statuses in yellow are optional and can be skipped. + +Statuses in red mean the transaction is in an error status or it has expired. + +::: + +### Verifying KYC Information + +SEP-6 does not require the user submit KYC information prior to initiating a transaction. If there are any KYC requirements for a transaction, the required SEP-9 fields can be communicated to the user by making a `request_customer_info_update` JSON-RPC request and providing the required fields names. + + + +```json +// reuest-customer-info-update.json +[ + { + "id": "1", + "jsonrpc": "2.0", + "method": "request_customer_info_update", + "params": { + "id": "", + "message": "Please update your information to continue", + "required_customer_info_message": "A government issued ID is required for deposits over $1000.", + "required_customer_info_updates": [ + "id_type", + "id_country_code", + "id_issue_date", + "id_expiration_date", + "id_number" + ] + } + } +] +``` + + + +- `required_customer_info_message` is an optional message explaining why the user needs to update their information. +- `required_customer_info_updates` is an array of SEP-9 fields that the user must update. + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh request-customer-info-update.json +``` + + + +### Ready to Receive Funds + +After the user has submitted their KYC information, the anchor can notify the Platform that they are ready to receive funds. The anchor should use the `request_offchain_funds` RPC to provide the final amounts to the user. To do so, make the following JSON-RPC request. + + + +```json +// request-offchain-funds.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "request_offchain_funds", + "params": { + "transaction_id": "", + "message": "Request offchain funds", + "amount_in": { + "amount": 10, + "asset": "iso4217:USD" + }, + "amount_out": { + "amount": 9, + "asset": "stellar:USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5" + }, + "amount_fee": { + "amount": 1, + "asset": "iso4217:USD" + }, + "amount_expected": { + "amount": 10 + }, + "instructions": { + "organization.bank_number": { + "value": "123456789", + "description": "US Bank routing number" + }, + "organization.bank_account_number": { + "value": "123456789", + "description": "US Bank account number" + } + } + } + } +] +``` + + + +- `amount_in` is the amount the user has to sent to the business. +- `amount_out` is the amount the user will receive. +- `amount_fee` is the total amount of fees collected by the business. +- `asset` is part of the `amount_x` field and is in a SEP-38 format. In this example, it's set to USD, assuming the user made a bank transfer to the system using USD. +- `instructions` is the set of SEP-9 standard fields that user should use to send funds to the business. In this example, the user should send funds to the bank account with the routing number `123456789` and account number `123456789`. + +Information about amounts (in/out/fee) is required if you want to move the transaction to the `pending_user_transfer_start` status. + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh request-offchain-funds.json +``` + + + +### Funds Received + +If offchain funds were received, you'll want to provide updated transaction information. + + + +```json +// offchain-funds-received.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_offchain_funds_received", + "params": { + "transaction_id": "", + "message": "Offchain funds received", + "funds_received_at": "2023-07-04T12:34:56Z", + "external_transaction_id": "7...9", + "amount_in": { + "amount": 10 + }, + "amount_out": { + "amount": 9 + }, + "amount_fee": { + "amount": 1 + }, + "amount_expected": { + "amount": 10 + } + } + } +] +``` + + + +- `funds_received_at` is the date and time of receiving funds. +- `external_transaction_id` is the ID of transaction on external network. + +The amount fields are optional. If skipped, the values prior to this request will be used. + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh offchain-funds-received.json +``` + + + +### Waiting For User Funds + +In the real world, the transfer confirmation process may take time. In such cases, transactions should be set to a new status indicating that the confirmation of the transfer has been received but the funds themselves have not been received yet. + + + +```json +// offchain-funds-sent.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_offchain_funds_sent", + "params": { + "transaction_id": "", + "message": "Offchain funds sent", + "funds_received_at": "2023-07-04T12:34:56Z", + "external_transaction_id": "7...9" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh offchain-funds-sent.json +``` + + + +### Sending Onchain Funds + +Next, send a transaction on the Stellar network to fulfill the user deposit. After the Stellar transaction has been submitted, it's necessary to send the `notify_onchain_funds_sent` JSON-RPC request to notify a user that the funds were successfully sent. + + + +```json +// onchain-funds-sent.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_onchain_funds_sent", + "params": { + "transaction_id": "", + "message": "Onchain funds sent", + "stellar_transaction_id": "7...9" + } + } +] +``` + + + +- `stellar_transaction_id` is the transaction id on Stellar network of the transfer. + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh onchain-funds-sent.json +``` + + + +After this JSON-RPC request, the transaction will be transferred to the `completed` status. + +### Sending Payment Via Custody Service + +The Anchor Platform provides a possibility to send a payment via custody services, such as Fireblocks. To make a payment via a custody service, make the following JSON-RPC request. + + + +```json +// do-stellar-payment.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "do_stellar_payment", + "params": { + "transaction_id": "", + "message": "Custody payment started" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh do-stellar-payment.json +``` + + + +After successful processing of the payment on a custody service, the Anchor Platform will automatically make the `notify_onchain_funds_sent` JSON-RPC request and the status of the transaction will be changed to `completed`. + +:::caution + +A user account may not be ready to receive funds. You can check that the account has established a [trustline](/docs/glossary#trustline). Otherwise, you can set the status of the transaction to the `pending_trust` to indicate that the anchor is waiting for the user to establish the trustline. + +If custody integration is enabled, the Anchor Platform will do this validation for you automatically. + +::: + +### Pending Trust + +This status has to be set if a payment requires an asset trustline that wasn't configured by the user. There are two ways of how the transaction may be moved to the `pending_trust` status. The first one is processing of a payment via custody service in case it detected that the trustline isn't configured. The second one is when the business itself detects that the trustline is missing and wants to notify the user that it has to be configured. To move the transaction to the `pending_trust` status, make the following JSON-RPC request. + + + +```json +// request-trust.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "request_trust", + "params": { + "transaction_id": "", + "message": "Asset trustine not configured" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh request-trust.json +``` + + + +:::info + +Payment via custody service periodically checks if the trustline was configured. If it was, it will automatically send a payment to a custody service and change the status of the transaction to `pending_stellar`. + +::: + +### Trust Set + +This status has to be set if the business has detected that the trustline was or wasn't configured by user. + + + +```json +// trust-set.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_trust_set", + "params": { + "transaction_id": "", + "message": "Asset trustine set", + "success": "true" + } + } +] +``` + + + +- `success` flag which defines if trustline was or wasn't configured by user + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh trust-set.json +``` + + + +:::info + +Depending on the `success` flag, the status of the transaction will be changed to `pending_stellar` if the trustline was set, or to `pending_anchor` if it wasn't. + +::: + +### Refund Sent + +Sometimes, funds need to be sent back to the user (refund). You can refund the whole sum (full refund) or do a set of partial refunds. Also, if user sent more money than expected, you can refund a part of the sum back to the user and send the rest as onchain funds. + + + +```json +// refund-sent.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_refund_sent", + "params": { + "transaction_id": "", + "message": "Refund sent", + "refund": { + "id": "1c186184-09ee-486c-82a6-aa7a0ab1119c", + "amount": { + "amount": 10, + "asset": "iso4217:USD" + }, + "amount_fee": { + "amount": 1, + "asset": "iso4217:USD" + } + } + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh refund-sent.json +``` + + + +:::info + +If a sum of refunds is less than `amount_in`, the status of the transaction will be set to `pending_anchor`. Only if the sum of refunds is equal to `amount_in`, the status of the transaction will be set to `refunded`. + +::: + +### Refund Pending + +This is similar to [Refund Sent](#refund-sent), but it handles the case when a refund has been submitted to external network but is not yet confirmed. The status of the transaction is set to `pending_external`. This is the status that will be set when waiting for Bitcoin or other external crypto network to complete a transaction, or when waiting for a bank transfer. + +### Transaction Error + +If you encounter an unrecoverable error when processing the transaction, it's required to set the transaction status to `error`. You can use the message field to describe the error details. + + + +```json +// transaction-error.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_transaction_error", + "params": { + "transaction_id": "", + "message": "Error occurred" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh transaction-error.json +``` + + + +:::tip + +If a user has made a transfer, you should do a transaction recovery, and then you can retry processing the transaction or initiate a refund. + +::: + +### Expired Transaction + +Your business may want to expire transactions that have been abandoned by the user after some time. It's good practice to clean up inactive transactions in the `incomplete` status. To do so, make the following JSON-RPC request to expire a transaction. + + + +```json +// transaction-expired.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_transaction_expired", + "params": { + "transaction_id": "", + "message": "Transaction expired" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh transaction-expired.json +``` + + + +:::tip + +This JSON-RPC method can't be used after the user has made a transfer. + +::: + +### Transaction Recovery + +Transaction status can be changed from `error/expired` to `pending_anchor`. After recovery, you can refund the received assets or proceed with processing of the transaction. To recover a transaction, make the following JSON-RPC request. + + + +```json +// transaction-recovery.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_transaction_recovery", + "params": { + "transaction_id": "", + "message": "Transaction recovered" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh transaction-recovery.json +``` + + + +## Updating Withdrawal (Exchange) Transaction Via JSON-RPC + +The SEP-6 withdrawal flow diagram defines the sequence/rules of the transaction's status transition. You can't define the status you want to set for a specific transaction in your requests. Each JSON-RPC method defines data structures that it expects in request. If request doesn't contain a required attributes, the Anchor Platform will return and error and won't change status of the transaction. + +[![sep6 withdrawal flow](/assets/sep6-withdrawal-flow-diagram.png)](/assets/sep6-withdrawal-flow-diagram.png) + +:::tip + +Statuses in green are mandatory and define the shortest way. + +Statuses in yellow are optional and can be skipped. + +Statuses in red mean the transaction is in an error status or it has expired. + +::: + +Once the withdrawal flow is finished, implementing the withdrawal is straightforward. Some parts of the flow are similar and can be reused. + +The starting point both for withdrawal and for deposit is the same. + +### Ready to Receive Funds + +Similarly to deposit, the step after KYC has been collected is to notify the user that the anchor is ready to receive funds. However, as your service will be receiving transactions over the Stellar network, the RPC request will be different. The anchor should use the `request_onchain_funds` RPC to provide the final amounts to the user. To do so, make the following JSON-RPC request. + + + +```json +// request-onchain-funds.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "request_onchain_funds", + "params": { + "transaction_id": "", + "message": "Request onchain funds", + "amount_in": { + "amount": 10, + "asset": "stellar:USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5" + }, + "amount_out": { + "amount": 9, + "asset": "iso4217:USD" + }, + "amount_fee": { + "amount": 1, + "asset": "stellar:USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5" + }, + "amount_expected": { + "amount": 10 + }, + "destination_account": "GD...G", + "memo": "12345", + "memo_type": "id" + } + } +] +``` + + + +- `memo` is the memo the user should use when sending their onchain funds to the anchor. +- `memo_type` is the memo type the user should use when sending their onchain funds to the anchor. +- `destination_account` is the account the user should send the funds to. + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh request-onchain-funds.json +``` + + + +:::tip + +Setting `memo`, `memo_type`, and `destination_account` is optional. + +If integration with a third-party custodian is enabled, the Anchor Platform can generate `memo`, `memo_type`, and `destination_address` if a corresponding `deposit_info_generator_type` is chosen. Also, you can provide `memo` and `memo_type` to the request as shown above. Note that the memo must be unique, this is what helps to associate Stellar transactions with SEP transactions. + +If your business manages the assets, the Anchor Platform can generate memos for you. When the status is changed to `pending_user_transfer_start`, the Anchor Platform sets the `memo` and `memo_type` automatically (only if it's not included in the request). + +::: + +:::note + +The Stellar account that will be used to receive funds should be configured. + +::: + +### Funds Received + +If onchain funds were received, you need to provide amounts and change the status of the transaction to `pending_anchor`. + + + +```json +// onchain-funds-received.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_onchain_funds_received", + "params": { + "transaction_id": "", + "message": "Onchain funds received", + "stellar_transaction_id": "7...9", + "amount_in": { + "amount": 10 + }, + "amount_out": { + "amount": 9 + }, + "amount_fee": { + "amount": 1 + } + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh onchain-funds-received.json +``` + + + +:::tip + +This method will be called automatically by the custody server if the custody integration is enabled. + +::: + +### Offchain Funds Available + +You can move transaction status to `pending_user_transfer_complete` if offchain funds were sent, and if it's ready for the user / recipient to pick it up. + + + +```json +// offchain-funds-available.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_offchain_funds_available", + "params": { + "transaction_id": "", + "message": "Offchain funds available", + "external_transaction_id": "a...c" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh offchain-funds-available.json +``` + + + +### Offchain Funds Pending + +Another option is to move the transaction's status to `pending_external`. This status means that the payment has been submitted to an external network, but is not yet confirmed. + + + +```json +// offchain-funds-pending.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_offchain_funds_pending", + "params": { + "transaction_id": "", + "message": "Offchain funds pending", + "external_transaction_id": "a...c" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh offchain-funds-pending.json +``` + + + +### Offchain Funds Sent + +To complete the transaction and change its status to `completed`, you need to make the `notify_offchain_funds_sent` JSON-RPC request. + + + +```json +// offchain-funds-sent.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "notify_offchain_funds_sent", + "params": { + "transaction_id": "", + "message": "Offchain funds sent", + "funds_sent_at": "2023-07-04T12:34:56Z", + "external_transaction_id": "a...c" + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh offchain-funds-sent.json +``` + + + +### Refund Sent + +The refund logic works in the same way as for the deposit flow. For more details, see [Refund Sent](#refund-sent) of the deposit flow. + +### Do Stellar Refund + +Integration with a custody service allows you to do a refund via a custody service, such as Fireblocks. + + + +```json +// do-stellar-refund.json +[ + { + "id": 1, + "jsonrpc": "2.0", + "method": "do_stellar_refund", + "params": { + "transaction_id": "", + "message": "Do stellar refund", + "refund": { + "amount": { + "amount": 9, + "asset": "stellar:USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5" + }, + "amount_fee": { + "amount": 1, + "asset": "stellar:USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5" + } + } + } + } +] +``` + + + +To execute this, you need to run: + + + +```bash +./call-json-rpc.sh do-stellar-refund.json +``` + + + +:::note + +Similarly to the deposit flow, you can make a full refund or a set of partial refunds. The transaction will stay in `pending_anchor` status until the sum of refunds is less than `amount_in`. If the sum of refunds is equal to `amount_in`, the Anchor Platform will automatically change the status of the transaction to `refunded`. + +::: + +### Transaction Error + +Works in the same manner as for the deposit flow. For more details, see [Transaction Error](#transaction-error) of the deposit flow. + +### Expired Transaction + +Works in the same manner as for the deposit flow. For more details, see [Expired Transaction](#expired-transaction) of the deposit flow. + +### Transaction Recovery + +Works in the same manner as for the deposit flow. For more details, see [Transaction Recovery](#transaction-recovery) of the deposit flow. + +## Tracking Stellar Transactions + +Using the Payment Observer allows you to delegate this step to the Anchor Platform. To enable the Payment Observer, use the `--stellar-observer` flag in the command section of the [compose file](#configuration). + +The Payment Observer will track all transactions sent to the distribution account. When the transaction with the expected memo is detected in the network, the status will automatically change to `pending_anchor` and event will be the emitted (if Kafka is used). + +In order to update the transaction's statuses, the observer makes corresponding JSON-RPC requests to the platform. It should use the following URL. + + + +```bash +# dev.env +PLATFORM_API_BASE_URL=http://platform-server:8085 +``` + + + +:::caution + +The Payment Observer won't validate the amounts. It's your responsibility to verify that the amount sent by the user is correct. + +::: + +:::info + +If you already have a system that monitors payments, make sure that the logic of the system matches the description below: + +First, wait for the transaction to be included in the ledger (using an SDK). This transaction must have the expected memo and destination address (distribution account). Once this transaction has been detected and verified, notify the user that the funds have been received using the [notify_onchain_funds_received](#onchain-funds-received) JSON-RPC request. diff --git a/static/assets/sep6-deposit-flow-diagram.png b/static/assets/sep6-deposit-flow-diagram.png new file mode 100644 index 000000000..75d4d271a Binary files /dev/null and b/static/assets/sep6-deposit-flow-diagram.png differ diff --git a/static/assets/sep6-withdrawal-flow-diagram.png b/static/assets/sep6-withdrawal-flow-diagram.png new file mode 100644 index 000000000..0bf199f47 Binary files /dev/null and b/static/assets/sep6-withdrawal-flow-diagram.png differ diff --git a/static/definitions/sep24_31_status_transition_diagrams.drawio b/static/definitions/sep6_24_31_status_transition_diagrams.drawio similarity index 56% rename from static/definitions/sep24_31_status_transition_diagrams.drawio rename to static/definitions/sep6_24_31_status_transition_diagrams.drawio index c1e830383..61dbea4f8 100644 --- a/static/definitions/sep24_31_status_transition_diagrams.drawio +++ b/static/definitions/sep6_24_31_status_transition_diagrams.drawio @@ -1,6 +1,6 @@ - + - + @@ -338,7 +338,7 @@ - + @@ -791,4 +791,599 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +