Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: detect incoming transactions using accounts API #4927

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a7d52c5
Initial draft of incoming transactions via accounts API
matthewwalsh0 Nov 8, 2024
3dacd21
Optimise requests with start timestamps
matthewwalsh0 Nov 11, 2024
9071806
Add unit tests for accounts API
matthewwalsh0 Nov 11, 2024
8b7874c
Fix unit tests for incoming transaction helper
matthewwalsh0 Nov 12, 2024
a3f8df4
Remove multiple incoming transaction helpers
matthewwalsh0 Nov 14, 2024
2be68f1
Remove logs
matthewwalsh0 Nov 14, 2024
e7aedd3
Remove export
matthewwalsh0 Nov 14, 2024
5d395a9
Add initial unit tests for remote transaction source
matthewwalsh0 Nov 19, 2024
95a8288
Update incoming transaction events
matthewwalsh0 Nov 20, 2024
de5d2fd
Update coverage targets
matthewwalsh0 Nov 20, 2024
b8a839d
Merge branch 'main' into feat/incoming-transactions-accounts-api
matthewwalsh0 Nov 21, 2024
2776467
Add client header
matthewwalsh0 Nov 21, 2024
adf090d
Remove unused constants
matthewwalsh0 Nov 21, 2024
fd7ad7d
Merge branch 'main' into feat/incoming-transactions-accounts-api
matthewwalsh0 Nov 21, 2024
93be323
Export supported chains
matthewwalsh0 Nov 21, 2024
8b11638
Cache cursors instead of timestamps
matthewwalsh0 Nov 21, 2024
690da12
Revert state rename
matthewwalsh0 Nov 21, 2024
47bf38a
Remove start timestamp if using cursor
matthewwalsh0 Nov 22, 2024
2baa570
Update duplicate logic
matthewwalsh0 Nov 25, 2024
5a6b3e0
Merge branch 'main' into feat/incoming-transactions-accounts-api
matthewwalsh0 Nov 25, 2024
92a591a
Add client header to all requests
matthewwalsh0 Nov 25, 2024
fffb29b
Set toSmartContract on incoming transactions
matthewwalsh0 Nov 25, 2024
6879d4c
Merge branch 'main' into feat/incoming-transactions-accounts-api
matthewwalsh0 Nov 25, 2024
b481710
Move filtering to helper
matthewwalsh0 Nov 26, 2024
76d5293
Merge branch 'main' into feat/incoming-transactions-accounts-api
matthewwalsh0 Nov 26, 2024
09dff6f
Update changelog
matthewwalsh0 Nov 26, 2024
0737543
Release/258.0.0 (#4979)
adonesky1 Nov 26, 2024
7f0e3c6
Release 259.0.0 (#4982)
matthewwalsh0 Nov 26, 2024
dfa7bbe
feat: revoke CAIP-25 endowment if only eip155 account or scope is rem…
jiexi Nov 26, 2024
71968c2
Release/260.0.0 (#4983)
jiexi Nov 26, 2024
b587148
Merge branch 'main' into feat/incoming-transactions-accounts-api
matthewwalsh0 Nov 26, 2024
2eec965
Fix changelog
matthewwalsh0 Nov 26, 2024
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
23 changes: 23 additions & 0 deletions packages/transaction-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Retrieve incoming transactions using Accounts API ([#4927](https://github.com/MetaMask/core/pull/4927))
- Add `INCOMING_TRANSACTIONS_SUPPORTED_CHAIN_IDS` constant.

### Changed

- **BREAKING:** Retrieve incoming transactions using Accounts API ([#4927](https://github.com/MetaMask/core/pull/4927))
- Rename `TransactionControllerIncomingTransactionBlockReceivedEvent` to `TransactionControllerIncomingTransactionsReceivedEvent`.
- Replace `networkClientIds` argument with `chainIds` in following methods:
- `startIncomingTransactionPolling`
- `stopIncomingTransactionPolling`
- `updateIncomingTransactions`

### Removed

- **BREAKING:** Retrieve incoming transactions using Accounts API ([#4927](https://github.com/MetaMask/core/pull/4927))
- Remove `ETHERSCAN_SUPPORTED_NETWORKS` constant.
- Remove types:
- `EtherscanTransactionMeta`
- `RemoteTransactionSource`
- `RemoteTransactionSourceRequest`

## [41.0.0]

### Added
Expand Down
8 changes: 4 additions & 4 deletions packages/transaction-controller/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ module.exports = merge(baseConfig, {
// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
branches: 93.23,
functions: 97.61,
lines: 98.26,
statements: 98.28,
branches: 91.76,
functions: 94.76,
lines: 96.83,
statements: 96.82,
},
},

Expand Down
130 changes: 50 additions & 80 deletions packages/transaction-controller/src/TransactionController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -657,11 +657,6 @@ describe('TransactionController', () => {
(controller as any).update(() => state);
}

multichainTrackingHelperClassMock.mock.calls[0][0].createIncomingTransactionHelper(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{} as any,
);

multichainTrackingHelperClassMock.mock.calls[0][0].createPendingTransactionTracker(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{} as any,
Expand Down Expand Up @@ -777,6 +772,8 @@ describe('TransactionController', () => {
}

beforeEach(() => {
jest.resetAllMocks();

jest.spyOn(Date, 'now').mockImplementation(() => {
timeCounter += 1;
return timeCounter;
Expand Down Expand Up @@ -2613,21 +2610,6 @@ describe('TransactionController', () => {
expect(controller.state.transactions).toHaveLength(1);
expect(controller.state.transactions[0].id).toBe('4');
});
});

describe('handleMethodData', () => {
it('invokes helper', async () => {
const { controller } = setupController();

methodDataHelperMock.lookup.mockResolvedValueOnce(METHOD_DATA_MOCK);

const result = await controller.handleMethodData(
'mockMethodData',
NETWORK_CLIENT_ID_MOCK,
);

expect(result).toStrictEqual(METHOD_DATA_MOCK);
});

it('updates state when helper emits update event', async () => {
const { controller } = setupController();
Expand Down Expand Up @@ -4106,41 +4088,13 @@ describe('TransactionController', () => {

// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await (incomingTransactionHelperMock.hub.on as any).mock.calls[0][1]({
added: [TRANSACTION_META_MOCK, TRANSACTION_META_2_MOCK],
updated: [],
});

expect(controller.state.transactions).toStrictEqual([
{ ...TRANSACTION_META_MOCK, networkClientId: NETWORK_CLIENT_ID_MOCK },
{ ...TRANSACTION_META_2_MOCK, networkClientId: NETWORK_CLIENT_ID_MOCK },
await (incomingTransactionHelperMock.hub.on as any).mock.calls[0][1]([
TRANSACTION_META_MOCK,
TRANSACTION_META_2_MOCK,
]);
});

it('updates existing transactions in state', async () => {
const { controller } = setupController({
options: {
state: {
transactions: [TRANSACTION_META_MOCK, TRANSACTION_META_2_MOCK],
},
},
});

const updatedTransaction = {
...TRANSACTION_META_MOCK,
networkClientId: NETWORK_CLIENT_ID_MOCK,
status: 'failed',
};

// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await (incomingTransactionHelperMock.hub.on as any).mock.calls[0][1]({
added: [],
updated: [updatedTransaction],
});

expect(controller.state.transactions).toStrictEqual([
updatedTransaction,
{ ...TRANSACTION_META_MOCK, networkClientId: NETWORK_CLIENT_ID_MOCK },
{ ...TRANSACTION_META_2_MOCK, networkClientId: NETWORK_CLIENT_ID_MOCK },
]);
});
Expand All @@ -4152,58 +4106,74 @@ describe('TransactionController', () => {

// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await (incomingTransactionHelperMock.hub.on as any).mock.calls[0][1]({
added: [TRANSACTION_META_MOCK, TRANSACTION_META_2_MOCK],
updated: [],
});
await (incomingTransactionHelperMock.hub.on as any).mock.calls[0][1]([
TRANSACTION_META_MOCK,
TRANSACTION_META_2_MOCK,
]);

expect(controller.state.transactions).toStrictEqual([
{ ...TRANSACTION_META_2_MOCK, networkClientId: NETWORK_CLIENT_ID_MOCK },
]);
});
});

describe('on incoming transaction helper lastFetchedBlockNumbers event', () => {
it('updates state', async () => {
const { controller } = setupController();
it('publishes TransactionController:incomingTransactionsReceived', async () => {
const listener = jest.fn();

const lastFetchedBlockNumbers = {
key: 234,
};
const { messenger } = setupController();
messenger.subscribe(
'TransactionController:incomingTransactionsReceived',
listener,
);

// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await (incomingTransactionHelperMock.hub.on as any).mock.calls[1][1]({
lastFetchedBlockNumbers,
blockNumber: 123,
});
await (incomingTransactionHelperMock.hub.on as any).mock.calls[0][1]([
TRANSACTION_META_MOCK,
TRANSACTION_META_2_MOCK,
]);

expect(controller.state.lastFetchedBlockNumbers).toStrictEqual(
lastFetchedBlockNumbers,
);
expect(listener).toHaveBeenCalledTimes(1);
expect(listener).toHaveBeenCalledWith([
{ ...TRANSACTION_META_MOCK, networkClientId: NETWORK_CLIENT_ID_MOCK },
{ ...TRANSACTION_META_2_MOCK, networkClientId: NETWORK_CLIENT_ID_MOCK },
]);
});

it('publishes TransactionController:incomingTransactionBlockReceived', async () => {
const blockNumber = 123;
it('does not publish TransactionController:incomingTransactionsReceived if no new transactions', async () => {
const listener = jest.fn();

const { messenger } = setupController();

messenger.subscribe(
'TransactionController:incomingTransactionBlockReceived',
'TransactionController:incomingTransactionsReceived',
listener,
);

// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await (incomingTransactionHelperMock.hub.on as any).mock.calls[1][1]({
lastFetchedBlockNumbers: {
key: 234,
await (incomingTransactionHelperMock.hub.on as any).mock.calls[0][1]([]);

expect(listener).toHaveBeenCalledTimes(0);
});
});

describe('on incoming transaction helper updateCache call', () => {
it('updates state', async () => {
const { controller } = setupController();
const key = 'testKey';
const value = 123;

// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
incomingTransactionHelperClassMock.mock.calls[0][0].updateCache(
(cache) => {
cache[key] = value;
},
blockNumber,
});
);

expect(listener).toHaveBeenCalledTimes(1);
expect(listener).toHaveBeenCalledWith(blockNumber);
expect(controller.state.lastFetchedBlockNumbers).toStrictEqual({
[key]: value,
});
});
});

Expand Down
Loading
Loading