Automated testing/RoboVASPs

RoboVASPs are sandbox VASPs that answer every transfer the same way, so you can test how your integration handles each response a counterparty can give before you go live. They exist only in the sandbox, and no funds move.

RoboVASPDIDWhat it does
Authorizedid:web:notabeneid-f2afc.sandbox.notabene.id:grAuthorizes the transfer
Confirm addressdid:web:notabeneid-e42f7.sandbox.notabene.id:usConfirms that it controls the settlement address
Add custodiandid:web:notabeneid-60dbe.sandbox.notabene.id:krAdds a custodian to the transfer
Rejectdid:web:notabeneid-9b030.sandbox.notabene.id:deRejects the transfer
Replacedid:web:notabeneid-8f281.sandbox.notabene.id:thReplaces itself with another VASP
Send PIIdid:web:notabeneid-36ea1.sandbox.notabene.id:inSends the originator's PII when you ask for it

Send a transfer to a RoboVASP

Create an outgoing transfer with the RoboVASP's DID in two places: the beneficiary's VASP agent and the for of the SettlementAddress agent. {{originatorVASPdid}} is your DID. The RoboVASP answers within a few seconds, and you see its answer in your webhooks and in the transfer's agents.

{
  "originator": {
    "@id": "{{originatorID}}"
  },
  "beneficiary": {
    "@id": "{{beneficiaryID}}"
  },
  "asset": "{{BTC CAIP19}}",
  "amount": "{{$randomInt}}",
  "agents": [
    {
      "@id": "did:pkh:{{BTC CAIP2}}:{{$randomBitcoin}}",
      "for": "{{originatorVASPdid}}",
      "role": "SourceAddress"
    },
    {
      "@id": "{{originatorVASPdid}}",
      "for": "{{originatorID}}",
      "role": "VASP"
    },
    {
      "@id": "{{roboVASPdid}}",
      "for": "{{beneficiaryID}}",
      "role": "VASP"
    },
    {
      "@id": "did:pkh:{{BTC CAIP2}}:{{$randomBitcoin}}",
      "for": "{{roboVASPdid}}",
      "role": "SettlementAddress"
    }
  ],
  "ref": "{{$randomUUID}}"
}

Authorize

The RoboVASP authorizes, and you receive notification.transferAgentStatusChanged with its agent moving to AUTHORIZED:

{
    "message": "notification.transferAgentStatusChanged",
    "payload": {
        "agentID": "did:web:notabeneid-f2afc.sandbox.notabene.id:gr",
        "for": "{{originatorVASPdid}}",
        "fromStatus": "PROCESSING",
        "id": "fe895271-2ffb-4f56-84db-a509acd4acd2",
        "toStatus": "AUTHORIZED"
    },
    "version": "1.0.0"
}

The transfer itself moves to AUTHORIZED, with notification.transferStatusChanged, when you authorize it too and none of your own policies is still pending. This RoboVASP does not confirm addresses, so turn off Settlement Address Confirmation in your outgoing policies for this test.

Confirm address

Turn on Settlement Address Confirmation in your outgoing policies, then send the transfer. The RoboVASP confirms that it controls the settlement address, and you receive tap.requireRelationshipConfirmationSatisfied with the relationship CONFIRMED:

{
    "message": "tap.requireRelationshipConfirmationSatisfied",
    "payload": {
        "agentID": "did:pkh:bip122:000000000019d6689c085ae165831e93:1NJaTmEc2ZC82LcUKpEwoJyb9UKSAVsuSn",
        "for": "{{originatorVASPdid}}",
        "from": "did:pkh:bip122:000000000019d6689c085ae165831e93:1NJaTmEc2ZC82LcUKpEwoJyb9UKSAVsuSn",
        "id": "ea0f75df-d4ff-4de8-90b2-fba4f1aa5c5a",
        "relationshipId": "4803715f-79ca-4894-afaa-110b80b8faf5",
        "status": "CONFIRMED",
        "to": "did:web:notabeneid-e42f7.sandbox.notabene.id:us"
    },
    "version": "1.0.0"
}

Add custodian

The RoboVASP adds did:web:notabene.id:test:ck to the transfer as a Custodian agent and stays on it as the beneficiary's VASP, and you receive notification.transferAgentAdded. Code that reads the agents should not expect a fixed number of them.

