Skip to content

Latest commit

 

History

History
141 lines (102 loc) · 4.74 KB

File metadata and controls

141 lines (102 loc) · 4.74 KB

SEP-0008 - Regulated Assets

Regulated Assets are assets that require an issuer’s approval (or a delegated third party’s approval, such as a licensed securities exchange) on a per-transaction basis. SEP-08 standardizes the identification of such assets as well as defines the protocol for performing compliance checks and requesting issuer approval.

Create a RegulatedAssetsService instance

Let's start with creating a RegulatedAssetsService object, which we'll use for all SEP-08 interactions.

Via it's constructor:

final service = RegulatedAssetsService(tomlData);

The parameter tomlData of type StellarToml represents stellar.toml data provided by the Server (e.g. Anchor) as described in the SEP-01 Example

Or by providing the domain hosting the stellar.toml file

final service = await RegulatedAssetsService.fromDomain("place.domain.com");

This will automatically load and parse the stellar.toml file. It will then create the RegulatedAssetsService instance by using the needed data provided in the stellar.toml file by the Server.

Get regulated assets

During initialization, the service extracts the relevant assets from the provided toml data. It considers only those currencies that are regulated and have an approval server set.

You can access them as follows:

List<RegulatedAssets> regulatedAssets = service.regulatedAssets;

Authorization required

By using the service, you can check if a given asset needs authorization.

bool needsAuthorization = await service.authorizationRequired(regulatedAsset);

This loads the issuer account data from the Stellar Network and checks if the both flags authRequired and authRevocable are set.

Send transaction to approval server

First let's create the transaction:

var xAsset = regulatedAssets.first;

// Operation 1: AllowTrust op where issuer fully authorizes account A, asset X
var op1 = SetTrustLineFlagsOperationBuilder(
        accountAId, xAsset, 0, XdrTrustLineFlags.AUTHORIZED_FLAG.value)
    .setSourceAccount(xAsset.issuerId)
    .build();

// Operation 2: Account A manages offer to buy asset X
var op2 =
    ManageBuyOfferOperationBuilder(Asset.NATIVE, xAsset, '10', '0.1')
        .build();

// Operation 3: AllowTrust op where issuer sets account A, asset X to AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG state
var op3 = SetTrustLineFlagsOperationBuilder(accountAId, xAsset, 0,
        XdrTrustLineFlags.AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG.value)
    .setSourceAccount(xAsset.issuerId)
    .build();

var tx = TransactionBuilder(accountA)
    .addOperation(op1)
    .addOperation(op2)
    .addOperation(op3)
    .build();

String txBase64Xdr = tx.toXdrBase64();

Next let's send it to the approval server using our service:

var postResponse =
        await service.postTransaction(txBase64Xdr, xAsset.approvalServer);

Depending on the postResponse type you can now access the corresponding data.

if (postResponse is PostTransactionSuccess) {
  // Transaction has been approved and signed by the issuer
  print(postResponse.tx);
  print(postResponse.message);
} else if (postResponse is PostTransactionRevised) {
  // Transaction has been revised to be made compliant, and signed by the issuer. 
  print(postResponse.tx);
  print(postResponse.message);
} else if (postResponse is PostTransactionPending) {
  // The issuer could not determine whether to approve this transaction at the moment. 
  print(postResponse.timeout);
  print(postResponse.message);
} else if (postResponse is PostTransactionActionRequired) {
  // Transaction requires a user action to be completed.
  print(postResponse.actionUrl);
  print(postResponse.actionMethod);
  print(postResponse.actionFields);
  print(postResponse.message);
} else if (postResponse is PostTransactionRejected) {
  // Wallet should display the associated error message to the user.
  print(postResponse.error);
}

Following the Action URL

If the approval server response is PostTransactionActionRequired and the postResponse.actionMethod is POST you can use the service to send the values for the requested fields.

var actionResponse = await service.postAction(actionUrl,
    {'email_address': '[email protected]', 
    'mobile_number': '+3472829839222'});

if (actionResponse is PostActionNextUrl) {
    print(actionResponse.message);
    print(actionResponse.nextUrl);
    // ...
} else if (actionResponse is PostActionDone) {
  // resend tx
}

Further readings

SDK's SEP-08 test cases.