# 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.

```jsx
// 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:

```jsx
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

```jsx
// 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.

```jsx
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:

```jsx
const DeleteWeb3RecordTypes = {
  DeleteWeb3Record: [
    { name: 'domain', type: 'string' },
    { name: 'symbol', type: 'string' },
    { name: 'signatureExpiresAt', type: 'uint256' },
  ],
};

```

#### Example

```jsx
// 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).

```jsx
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:

```jsx
const SetPrimaryNameTypes = {
  SetPrimaryName: [
    { name: 'name', type: 'string' },
    { name: 'signatureExpiresAt', type: 'uint256' },
  ],
};

```

#### Example

```jsx
// 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.

```jsx
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:

```jsx
const UnsetPrimaryNameTypes = {
  UnsetPrimaryName: [
    { name: 'signatureExpiresAt', type: 'uint256' }
  ],
};

```

#### Example

```jsx
// 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:

```jsx
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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.d3.app/channel-partner-integrations/d3-api/signing-requests-for-wallet-mapping-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
