Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
da8e0be
feat: cow-swap
khanti42 Sep 1, 2025
0c8f25e
fix: include missing metadata on intent swap transaction
khanti42 Sep 3, 2025
cf9d91d
Merge branch 'main' into wip/cow-swap-intent
dawnseeker8 Sep 8, 2025
6cc5fe4
Fix all lint relative error and give proper type declaration.
dawnseeker8 Sep 8, 2025
c2bf9a2
Fix pipeline lint issue,
dawnseeker8 Sep 8, 2025
c76a00c
fix node 22 lint and build issue.
dawnseeker8 Sep 8, 2025
73604f1
Merge branch 'main' into wip/cow-swap-intent
dawnseeker8 Sep 8, 2025
63dc8ac
Update snapshot for unit tests.
dawnseeker8 Sep 8, 2025
331bec5
Fix all unit tests failure for bridge-status-controller.test.ts
dawnseeker8 Sep 8, 2025
37f72b5
Add stub module called `Intent-manager`
dawnseeker8 Sep 10, 2025
2493ab2
add ts-bridge as dev dependancies for build
dawnseeker8 Sep 10, 2025
1673f1f
wip: buildable version of intent manager and bridge-status-controller.
dawnseeker8 Sep 10, 2025
2ea099e
wip: fix the build issue.
dawnseeker8 Sep 10, 2025
74e6893
WIP: Remove the generateQuote and relative private method calls.
dawnseeker8 Sep 10, 2025
19fdb0e
feat: add a temp onlyIntent parameter.
dawnseeker8 Sep 24, 2025
dc76678
Merge branch 'main' into wip/intent-swap-architecture-refactory
dawnseeker8 Sep 24, 2025
018cd69
rebase from main
dawnseeker8 Sep 24, 2025
fdf4f04
Rebase from main
dawnseeker8 Sep 24, 2025
4e200c7
revert back to main version
dawnseeker8 Sep 24, 2025
83a36c1
update lock file
dawnseeker8 Sep 24, 2025
6a6ee79
update lock file to fix the pipeline failure
dawnseeker8 Sep 24, 2025
608187f
Merge branch 'main' into wip/intent-swap-architecture-refactory
dawnseeker8 Sep 24, 2025
7516d3b
fix unit tests and pipeline issue.
dawnseeker8 Sep 24, 2025
3e9f379
Try to fix the pipeline failure of lock file change.
dawnseeker8 Sep 24, 2025
9445620
try to avoid the pipeline failure of lock file change.
dawnseeker8 Sep 24, 2025
7f670b5
refactor: simplify logic for determining transaction hashes in Bridge…
dawnseeker8 Sep 24, 2025
e8eb450
Fix the lint error in node 22 version
dawnseeker8 Sep 24, 2025
ce7a2d1
Fix weird lock file change failure issue in pipeline.
dawnseeker8 Sep 24, 2025
7547553
Run prettier format the README.md file.
dawnseeker8 Sep 24, 2025
5d56313
change lock file again
dawnseeker8 Sep 24, 2025
07c15ac
Merge branch 'main' into wip/intent-swap-architecture-refactory
dawnseeker8 Sep 24, 2025
c5a0678
Merge branch 'main' into wip/intent-swap-architecture-refactory
dawnseeker8 Sep 25, 2025
60a4a13
update lock file after rebase from main to resolve conflict.
dawnseeker8 Sep 25, 2025
ae7c3cc
Reapply lock version with correct hash to pass the pipeline.
dawnseeker8 Sep 25, 2025
48b8230
Try to fix th lock file change pipeline broken
dawnseeker8 Sep 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/Intent-manager/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 MetaMask

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
320 changes: 320 additions & 0 deletions packages/Intent-manager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
<!-- cSpell:words cowswap unregisters -->

# `@metamask/intent-manager`

A comprehensive intent management system for MetaMask that orchestrates cross-chain token swaps and bridging operations through multiple decentralized exchange (DEX) providers. This package provides order execution and lifecycle management for user intents.

## Overview

The Intent Manager provides a unified interface for:

- **Cross-Chain Operations**: Support for token swaps and bridging across different blockchain networks
- **Order Lifecycle Management**: Handle order submission, execution tracking, and status monitoring
- **Provider Management**: Pluggable architecture for adding new DEX providers
- **State Management**: Track intent orders and maintain execution history

## Key Features

- 🔄 **Cross-chain token swaps** through multiple providers
- 🏪 **Multi-provider support** with extensible provider architecture
- 📊 **Real-time order tracking** and status updates
- 🛡️ **Order lifecycle management** with comprehensive error handling

## Installation

```bash
yarn add @metamask/intent-manager
```

or

```bash
npm install @metamask/intent-manager
```

## Quick Start

```typescript
import { IntentManager } from '@metamask/intent-manager';
import type { IntentSubmissionParams } from '@metamask/intent-manager';

// Initialize the intent manager
const intentManager = new IntentManager();

// Submit an intent order (order data would come from backend)
const submissionParams: IntentSubmissionParams = {
providerName: 'cowswap',
chainId: 1, // Ethereum Mainnet
orderData: {
sellToken: '0xA0b86a33E6441e6e80D0c4C6C7527d72', // USDC
buyToken: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', // WETH
sellAmount: '1000000000000000000', // 1 token (18 decimals)
// ... other order data from backend
},
signature: '0x...', // User signature
userAddress: '0x742d35Cc6634C0532925a3b8D4C9db96',
};

const order = await intentManager.submitIntent(submissionParams);

// Monitor order status
const status = await intentManager.getOrderStatus(order.id, 'cowswap', 1);
```

