Signing requests for wallet mapping API
Introduction
The Wallet Mapping API allows users to associate blockchain wallet addresses with domain names. This document explains how to properly sign requests for various operations in the API.
Authentication
All API requests require:
An API key provided in the header as 'api-key'
A valid EIP-712 signature for the operation being performed
API Endpoints
1. Set Wallet Mapping
Associates a blockchain wallet address with a domain for a specific chain/symbol.
// Function to set a wallet mapping
async function setWalletMapping(symbol, name) {
const payload = {
domain: name,
symbol,
address: wallet.address,
signatureExpiresAt: Date.now() + 5 * 60 * 1000, // 5 minutes
};
const signature = await wallet.signTypedData(
SignDomain,
SetWeb3RecordTypes,
payload
);
return fetch(`https://api-public.d3.app/v1/domain/${name}/records/web3`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
},
body: JSON.stringify({
symbol,
address: wallet.address,
signature,
signatureExpiresAt: payload.signatureExpiresAt,
}),
});
}
The SignDomain and SetWeb3RecordTypes constants are defined as:
const SignDomain = {
name: 'D3 API',
version: '1',
};
const SetWeb3RecordTypes = {
SetWeb3Record: [
{ name: 'domain', type: 'string' },
{ name: 'symbol', type: 'string' },
{ name: 'address', type: 'string' },
{ name: 'signatureExpiresAt', type: 'uint256' },
],
};
Example
// Set "ETH" wallet mapping for domain "example.com"
const response = await setWalletMapping("ETH", "example.d3");
console.log(await response.json());
// Example response: { success: true }
2. Delete Wallet Mapping
Removes the association between a wallet address and a domain for a specific chain/symbol.
async function deleteWalletMapping(symbol, name) {
const payload = {
domain: name,
symbol,
signatureExpiresAt: Date.now() + 5 * 60 * 1000, // 5 minutes
};
const signature = await wallet.signTypedData(
SignDomain,
DeleteWeb3RecordTypes,
payload
);
return fetch(`https://api-public.d3.app/v1/domain/${name}/records/web3`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
},
body: JSON.stringify({
symbol,
signature,
signatureExpiresAt: payload.signatureExpiresAt,
}),
});
}
The DeleteWeb3RecordTypes constant is defined as:
const DeleteWeb3RecordTypes = {
DeleteWeb3Record: [
{ name: 'domain', type: 'string' },
{ name: 'symbol', type: 'string' },
{ name: 'signatureExpiresAt', type: 'uint256' },
],
};
Example
// Delete "ETH" wallet mapping for domain "example.com"
const response = await deleteWalletMapping("ETH", "example.com");
console.log(await response.json());
// Example response: { success: true }
3. Set Primary Name
Sets a domain as the primary name for a wallet address (reverse resolution).
async function setPrimaryName(wallet, name) {
const payload = {
name,
signatureExpiresAt: Date.now() + 5 * 60 * 1000, // 5 minutes
};
const signature = await wallet.signTypedData(
SignDomain,
SetPrimaryNameTypes,
payload
);
return fetch(`https://api-public.d3.app/v1/reverse-registry/${wallet.address}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
},
body: JSON.stringify({
name,
signature,
signatureExpiresAt: payload.signatureExpiresAt,
}),
});
}
The SetPrimaryNameTypes constant is defined as:
const SetPrimaryNameTypes = {
SetPrimaryName: [
{ name: 'name', type: 'string' },
{ name: 'signatureExpiresAt', type: 'uint256' },
],
};
Example
// Set "example.com" as the primary name for the wallet
const response = await setPrimaryName(wallet, "example.com");
console.log(await response.json());
// Example response: { success: true }
4. Unset Primary Name
Removes the primary name association for a wallet address.
async function unsetPrimaryName(wallet) {
const payload = {
signatureExpiresAt: Date.now() + 5 * 60 * 1000, // 5 minutes
};
const signature = await wallet.signTypedData(
SignDomain,
UnsetPrimaryNameTypes,
payload
);
return fetch(`https://api-public.d3.app/v1/reverse-registry/${wallet.address}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
},
body: JSON.stringify({
signature,
signatureExpiresAt: payload.signatureExpiresAt,
}),
});
}
The UnsetPrimaryNameTypes constant is defined as:
const UnsetPrimaryNameTypes = {
UnsetPrimaryName: [
{ name: 'signatureExpiresAt', type: 'uint256' }
],
};
Example
// Remove the primary name for the wallet
const response = await unsetPrimaryName(wallet);
console.log(await response.json());
// Example response: { success: true }
Complete Working Example
Here's a complete example that demonstrates all operations:
const { ethers } = require('ethers');
// Configuration
const API_KEY = 'your-api-key-here';
const PRIVATE_KEY = 'your-private-key'; // Should be stored securely
const wallet = new ethers.Wallet(PRIVATE_KEY);
// EIP-712 domain
const SignDomain = {
name: 'D3 API',
version: '1',
};
// Type definitions for signatures
const SetWeb3RecordTypes = {
SetWeb3Record: [
{ name: 'domain', type: 'string' },
{ name: 'symbol', type: 'string' },
{ name: 'address', type: 'string' },
{ name: 'signatureExpiresAt', type: 'uint256' },
],
};
const DeleteWeb3RecordTypes = {
DeleteWeb3Record: [
{ name: 'domain', type: 'string' },
{ name: 'symbol', type: 'string' },
{ name: 'signatureExpiresAt', type: 'uint256' },
],
};
const SetPrimaryNameTypes = {
SetPrimaryName: [
{ name: 'name', type: 'string' },
{ name: 'signatureExpiresAt', type: 'uint256' },
],
};
const UnsetPrimaryNameTypes = {
UnsetPrimaryName: [
{ name: 'signatureExpiresAt', type: 'uint256' }
],
};
// Example usage
async function demonstrateAllOperations() {
const domain = "example.com";
const symbol = "ETH";
// 1. Set wallet mapping
console.log(`Setting ${symbol} wallet mapping for ${domain}...`);
const setResponse = await setWalletMapping(symbol, domain);
console.log(await setResponse.json());
// 2. Set primary name
console.log(`Setting ${domain} as primary name for wallet...`);
const setPrimaryResponse = await setPrimaryName(wallet, domain);
console.log(await setPrimaryResponse.json());
// Wait to demonstrate the operations
await new Promise(resolve => setTimeout(resolve, 2000));
// 3. Delete wallet mapping
console.log(`Deleting ${symbol} wallet mapping for ${domain}...`);
const deleteResponse = await deleteWalletMapping(symbol, domain);
console.log(await deleteResponse.json());
// 4. Unset primary name
console.log(`Unsetting primary name for wallet...`);
const unsetResponse = await unsetPrimaryName(wallet);
console.log(await unsetResponse.json());
}
// Implementation of API functions
// [Include all the function implementations from above]
// Run the demonstration
demonstrateAllOperations().catch(console.error);
Important Notes
All signatures expire after the time specified in
signatureExpiresAt(in milliseconds since epoch)The wallet address is derived from the signature, ensuring that only the wallet owner can make changes
Store your API key and private key securely and never expose them in client-side code
All endpoints will respond with 200 with an empty body in case of success
Error Handling
The API returns appropriate HTTP status codes and JSON responses for errors:
400 - Bad Request: Invalid parameters or signature
401 - Unauthorized: Invalid API key
403 - Forbidden: Signature expired or incorrect
404 - Not Found: Domain or wallet not found
Last updated