Skip to content

Commit 61b8900

Browse files
committed
chore: closing connection logic, tests
1 parent 10f333c commit 61b8900

File tree

3 files changed

+397
-9
lines changed

3 files changed

+397
-9
lines changed

packages/gator-permissions-controller/src/GatorPermissionsController.test.ts

Lines changed: 265 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,32 @@ describe('GatorPermissionsController', () => {
279279
});
280280
});
281281

282+
it('fetches gator permissions with optional params', async () => {
283+
const mockHandleRequestHandler = jest
284+
.fn()
285+
.mockResolvedValue(MOCK_GATOR_PERMISSIONS_STORAGE_ENTRIES);
286+
const rootMessenger = getRootMessenger({
287+
snapControllerHandleRequestActionHandler: mockHandleRequestHandler,
288+
});
289+
290+
const controller = new GatorPermissionsController({
291+
messenger: getMessenger(rootMessenger),
292+
});
293+
294+
await controller.enableGatorPermissions();
295+
296+
const params = { origin: 'https://example.com', chainId: '0x1' };
297+
await controller.fetchAndUpdateGatorPermissions(params);
298+
299+
expect(mockHandleRequestHandler).toHaveBeenCalledWith(
300+
expect.objectContaining({
301+
request: expect.objectContaining({
302+
params,
303+
}),
304+
}),
305+
);
306+
});
307+
282308
it('handles error during fetch and update', async () => {
283309
const rootMessenger = getRootMessenger({
284310
snapControllerHandleRequestActionHandler: async () => {
@@ -774,6 +800,240 @@ describe('GatorPermissionsController', () => {
774800
);
775801
});
776802
});
803+
804+
describe('addPendingRevocation', () => {
805+
beforeEach(() => {
806+
jest.useFakeTimers();
807+
});
808+
809+
afterEach(() => {
810+
jest.useRealTimers();
811+
});
812+
813+
it('should submit revocation when transaction is confirmed', async () => {
814+
const mockHandleRequestHandler = jest.fn().mockResolvedValue(undefined);
815+
const rootMessenger = getRootMessenger({
816+
snapControllerHandleRequestActionHandler: mockHandleRequestHandler,
817+
});
818+
const messenger = getMessenger(rootMessenger);
819+
820+
const controller = new GatorPermissionsController({
821+
messenger,
822+
state: {
823+
isGatorPermissionsEnabled: true,
824+
gatorPermissionsProviderSnapId:
825+
MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
826+
},
827+
});
828+
829+
const txId = 'test-tx-id';
830+
const permissionContext = '0x1234567890abcdef1234567890abcdef12345678';
831+
832+
await controller.addPendingRevocation(txId, permissionContext);
833+
834+
// Emit transaction confirmed event
835+
rootMessenger.publish('TransactionController:transactionConfirmed', {
836+
id: txId,
837+
});
838+
839+
// Wait for async operations
840+
await Promise.resolve();
841+
842+
expect(mockHandleRequestHandler).toHaveBeenCalledWith({
843+
snapId: MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
844+
origin: 'metamask',
845+
handler: 'onRpcRequest',
846+
request: {
847+
jsonrpc: '2.0',
848+
method: 'permissionsProvider_submitRevocation',
849+
params: { permissionContext },
850+
},
851+
});
852+
});
853+
854+
it('should cleanup without submitting revocation when transaction fails', async () => {
855+
const mockHandleRequestHandler = jest.fn().mockResolvedValue(undefined);
856+
const rootMessenger = getRootMessenger({
857+
snapControllerHandleRequestActionHandler: mockHandleRequestHandler,
858+
});
859+
const messenger = getMessenger(rootMessenger);
860+
861+
const controller = new GatorPermissionsController({
862+
messenger,
863+
state: {
864+
isGatorPermissionsEnabled: true,
865+
gatorPermissionsProviderSnapId:
866+
MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
867+
},
868+
});
869+
870+
const txId = 'test-tx-id';
871+
const permissionContext = '0x1234567890abcdef1234567890abcdef12345678';
872+
873+
await controller.addPendingRevocation(txId, permissionContext);
874+
875+
// Emit transaction failed event
876+
rootMessenger.publish('TransactionController:transactionFailed', {
877+
transactionMeta: { id: txId },
878+
error: 'Transaction failed',
879+
});
880+
881+
// Wait for async operations
882+
await Promise.resolve();
883+
884+
// Should not call submitRevocation
885+
expect(mockHandleRequestHandler).not.toHaveBeenCalled();
886+
});
887+
888+
it('should cleanup without submitting revocation when transaction is dropped', async () => {
889+
const mockHandleRequestHandler = jest.fn().mockResolvedValue(undefined);
890+
const rootMessenger = getRootMessenger({
891+
snapControllerHandleRequestActionHandler: mockHandleRequestHandler,
892+
});
893+
const messenger = getMessenger(rootMessenger);
894+
895+
const controller = new GatorPermissionsController({
896+
messenger,
897+
state: {
898+
isGatorPermissionsEnabled: true,
899+
gatorPermissionsProviderSnapId:
900+
MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
901+
},
902+
});
903+
904+
const txId = 'test-tx-id';
905+
const permissionContext = '0x1234567890abcdef1234567890abcdef12345678';
906+
907+
await controller.addPendingRevocation(txId, permissionContext);
908+
909+
// Emit transaction dropped event
910+
rootMessenger.publish('TransactionController:transactionDropped', {
911+
id: txId,
912+
});
913+
914+
// Wait for async operations
915+
await Promise.resolve();
916+
917+
// Should not call submitRevocation
918+
expect(mockHandleRequestHandler).not.toHaveBeenCalled();
919+
});
920+
921+
it('should cleanup without submitting revocation when timeout is reached', async () => {
922+
const mockHandleRequestHandler = jest.fn().mockResolvedValue(undefined);
923+
const rootMessenger = getRootMessenger({
924+
snapControllerHandleRequestActionHandler: mockHandleRequestHandler,
925+
});
926+
const messenger = getMessenger(rootMessenger);
927+
928+
const controller = new GatorPermissionsController({
929+
messenger,
930+
state: {
931+
isGatorPermissionsEnabled: true,
932+
gatorPermissionsProviderSnapId:
933+
MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
934+
},
935+
});
936+
937+
const txId = 'test-tx-id';
938+
const permissionContext = '0x1234567890abcdef1234567890abcdef12345678';
939+
940+
await controller.addPendingRevocation(txId, permissionContext);
941+
942+
// Fast-forward time by 2 hours
943+
jest.advanceTimersByTime(2 * 60 * 60 * 1000);
944+
945+
// Wait for async operations
946+
await Promise.resolve();
947+
948+
// Should not call submitRevocation
949+
expect(mockHandleRequestHandler).not.toHaveBeenCalled();
950+
});
951+
952+
it('should not submit revocation for different transaction IDs', async () => {
953+
const mockHandleRequestHandler = jest.fn().mockResolvedValue(undefined);
954+
const rootMessenger = getRootMessenger({
955+
snapControllerHandleRequestActionHandler: mockHandleRequestHandler,
956+
});
957+
const messenger = getMessenger(rootMessenger);
958+
959+
const controller = new GatorPermissionsController({
960+
messenger,
961+
state: {
962+
isGatorPermissionsEnabled: true,
963+
gatorPermissionsProviderSnapId:
964+
MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
965+
},
966+
});
967+
968+
const txId = 'test-tx-id';
969+
const permissionContext = '0x1234567890abcdef1234567890abcdef12345678';
970+
971+
await controller.addPendingRevocation(txId, permissionContext);
972+
973+
// Emit transaction confirmed event for different transaction
974+
rootMessenger.publish('TransactionController:transactionConfirmed', {
975+
id: 'different-tx-id',
976+
});
977+
978+
// Wait for async operations
979+
await Promise.resolve();
980+
981+
// Should not call submitRevocation for different transaction
982+
expect(mockHandleRequestHandler).not.toHaveBeenCalled();
983+
});
984+
985+
it('should handle revocation submission errors gracefully', async () => {
986+
const mockHandleRequestHandler = jest
987+
.fn()
988+
.mockRejectedValue(new Error('Revocation submission failed'));
989+
const rootMessenger = getRootMessenger({
990+
snapControllerHandleRequestActionHandler: mockHandleRequestHandler,
991+
});
992+
const messenger = getMessenger(rootMessenger);
993+
994+
const controller = new GatorPermissionsController({
995+
messenger,
996+
state: {
997+
isGatorPermissionsEnabled: true,
998+
gatorPermissionsProviderSnapId:
999+
MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
1000+
},
1001+
});
1002+
1003+
const txId = 'test-tx-id';
1004+
const permissionContext = '0x1234567890abcdef1234567890abcdef12345678';
1005+
1006+
await controller.addPendingRevocation(txId, permissionContext);
1007+
1008+
// Emit transaction confirmed event
1009+
rootMessenger.publish('TransactionController:transactionConfirmed', {
1010+
id: txId,
1011+
});
1012+
1013+
// Wait for async operations
1014+
await Promise.resolve();
1015+
1016+
// Should have attempted to call submitRevocation even though it failed
1017+
expect(mockHandleRequestHandler).toHaveBeenCalled();
1018+
});
1019+
1020+
it('should throw GatorPermissionsNotEnabledError when gator permissions are disabled', async () => {
1021+
const messenger = getMessenger();
1022+
const controller = new GatorPermissionsController({
1023+
messenger,
1024+
state: {
1025+
isGatorPermissionsEnabled: false,
1026+
},
1027+
});
1028+
1029+
const txId = 'test-tx-id';
1030+
const permissionContext = '0x1234567890abcdef1234567890abcdef12345678';
1031+
1032+
await expect(
1033+
controller.addPendingRevocation(txId, permissionContext),
1034+
).rejects.toThrow('Gator permissions are not enabled');
1035+
});
1036+
});
7771037
});
7781038

7791039
/**
@@ -838,6 +1098,10 @@ function getMessenger(
8381098
return rootMessenger.getRestricted({
8391099
name: 'GatorPermissionsController',
8401100
allowedActions: ['SnapController:handleRequest', 'SnapController:has'],
841-
allowedEvents: [],
1101+
allowedEvents: [
1102+
'TransactionController:transactionConfirmed',
1103+
'TransactionController:transactionFailed',
1104+
'TransactionController:transactionDropped',
1105+
],
8421106
});
8431107
}

0 commit comments

Comments
 (0)