Start integrating dKit API in under 5 minutes
curl --location 'https://api.dkit.xyz/v1/quote' \
--header 'Content-Type: application/json' \
--header 'api-key: 86c3fc76-25c8-455c-8d6d-0ecea88d0f6e' \
--data '{
"sellAsset": "ZEC.ZEC",
"sellAmount": "2",
"buyAsset": "ETH.ETH",
"slippage": 1,
"affiliate": "eld",
"affiliateFee": 88,
"includeTx": true,
"providers": [
"MAYACHAIN"
],
"sourceAddress": "t1Tmw3syVocrsRUDuCq7jteVjMSNfwpgz88",
"destinationAddress": "0x817bFA97Cc8E5Bfa499D401f43E3087B07AE96f9"
}'
const route = quote.routes[0]; // Select best route
// Send native transaction to the inbound address with memo
const tx = {
to: route.inboundAddress,
value: sellAmount,
memo: route.memo // Required for THORChain/Maya
};
// Execute with your wallet
const txHash = await wallet.sendTransaction(tx);
const trackSwap = async (txHash, chainId, quoteId, routeIndex) => {
const response = await fetch('https://api.dkit.xyz/v1/track', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': '86c3fc76-25c8-455c-8d6d-0ecea88d0f6e'
},
body: JSON.stringify({
hash: txHash,
chainId: chainId,
quoteId: quoteId,
routeIndex: routeIndex
})
});
const tracking = await response.json();
if (tracking.success) {
console.log(`Status: ${tracking.data.trackingStatus}`);
// Check if complete
if (tracking.data.trackingStatus === 'completed') {
console.log(`Output tx: ${tracking.data.trackMeta.outputTxHash}`);
}
}
return tracking;
};
// Poll for updates
const pollStatus = async (params) => {
let status = 'not_started';
while (status !== 'completed' && status !== 'refunded') {
const result = await trackSwap(params);
if (result.success) {
status = result.data.trackingStatus;
console.log(`Current status: ${status}`);
}
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
}
};
async function performSwap() {
try {
// 1. Get quote
const quote = await fetch('https://api.dkit.xyz/v1/quote', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sellAsset: 'ETH.ETH',
buyAsset: 'BTC.BTC',
sellAmount: '1.0',
sourceAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8',
destinationAddress: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
slippage: 3
})
}).then(r => r.json());
console.log(`Got ${quote.routes.length} routes`);
// 2. Select best route
const route = quote.routes[0];
console.log(`Best route: ${route.providers.join(' → ')}`);
console.log(`Expected output: ${route.expectedBuyAmount} sats`);
// 3. Execute swap (implementation depends on your wallet)
const txHash = await executeSwap(route);
console.log(`Transaction sent: ${txHash}`);
// 4. Track the swap
let tracking;
do {
tracking = await fetch('https://api.dkit.xyz/v1/track', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
hash: txHash,
chainId: '1', // Ethereum mainnet
quoteId: quote.quoteId,
routeIndex: 0
})
}).then(r => r.json());
if (tracking.success) {
console.log(`Status: ${tracking.data.trackingStatus}`);
if (tracking.data.isStreaming) {
const progress = tracking.data.streamingProgress;
console.log(`Streaming: ${progress.percentage}% complete`);
}
}
await new Promise(r => setTimeout(r, 5000)); // Wait 5 seconds
} while (
tracking.success &&
!['completed', 'refunded'].includes(tracking.data.trackingStatus)
);
if (tracking.data.trackingStatus === 'completed') {
console.log('Swap completed successfully!');
console.log(`Output tx: ${tracking.data.trackMeta.outputTxHash}`);
}
} catch (error) {
console.error('Swap failed:', error);
}
}
Wallet Integration
// MetaMask example
const executeEVMSwap = async (route) => {
const accounts = await ethereum.request({
method: 'eth_requestAccounts'
});
const tx = {
from: accounts[0],
to: route.targetAddress || route.inboundAddress,
value: route.tx?.value || '0x0',
data: route.tx?.data || route.memo || '0x'
};
return await ethereum.request({
method: 'eth_sendTransaction',
params: [tx]
});
};
Error Recovery
const swapWithRetry = async (params, maxRetries = 3) => {
for (let i = 0; i < maxRetries; i++) {
try {
const quote = await getQuote(params);
if (quote.routes.length > 0) {
return await executeSwap(quote.routes[0]);
}
// Check provider errors
if (quote.providerErrors) {
const retriable = quote.providerErrors.some(e =>
e.errorCode === 'RATE_LIMITED' ||
e.errorCode === 'PROVIDER_UNAVAILABLE'
);
if (!retriable) throw new Error('No routes available');
}
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
}
}
};
Amount Formatting
// Convert human-readable amounts to base units
const toBaseUnits = (amount, decimals) => {
const factor = BigInt(10 ** decimals);
const [whole, fraction = ''] = amount.split('.');
const fractionPadded = fraction.padEnd(decimals, '0').slice(0, decimals);
return (BigInt(whole) * factor + BigInt(fractionPadded)).toString();
};
// Convert base units to human-readable
const fromBaseUnits = (amount, decimals) => {
const value = BigInt(amount);
const factor = BigInt(10 ** decimals);
const whole = value / factor;
const remainder = value % factor;
if (remainder === 0n) return whole.toString();
const fraction = remainder.toString().padStart(decimals, '0');
return `${whole}.${fraction.replace(/0+$/, '')}`;
};