# Ethos Everywhere Wallet Integration

### Overview

Ethos Everywhere Wallet is a managed wallet solution that brings Ethos functionality into partner applications. Users can post reviews, vote, and reply on Ethos directly from those apps, without wallet popups or manual transaction signing. This creates a seamless user experience while maintaining full security through server-side managed wallets powered by Privy.

#### What is Ethos Everywhere Wallet?

Ethos Everywhere Wallet allows users to interact with the Ethos Network from any partner application without needing to:

* Install a crypto wallet
* Manually sign transactions
* Pay gas fees (for qualified users)
* Switch from the partner app to Ethos and back

Once a user is authenticated on Ethos and has enabled Ethos Everywhere Wallet in their settings, they can immediately start posting reviews, voting on content, and engaging with the Ethos community from partner applications - all with a single click.

#### Use Cases

Partner applications can integrate Ethos Everywhere Wallet to enable users to:

* **Post Reviews**: Submit credibility reviews for Ethereum addresses, Twitter accounts, or other supported subjects
* **Vote on Activities**: Upvote or downvote reviews, vouches, attestations, slashes, broker posts, projects, reputation markets, and replies
* **Vote on Slashes**: Support or oppose community moderation actions for alleged unethical behavior
* **Reply to Content**: Post comments and engage in discussions on any activity type

#### Benefits

**For Users:**

* No wallet installation required
* No transaction signing popups
* No gas fees for users with sufficient credibility score
* Seamless single-click interactions
* Unified Ethos identity across all partner applications

**For Partners:**

* Lower friction for user onboarding
* Higher engagement rates
* Access to Ethos credibility data
* Enhanced user experience
* Built-in spam protection through credibility requirements

### Becoming an Allowlisted Partner

To integrate Ethos Everywhere Wallet into your application, you must be added to the Ethos partner allowlist. This process ensures the security and integrity of the Ethos Network.

#### Requirements

To become an allowlisted partner, your application must meet the following requirements:

1. **Domain Verification**: You must own and control the domain from which API requests will be made
2. **Security Review**: Your application will undergo a security review to ensure it follows best practices
3. **Clear Use Case**: Provide a clear description of how you plan to use Ethos Everywhere Wallet
4. **User Experience**: Demonstrate that your integration provides value to Ethos users
5. **Client Identification**: Implement the `X-Ethos-Client` header with your application name/version

#### Application Process

