Robot VASPs

The TestNet hosts three convenience “robot VASPs” (rVASPs) services to facilitate integration and testing with the TRISA TestNet. These services are as follows:

  • Alice (api.alice.vaspbot.net:443): the primary integration rVASP used to trigger and receive TRISA messages.
  • Bob (api.bob.vaspbot.net:443): a demo rVASP to view exchanges with Alice.
  • Evil (api.evil.vaspbot.net:443): an “evil” rVASP that is not a TRISA TestNet member, used to test non-authenticated interactions.

Note: the rVASPs are currently primarily configured for demos. Work has begun on making them more robust for integration purposes; please check in with this documentation regularly for any changes. If you notice any bugs in the rVASP code or behavior, please open an issue.

Getting Started with rVASPs

There are two ways that you can use the rVASPs to develop your TRISA service:

  1. You can trigger the rVASP to send a TRISA exchange message to your service.
  2. You can send a TRISA message to the rVASP with a valid (or invalid) rVASP customer.

The rVASPs have a built-in database of fake customers with fake wallet addresses. Their response to TRISA messages or to a triggered transfer requires the originator/beneficiary customer to be valid for the rVASP. E.g. if the customer wallet address is a valid Alice address and Alice is the beneficiary, the rVASP will respond with the customer’s fake KYC data but if not, it will return an TRISA error code.

The following table of “customers” for Alice, Bob, and Evil can be used as a reference for interacting with each rVASP:

VASP“Crypto Wallet”EmailOriginator PolicyBeneficiary Policy
api.bob.vaspbot.netmoJuU1GjhJzUdUGukw13a4w6CWjfFsJ92qrobert.test@bobvasp.co.ukSendPartialSyncRepair
api.bob.vaspbot.net18nxAxBktHZDrMoJ3N2fk9imLX8xNnYbNhrobert@bobvasp.co.ukSendPartialSyncRepair
api.bob.vaspbot.netn1CqdbqoPZ8Y11UzQG6KyapWj4vcN3owcsgeorge.test@bobvasp.co.ukSendFullSyncRequire
api.bob.vaspbot.net1LgtLYkpaXhHDu1Ngh7x9fcBs5KuThbSzwgeorge@bobvasp.co.ukSendFullSyncRequire
api.bob.vaspbot.netmj2RQ7AcYs5sMQVJVTUn6ZZX7iMiMzn75olarry.test@bobvasp.co.ukSendFullAsyncRepair
api.bob.vaspbot.net14WU745djqecaJ1gmtWQGeMCFim1W5MNp3larry@bobvasp.co.ukSendFullAsyncRepair
api.bob.vaspbot.netmxWc29f1JHYSupfmveBYTHKMUYsnNcrJDVfred.test@bobvasp.co.ukSendErrorAsyncReject
api.bob.vaspbot.net1Hzej6a2VG7C8iCAD5DAdN72cZH5THSMt9fred@bobvasp.co.ukSendErrorAsyncReject
api.alice.vaspbot.netmpxi8gszWxQtayy3dztQZ1rheWRDFZ2QWpmary.test@alicevasp.usSendPartialSyncRepair
api.alice.vaspbot.net1ASkqdo1hvydosVRvRv2j6eNnWpWLHucMXmary@alicevasp.usSendPartialSyncRepair
api.alice.vaspbot.netn1wAFyKnzpyPchDUUwRpgXsrJYdekV7KGRalice.test@alicevasp.usSendFullSyncRequire
api.alice.vaspbot.net1MRCxvEpBoY8qajrmNTSrcfXSZ2wsrGehaalice@alicevasp.usSendFullSyncRequire
api.alice.vaspbot.netmioiUW2dR9y7PdAFs8gPPhthaZgmpHhgGdjane.test@alicevasp.usSendFullAsyncRepair
api.alice.vaspbot.net14HmBSwec8XrcWge9Zi1ZngNia64u3Wd2vjane@alicevasp.usSendFullAsyncRepair
api.alice.vaspbot.netmpJCwniMFW9FXGeFejtksrpPunjLEmPZsusarah.test@alicevasp.usSendErrorAsyncReject
api.alice.vaspbot.net19nFejdNSUhzkAAdwAvP3wc53o8dL326QQsarah@alicevasp.usSendErrorAsyncReject
api.evil.vaspbot.netn3mRAXVqEsN22rnXWEsnRMQMc9QmM47qUXvoldemort.test@evilvasp.ggSendPartialSyncRepair
api.evil.vaspbot.net1PFTsUQrRqvmFkJunfuQbSC2k9p4RfxYLFvoldemort@evilvasp.ggSendPartialSyncRepair
api.evil.vaspbot.netmmYjRCpKYYm22RGKjVuruADHBR8c5dni68launderer.test@evilvasp.ggSendFullSyncRequire
api.evil.vaspbot.net172n89jLjXKmFJni1vwV5EzxKRXuAAoxUzlaunderer@evilvasp.ggSendFullSyncRequire
api.evil.vaspbot.netmfdz3J9kQ6skqRjrdkQyoSg95WZqmRXmBAbadnews.test@evilvasp.ggSendFullAsyncRepair
api.evil.vaspbot.net182kF4mb5SW4KGEvBSbyXTpDWy8rK1Dpubadnews@evilvasp.ggSendFullAsyncRepair
api.evil.vaspbot.netmqPCJiSRPYqFmA7MtxxCwwABFQ52nzC4gVgambler.test@evilvasp.ggSendErrorAsyncReject
api.evil.vaspbot.net1AsF1fMSaXPzz3dkBPyq81wrPQUKtT2tizgambler@evilvasp.ggSendErrorAsyncReject

