Off-ramp Flow
To off-ramp to a Holyheld account the following steps should be completed:
- Get settings and ensure that off-ramping is available using
getServerSettings
method. - Check that selected wallet or holytag can transact using methods:
validateAddress
for a wallet orgetTagInfoForTopUp
for a $holytag. - Provide two parameters: token and amount.
- Get binary data to pass as swap parameters using
convertTokenToEUR
orconvertEURToToken
methods. - Call the
topup
method to execute the transaction.
🔔 If multiple wallet interactions are required (signing allowance and executing a transaction, or permit signing and executing a transaction), they will be processed automatically.
- Wait for the transaction hash of the operation to be received.
Here are the functions that are available for you to use.
getServerSettings
Get settings:
This method gets current state/settings for interacting with the service. Please always use this method to check:
- if the feature is available;
- the minimum and maximum allowed amounts to off-ramp.
🔔 Please note, that financial values are provided and consumed as strings to avoid floating point conversion problems.
(async () => {
const data = await holyheldSDK.getServerSettings();
})();
Types:
type Response = {
external: {
// indicates if the sending feature is available at the moment
isTopupEnabled: boolean;
// maximum amount (equivalent in EUR) that is allowed to be processed
maxTopUpAmountInEUR: string; // example: '1000'
// minimum amount (equivalent in EUR) that is allowed to be processed
minTopUpAmountInEUR: string; // example: '5'
};
common: {
// fee (in percent) that is deducted when making an off-ramping operation on mainnet
topUpFeePercent: string; // example: '0.75'
};
}
validateAddress
Get wallet information:
User wallet address is a unique identifier which can have account, card and a $holytag bound to it. It is alphanumeric string.
🔔 Please note that a valid wallet address is 42 strings long and begins with
0x
prefix.
🔔 Please note that this method does not support ENS domains.
(async () => {
// a wallet address could be pre-set or have to be input by user, depends on the application
const data = await holyheldSDK.validateAddress('0x000000000000000000000000000000000000dEaD');
})();
Types:
type Response = {
isTopupAllowed: boolean;
isOnRampAllowed: boolean;
}
getTagInfoForTopUp
Get tag information:
$Holytag is a unique identifier which can have account, card and multiple Ethereum addresses bound to it. It is alphanumeric string with a few special characters allowed.
🔔 Please note that a valid HH tag could be as short as one character in length.
When displaying $holytag usually is prepended with a $
prefix, for example: $JohnSmith holytag is JohnSmith
or $PEPE holytag PEPE
, etc.
Tags are stored case-sensitive for display, but not case-sensitive for search, and are not allowed to have multiple case variants registered, meaning if there is a tag $ToTheMoon
registered, there couldn't be tag $toTHEmoon
created afterwards.
🔔 Test $holytag
You can use
TESTSDK
as a test $holytag. All transactions to this $holytag will NOT trigger an actual fiat transaction, but will return a fully valid response. There is no minimum amount set for the test $holytag. Funds can be retrieved back. This test $holytag works across all supported networks an tokens.
(async () => {
// a tag name could be pre-set or have to be input by user, depends on the application
const data = await holyheldSDK.offRamp.getTagInfoForTopUp('TESTSDK');
})();
Types:
type Response = {
// if the tag exists and active
found: boolean;
// tag name (with writing preserving capital case, as registered)
tag?: string; // example: 'TESTSDK'
// if created, a link to avatar image (tag can have avatar picture set)
avatarSrc?: string; // example: 'https://holyheld.com/static/avatar.png'
}
getWalletBalances
Get wallet balances:
You can use getWalletBalances
method to retrieve all tokens on the connected user wallet address. Holyheld natively supports 14 Networks. The full list of supported networks is here.
(async () => {
const data = await holyheldSDK.getWalletBalances(
'0x...', // user wallet address
);
})();
Types:
import { Network } from '@holyheld/sdk';
type WalletToken = {
// name of the token
name: string; // example: 'Ether'
// smart contract address of the token
address: string; // example: '0x...'
// token symbol
symbol: string; // example: 'ETH'
// token decimal digits (as in ERC20 implementation)
decimals: number; // example: 18
// network (blockchain), on which this token resides
network: Network;
// logo (picture) for the token
iconURL: string; // example: 'https://holyheld.com/static/tokens/eth/eth.png'
// current estimated price (in USD)
priceUSD: string; // example: '1796.55'
// amount of token in the user's wallet
balance: string; // example: '0.0000099999999'
// if the token supports permit signatures
hasPermit: boolean;
// type of permit signature, 'erc2612' is expected
permitType?: string;
// permit version (currently, if permit supported, '1' is expected)
permitVersion?: string; // example: '1'
// token price converted from USD valuation to EUR
priceInEURForTopUp: string; // example: '1726.53'
};
type Response = {
tokens: WalletToken[];
}
convertTokenToEUR
Convert token to EUR:
This method is used to estimate a token value in EUR to proceed with the off-ramping. convertTokenToEUR
method can also be used in some scenarios/apps where token to be sent is pre-set and not selectable.
This method also returns transferData
— a hexadecimal string which can contain token-specific transfer, unwrap or swap data that is passed in off-ramping transaction.
import { Network } from '@holyheld/sdk';
(async () => {
const data = await holyheldSDK.offRamp.convertTokenToEUR(
'0x...', // token address
6, // token decimals
'9.99', // token amount
Network.ethereum, // token network
);
})();
Types:
import type { TransferData } from '@holyheld/sdk';
type Response = {
// amount of token that was passed to query
tokenAmount: string; // example: '1.99'
// EUR valuation of the token amount provided
EURAmount: string; // example: '314.25'
// data to be passed in sending transaction for this specific token (and amount)
transferData?: TransferData;
}
convertEURToToken
Convert EUR to token:
convertEURToToken
method returns a calculated token amount to match provided (expected) EUR amount.
This method also returns transferData
, that is hexadecimal string which could contain token-specific transfer, unwrap or swap data that is passed in sending to tag transaction.
import { Network } from '@holyheld/sdk';
(async () => {
const data = await holyheldSDK.offRamp.convertEURToToken(
'0x...', // token address
6, // token decimals
'999.99', // EUR amount
Network.ethereum, // token network
);
})();
Types:
import type { TransferData } from '@holyheld/sdk';
type Response = {
// amount (in EUR) that was passed to query
EURAmount: string; // example: '30.00'
// token amount to match expected valuation
tokenAmount: string; // example: '4.18'
// data to be passed in sending transaction for this specific token (and amount)
transferData?: TransferData;
}
Off-ramp:
This is the 'main' method to call that executes off-ramping to the user card. Parameter values should be retrieved using methods described above, such as transferData
matching token and token amount provided.
🚨 Some wallets like Metamask are single-network handled. It means that while Holyheld can return/accept transaction on any supported network, user must switch to the correct network in the wallet, in order for the transaction to be processed.
import { Network } from '@holyheld/sdk';
import * as chains from 'viem/chains';
import { createPublicClient, createWalletClient, custom, http } from 'viem';
const provider; // current provider in your app (see examples below)
const transferData; // transfer data from conversion methods or undefined
const callbackConfig; // callbacks
const chainId; // token chain id
// get chain entity from viem
const chain = Object.values(chains).find((item) => item.id === chainId);
// create viem public client
// https://viem.sh/docs/clients/public.html
const publicClient = createPublicClient({
chain,
transport: http(),
});
// wrap your provider in viem wallet client
// https://viem.sh/docs/clients/wallet.html
const walletClient = createWalletClient({
chain,
transport: custom(provider), // current provider in your app (see examples below)
account: '0x...', // wallet address
});
(async () => {
await holyheldSDK.offRamp.topup(
publicClient,
walletClient,
'0x...', // wallet address
'0x...', // token address
Network.ethereum, // token network
'5.25', // token amount
transferData, // if was provided by 'convertTokenToEUR' and/or 'convertEURToToken'
'TESTSDK', // funds recipient tag
true, // true if connected wallet supportsSignTypedDataV4 (for more human friendly signature request)
callbackConfig, // callbacks (see below)
);
})();
Types:
enum TopUpStep {
Confirming = 'confirming', // user is confirming action on review screen
Approving = 'approving', // a request was sent to wallet for approval or permit signature
Sending = 'sending', // a request was sent to wallet for executing sending funds to a tag
}
interface TopUpCallbackConfig {
onHashGenerate?: (hash: string) => void;
onStepChange?: (step: TopUpStep) => void;
}