Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions packages/bridge-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Bump `@metamask/assets-controller` from `^8.0.0` to `^8.0.1` ([#8874](https://github.com/MetaMask/core/pull/8874))

### Added

- Add `gasIncluded` and `gasIncluded7702` to `BatchSellTradesResponseSchema`

### Removed

- **BREAKING**: Deprecate `BridgeUserAction` and `BridgeBackgroundAction` enums

## [73.0.1]

### Changed
Expand Down
2 changes: 0 additions & 2 deletions packages/bridge-controller/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ export {
SortOrder,
ChainId,
RequestStatus,
BridgeUserAction,
BridgeBackgroundAction,
type TokenFeature,
type QuoteStreamCompleteData,
type BridgeControllerGetStateAction,
Expand Down
21 changes: 0 additions & 21 deletions packages/bridge-controller/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,27 +361,6 @@ export enum RequestStatus {
ERROR = 2,
}

/**
* @deprecated Use the separate method action types (e.g.,
* `BridgeControllerFetchQuotesAction`) instead.
*/
export enum BridgeUserAction {
SELECT_DEST_NETWORK = 'selectDestNetwork',
UPDATE_QUOTE_PARAMS = 'updateBridgeQuoteRequestParams',
}

/**
* @deprecated Use the separate method action types (e.g.,
* `BridgeControllerFetchQuotesAction`) instead.
*/
export enum BridgeBackgroundAction {
SET_CHAIN_INTERVAL_LENGTH = 'setChainIntervalLength',
RESET_STATE = 'resetState',
TRACK_METAMETRICS_EVENT = 'trackUnifiedSwapBridgeEvent',
STOP_POLLING_FOR_QUOTES = 'stopPollingForQuotes',
FETCH_QUOTES = 'fetchQuotes',
}

export type BridgeControllerState = {
quoteRequest: Partial<GenericQuoteRequest>[];
quotes: (QuoteResponse & L1GasFees & NonEvmFees)[];
Expand Down
33 changes: 18 additions & 15 deletions packages/bridge-controller/src/utils/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,21 +547,24 @@ export const SimulatedGasFeeLimitsSchema = type({
maxPriorityFeePerGas: HexStringSchema,
});

export const BatchSellTradesResponseSchema = type({
transactions: array(
intersection([
TxDataSchema,
SimulatedGasFeeLimitsSchema,
type({ type: enums(Object.values(BatchSellTransactionType)) }),
]),
),
fee: optional(
type({
asset: BridgeAssetSchema,
amount: NumberStringSchema,
}),
),
});
export const BatchSellTradesResponseSchema = intersection([
type({
transactions: array(
intersection([
TxDataSchema,
SimulatedGasFeeLimitsSchema,
type({ type: enums(Object.values(BatchSellTransactionType)) }),
]),
),
fee: optional(
type({
asset: BridgeAssetSchema,
amount: NumberStringSchema,
}),
),
}),
GaslessPropertiesSchema,
]);

export const validateBatchSellTradesResponse = (
data: unknown,
Expand Down
11 changes: 11 additions & 0 deletions packages/bridge-status-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **BREAKING:** Implement `submitBatchSell` method to submit BatchSell transactions to the TransactionController via STX or 7702. This requires clients to add `BridgeControllerGetStateAction` as an allowed action ([#8775](https://github.com/MetaMask/core/pull/8775))
- Wire up post-submission BatchSell history ([#8775](https://github.com/MetaMask/core/pull/8775))
- Create a history item for each STX trade in a batch, with the same batchId (key by `txMeta.id`)
- Create a history item for each trade submitted through a 7702 batch (key by `quoteId`). These won't have a reference to the batchId, and will only include quote and fee data
- Create a history item for the 7702 batch's delegation tx (key by `txMeta.id`). BatchSell delegation transactions include a list of `quoteIds` to associate the corresponding BatchSell trades with the delegation tx
- Expose `getHistoryItemsForTxHash` util that returns history items matching either a delegation tx hash or an STX hash
- Expose `isBatchSellHistoryItem` util that returns whether a history item is a BatchSell operation

### Changed

- Update controller and submit strategies to support an array of quotes instead of a single one ([#8775](https://github.com/MetaMask/core/pull/8775))
- Refactor tx submission into strategies to reduce quote-specific branching in the controller, and to de-duplicate shared logic between `submitTx` and `submitIntent`. Each strategy yields payloads that the controller uses to update history, poll, and publish metrics ([#8257](https://github.com/MetaMask/core/pull/8257))
- Bump `@metamask/bridge-controller` from `^72.0.4` to `^73.0.1` ([#8850](https://github.com/MetaMask/core/pull/8850), [#8866](https://github.com/MetaMask/core/pull/8866))
- Refactor batch transaction utils to handle multiple quote requests within a batch (for BatchSell integration) ([#8886](https://github.com/MetaMask/core/pull/8886))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ export type BridgeStatusControllerGetBridgeHistoryItemByTxMetaIdAction = {
handler: BridgeStatusController['getBridgeHistoryItemByTxMetaId'];
};

export type BridgeStatusControllerSubmitBatchSellAction = {
type: `BridgeStatusController:submitBatchSell`;
handler: BridgeStatusController['submitBatchSell'];
};

/**
* Union of all BridgeStatusController action types.
*/
Expand All @@ -50,4 +55,5 @@ export type BridgeStatusControllerMethodActions =
| BridgeStatusControllerSubmitTxAction
| BridgeStatusControllerSubmitIntentAction
| BridgeStatusControllerRestartPollingForFailedAttemptsAction
| BridgeStatusControllerGetBridgeHistoryItemByTxMetaIdAction;
| BridgeStatusControllerGetBridgeHistoryItemByTxMetaIdAction
| BridgeStatusControllerSubmitBatchSellAction;
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
QuoteResponse,
Trade,
FeatureId,
BatchSellTradesResponse,
} from '@metamask/bridge-controller';
import {
isNonEvmChainId,
Expand Down Expand Up @@ -49,7 +50,11 @@ import type { BridgeStatusControllerMessenger } from './types';
import { BridgeClientId } from './types';
import { getAccountByAddress } from './utils/accounts';
import { getJwt } from './utils/authentication';
import { stopPollingForQuotes, trackMetricsEvent } from './utils/bridge';
import {
getBatchSellTrades,
stopPollingForQuotes,
trackMetricsEvent,
} from './utils/bridge';
import {
fetchBridgeTxStatus,
getStatusRequestWithSrcTxHash,
Expand Down Expand Up @@ -109,6 +114,7 @@ const MESSENGER_EXPOSED_METHODS = [
'resetState',
'submitTx',
'submitIntent',
'submitBatchSell',
'restartPollingForFailedAttempts',
'getBridgeHistoryItemByTxMetaId',
] as const;
Expand Down Expand Up @@ -1029,26 +1035,40 @@ export class BridgeStatusController extends StaticIntervalPollingController<Brid
* Submits a cross-chain swap transaction
*
* @param accountAddress - The address of the account to submit the transaction for
* @param quoteResponse - The quote response
* @param maybeQuoteResponses - A single quote response or an array of quote responses
* @param isStxEnabled - Whether smart transactions are enabled on the client, for example the getSmartTransactionsEnabled selector value from the extension
* @param quotesReceivedContext - The context for the QuotesReceived event
* @param location - The entry point from which the user initiated the swap or bridge (e.g. Main View, Token View, Trending Explore)
* @param abTests - Legacy A/B test context for `ab_tests` (backward compatibility)
* @param activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.
* @param tokenSecurityTypeDestination - The security classification of the destination token, supplied by the client (e.g. from token security/scanning data). Pass `null` when no security data is available.
* @param batchSellTrades - Contains transaction data for the quotes, provided by the obtainGaslessBatch API
* @returns The transaction meta
* @throws An error if transaction submission fails before it gets published
*/
submitTx = async (
accountAddress: string,
quoteResponse: QuoteResponse<Trade, Trade> & QuoteMetadata,
maybeQuoteResponses:
| (QuoteResponse<Trade, Trade> & QuoteMetadata)
| (QuoteResponse<Trade, Trade> & QuoteMetadata)[],
isStxEnabled: boolean,
quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived],
location: MetaMetricsSwapsEventSource = MetaMetricsSwapsEventSource.MainView,
abTests?: Record<string, string>,
activeAbTests?: { key: string; value: string }[],
tokenSecurityTypeDestination?: string | null,
batchSellTrades?: BatchSellTradesResponse,
): Promise<TransactionMeta> => {
/**
* If there are multiple quote responses, we assume that they all originate from the same src chain
* and the same account. In this case its safe to use the first quote response's properties for
* metrics and other pre-submission logic
*/
const quoteResponses = Array.isArray(maybeQuoteResponses)
? maybeQuoteResponses
: [maybeQuoteResponses];
const quoteResponse = quoteResponses[0];

const { featureId, quote } = quoteResponse;
const startTime = Date.now();

Expand Down Expand Up @@ -1104,7 +1124,8 @@ export class BridgeStatusController extends StaticIntervalPollingController<Brid

const strategyParams: SubmitStrategyParams<Trade> = {
messenger: this.messenger,
quoteResponse,
quoteResponses,
batchSellTrades,
isStxEnabled,
isBridgeTx,
isDelegatedAccount,
Expand Down Expand Up @@ -1192,6 +1213,39 @@ export class BridgeStatusController extends StaticIntervalPollingController<Brid
);
};

submitBatchSell = async (params: {
quoteResponses: ((QuoteResponse<Trade, Trade> & QuoteMetadata) | null)[];
accountAddress: string;
location?: MetaMetricsSwapsEventSource;
abTests?: Record<string, string>;
activeAbTests?: { key: string; value: string }[];
isStxEnabled?: boolean;
quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived];
tokenSecurityTypeDestination?: string | null;
}): Promise<TransactionMeta> => {
/**
* Retrieve the batch sell trades from the BridgeController's state to ensure we submit
* the original response data from the bridge-api
*/
const batchSellTrades = getBatchSellTrades(this.messenger);
return await this.submitTx(
params.accountAddress,
params.quoteResponses.filter(
(
quoteResponse,
): quoteResponse is QuoteResponse<Trade, Trade> & QuoteMetadata =>
quoteResponse !== null,
),
params.isStxEnabled ?? false,
params.quotesReceivedContext,
params.location,
params.abTests,
params.activeAbTests,
params.tokenSecurityTypeDestination,
batchSellTrades,
);
};

readonly #trackPollingStatusUpdatedEvent = (
historyKey: string,
pollingStatus: PollingStatus,
Expand Down
5 changes: 5 additions & 0 deletions packages/bridge-status-controller/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,8 @@ export type {
export { BridgeId, BridgeStatusAction } from './types';

export { BridgeStatusController } from './bridge-status-controller';

export {
getHistoryItemsForTxHash,
isBatchSellHistoryItem,
} from './utils/history';
Loading
Loading