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.
| RoboVASP | DID | What it does |
|---|---|---|
| Authorize | did:web:notabeneid-f2afc.sandbox.notabene.id:gr | Authorizes the transfer |
| Confirm address | did:web:notabeneid-e42f7.sandbox.notabene.id:us | Confirms that it controls the settlement address |
| Add custodian | did:web:notabeneid-60dbe.sandbox.notabene.id:kr | Adds a custodian to the transfer |
| Reject | did:web:notabeneid-9b030.sandbox.notabene.id:de | Rejects the transfer |
| Replace | did:web:notabeneid-8f281.sandbox.notabene.id:th | Replaces itself with another VASP |
| Send PII | did:web:notabeneid-36ea1.sandbox.notabene.id:in | Sends 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"
}Updated 5 days ago
