From 6c88f899fe9f8829a328a8c9c23bc2444aeaa7e6 Mon Sep 17 00:00:00 2001 From: nthpool Date: Tue, 20 Jan 2026 12:42:23 -0500 Subject: [PATCH] feat: add support for signed transactions with metadata in SmartTransactionsController - Introduced new types: SentinelMeta and SignedTransactionWithMetadata. - Updated SmartTransactionsController to handle signed transactions with metadata. - Enhanced tests to verify inclusion and omission of rawTxsWithMetadata in request body based on provided data. --- src/SmartTransactionsController.test.ts | 70 +++++++++++++++++++++++++ src/SmartTransactionsController.ts | 4 ++ src/index.ts | 2 + src/types.ts | 10 ++++ 4 files changed, 86 insertions(+) diff --git a/src/SmartTransactionsController.test.ts b/src/SmartTransactionsController.test.ts index ae3616c..2d77a73 100644 --- a/src/SmartTransactionsController.test.ts +++ b/src/SmartTransactionsController.test.ts @@ -24,6 +24,7 @@ import type { import { type TransactionParams, TransactionStatus, + TransactionType, } from '@metamask/transaction-controller'; import type { Hex } from '@metamask/utils'; import nock from 'nock'; @@ -1493,6 +1494,75 @@ describe('SmartTransactionsController', () => { }); }); + it('includes signedTransactionsWithMetadata in request body as rawTxsWithMetadata', async () => { + await withController(async ({ controller }) => { + const signedTransaction = createSignedTransaction(); + const submitTransactionsApiResponse = + createSubmitTransactionsApiResponse(); + + const signedTransactionsWithMetadata = [ + { + tx: signedTransaction, + metadata: { + txType: TransactionType.swap, + }, + }, + ]; + + let requestBody: any; + nock(API_BASE_URL) + .post( + `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + (body) => { + requestBody = body; + return true; + }, + ) + .reply(200, submitTransactionsApiResponse); + + await controller.submitSignedTransactions({ + signedTransactions: [signedTransaction], + signedTransactionsWithMetadata, + txParams: createTxParams(), + }); + + // Verify the request includes rawTxsWithMetadata + expect(requestBody).toBeDefined(); + expect(requestBody.rawTxsWithMetadata).toStrictEqual( + signedTransactionsWithMetadata, + ); + }); + }); + + it('omits rawTxsWithMetadata from request body when signedTransactionsWithMetadata is not provided', async () => { + await withController(async ({ controller }) => { + const signedTransaction = createSignedTransaction(); + const submitTransactionsApiResponse = + createSubmitTransactionsApiResponse(); + + let requestBody: any; + nock(API_BASE_URL) + .post( + `/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`, + (body) => { + requestBody = body; + return true; + }, + ) + .reply(200, submitTransactionsApiResponse); + + await controller.submitSignedTransactions({ + signedTransactions: [signedTransaction], + txParams: createTxParams(), + // signedTransactionsWithMetadata not provided + }); + + // Verify the request does not include rawTxsWithMetadata + expect(requestBody).toBeDefined(); + expect(requestBody.rawTxsWithMetadata).toBeUndefined(); + }); + }); + it('works without txParams', async () => { await withController(async ({ controller }) => { const signedTransaction = createSignedTransaction(); diff --git a/src/SmartTransactionsController.ts b/src/SmartTransactionsController.ts index 89d412a..ee5dc6f 100644 --- a/src/SmartTransactionsController.ts +++ b/src/SmartTransactionsController.ts @@ -52,6 +52,7 @@ import type { IndividualTxFees, SignedCanceledTransaction, SignedTransaction, + SignedTransactionWithMetadata, SmartTransaction, SmartTransactionsStatus, UnsignedTransaction, @@ -903,10 +904,12 @@ export class SmartTransactionsController extends StaticIntervalPollingController txParams, signedTransactions, signedCanceledTransactions = [], + signedTransactionsWithMetadata, networkClientId, }: { signedTransactions: SignedTransaction[]; signedCanceledTransactions?: SignedCanceledTransaction[]; + signedTransactionsWithMetadata?: SignedTransactionWithMetadata[]; transactionMeta?: TransactionMeta; txParams?: TransactionParams; networkClientId?: NetworkClientId; @@ -930,6 +933,7 @@ export class SmartTransactionsController extends StaticIntervalPollingController body: JSON.stringify({ rawTxs: signedTransactions, rawCancelTxs: signedCanceledTransactions, + rawTxsWithMetadata: signedTransactionsWithMetadata, }), }, ), diff --git a/src/index.ts b/src/index.ts index ee40168..187df8d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,8 @@ export { type IndividualTxFees, type FeatureFlags, type SmartTransaction, + type SentinelMeta, + type SignedTransactionWithMetadata, type SmartTransactionsNetworkConfig, type SmartTransactionsFeatureFlagsConfig, SmartTransactionMinedTx, diff --git a/src/types.ts b/src/types.ts index 446f138..38c9411 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,13 @@ import type { NetworkClientId } from '@metamask/network-controller'; +import type { TransactionType } from '@metamask/transaction-controller'; import type { CaipChainId, Hex } from '@metamask/utils'; import type { SmartTransactionsNetworkConfig } from './featureFlags'; +export type SentinelMeta = { + txType?: TransactionType; +}; + /** API */ export enum APIType { 'GET_FEES', @@ -126,6 +131,11 @@ export type UnsignedTransaction = any; // TODO export type SignedTransaction = any; +export type SignedTransactionWithMetadata = { + tx: string; + metadata?: SentinelMeta; +}; + // TODO export type SignedCanceledTransaction = any;