Note that all rVASP data was generated using a Faker tool to produce realistic/consistent test data and fixtures; this data is completely fictional. For example, the records for Alice VASP (a fake US company) are primarily in North America, etc.

If you’re a Traveler customer, the bold addresses above have some attribution data associated with them, and are a good candidate for Traveler-based rVASP interactions.

In order to support multiple behaviors at once, such as synchronous and asynchronous responses, each wallet address is configured with an originator policy and a beneficiary policy. The originator policy defines how the rVASP will behave when initiating transfers to a remote VASP. The beneficiary policy defines how the rVASP will behave when responding to transfers from a remote VASP. These policies are described in depth below.

There are two wallets for each customer to support wallet addresses that look like either testnet or mainnet crypto addresses, however the rVASP behavior and data is exactly the same for each pair. Note that rVASPs don’t interact with any real chain; the wallet addresses are simply a mechanism to configure behavior as described below.

Preliminaries

This documentation assumes that you have a service that is running the latest TRISANetwork service and that this service has been registered in the TRISA TestNet and has TestNet certificates correctly installed. See TRISA Integration Overview for more information. WARNING: the rVASPs do not participate in the TRISA production network. They will only respond to verified TRISA TestNet mTLS connections.

To interact with the rVASP API, you may either:

  1. Use the rvasp CLI tool
  2. Use the rVASP protocol buffers and interact with the API directly

To install the CLI tool, either download the rvasp executable for the appropriate architecture at the TestNet releases page, clone the TestNet repository and build the cmd/rvasp binary or install with go install as follows:

$ go install github.com/trisacrypto/testnet/cmd/rvasp@latest

To use the rVASP protocol buffers, clone or download them from the TestNet repository then compile them to your preferred language using protoc.

Triggering an rVASP to send a message

The rVASP admin endpoints are used to interact with the rVASP directly for development and integration purposes. Note that this endpoint is different than the TRISA endpoint, which was described above.

  • Alice: admin.alice.vaspbot.net:443
  • Bob: admin.bob.vaspbot.net:443
  • Evil: admin.evil.vaspbot.net:443

To use the command line tool to trigger a message, run the following command:

$ rvasp transfer -e admin.alice.vaspbot.net:443 \
        -a mary@alicevasp.us \
        -d 0.3 \
        -B trisa.example.com \
        -b cryptowalletaddress \
        -E

This message sends the Alice rVASP a message using the -e or --endpoint flag, and specifies that the originating account should be “mary@alicevasp.us” using the -a or --account flag. The originating account is used to determine what IVMS101 data to send to the beneficiary. The -d or --amount flag specifies the amount of “AliceCoin” to send. Finally, the -b or --beneficiary flag specifies the crypto wallet address of the beneficiary you intend as the recipient.

The next two parts are critical. The -E or --external-demo flag tells the rVASP to trigger a request to your service rather than to perform a demo exchange with another rVASP. This flag is required! Finally, the -B or --beneficiary-vasp flag specifies where the rVASP will send the request. This field should be searchable in the TRISA TestNet directory service; e.g. it should be your common name or the name of your VASP if it is searchable.

Note that you can set the $RVASP_ADDR and $RVASP_CLIENT_ACCOUNT environment variables to specify the -e and -a flags respectively.

To use the protocol buffers directly, use the TRISAIntegration service Transfer RPC with the following TransferRequest:

{
    "account": "mary@alicevasp.us",
    "amount": 0.3,
    "beneficiary": "cryptowalletaddress",
    "beneficiary_vasp": "trisa.example.com",
    "check_beneficiary": false,
    "external_demo": true
}

These values have the same exact specification as the ones in the command line program.

Responding to a TRISA message from an rVASP

Envelopes received from rVASPs can be decrypted using the private unsealing key paired with the public key you exchanged with the rVASP. The payload that you receive from the rVASP will be determined by the originator policy associated with the originator address in the transaction payload.

It is then up to your TRISA node to determine how to handle the payload. Your options are:

  1. Reject: return an error in the secure envelope without a payload
  2. Pending: return a trisa.data.generic.v1beta1.Pending in the transaction payload
  3. Accept: ensure the identity payload is complete and return payload with received_at

The rVASP handles each type of response appropriately. If a reject message is returned, the rVASP fails the transaction; if accept it “executes” the transaction.

The pending message initiates an asynchronous transaction as defined in the TRISA whitepaper. The transaction is placed into an “await” state until the rVASP receives a follow-up reject or accept response with the same envelope id.

Originator Policies

An originator policy determines how the rVASP constructs an outgoing payload and handles the response from the transfer. The originator policy is loaded when the rvasp command is used to instruct the rVASP to send an outgoing message either to another rVASP or to your own TRISA node. Originator policies are mapped to wallet addresses, and the rVASP identifies the originator address using the wallet address in the transaction payload. A description of the originator policies follow:

SendPartial

For the SendPartial policy, the rVASP sends an envelope containing a transaction payload and a partial identity payload containing a full originator identity and a partial beneficiary identity. For acceptance, the recipient must complete the identity payload by filling in the beneficiary identity.

SendFull

For the SendFull policy, the rVASP sends an envelope containing a transaction payload and a complete identity payload. For acceptance, the recipient must reseal and echo the envelope back with a received_at timestamp.

SendError

For the SendError policy, the rVASP will simply send an envelope containing a ComplianceCheckFail TRISA error. The rVASP expects the recipient to also return an envelope with an error in it, otherwise an error will be returned by the CLI to the user. This is useful for simulating synchronous rejections or cancellations from the rVASP.

Sending a TRISA message to an rVASP

The rVASP expects a trisa.data.generic.v1beta1.Transaction as the transaction payload and an ivms101.IdentityPayload as the identity payload. The transaction payload must contain a beneficiary address that matches the rVASP beneficiaries from the table above; e.g. use:

{
    "originator": "anydatahereisfine",
    "beneficiary": "1MRCxvEpBoY8qajrmNTSrcfXSZ2wsrGeha",
    "amount": 0.3,
    "network": "TestNet"
}

You may specify any originator “wallet address” string. The network and asset_type fields can be ignored if you would like to simulate other transaction information.

The identity payload cannot be null and must be valid IVMS101, but may be partially or completely filled in depending on the corresponding beneficiary policy.

  • Partial Identity: Contains only the originator and originating vasp identities
  • Complete Identity: Contains the originator, beneficiary, and originating and beneficiary vasp identities

Create a sealed envelope using either the directory service or direct key exchange to fetch the rVASP RSA public keys and use AES256-GCM and HMAC-SHA256 as the envelope cryptography. Then, use the TRISANetwork service Transfer RPC to send the sealed envelope to the rVASP.

See Secure Envelopes for more on how to compose a valid secure envelope for transfers and the TRISA CLI for more on how to use a command line application for sending transfers.

Beneficiary Policies

The beneficiary policy determines how an rVASP responds to an incoming TRISA transfer message to its TRISA endpoint. Beneficiary policies are mapped to wallet addresses found in the transaction payload, which the rVASP uses to identify the beneficiary address. A description of the beneficiary policies follow:

SyncRepair

For the SyncRepair policy, the identity payload does not have to include the beneficiary identity, although it must be not null. The rVASP will respond synchronously by sending an accept response containing a received_at timestamp and the complete beneficiary identity.

SyncRequire

For the SyncRequire policy, the identity payload must contain a complete beneficiary identity as defined in the TRISA whitepaper. The rVASP will respond synchronously by sending an accept response containing a received_at timestamp in the payload. If the beneficiary information is incomplete or incorrect, the rVASP will respond with a rejection error.

AsyncRepair

For the AsyncRepair policy, the identity payload does not have to include the beneficiary identity. In order to complete the transaction, the originator must:

  1. Send a Transfer request to the rVASP containing “partial” transaction and identity information. The transaction payload must contain a valid beneficiary address but the identity payload does not have to contain full beneficiary info.
  2. Receive a trisa.data.generic.v1beta1.Pending response from the rVASP containing reply_not_before and reply_not_after timestamps, specifiying the beginning of an asynchronous transaction.
  3. Be ready to receive an asynchronous callback from the rVASP within the time window. This can be done by caching the original pending message and waiting for a Transfer request from the rVASP with the same envelope Id and within the time window specified in the pending message.
  4. Respond to the callback RPC with a resealed envelope containing a received_at timestamp in the payload.
  5. Initiate a new Transfer request to the rVASP containing any final transaction details (txid, etc.).
  6. Receive another pending response from the rVASP which initiates a final asynchronous handshake.
  7. Receive a second Transfer callback request from the rVASP containing the full transaction payload and full identity payload along with a received_at timestamp.
  8. Finalize the transaction by echoing the envelope back to the rVASP.

The entire AsyncRepair workflow between two rVASPs is displayed below, where Alice is acting as the originator and Bob is acting as the beneficiary.

sequenceDiagram
autonumber
    Alice->>Bob: Transfer() Partial Identity Info + Partial Transaction
    activate Bob
    Bob-->>Alice: Pending (5-10 min)
    activate Alice
    Bob->>Alice: Transfer() Full Identity Info + received_at
    deactivate Bob
    Alice->>Bob: Echo Payload
    deactivate Alice
    Alice->>Bob: Transfer() Full Identity Info + Full Transaction
    activate Bob
    Bob-->>Alice: Pending (5-10 min)
    activate Alice
    Bob->>Alice: Transfer() Full Identity Info + Full Transaction + received_at
    deactivate Bob
    Alice->>Bob: Echo Payload
    deactivate Alice
AsyncReject

The AsyncReject policy simulates a synchronous rejected transaction. In this policy, the identity payload does not have to include the beneficiary identity, and the rVASP will respond with a pending message as in the AsyncRepair policy. The difference is that the rVASP will send a callback Transfer within the time window containing an TRISA rejection error, indicating that the transaction has been rejected.