Skip to content

Commit c8b255e

Browse files
authored
Support batch transactions during submit, save txHashes (#504)
1 parent c61d0d3 commit c8b255e

File tree

3 files changed

+113
-7
lines changed

3 files changed

+113
-7
lines changed

src/SmartTransactionsController.test.ts

+99
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,105 @@ describe('SmartTransactionsController', () => {
722722
expect(submittedSmartTransaction.deviceModel).toBe('ledger');
723723
});
724724
});
725+
726+
it('submits a batch of signed transactions', async () => {
727+
await withController(async ({ controller }) => {
728+
const signedTransaction1 = createSignedTransaction();
729+
const signedTransaction2 = createSignedTransaction();
730+
const submitTransactionsApiResponse =
731+
createSubmitTransactionsApiResponse(); // It has uuid.
732+
nock(API_BASE_URL)
733+
.post(
734+
`/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`,
735+
)
736+
.reply(200, submitTransactionsApiResponse);
737+
738+
const txParams = createTxParams();
739+
const result = await controller.submitSignedTransactions({
740+
signedTransactions: [signedTransaction1, signedTransaction2],
741+
txParams,
742+
});
743+
744+
// Check response has both txHash and txHashes
745+
expect(result.uuid).toBe('dP23W7c2kt4FK9TmXOkz1UM2F20');
746+
expect(result.txHash).toBeDefined();
747+
expect(result.txHashes).toBeDefined();
748+
expect(result.txHashes?.length).toBe(2);
749+
750+
// Check smart transaction has correct properties
751+
const submittedSmartTransaction =
752+
controller.state.smartTransactionsState.smartTransactions[
753+
ChainId.mainnet
754+
][0];
755+
expect(submittedSmartTransaction.uuid).toBe(
756+
'dP23W7c2kt4FK9TmXOkz1UM2F20',
757+
);
758+
expect(submittedSmartTransaction.txHashes).toBeDefined();
759+
expect(submittedSmartTransaction.txHashes?.length).toBe(2);
760+
expect(submittedSmartTransaction.txHash).toBe(result.txHashes[0]);
761+
});
762+
});
763+
764+
it('works with optional signedCanceledTransactions', async () => {
765+
await withController(async ({ controller }) => {
766+
const signedTransaction = createSignedTransaction();
767+
const submitTransactionsApiResponse =
768+
createSubmitTransactionsApiResponse();
769+
770+
// Verify that the request body has empty rawCancelTxs array when signedCanceledTransactions is omitted
771+
let requestBody: any;
772+
nock(API_BASE_URL)
773+
.post(
774+
`/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`,
775+
(body) => {
776+
requestBody = body;
777+
return true;
778+
},
779+
)
780+
.reply(200, submitTransactionsApiResponse);
781+
782+
await controller.submitSignedTransactions({
783+
signedTransactions: [signedTransaction],
784+
txParams: createTxParams(),
785+
// No signedCanceledTransactions provided
786+
});
787+
788+
// Verify the request was made with an empty rawCancelTxs array
789+
expect(requestBody).toBeDefined();
790+
expect(requestBody.rawCancelTxs).toStrictEqual([]);
791+
});
792+
});
793+
794+
it('works without txParams', async () => {
795+
await withController(async ({ controller }) => {
796+
const signedTransaction = createSignedTransaction();
797+
const submitTransactionsApiResponse =
798+
createSubmitTransactionsApiResponse();
799+
800+
nock(API_BASE_URL)
801+
.post(
802+
`/networks/${ethereumChainIdDec}/submitTransactions?stxControllerVersion=${packageJson.version}`,
803+
)
804+
.reply(200, submitTransactionsApiResponse);
805+
806+
// This should not throw an error when txParams is missing
807+
const result = await controller.submitSignedTransactions({
808+
signedTransactions: [signedTransaction],
809+
// No txParams provided
810+
});
811+
812+
expect(result.uuid).toBe('dP23W7c2kt4FK9TmXOkz1UM2F20');
813+
814+
// The transaction should still be created in state
815+
const submittedSmartTransaction =
816+
controller.state.smartTransactionsState.smartTransactions[
817+
ChainId.mainnet
818+
][0];
819+
expect(submittedSmartTransaction.uuid).toBe(
820+
'dP23W7c2kt4FK9TmXOkz1UM2F20',
821+
);
822+
});
823+
});
725824
});
726825

727826
describe('fetchSmartTransactionsStatus', () => {

src/SmartTransactionsController.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -916,11 +916,11 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo
916916
transactionMeta,
917917
txParams,
918918
signedTransactions,
919-
signedCanceledTransactions,
919+
signedCanceledTransactions = [],
920920
networkClientId,
921921
}: {
922922
signedTransactions: SignedTransaction[];
923-
signedCanceledTransactions: SignedCanceledTransaction[];
923+
signedCanceledTransactions?: SignedCanceledTransaction[];
924924
transactionMeta?: TransactionMeta;
925925
txParams?: TransactionParams;
926926
networkClientId?: NetworkClientId;
@@ -948,10 +948,12 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo
948948
const time = Date.now();
949949
let preTxBalance;
950950
try {
951-
const preTxBalanceBN = await query(ethQuery, 'getBalance', [
952-
txParams?.from,
953-
]);
954-
preTxBalance = new BigNumber(preTxBalanceBN).toString(16);
951+
if (txParams?.from) {
952+
const preTxBalanceBN = await query(ethQuery, 'getBalance', [
953+
txParams.from,
954+
]);
955+
preTxBalance = new BigNumber(preTxBalanceBN).toString(16);
956+
}
955957
} catch (error) {
956958
console.error('provider error', error);
957959
}
@@ -970,9 +972,12 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo
970972
nonceDetails = nonceLock.nonceDetails;
971973
txParams.nonce ??= nonce;
972974
}
975+
976+
const txHashes = signedTransactions.map((tx) => getTxHash(tx));
973977
const submitTransactionResponse = {
974978
...data,
975-
txHash: getTxHash(signedTransactions[0]),
979+
txHash: txHashes[0], // For backward compatibility
980+
txHashes,
976981
};
977982

978983
try {
@@ -990,6 +995,7 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo
990995
type: transactionMeta?.type ?? 'swap',
991996
transactionId: transactionMeta?.id,
992997
networkClientId: selectedNetworkClientId,
998+
txHashes, // Add support for multiple transaction hashes
993999
},
9941000
{ chainId, ethQuery },
9951001
);

src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export type SmartTransactionsStatus = {
7373
export type SmartTransaction = {
7474
uuid: string;
7575
txHash?: string;
76+
txHashes?: string[];
7677
chainId?: string;
7778
destinationTokenAddress?: string;
7879
destinationTokenDecimals?: string;

0 commit comments

Comments
 (0)