1. **Contact the Ethos Team**: Reach out through one of these channels:
   * Email: <help@ethos.network>
   * Discord: Join the [Ethos Discord](https://discord.gg/trust-ethos)
   * Twitter: [@ethos\_network](https://x.com/ethos_network)
2. **Provide Application Details**:
   * Application name and description
   * Domain(s) that will make API requests
   * Expected use cases and integration plans
   * Technical contact information
3. **Security Review**: The Ethos team will review your application and may request additional information or security measures
4. **Allowlist Configuration**: Once approved, the Ethos team will:
   * Add your domain to the CORS allowlist (`isAllowedOrigin()`)
   * Configure your client to show in up the "this review left from" display

#### API Endpoints

All Ethos Everywhere Wallet endpoints are available under the `wallets` tag in the [API v2 reference](https://api.ethos.network/docs/openapi.json).

**Authentication**

**GET /wallets/privy/auth-check**

Verify that the user is authenticated and has access to Ethos Everywhere Wallet.

* Returns: `{ ok: boolean, profileId?: number }`
* Use this to check if the user can perform wallet actions
* Automatically refreshes expired access tokens

**Review Creation**

**POST /wallets/privy/post/review**

Create a review using the Ethos Everywhere Wallet. Requires review subject, score, title, and optional content.

**POST /wallets/privy/post/review/by-address**

Create a review for a specific Ethereum address.

**POST /wallets/privy/post/review/by-x**

Create a review for a Twitter (x.com) account by ID or username.

All review endpoints return:

* `hash`: Transaction hash
* `review`: Review data (if available within timeout)
* `reviewSlug`: Slug for the review URL

**Voting**

**POST /wallets/activity/{activityType}/{id}/vote**

Submit an upvote or downvote on any activity type:

* `review`, `vouch`, `attestation`, `slash`, `broker-post`, `project`, `reputation-market`, `reply`

Parameters:

* `activityType`: The type of activity to vote on
* `id`: The activity ID
* `isUpvote`: `true` for upvote, `false` for downvote

**Replies**

**POST /wallets/activity/{activityType}/{id}/reply**

Post a reply to any activity type:

* `review`, `vouch`, `attestation`, `slash`, `broker-post`, `project`, `reputation-market`, `reply`

Parameters:

* `activityType`: The type of activity to reply to
* `id`: The activity ID
* `content`: Reply text content
* `metadata`: Optional metadata object

#### Integration Examples

**Authentication Check**

```typescript
async function checkWalletAuth() {
  try {
    const response = await fetch('https://api.ethos.network/api/v2/wallets/privy/auth-check', {
      method: 'GET',
      headers: {
        'X-Ethos-Client': 'my-app@1.0.0',
      },
      credentials: 'include', // Important: include cookies
    });

    const data = await response.json();
    
    if (data.ok) {
      console.log('User is authenticated with profile ID:', data.profileId);
      return true;
    }
    
    return false;
  } catch (error) {
    console.error('Auth check failed:', error);
    return false;
  }
}
```

**Posting a Review**

```typescript
async function postReview(address: string, score: 'positive' | 'neutral' | 'negative', title: string, content?: string) {
  try {
    const response = await fetch('https://api.ethos.network/api/v2/wallets/privy/post/review/by-address', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Ethos-Client': 'my-app@1.0.0',
      },
      credentials: 'include', // Important: include cookies
      body: JSON.stringify({
        address,
        score,
        title,
        content,
        waitForReviewTimeoutSeconds: 5, // Wait up to 5 seconds for review data
      }),
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message || 'Failed to post review');
    }

    const data = await response.json();
    console.log('Review posted with hash:', data.hash);
    
    if (data.review) {
      console.log('Review ID:', data.review.id);
      console.log('Review URL:', `https://ethos.network/review/${data.reviewSlug}`);
    }
    
    return data;
  } catch (error) {
    console.error('Failed to post review:', error);
    throw error;
  }
}
```

**Voting on an Activity**

```typescript
async function voteOnReview(reviewId: number, isUpvote: boolean) {
  try {
    const response = await fetch(`https://api.ethos.network/api/v2/wallets/activity/review/${reviewId}/vote`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Ethos-Client': 'my-app@1.0.0',
      },
      credentials: 'include',
      body: JSON.stringify({
        activityType: 'review',
        id: reviewId,
        isUpvote,
      }),
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message || 'Failed to vote');
    }

    const data = await response.json();
    console.log('Vote submitted with hash:', data.hash);
    return data;
  } catch (error) {
    console.error('Failed to vote:', error);
    throw error;
  }
}
```

#### Error Handling

Ethos Everywhere Wallet endpoints may return various error codes:

| Error Code                  | HTTP Status | Description                          |
| --------------------------- | ----------- | ------------------------------------ |
| `UNAUTHENTICATED`           | 401         | User is not authenticated            |
| `WALLET_NOT_FOUND`          | 404         | User does not have a wallet          |
| `EMBEDDED_WALLET_NOT_FOUND` | 404         | Embedded wallet not found for user   |
| `INSUFFICIENT_FUNDS`        | 400         | Not enough funds for transaction     |
| `NONCE_CONFLICT`            | 409         | Nonce collision; retry the request   |
| `CONTRACT_REVERT`           | 400         | Transaction reverted on-chain        |
| `RATE_LIMITED`              | 429         | Too many requests                    |
| `BLOCKCHAIN_UNAVAILABLE`    | 503         | Network is unavailable               |
| `ENDPOINT_DISABLED`         | 404         | Feature is not enabled for this user |

**Error Handling Pattern:**

```typescript
async function handleWalletRequest(requestFn: () => Promise<Response>) {
  try {
    const response = await requestFn();
    
    if (!response.ok) {
      const error = await response.json();
      
      switch (error.code) {
        case 'UNAUTHENTICATED':
          // Redirect to login or show authentication prompt
          redirectToLogin();
          break;
          
        case 'INSUFFICIENT_FUNDS':
          // Show message that user needs to add funds
          showError('Insufficient funds. Please add ETH to your wallet.');
          break;
          
        case 'NONCE_CONFLICT':
          // Retry the request once
          console.log('Nonce conflict, retrying...');
          return await requestFn();
          
        case 'RATE_LIMITED':
          // Back off and retry later
          showError('Too many requests. Please try again in a moment.');
          break;
          
        case 'ENDPOINT_DISABLED':
          // Feature not available for this user
          showError('This feature is not available for your account.');
          break;
          
        default:
          // Generic error handling
          showError(error.message || 'An error occurred');
      }
      
      return null;
    }
    
    return await response.json();
  } catch (error) {
    console.error('Request failed:', error);
    showError('Network error. Please check your connection.');
    return null;
  }
}
```

### Best Practices

1. **Always Include Credentials**: Set `credentials: 'include'` in fetch requests to send cookies
2. **Set X-Ethos-Client Header**: Include your app identifier in every request
3. **Check Authentication First**: Use `/auth-check` before attempting wallet operations
4. **Handle Errors Gracefully**: Implement proper error handling for all error codes
5. **Respect Rate Limits**: Implement exponential backoff for rate limit errors
6. **Use Appropriate Timeouts**: Set reasonable `waitForReviewTimeoutSeconds` values (5-10 seconds)
7. **Monitor Transaction Status**: Use the returned transaction hash to verify on-chain status if needed
8. **Cache Authentication State**: Avoid redundant auth checks by caching the authentication state
9. **Provide User Feedback**: Show loading states and success/error messages for all operations

### Support

If you encounter issues or have questions:

* **Documentation**: <https://developers.ethos.network>
* **API Reference**: <https://api.ethos.network/docs/openapi.json>
* **Email**: <help@ethos.network>
* **Discord**: Join the [Ethos Discord](https://discord.gg/trust-ethos)
* **Status Page**: Check [status.ethos.network](https://status.ethos.network) for service status


---

# 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://developers.ethos.network/api-documentation/ethos-everywhere-wallet-integration.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.
