TrustVault provides webhooks to alert you of the changes in that status of your transactions. These are POST requests delivered to your server and are sent as soon as an event occurs. The body of the request contains the details of the event.
Upon receiving a webhook notification, it should be acknowledged with a HTTP success response 20x. Otherwise the webhoook notification will be attempted to be sent again according to the following schedule:
1 minute from the previous attempt
2 minutes from the previous attempt
15 minutes from the previous attempt
2 hours from the previous attempt
10 hours from the previous attempt
24 hours from the previous attempt
NB: Webhooks will NOT follow a redirect of 30x. This is to prevent potential security risks.
If you need to register a webhook, just get in touch with Bitpanda Custody Support via help@bitpandacustody.com
Webhook Security
Webhook notifications should be verified using the message hash signature in the header and the secret key to prevent attackers from imitating valid webhooks.
Each webhook is associated with a single secret key, which is given upon registration of the webhook. The secret key is used to generate an HMAC using SHA-256 hash algorithm.
Webhook notifications will have an X-Sha2-Signature header in the request, containing the HMAC. The secret key should be used to compute the message hash signature using the complete event object. You must ensure that the generated hash signature matches the X-Sha2-Signature header sent by TrustVault.
All TrustVault webhooks will have the following header: User-Agent: "TrustVaultWebHook"
ERC-20 Tokens
Please note that ERC-20 tokens follow the EIP-20 spec. This means that:
The contract method symbol and name (which drives the assetName) are optional and can be named by the contract creator. Do not expect unique names (spammers may deliberately copy common token names). For a unique key use the contractAddress
The contract method decimals(which are used to derive the more friendly quantity field) are optional. For the canonical truth use the rawQuantity field which will always be the quantity specified within the contract
Please see the “Token Data” information lower in this page where erc-20 details are exposed.
Verifying HMAC-256 signature
1 2 3 4 5 6 7 8 9 10 11 12 13
import * as crypto from"crypto";
// NOTE: Do not hard code your secret key. Store it somewhere safe const secretKey = "SECRET_KEY"; const hmac = crypto.createHmac("SHA256", secretKey);
// Compute the hash from the stringified JSON request.body const computedHashSignature = hmac.update(request.body).digest("hex"); const expectedHashSignature = request.headers["X-Sha2-Signature"];
if (computedHashSignature !== expectedHashSignature) { thrownewError("Webhook hash signature mismatch"); }
Handle Duplicate Events
Webhook endpoints might occasionally receive the same event more than once. In particular, during chain re-organisation a webhook event could be re-sent for the exact same transaction. We advise you to guard against duplicated event receipts by making your event processing idempotent.
Events
Wallet Specific
Event
Description
Event type
Creation Delegate Signed
A wallet creation has been signed by a valid delegate
WALLET_CREATION_DELEGATE_SIGNED
Change Delegate Signed
A wallet change has been signed by a valid delegate
WALLET_CHANGE_DELEGATE_SIGNED
Policy Change Request Created
There is a request to change the policy associated with a wallet
POLICY_CHANGE_REQUEST_CREATED *
* - This webhook event type is likely to change name in the future
BITCOIN
Event
Description
Event type
Bitcoin Received
A Bitcoin subwallet has received a transaction
BITCOIN_TRANSACTION_RECEIVED
Bitcoin Transaction Created
A Bitcoin transaction has been created
BITCOIN_TRANSACTION_CREATED
Transaction Delegate Signed
A transaction request has been signed by a valid delegate
BITCOIN_TRANSACTION_DELEGATE_SIGNED
Bitcoin Transaction Signed
An outbound Bitcoin transaction has been signed by private keys
BITCOIN_TRANSACTION_SIGNED
Ethereum
Event
Description
Event type
Ethereum Received
An ethereum subwallet has received a ETH or ERC20 transaction
ETHEREUM_TRANSACTION_RECEIVED
Ethereum Transaction Created
An Ethereum transaction has been created
ETHEREUM_TRANSACTION_CREATED
Delegate Signed
A request has been signed by a valid delegate
ETHEREUM_TRANSACTION_DELEGATE_SIGNED
Ethereum Transaction Signed
An outbound Ethereumtransaction has been signed by private keys
ETHEREUM_TRANSACTION_SIGNED
Ethereum Internal Transfers have been received
An ethereum subwallet has received an internal transfer
ETHEREUM_BLOCK_INTERNAL_TRANSFERS_RECEIVED
EVM Based (via MetaMask)
Webhooks via MetaMask will be renamed to UNSUPPORTED_ETHEREUM_XXXX. This is to help better associated known chains and unknown chains. Since these webhooks would have previously been called ETHEREUM_XXXX, they will continue to be sent under the old and new name.
Event
Description
Event type
Unsupported Ethereum Transaction Created
A transaction created on an Unsupported Ethereum chain has been created (MM)
UNSUPPORTED_ETHEREUM_TRANSACTION_CREATED
Delegate Signed
A request has been signed by a valid delegate
UNSUPPORTED_ETHEREUM_TRANSACTION_DELEGATE_SIGNED
Unsupported Ethereum Transaction Signed
An outbound Unsupported Ethereumtransaction has been signed by private keys
UNSUPPORTED_ETHEREUM_TRANSACTION_SIGNED
Sign Request Webhooks (EVM Based)
The following sign requests webhooks are not chain specific and are applicable for any EVM based chain
Event
Description
Event type
Sign Request Created (Typed)
A request to sign a typed data on an EVM chain has been created
ETHEREUM_SIGN_TYPED_DATA_CREATED
Sign Request Created (Personal)
A request to sign data on an EVM chain has been created
ETHEREUM_PERSONAL_SIGN_CREATED
Binance Smart Chain
Event
Description
Event type
BSC Received
An BSC wallet has received a BNB or BEP-20 transaction
BINANCE_SMART_CHAIN_TRANSACTION_RECEIVED
BSC Transaction Created
An BSC transaction has been created
BINANCE_SMART_CHAIN_TRANSACTION_CREATED
Delegate Signed
A request has been signed by a valid delegate
BINANCE_SMART_CHAIN_TRANSACTION_DELEGATE_SIGNED
BSC Transaction Signed
An outbound BSC transaction has been signed by private keys
BINANCE_SMART_CHAIN_TRANSACTION_SIGNED
XDC.NETWORK Smart Chain
Event
Description
Event type
XdcNetwork Received
An XdcNetwork wallet has received a ETH or ERC20 transaction
XDCNETWORK_TRANSACTION_RECEIVED
XdcNetwork Transaction Created
An XdcNetwork transaction has been created
XDCNETWORK_TRANSACTION_CREATED
Delegate Signed
A request has been signed by a valid delegate
XDCNETWORK_TRANSACTION_DELEGATE_SIGNED
XdcNetwork Transaction Signed
An outbound XdcNetwork transaction has been signed by private keys
XDCNETWORK_TRANSACTION_SIGNED
RADIX
Event
Description
Event type
External Item Signed
An external item has been signed
RADIX_ITEM_SIGNED
Delegate Signed
A request has been signed by a valid delegate
RADIX_DELEGATE_SIGNED
Legacy Events
From 20th Decemember 2021, the following events were deprecated and you should migrate off them as soon as posisble.
Event
Description
Event type
External Item Signed
An external item has been signed
EXTERNAL_ITEM_SIGNED
Delegate Signed
A request belonging to the trustId has been signed by a valid delegate
DELEGATE_SIGNED
Migration of events
Old Event
New Event
Notes
EXTERNAL_ITEM_SIGNED
RADIX_ITEM_SIGNED
Renamed to be more consistent with other webhooks associated with a specific chain
ETHERUEM_TRANSACTION_RECEIVED
{CHAIN}_TRANSACTION_RECEIVED
Previously all EVM based trasnsactions would have been called ETHEREUM_XXX. This has been changed to be chian specific.
Legacy Event Triggers
This are still valid events but will but will be deprecetaed in the future.
Event type
Trigger
POLICY_CHANGE_REQUEST_CREATED
API only: A request has been created to change the wallet policy via the API or SDK
EXTERNAL_ITEM_SIGNED
TrustVault has signed the external item due to enough signature(s) were collected to satisfy the delegate schedule
DELEGATE_SIGNED
A request belonging to the trustId has been signed by a valid delegate
ETHEREUM_SIGN_TYPED_DATA_CREATED
A request to sign typed data has been created
ETHEREUM_PERSONAL_SIGN_CREATED
A request to sign personal data has been created
Event Object
Attribute
Description
messageId
string Unique identifier for the webhook notification
version
string The webhook version
type
string The webhook notification type
timestamp
integer The timestamp of the webhook notification
isoTimestamp
string The timestamp of the webhook notification in ISO 8601 format
payload
object The payload for the webhook notification
Bitcoin Received Event
The bitcoin received webhook will be triggered as soon as there is 1 confirmation from a miner.
Bitcoin Transaction Received Payload
Attribute
Description
trustId
string Unique identifier for the TrustVault user
subWalletId
object Unique identifier for the sub-wallet
subWalletIdString
string Unique identifier for the sub-wallet, in string format
transactionAmount
string The transaction amount in satoshi (integer string)
bitcoinAddress
string The UTXO receive address of the transaction
transactionType
string The type of transaction - RECEIVED or SELF
blockHeight
integer The block number where the transaction was included in
transactionId
string Unique identifier for the transaction in the blockchain
transactionBlockTime
integer The timestamp of the block
transactionAmountInBtc
string The transaction amount in BTC (float string)
complianceInfo
object? (optional) Compliance info of the transaction
Ethereum Received Event
The ethereum received webhook will be triggered as soon as there is 1 confirmation from a miner.
Ethereum Transaction Received Payload
Attribute
Description
trustId
string Unique identifier for the TrustVault user
subWalletId
object Unique identifier for the sub-wallet
subWalletIdString
string Unique identifier for the sub-wallet, in string format
from
string Ethereum address where the transaction was sent from
to
string Ethereum address where the transaction was sent to (*)
transactionValue
string Transaction value in Wei
transactionValueInEth
string Transaction value in Eth
transactionType
string The type of transaction - RECEIVED/SELF
tokensData
array Token data (see “Token Data” structure below) (**)
transactionId
string Unique identifier for the transaction in the blockchain
blockHeight
string The block number where the transaction was included in
blockHash
string Unique identifier for the block the transaction was included in
gasUsed
string Gas used by the transaction
gasPrice
string Gas price of the transaction
transactionBlockTime
number The timestamp of the block
decodedInput
object The decoded input field of the transaction
decodedEvents
array Array with all the emitted decoded events
complianceInfo
object? (optional) Compliance info of the transaction
(*)
In Ether transfers, to has the value of ethereum address where the Ether is transferred to.
In ERC20 transfers, to has the value of smart contract that manages the token transfer.
(**)
In Ether transfers, this array will be empty.
Ethereum Transaction Created Payload
Attribute
Description
trustId
string Unique identifier for the TrustVault user
subWalletId
object Unique identifier for the sub-wallet
subWalletIdString
string Unique identifier for the sub-wallet, in string format
assetSymbol
string The symbol associated with the asset being transacted
chain
string The chain associated with this transaction. i..e ETHEREUM
signData
object The full chain specific data associated with this transaction
policyData
object The full wallet policy
transferValueDefinition
object The transfer value of the transaction in native and fiat amounts
Bitcoin Transaction Created Payload
Attribute
Description
trustId
string Unique identifier for the TrustVault user
subWalletId
object Unique identifier for the wallet
subWalletIdString
string Unique identifier for the wallet, in string format
assetSymbol
string The symbol associated with the asset being transacted
chain
string The chain associated with this transaction. i..e BITCOIN
fee
string Fee in Satoshis for this transaction
signData
object The full chain specific data associated with this transaction
policyData
object The full wallet policy
transferValueDefinition
object The transfer value of the transaction in native and fiat amounts
Delegate Signed Payload
Attribute
Description
trustId
string Unique identifier for the TrustVault user
requestId
string Unique identifier for the request that was signed
requestType
string The type of the request that was signed. See Request Types below
walletId
string (Optional) Unique identifier for the parent wallet associated with the request that was signed. Does not exist for CREATION type
subWalletId
string (Optional) Unique identifier for the sub-wallet associated with the transaction, in string format. Does not exist for RECOVERY / CREATION types
assetSymbol
string (Optional) The symbol associated with the asset being transacted. Does not exist for RECOVERY / CREATION types
chain
string (Optional) The chain associated with this transaction. i..e ETHEREUM. Does not exist for RECOVERY / CREATION types
publicKeys
object Contains the list of valid delgate public keys that have signed the request so far
policy
object The delegate schedule of the wallet that is associated with the request
Request Types
Attribute
Description
RECOVERY
A request to change the policy of a wallet (i.e. recover it)
CREATION
A request to create a new wallet with a defined policy
ETH_TRANSACTION
A request to send an ETH / ERC20 transaction
EXTERNAL_ETH_TRANSACTION
A request to send an ETH / ERC20 transaction which coming from a 3rd party (i.e. MetaMask x TrustVault extension)
BTC_TRANSACTION
A request to send a bitcoin transaction
BINANCE_TRANSACTION
A request to send BNB / BEP-2 transaction
EXCHANGE_TRANSFER
A request to transfer assets between exchange accounts
ETH_PERSONAL_SIGN
A request to sign an Eth Personal Sign message
ETH_TYPED_DATA_SIGN
A request to sign an Eth Typed Data message
EXTERNAL_SIGN
A request to sign data which comes from a 3rd party
TransferValueDefinition Field
It should be noted that not all transactions can be valued. Sending ETH or BTC is quite straight forward, as is sending supported ERC-20 tokens. However, when sending to contracts it can get difficult to value the transaction. As such, we currently only support valuing the following:
ERC-20 supported transactions
ETH value transfers
BTC value transfers
At this time ETH transfers to any contract (including a on-chain wallet or vault) are not valued. Transactions that cannot be valued will have transferValueDefinition.transferAmount and transferValueDefinition.convertedAmount fields set to undefined.
Token Data
Please note that ERC-20 tokens follow the EIP-20 spec. See details at the top of this page.
Attribute
Description
to
string Ethereum address where the tokens were transferred to
quantity
string Quantity of tokens transferred taking into account the decimals value that the contract offers. If decimals is not defined, defaults to the rawQuantity value
rawQuantity
string Canonical truth for the quantity of tokens transferred in the raw units
symbol
string Token symbol (empty string if not defined)
assetName
string Name of the token (empty string if not defined)
tokenDirectionType
string Direction of token transfer - RECEIVED/SELF
contractAddress
string The contract address. The ideal unique key for assets
Compliance Info
Attribute
Description
asset
string Symbol associated with the asset of the transaction (BTC, ETH etc..)
transferReference
string transactionHash:outputAddress
status
string SUCCESS/FAIL to query KYC/AML data
decision
string ALLOW/QUARANTINE
riskRating
string UNKNOWN/HIGH/LOW: Risk level of the transaction
cluster
string Cluster the transaction belongs to
Policy Change Request Created
Attribute
Description
trustId
string Unique identifier for the TrustVault user
requestId
string Unique identifier for the request
policyTemplate
object Object containing the new policy for the wallet
recovererTrustVaultSignature
string The r, s values of the signature of the SHA-256(DER(policy)) as signed by the TrustVault provenance key. This ensures that you can confirm that the policy has come from TrustVault
unverifiedDigestData
string The policy object containing properties for easy signing
UnverifiedDigestData
Called “unverified” because the onus is on the caller to ensure that the message contains the same data that has been requested for this wallet. i.e. if you requested a new policy you can construct the policy object you expect, DER encode it, SHA-256 hash it and then check that your digest matches the shaSignData. Additionally, you can verify the recovererTrustVaultSignature to ensure the data was signed by TrustVault.
For testing, verification is not required and you can simply sign the shaSignData or signData depending on if your signing code request the raw message or the digest (SHA-256).
The variables decodedInput and decodedEvents contain the human readable decoding of the input and events variables of an Ethereum transaction. The following snippet in Typescript shows a decodedData interface that can be used to parse those two fields: