Skip to content

Commit

Permalink
chore: add bridge SELECT_DEST_NETWORK action
Browse files Browse the repository at this point in the history
  • Loading branch information
micaelae committed Aug 6, 2024
1 parent b4fc0da commit 3b3bd5b
Show file tree
Hide file tree
Showing 19 changed files with 293 additions and 28 deletions.
32 changes: 32 additions & 0 deletions app/scripts/controllers/bridge/bridge-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ describe('BridgeController', function () {
'src-network-allowlist': [10, 534352],
'dest-network-allowlist': [137, 42161],
});
nock(BRIDGE_API_BASE_URL)
.get('/getTokens?chainId=10')
.reply(200, [
{
address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
symbol: 'ABC',
decimals: 16,
},
{
address: '0x1291478912',
symbol: 'DEF',
decimals: 16,
},
]);
});

it('constructor should setup correctly', function () {
Expand All @@ -51,4 +65,22 @@ describe('BridgeController', function () {
expectedFeatureFlagsResponse,
);
});

it('selectDestNetwork should set the bridge dest tokens', async function () {
await bridgeController.selectDestNetwork('0xa');
expect(bridgeController.state.bridgeState.destTokens).toStrictEqual({
'0x0000000000000000000000000000000000000000': {
address: '0x0000000000000000000000000000000000000000',
decimals: 18,
iconUrl: './images/eth_logo.svg',
name: 'Ether',
symbol: 'ETH',
},
'0x1f9840a85d5af5bf1d1762f925bdaddc4201f984': {
address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
symbol: 'ABC',
decimals: 16,
},
});
});
});
22 changes: 21 additions & 1 deletion app/scripts/controllers/bridge/bridge-controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { BaseController, StateMetadata } from '@metamask/base-controller';
import { fetchBridgeFeatureFlags } from '../../../../ui/pages/bridge/bridge.util';
import { Hex } from '@metamask/utils';
import {
fetchBridgeFeatureFlags,
fetchBridgeTokens,
} from '../../../../ui/pages/bridge/bridge.util';
import {
BRIDGE_CONTROLLER_NAME,
DEFAULT_BRIDGE_CONTROLLER_STATE,
Expand Down Expand Up @@ -30,6 +34,10 @@ export default class BridgeController extends BaseController<
`${BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`,
this.setBridgeFeatureFlags.bind(this),
);
this.messagingSystem.registerActionHandler(
`${BRIDGE_CONTROLLER_NAME}:selectDestNetwork`,
this.selectDestNetwork.bind(this),
);
}

resetState = () => {
Expand All @@ -47,4 +55,16 @@ export default class BridgeController extends BaseController<
_state.bridgeState = { ...bridgeState, bridgeFeatureFlags };
});
};

selectDestNetwork = async (chainId: Hex) => {
await this.#setTokens(chainId, 'destTokens');
};

#setTokens = async (chainId: Hex, stateKey: 'srcTokens' | 'destTokens') => {
const { bridgeState } = this.state;
const tokens = await fetchBridgeTokens(chainId);
this.update((_state) => {
_state.bridgeState = { ...bridgeState, [stateKey]: tokens };
});
};
}
1 change: 1 addition & 0 deletions app/scripts/controllers/bridge/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export const DEFAULT_BRIDGE_CONTROLLER_STATE: BridgeControllerState = {
[BridgeFeatureFlagsKey.NETWORK_SRC_ALLOWLIST]: [],
[BridgeFeatureFlagsKey.NETWORK_DEST_ALLOWLIST]: [],
},
destTokens: {},
};
8 changes: 7 additions & 1 deletion app/scripts/controllers/bridge/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
RestrictedControllerMessenger,
} from '@metamask/base-controller';
import { Hex } from '@metamask/utils';
import { SwapsTokenObject } from '../../../../shared/constants/swaps';
import BridgeController from './bridge-controller';
import { BRIDGE_CONTROLLER_NAME } from './constants';

Expand All @@ -20,8 +21,12 @@ export type BridgeFeatureFlags = {

export type BridgeControllerState = {
bridgeFeatureFlags: BridgeFeatureFlags;
destTokens: Record<string, SwapsTokenObject>;
};

export enum BridgeUserAction {
SELECT_DEST_NETWORK = 'selectDestNetwork',
}
export enum BridgeBackgroundAction {
SET_FEATURE_FLAGS = 'setBridgeFeatureFlags',
}
Expand All @@ -33,7 +38,8 @@ type BridgeControllerAction<FunctionName extends keyof BridgeController> = {

// Maps to BridgeController function names
type BridgeControllerActions =
BridgeControllerAction<BridgeBackgroundAction.SET_FEATURE_FLAGS>;
| BridgeControllerAction<BridgeBackgroundAction.SET_FEATURE_FLAGS>
| BridgeControllerAction<BridgeUserAction.SELECT_DEST_NETWORK>;

type BridgeControllerEvents = ControllerStateChangeEvent<
typeof BRIDGE_CONTROLLER_NAME,
Expand Down
1 change: 1 addition & 0 deletions app/scripts/lib/setupSentry.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export const SENTRY_BACKGROUND_STATE = {
destNetworkAllowlist: [],
srcNetworkAllowlist: [],
},
destTokens: {},
},
},
CronjobController: {
Expand Down
10 changes: 9 additions & 1 deletion app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,10 @@ import { updateSecurityAlertResponse } from './lib/ppom/ppom-util';
import createEvmMethodsToNonEvmAccountReqFilterMiddleware from './lib/createEvmMethodsToNonEvmAccountReqFilterMiddleware';
import { isEthAddress } from './lib/multichain/address';
import { decodeTransactionData } from './lib/transaction/decode/util';
import { BridgeBackgroundAction } from './controllers/bridge/types';
import {
BridgeUserAction,
BridgeBackgroundAction,
} from './controllers/bridge/types';
import BridgeController from './controllers/bridge/bridge-controller';
import { BRIDGE_CONTROLLER_NAME } from './controllers/bridge/constants';

Expand Down Expand Up @@ -3682,6 +3685,11 @@ export default class MetamaskController extends EventEmitter {
this.controllerMessenger,
`${BRIDGE_CONTROLLER_NAME}:${BridgeBackgroundAction.SET_FEATURE_FLAGS}`,
),
[BridgeUserAction.SELECT_DEST_NETWORK]:
this.controllerMessenger.call.bind(
this.controllerMessenger,
`${BRIDGE_CONTROLLER_NAME}:${BridgeUserAction.SELECT_DEST_NETWORK}`,
),

// Smart Transactions
fetchSmartTransactionFees: smartTransactionsController.getFees.bind(
Expand Down
1 change: 1 addition & 0 deletions test/e2e/default-fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ function defaultFixture(inputChainId = CHAIN_IDS.LOCALHOST) {
srcNetworkAllowlist: ['0x1', '0xa', '0xe708'],
destNetworkAllowlist: ['0x1', '0xa', '0xe708'],
},
destTokens: {},
},
},
CurrencyController: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
"1": "string",
"2": "string"
}
}
},
"destTokens": {}
}
},
"CronjobController": { "jobs": "object" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@
"1": "string",
"2": "string"
}
}
},
"destTokens": {}
},
"ensEntries": "object",
"ensResolutionsByAddress": "object",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@
"1": "string",
"2": "string"
}
}
},
"destTokens": {}
}
},
"SubjectMetadataController": { "subjectMetadata": "object" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@
"1": "string",
"2": "string"
}
}
},
"destTokens": {}
}
},
"TransactionController": { "transactions": "object" },
Expand Down
2 changes: 2 additions & 0 deletions test/jest/mock-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ export const createBridgeMockStore = (
featureFlagOverrides = {},
bridgeSliceOverrides = {},
swapsSliceOverrides = {},
bridgeStateOverrides = {},
) => {
const swapsStore = createSwapsMockStore();
return {
Expand All @@ -694,6 +695,7 @@ export const createBridgeMockStore = (
destNetworkAllowlist: [],
...featureFlagOverrides,
},
...bridgeStateOverrides,
},
},
};
Expand Down
29 changes: 23 additions & 6 deletions ui/ducks/bridge/actions.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { BridgeBackgroundAction } from '../../../app/scripts/controllers/bridge/types';
import { ProviderConfig } from '@metamask/network-controller';
import { Hex } from '@metamask/utils';
import {
BridgeBackgroundAction,
BridgeUserAction,
} from '../../../app/scripts/controllers/bridge/types';
import { forceUpdateMetamaskState } from '../../store/actions';
import { submitRequestToBackground } from '../../store/background-connection';
import { MetaMaskReduxDispatch } from '../../store/store';
import { swapsSlice } from '../swaps/swaps';
import { RPCDefinition } from '../../../shared/constants/network';
import { MetaMaskReduxDispatch } from '../../store/store';
import { bridgeSlice } from './bridge';

// Proxied swaps actions
export const { setFromToken, setToToken, setFromTokenInputValue } =
swapsSlice.actions;

export const { setToChain } = bridgeSlice.actions;
const { setToChain: setToChain_ } = bridgeSlice.actions;

const callBridgeControllerMethod = <T>(
bridgeAction: BridgeBackgroundAction,
bridgeAction: BridgeUserAction | BridgeBackgroundAction,
args?: T[],
) => {
return async (dispatch: MetaMaskReduxDispatch) => {
Expand All @@ -21,8 +27,6 @@ const callBridgeControllerMethod = <T>(
};
};

// User actions

// Background actions
export const setBridgeFeatureFlags = () => {
return async (dispatch: MetaMaskReduxDispatch) => {
Expand All @@ -31,3 +35,16 @@ export const setBridgeFeatureFlags = () => {
);
};
};

// User actions
export const setToChain = (network: ProviderConfig | RPCDefinition) => {
return async (dispatch: MetaMaskReduxDispatch) => {
const { chainId } = network;
dispatch(setToChain_(network));
dispatch(
callBridgeControllerMethod<Hex>(BridgeUserAction.SELECT_DEST_NETWORK, [
chainId,
]),
);
};
};
25 changes: 21 additions & 4 deletions ui/ducks/bridge/bridge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import thunk from 'redux-thunk';
import { createBridgeMockStore } from '../../../test/jest/mock-store';
import { CHAIN_IDS } from '../../../shared/constants/network';
import { setBackgroundConnection } from '../../store/background-connection';
import { BridgeBackgroundAction } from '../../../app/scripts/controllers/bridge/types';
import {
BridgeUserAction,
BridgeBackgroundAction,
} from '../../../app/scripts/controllers/bridge/types';
import bridgeReducer from './bridge';
import { setBridgeFeatureFlags, setToChain } from './actions';

Expand All @@ -14,14 +17,28 @@ describe('Ducks - Bridge', () => {
const store = configureMockStore<any>(middleware)(createBridgeMockStore());

describe('setToChain', () => {
it('calls the "bridge/setToChain" action', () => {
it('calls the "bridge/setToChain" action and the selectDestNetwork background action', () => {
const state = store.getState().bridge;
const actionPayload = CHAIN_IDS.BSC;
store.dispatch(setToChain(actionPayload));
const actionPayload = { chainId: CHAIN_IDS.OPTIMISM, id: '2313-314njk' };

const mockSelectDestNetwork = jest.fn().mockReturnValue({});
setBackgroundConnection({
[BridgeUserAction.SELECT_DEST_NETWORK]: mockSelectDestNetwork,
} as never);

store.dispatch(setToChain(actionPayload as never) as never);

// Check redux state
const actions = store.getActions();
expect(actions[0].type).toBe('bridge/setToChain');
const newState = bridgeReducer(state, actions[0]);
expect(newState.toChain).toBe(actionPayload);
// Check background state
expect(mockSelectDestNetwork).toHaveBeenCalledTimes(1);
expect(mockSelectDestNetwork).toHaveBeenCalledWith(
'0xa',
expect.anything(),
);
});
});

Expand Down
33 changes: 33 additions & 0 deletions ui/ducks/bridge/selectors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
getToChain,
getToChains,
getToToken,
getToTokens,
} from './selectors';

describe('Bridge selectors', () => {
Expand Down Expand Up @@ -376,4 +377,36 @@ describe('Bridge selectors', () => {
expect(result).toStrictEqual('0');
});
});

describe('getToTokens', () => {
it('returns dest tokens from controller state when toChain is defined', () => {
const state = createBridgeMockStore(
{},
{ toChain: { chainId: '0x1' } },
{},
{
destTokens: { '0x00': { address: '0x00', symbol: 'TEST' } },
},
);
const result = getToTokens(state as never);

expect(result).toStrictEqual({
'0x00': { address: '0x00', symbol: 'TEST' },
});
});

it('returns empty dest tokens from controller state when toChain is undefined', () => {
const state = createBridgeMockStore(
{},
{},
{},
{
destTokens: { '0x00': { address: '0x00', symbol: 'TEST' } },
},
);
const result = getToTokens(state as never);

expect(result).toStrictEqual({});
});
});
});
3 changes: 3 additions & 0 deletions ui/ducks/bridge/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ export const getFromToken = (state: BridgeAppState) => {
export const getToToken = (state: BridgeAppState) => {
return swapsSlice.getToToken(state);
};
export const getToTokens = (state: BridgeAppState) => {
return state.bridge.toChain ? state.metamask.bridgeState.destTokens : {};
};

export const getFromAmount = (state: BridgeAppState) =>
swapsSlice.getFromTokenInputValue(state);
Expand Down
Loading

0 comments on commit 3b3bd5b

Please sign in to comment.