## API Reference

### IntentManager

The main class that orchestrates intent operations across multiple providers.

#### Constructor

```typescript
new IntentManager(initialState?: Partial<IntentManagerState>)
```

#### Core Methods

##### `submitIntent(params): Promise<IntentOrder>`

Submits an intent order with the provided order data.

```typescript
const order = await intentManager.submitIntent({
providerName: 'cowswap',
chainId: 1,
orderData: {
// Order data from backend
},
signature: '0x...',
userAddress: '0x...',
});
```

##### `getOrderStatus(orderId, providerName, chainId): Promise<IntentOrder>`

Retrieves the current status of an order.

```typescript
const status = await intentManager.getOrderStatus('order-123', 'cowswap', 1);
```

##### `cancelOrder(orderId, providerName, chainId): Promise<boolean>`

Cancels a pending order.

```typescript
const cancelled = await intentManager.cancelOrder('order-123', 'cowswap', 1);
```

#### Provider Management

##### `registerProvider(provider): void`

Registers a new intent provider.

```typescript
const customProvider = new CustomProvider(config);
intentManager.registerProvider(customProvider);
```

##### `unregisterProvider(providerName): boolean`

Unregisters an intent provider.

```typescript
const removed = intentManager.unregisterProvider('cowswap');
```

##### `getAvailableProviders(criteria?): BaseIntentProvider[]`

Gets available providers, optionally filtered by criteria.

```typescript
const providers = intentManager.getAvailableProviders({
chainId: 1,
tokenPair: ['0x...', '0x...'],
amount: '1000000000000000000',
});
```

## Core Types

### IntentOrder

Order information and status.

```typescript
type IntentOrder = {
id: string;
status: IntentOrderStatus;
txHash?: string;
createdAt: number;
updatedAt: number;
metadata: Record<string, unknown>;
};
```

### IntentOrderStatus

```typescript
enum IntentOrderStatus {
PENDING = 'pending',
SUBMITTED = 'submitted',
CONFIRMED = 'confirmed',
COMPLETED = 'completed',
FAILED = 'failed',
CANCELLED = 'cancelled',
EXPIRED = 'expired',
}
```

### ProviderSelectionCriteria

Criteria for filtering and sorting providers.

```typescript
type ProviderSelectionCriteria = {
chainId: number;
tokenPair: [string, string];
amount: string;
preferredProviders?: string[];
excludedProviders?: string[];
};
```

## Supported Providers

### CowSwap

The package includes built-in support for CowSwap, a DEX aggregator that provides:

- **MEV Protection**: Orders are protected from front-running and sandwich attacks
- **Gas-free Trading**: No gas fees for failed transactions
- **Multi-chain Support**: Ethereum, Arbitrum, Base, Avalanche, and Polygon
- **Batch Auctions**: Efficient price discovery through batch settlement

### Adding Custom Providers

You can extend the system by implementing the `BaseIntentProvider` interface:

```typescript
import { BaseIntentProvider } from '@metamask/intent-manager';

class CustomProvider extends BaseIntentProvider {
constructor(config: IntentProviderConfig) {
super(config);
}

getName(): string {
return 'custom-dex';
}

getVersion(): string {
return '1.0.0';
}

getSupportedChains(): number[] {
return [1, 42161]; // Ethereum and Arbitrum
}

async submitOrder(params: IntentSubmissionParams): Promise<IntentOrder> {
// Implement order submission logic
}

async getOrderStatus(orderId: string, chainId: number): Promise<IntentOrder> {
// Implement status checking logic
}

async cancelOrder(orderId: string, chainId: number): Promise<boolean> {
// Implement order cancellation logic
}
}

// Register the custom provider
const customProvider = new CustomProvider(config);
intentManager.registerProvider(customProvider);
```

## Error Handling

The Intent Manager provides comprehensive error handling:

```typescript
try {
const order = await intentManager.submitIntent(submissionParams);
} catch (error) {
if (error.message.includes('Unsupported chain')) {
// Handle unsupported chain error
} else if (error.message.includes('Provider not found')) {
// Handle provider error
} else {
// Handle other errors
}
}
```

## Best Practices

### Order Monitoring

- **Poll Status Regularly**: Check order status periodically for updates
- **Handle Timeouts**: Implement timeout logic for long-running orders
- **Retry Failed Orders**: Consider retrying with different providers

```typescript
async function monitorOrder(
orderId: string,
provider: string,
chainId: number,
) {
const maxAttempts = 60; // 5 minutes with 5-second intervals
let attempts = 0;

while (attempts < maxAttempts) {
const order = await intentManager.getOrderStatus(
orderId,
provider,
chainId,
);

if (order.status === IntentOrderStatus.COMPLETED) {
return order;
} else if (order.status === IntentOrderStatus.FAILED) {
throw new Error(`Order failed: ${order.id}`);
}

await new Promise((resolve) => setTimeout(resolve, 5000));
attempts++;
}

throw new Error('Order monitoring timeout');
}
```

## Contributing

This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme).

### Development

```bash
# Install dependencies
yarn install

# Run tests
yarn test

# Run tests in watch mode
yarn test:watch

# Build the package
yarn build

# Generate documentation
yarn build:docs
```

## License

MIT
26 changes: 26 additions & 0 deletions packages/Intent-manager/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/

const merge = require('deepmerge');
const path = require('path');

const baseConfig = require('../../jest.config.packages');

const displayName = path.basename(__dirname);

module.exports = merge(baseConfig, {
// The display name when running multiple projects
displayName,

// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
branches: 0,
functions: 0,
lines: 0,
statements: 0,
},
},
});
Loading
Loading