Custodied Wallets
Abstract​
The custodied wallet API facilitates the seamless creation of Ethereum Virtual Machine (EVM)-compliant custodied wallets. The B2B process involves direct interaction between the client's backend system and the API, ensuring secure and efficient wallet generation.
The API workflow starts with the B2B client initiating a request for a unique hash through its backend system, from information such as the user's email, allowed strategies (pin, 2FA or mail otp), and callbacks for success, failure and cancellation. This hash acts as a secure identifier for the subsequent wallet creation process. After this request, the client directs its end users to our website, where the creation of the custodied wallet takes place.
The url to our website is:
https://wallet.vottun.io/?hash={received-hash}&username={user-email}
On our website, users are guided through a user-friendly interface to enter the necessary information for portfolio creation. The custodied wallet is generated securely.Upon successful completion of the process, our API returns the public key of the wallet to the B2B client's backend system.
Key Features:
-
Hash Generation: B2B customers can initiate the wallet creation process by requesting a unique hash through the API, ensuring a secure and identifiable transaction.
-
Web-based Wallet Creation: Users are seamlessly redirected to our website, where they provide the information required for the creation of the custodied wallet through an intuitive and secure interface.
-
Security Measures: The custodied wallet creation process incorporates robust security practices to protect user data and private keys.
-
User Guidance: The website provides clear instructions to end users, ensuring a smooth and user-friendly experience throughout the wallet creation process.
-
Public Key Retrieval: Upon successful completion of the wallet creation process, the API quickly returns the wallet's public key to the B2B client's backend system, facilitating its integration into their platform.
This API for EVM Custodied Portfolio Creation simplifies the process for B2B customers to offer custodied portfolios to their users, providing a secure and efficient solution for managing EVM-based assets.
Users only need an email address to associate their wallet and, also, a way to ensure that only they will be able to make transactions with them. There are two options for this:
- User-created pin: The user enters a pin when the wallet is created and, from that moment on, he/she must use this pin for any status change operation (transfer, allowance...). This option, although offered for its simplicity, is highly discouraged due to its lack of security, since you will have to ask for this pin and resend it to our system.
- Single-use pin via Mobile App: The user will be able to use Google Authenticator, Microsoft Auhenticator or Authy App to protect your wallet. Every 30 seconds the mobile App will generate a new pin that can be used only once to perform a transaction with our wallet. This ensures that only your user will be able to perform these operations with total security. You can find more information at the end of this document in section Compatible Authentication Apps.
- Mail OTP: The user will receive an otp by mail to use as pin.
Endpoints​
Get New Hash​
This endpoint creates a new hash for a given user with the specified parameters. Its execution will return one limited life hash to be used in web to create a new Custodied Wallet.
The call that must be performed is:
POST https://api.vottun.tech/cwll/v1/hash/new
Request
The request must include a json body with the following fields:
name | type | required | description | example |
---|---|---|---|---|
username | string | yes | User's email | [email protected] |
strategies | []uint | yes | List of wallet strategies for the user (1 for pin (discouraged), 2 for 2FA and 3 for mail otp) | [2, 3] |
callbackUrl | string | yes | URL to receive successful hash creation callback | |
fallbackUrl | string | yes | URL to redirect to in case of an error | |
cancelUrl | string | yes | URL to redirect to if the user cancels the operation |
Example
{
"username": "[email protected]",
"strategies": [2,3],
"callbackUrl": "https://callback.vottun.tech/rest/v1/success/",
"fallbackUrl": "https://fallback.vottun.tech/rest/v1/error/",
"cancelUrl": "https://fallback.vottun.tech/rest/v1/cancel/"
}
Response If the hash is successcully created, the api returns a json with the following fields:
name | type | description | example |
---|---|---|---|
hash | string | The generated hash | |
expirationTime | int | Unix timestamp for the hash expiration |
Example
{
"hash": "a57d32fd0c7f186f3840f45e71817e7b86098f485ba4125558d6c1ea0c04d8fb316d9bbf4124a74...",
"expirationTime": 1672531199
}
Http status
result | http status |
---|---|
The hash has been created succesfully | 201 |
The customer is not authorized | 401 |
There is an error creating the hash | 503 |
Get Custodied Wallet Address​
This endpoint allows to get the wallet public address (the first account) for one of our users
The call that must be performed is:
GET|POST https://api.vottun.tech/cwll/v1/evm/wallet/custodied/address
Request
The request must include a json body with the following fields:
name | type | required | description | example |
---|---|---|---|---|
userEmail | string | yes | the user email to get the address | [email protected] |
Example
{
"userEmail": "[email protected]"
}
Response
If userEmail is found and owns a custodied wallet, the public address of the first account is returned:
name | type | description | example |
---|---|---|---|
accountAddress | string | the public address of the first account | 0xd941E010982..4D56aB1f173dcBD |
strategy | number | Integer representing the strategy. | 2 (2FA Authenticator) or 3 (2FA otp mail) |
Example
{
"accountAddress": "0xbB03fe627BfFB...35154cf21dB5964",
"strategy": 2
}
Http status
result | http status |
---|---|
The user has been found and the address returned | 200 |
The customer is not authorized | 401 |
The user has not been found | 404 |
There is server side error | 503 |
Get Customer Custodied Wallets​
This endpoint allows to get all the custodied wallets created for you. The execution returns a paginated list of custodied wallets.
The call that must be performed is:
GET https://api.vottun.tech/cwll/v1/evm/wallet/custodied/list
Query Params
name | type | required | description | example |
---|---|---|---|---|
o | int | no | The first element we want to get from the server | 0 |
n | int | no | The number of elements we want to receive from server starting from the one set at o param | 25 |
Response
The response is an array containing a list of elements with the following structure
name | type | description | example |
---|---|---|---|
id | string | Unique identifier for the entry. | "253eb3e3-9d34-401a-9ce3-16de01f8e505" |
strategy | number | Integer representing the strategy. | 2 (2FA Authenticator) or 3 (2FA otp mail) |
userEmail | string | Email associated with the user. | "[email protected]" |
accountHash | string | Hash associated with the user's account. | "0xB93b74d37566..8CE0226DcD6D7C7D" |
creationTimestamp | number | Timestamp indicating creation time. | 1700672507000 |
Example
[
{
"id": "253eb3e3-9d34-401a-9ce3-16de01f8e505",
"strategy": 2,
"userEmail": "[email protected]",
"accountHash": "0xB93b74d375..1B1C26B8CE0226DcD6D7C7D",
"creationTimestamp": 1700672507000
},
{
"id": "7d0b2c0b-a716-4f55-92e6-46633ceadb09",
"strategy": 3,
"userEmail": "[email protected]",
"accountHash": "0x9D8C3DA14C29a..bE4fac53964A4384590",
"creationTimestamp": 1700736340000
}
]
Http status
result | http status |
---|---|
The list has been returned (could be an empty array) | 200 |
The customer is not authorized | 401 |
There is server side error | 503 |
Create Signature Email OTP​
This endpoint allows you to ask a single use only email OTP to be sent to your user in order to sign a (mutable) transaction in the next 120 seconds. After that you need to ask the user for the received OTP to send it with the transaction request.
The call that must be performed is:
POST https://api.vottun.tech/cwll/v1/2fa/signature/otp/new?email=<user_email>
Query params
The request must include a query param with the following field:
name | type | required | description | example |
---|---|---|---|---|
email | string | yes | the user email to get the address | [email protected] |
Example
There is no example for this request because does not require json to be sent.
Response
The request will send an email containing the OTP to your user.
Example
There is no example for this response because it does not send json.
Http status
result | http status |
---|---|
The OTP has been sent succesfully | 201 |
The request does not include the correct information as per format or content | 400 |
The customer is not authorized or the otp is expired or not valid | 401 |
The user has not been found | 404 |
There is an error with any of the vottun dependencies or with the customer (in this case contact with Vottun) | 503 |
Send Transaction from custodied wallet​
This endpoint allows us to call any public function implemented in the smart contract and change its state. As discussed in the abstract, you need to know both the name of the function and its parameters in the right order.
If the smart contract has not been deployed by Vottun platform, then the ABI of the contract must be uploaded to the platform and get the contractSpecsId
identifier to be used instead of the smart contract address.
The call that must be performed is:
POST https://api.vottun.tech/core/v1/evm/wallet/custodied/transact/mutable?strategy=<value>
Query Params
name | type | required | description | example |
---|---|---|---|---|
strategy | int | yes | Integer representing the custodied wallet strategy | 2 (2FA Authenticator) or 3 (2FA otp mail) |
Request The request must include a json body with the following fields:
name | type | required | description | example |
---|---|---|---|---|
contractAddress | string | yes | It is the contract on which the transaction is to be executed. | 0xCC8b33F895F..6a4FfcFfD3C729Fd |
myReference | string | no | customer reference. It is used to retrieve information about the request if a problem occurs during the request. It is better to use different one for each request but if it is repeated there will not raise any error | REF0008A5F |
contractSpecsId | int | no | Contract Specs ID. If the transaction mast be executed on an external smart contract (not deployed by Vottun Platform), you need to inform this field in order to set what ABI must the execution use. | 3 |
sender | string | yes | sender address. The addres that will send the transaction | 0xfFc2780b3f4C..D04bEc41C60A |
blockchainNetwork | int | yes | The chain id | 1 |
value | int | yes | amount of native token to transfer from sender to recipient (denominated in WEI) | 1849367 |
gasLimit | int | no | the maximum amount of work you estimate a validator will do for the transaction. It this field is not set, the platform will estimate the gas in background before sending the transaction. | 4000000 |
gasPrice | int | no | the gas price to use in the transaction measured in GWEI. If it is not informed, it is requested to the chain. Required to accelerate a transaction | 25000 |
nonce | int | no | The nonce to use in this transaction. If it is not informed, it is requested to the chain. Required to accelerate a transaction | 47 |
method | string | yes | the smart contract function name written as it appears at the ABI file. That means, the name has to be the same that the one in the smart contract code. | "transfer" |
params | []any | yes | It is an array with all the parameters required for the smart contract constructor. The order is important | ["Vottun NFT","VTNFT"] |
pin | string | yes | the user pin (2FA pin via authenticator or mail otp) to sign the transaction | 123456 |
Example
{
"contractAddress": "0xCC8b33F895F..0f0F6a4FfcFfD3C729Fd",
"myReference": "6f5ee318-f536-4364-b7d7-78d63b774cc3",
"sender": "0xfFc2780b3f4C..07409427D04bEc41C60A",
"blockchainNetwork": 1,
"gasLimit": 250000,
"method": "transfer",
"params": [
"0x05447f753a75c16..56d18558b81DcF6B78",
100000000000000
],
"pin": "123456"
}
Response
The mutable transaction request will return a json with the following information (the transaction is not still confirmed):
name | type | description | example |
---|---|---|---|
txHash | string | The transaction Hash | 0xb3ba0828ac232..63ddfef73b5d6860a82a6 |
nonce | int | the transaction number from the account | 27 |
Example
{
"txHash": "0xb3ba0828ac232c48b69bb3..63ddfef73b5d6860a82a6",
"nonce": 27
}
Http status
result | http status |
---|---|
The transaction has been inserted succesfully | 201 |
The request does not include the correct information as per format or content or the gas limit informed is under the one estimated by the blockchain | 400 |
The customer is not authorized or the pin is not valid | 401 |
There is an error with any of the vottun dependencies or with the customer (in this case contact with Vottun) | 503 |
Transfer native assets from custodied wallet​
This endpoint allows you to transfer native assets (ETH, MATIC...) from a custodied account. Please note that it will be essential to indicate the wallet authentication strategy and to have previously obtained the pin or otp (Authenticator App or Email Otp).
The call that must be performed is:
GET|POST https://api.vottun.tech/core/v1/evm/wallet/custodied/transfer?strategy=<strategy>
Query Params
name | type | required | description | example |
---|---|---|---|---|
strategy | int | yes | Integer representing the custodied wallet strategy | 2 (2FA Authenticator) or 3 (2FA otp mail) |
Request
The request must include a json body with the following fields:
name | type | required | description | example |
---|---|---|---|---|
myReference | string | no | customer reference. It is used to retrieve information about the request if a problem occurs during the request. It is better to use different one for each request but if it is repeated there will not raise any error | REF0008A5F |
sender | string | yes | sender address. The addres that transfers the native assets. | 0xfFc2780..D04bEc41C60A |
recipient | string | yes | This field is the account to which the native assets are transferred. | 0xfE463ce3..1332A8994a |
blockchainNetwork | int | yes | The chain id | 1 |
value | int | yes | amount of native assets to transfer from sender to recipient (denominated in WEI) | 1849367 |
gasLimit | int | no | the maximum amount of work you estimate a validator will do for the transaction. It this field is not set, the platform will estimate the gas in background before sending the transaction. | 4000000 |
gasPrice | int | no | the gas price to use in the transaction measured in WEI. If it is not informed, it is requested to the chain. Required to accelerate or cancel a transaction | 25000 |
nonce | int | no | The nonce to use in this transaction. If it is not informed, it is requested to the chain. Required to accelerate a transaction | 47 |
pin | string | yes | the user pin (2FA pin via authenticator or mail otp) to sign the transaction | 123456 |
Example
{
"myReference": "cw-8847AF43D",
"recipient": "0xBAacAdb05..812A05BEad7ede01",
"sender": "0xc7101aa23e9..eAEeD0025972C0",
"blockchainNetwork": 80001,
"gasLimit": 54000,
"value": 0,
"pin": "456469"
}
Response
The mutable transaction request will return a json with the following information (the transaction is not still confirmed):
name | type | description | example |
---|---|---|---|
txHash | string | The transaction Hash | 0xb3ba0828ac232..63ddfef73b5d6860a82a6 |
nonce | int | the transaction number from the account | 27 |
Example
{
"txHash": "0xb3ba0828ac232c48b69bb3..63ddfef73b5d6860a82a6",
"nonce": 27
}
Http status
result | http status |
---|---|
The transaction has been inserted succesfully | 201 |
The request does not include the correct information as per format or content or the gas limit informed is under the one estimated by the blockchain | 400 |
The customer is not authorized or the pin is not valid | 401 |
There is an error with any of the vottun dependencies or with the customer (in this case contact with Vottun) | 503 |