{
    "message": "notification.transferAgentAdded",
    "payload": {
        "agent": {
            "for": "did:web:notabeneid-49944.sandbox.notabene.id:it",
            "id": "did:web:notabene.id:test:ck",
            "role": "Custodian"
        },
        "agentID": "did:web:notabene.id:test:ck",
        "for": "{{originatorVASPdid}}",
        "id": "7c2c31ce-1986-4f80-a251-d14379d59d84"
    },
    "version": "1.0.0"
}

Reject

The RoboVASP rejects, and you receive notification.transferAgentStatusChanged with its agent moving to REJECTED. Your transfer moves to FLAGGED at the same time, with notification.transferStatusChanged, and you should not send the funds.

{
    "message": "notification.transferAgentStatusChanged",
    "payload": {
        "agentID": "did:web:notabeneid-9b030.sandbox.notabene.id:de",
        "for": "{{originatorVASPdid}}",
        "fromStatus": "PROCESSING",
        "id": "aba31973-39cf-457b-848f-2a4fdbc42697",
        "toStatus": "REJECTED"
    },
    "version": "1.0.0"
}

Replace

The RoboVASP replaces itself with did:web:notabeneid-2999b.sandbox.notabene.id:ar, and you receive notification.transferAgentReplaced. Take the new VASP from toAgentID and carry on with it, because a real replacement can name any VASP.

{
    "message": "notification.transferAgentReplaced",
    "payload": {
        "for": "{{originatorVASPdid}}",
        "fromAgentID": "did:web:notabeneid-8f281.sandbox.notabene.id:th",
        "id": "8df49c03-1b46-4649-a321-8f706b29e83a",
        "toAgent": {},
        "toAgentID": "did:web:notabeneid-2999b.sandbox.notabene.id:ar"
    },
    "version": "1.0.0"
}

Send PII

This one tests a deposit that reached you without Travel Rule data. You create the transfer as the beneficiary, with "direction": "INCOMING", "status": "OUTGOING" and the RoboVASP as the originator's VASP. The deposit's transaction hash goes in settlementId, so the transfer is created as SETTLED, and in the sandbox any hash will do. {{beneficiaryVASPdid}} is your DID.

{
  "direction": "INCOMING",
  "status": "OUTGOING",
  "originator": {
    "@id": "{{originatorID}}"
  },
  "beneficiary": {
    "@id": "{{beneficiaryID}}"
  },
  "asset": "{{BTC CAIP19}}",
  "amount": "{{$randomInt}}",
  "settlementId": "{{BTC CAIP2}}:tx/{{txHash}}",
  "agents": [
    {
      "@id": "did:pkh:{{BTC CAIP2}}:{{$randomBitcoin}}",
      "for": "{{beneficiaryVASPdid}}",
      "role": "SettlementAddress"
    },
    {
      "@id": "{{beneficiaryVASPdid}}",
      "for": "{{beneficiaryID}}",
      "role": "VASP"
    },
    {
      "@id": "did:web:notabeneid-36ea1.sandbox.notabene.id:in",
      "for": "{{originatorID}}",
      "role": "VASP"
    },
    {
      "@id": "did:pkh:{{BTC CAIP2}}:{{$randomBitcoin}}",
      "for": "did:web:notabeneid-36ea1.sandbox.notabene.id:in",
      "role": "SourceAddress"
    }
  ],
  "ref": "{{$randomUUID}}"
}

The RoboVASP sends the originator's PII within a few seconds, and you receive tap.requirePresentationSatisfied with its DID as agentID. Get the transfer with decrypt=true to read the PII. The same call records any real deposit that arrives without Travel Rule data, once Reconcile received transfers finds no transfer for it.

{
    "message": "tap.requirePresentationSatisfied",
    "payload": {
        "agentID": "did:web:notabeneid-36ea1.sandbox.notabene.id:in",
        "for": "{{beneficiaryVASPdid}}",
        "id": "8102d36b-46b5-4b3d-8fe8-6491b64ed964",
        "policyType": "COUNTERPARTY_REQUIRE_PRESENTATION"
    },
    "version": "1.0.0"
}

Did this page help you?