Coins & Decimals
Which coins are supported by Notabene?
When your customer is performing a withdrawal, it is necessary to provide the virtual asset type and the amount with the correct number of decimal points so that we can calculate the current FIAT value of the transfer. Different jurisdictions have different thresholds for when an accompanying travel rule message needs to be sent.
- How many decimals should I use in
transactionAmount
?- You can check how many decimals a coin needs by calling the asset service API.
- What about coins that you do not support?
- You should compare the coins you currently support against ours and see if there is any we are missing.
- To request new or missing coins, see "Coins not supported" below.
- Do I need to check your decimals every time?
- The content of the asset service seldom changes, so you can cache a copy of it once every day.
- You do not need to store all the fields, just the "notabene_..."-fields.
Checking travel rule thresholds
When we receive the initial request through our widget or the validation API, we get the FIAT value in your local currency IF it is supported by Coingecko. This is then checked against the threshold in your jurisdiction:
"thresholds": [
{
"conditions": [
{
"fields": [
{
"field": "originatorName"
},
.....
],
"conditions": [
{
"fields": [
.....
],
"conditions": [],
"type": "OR"
}
],
"type": "AND"
}
],
"threshold": 1500
},
{
"conditions": [
{
"fields": [
{
......
}
],
"type": "AND"
}
],
"threshold": 0.000001
},....
"countryCode": "SG",
"currency": "SGD"
If it is above, travel rule information needs to be collected.
The final check happens when the transaction is created where the FIAT value of the virtual asset is reported in USD (chargedQuantity), and the currency of the the originator and beneficiary:
Decimals
When creating or validating a travel rule transfer, our APIs do not support commas or dots and therefore all amounts have to be expressed as integers of the smallest denominator of a coin. For example, if you want to create a transaction of 1 ETH in the payload of txCreate, you will have to express it in WEI by putting 1 followed by 18 zeros to get the correct amount.
Examples
1 ETH = 1000000000000000000 WEI
1 BTC = 100000000 SATOSHI
We recommend using a library such as ethers or viem to convert floats to int using the decimal places you find on our asset API below.
Assets service API
You can find our asset service at the following URL: https://api.notabene.id/v1/assets/assets and the Postman examples here.
{
"data": {
"asset_type": "eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7",
"notabene_asset": "USDT",
"notabene_description": "USDT",
"decimals": "6",
"coingecko_id": "tether",
"notabene_network": "ethereum",
"elliptic_asset": "ERC20",
"elliptic_blockchain": "ethereum",
"elliptic_token": "USDT",
"trmlabs_asset": "",
"trmlabs_chain": "",
"chainalysis_asset": "USDT",
"chainalysis_network": "Ethereum",
"coinfirm_asset_type": "",
"coinmarketcap_id": "",
"crystal_id": "1",
"crystal_currency": "btc"
}
}
Currently supported coins
https://api.notabene.id/v1/assets/assets
Coins not supported
For us to support a coin/virtual asset, there’s two things that are needed:
- It needs to be in Coingecko and it should have a price (if the value of it in Coingecko is 0, it will not trigger the threshold and therefore no travel rule will be required).
- It needs to be supported by Notabene (i.e. we have added into our list of supported tokens that you see above)
We can also use data from CoinMarketCap if, for some reason, the coin is not in / does not have a value in Coingeko.
Requesting new coins to be added
You can request coins in the discussions tab or send an email to [email protected]
If possible, please provide the token name, the number of decimals, contract address, the network, etc. to make the process faster.
Polymorphic asset field
We support three different ways of providing the transactionAsset in txCreate:
Format 1 - using Notabene coin standard: "asset": "USDC-SOL"
{
"transactionAsset": "USDC-SOL",
"transactionAmount": "1700000000000000000",
"originatorVASPdid": "{{vaspDID}}",
"beneficiaryVASPdid": "{{vaspDIDee}}",
"transactionBlockchainInfo": {
"origin": "{{$randomBitcoin}}",
"destination": "{{$randomBitcoin}}"
},
Format 2 - using Coingeko API ID + the network: "asset": { "coingeckoId": "usd-coin", "network": "solana" }
{
"transactionAsset":
{
"coingeckoId": "usd-coin",
"network": "solana"
},
"transactionAmount": "1700000000000000000",
"originatorVASPdid": "{{vaspDID}}",
"travelRuleBehavior": false,
"beneficiaryVASPdid": "{{vaspDIDee}}",
"beneficiaryVASPname":"",
"transactionBlockchainInfo": {
"origin": "{{$randomBitcoin}}",
"destination": "{{$randomBitcoin}}"
},
Format 3 - using the CAIP19 standard: "asset": { "caip19": "solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }
{
"transactionAsset":
{
"caip19": "solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
"transactionAmount": "1700000000000000000",
"originatorVASPdid": "{{vaspDID}}",
"travelRuleBehavior": false,
"beneficiaryVASPdid": "{{vaspDIDee}}",
"beneficiaryVASPname":"",
"transactionBlockchainInfo": {
"origin": "{{$randomBitcoin}}",
"destination": "{{$randomBitcoin}}"
},
Coins with memo or tag
A destination tag is a special identifier used in XRP transactions. In Stellar, the destination tag is called memo. Many VASPs have one XRP and XLM address for all customers and the only way to identify who should receive the payment is this identifier which is unique for every user.
To be able to include this information in the travel rule message you send, we recommend that the memo/tag is added as the "accountNumber":
Address: rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY
Tag: 12345
{
"transactionAsset": "xrp",
"transactionAmount": "72000000000",
"originatorVASPdid": "{{vaspDID}}",
"beneficiaryVASPdid": "did:ethr:0x270d4f239359471f1d1c80781a53cf8105f7d08f",
"transactionBlockchainInfo": {
"txHash": "",
"origin": "",
"destination": "rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY"
},
"beneficiary": {
"beneficiaryPersons": [
{
"naturalPerson": {
"name": [
{
"nameIdentifier": [
{
"primaryIdentifier": "Bruce",
"secondaryIdentifier": "Wayne",
"nameIdentifierType": "LEGL"
}
]
}
]
}
}
],
"accountNumber": [
"12345"
]
}
}
Some of the virtual assets that require a memo or tag now also have an integrated address format where everything is part of one string. If you are storing the old format in your internal address book and your counterparty is using the new, you need to decode it before looking it up to confirm that it's yours:
XRP X-address encode/decode
The new 𝗫-address format aims to replace the use of a separate destination tag when sending funds to a multi-user wallet the XRP ledger, like those of exchanges and custodial services.
If you are using the integrated address instead of the separated version, you use it as you would any other wallet address:
{
"transactionAsset": "xrp",
"transactionAmount": "72000000000",
"originatorVASPdid": "{{vaspDID}}",
"beneficiaryVASPdid": "did:ethr:0x270d4f239359471f1d1c80781a53cf8105f7d08f",
"transactionBlockchainInfo": {
"txHash": "",
"origin": "",
"destination": "XV5sbjUmgPpvXv4ixFWZ5ptAYZ6PD28Sq49uo34VyjnmK5H"
},
If you are not able to separate the tag/memo into separate parts, you can pass the information in the "destination" with a colon like this: rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY:12345
Updated 2 months ago
Let's have a look at the official technical standard for travel rule: