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.
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.
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;
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.
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);
}
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
}
SDK's SEP-08 test cases.