Skip to content

Commit

Permalink
Add onNameLookup to snaps-jest
Browse files Browse the repository at this point in the history
  • Loading branch information
david0xd committed Oct 23, 2024
1 parent ec811b7 commit 1432970
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 7 deletions.
21 changes: 14 additions & 7 deletions packages/examples/packages/name-lookup/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { describe, it } from '@jest/globals';
import { describe, expect, it } from '@jest/globals';
import { installSnap } from '@metamask/snaps-jest';
import type { ChainId } from '@metamask/snaps-sdk';

import { onNameLookup } from '.';

const DOMAIN_MOCK = 'test.domain';
const ADDRESS_MOCK = '0xc0ffee254729296a45a3885639AC7E10F9d54979';
const CHAIN_ID_MOCK = 'eip155:1' as ChainId;
Expand All @@ -14,7 +13,10 @@ describe('onNameLookup', () => {
chainId: CHAIN_ID_MOCK,
};

expect(await onNameLookup(request)).toStrictEqual({
const { onNameLookup } = await installSnap();
const response = await onNameLookup(request);

expect(response).toRespondWith({
resolvedAddresses: [
{
resolvedAddress: '0xc0ffee254729296a45a3885639AC7E10F9d54979',
Expand All @@ -31,7 +33,9 @@ describe('onNameLookup', () => {
chainId: CHAIN_ID_MOCK,
};

expect(await onNameLookup(request)).toStrictEqual({
const { onNameLookup } = await installSnap();

expect(await onNameLookup(request)).toRespondWith({
resolvedDomains: [
{ resolvedDomain: 'c0f.1.test.domain', protocol: 'test protocol' },
],
Expand All @@ -45,7 +49,9 @@ describe('onNameLookup', () => {
chainId: CHAIN_ID_MOCK,
} as any;

expect(await onNameLookup(request)).toStrictEqual({
const { onNameLookup } = await installSnap();

expect(await onNameLookup(request)).toRespondWith({
resolvedDomains: [
{ resolvedDomain: 'c0f.1.test.domain', protocol: 'test protocol' },
],
Expand All @@ -57,7 +63,8 @@ describe('onNameLookup', () => {
chainId: CHAIN_ID_MOCK,
};

// @ts-expect-error - Testing invalid request.
const { onNameLookup } = await installSnap();

expect(await onNameLookup(request)).toBeNull();
});
});
43 changes: 43 additions & 0 deletions packages/snaps-jest/src/helpers.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,49 @@ describe('installSnap', () => {
});
});

describe('onNameLookup', () => {
it('sends a name lookup request and returns the result', async () => {
jest.spyOn(console, 'log').mockImplementation();
const MOCK_DOMAIN = 'test.domain';

const { snapId, close: closeServer } = await getMockServer({
sourceCode: `
module.exports.onNameLookup = async (request) => {
return {
resolvedAddress: '0xc0ffee254729296a45a3885639AC7E10F9d54979',
protocol: 'test protocol',
domainName: request.domain,
};
};
`,
});

const { onNameLookup, close } = await installSnap(snapId);
const response = await onNameLookup({
chainId: 'eip155:1',
domain: MOCK_DOMAIN,
});

expect(response).toStrictEqual(
expect.objectContaining({
response: {
result: {
resolvedAddress: '0xc0ffee254729296a45a3885639AC7E10F9d54979',
protocol: 'test protocol',
domainName: MOCK_DOMAIN,
},
},
}),
);

// `close` is deprecated because the Jest environment will automatically
// close the Snap when the test finishes. However, we still need to close
// the Snap in this test because it's run outside the Jest environment.
await close();
await closeServer();
});
});

describe('runCronjob', () => {
it('runs a cronjob and returns the result', async () => {
jest.spyOn(console, 'log').mockImplementation();
Expand Down
2 changes: 2 additions & 0 deletions packages/snaps-jest/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export async function installSnap<
onKeyringRequest,
onInstall,
onUpdate,
onNameLookup,
mockJsonRpc,
close,
} = await getEnvironment().installSnap(...resolvedOptions);
Expand All @@ -196,6 +197,7 @@ export async function installSnap<
onKeyringRequest,
onInstall,
onUpdate,
onNameLookup,
mockJsonRpc,
close: async () => {
log('Closing execution service.');
Expand Down
43 changes: 43 additions & 0 deletions packages/snaps-simulation/src/helpers.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,49 @@ describe('helpers', () => {
});
});

describe('onNameLookup', () => {
it('sends a name lookup request and returns the result', async () => {
jest.spyOn(console, 'log').mockImplementation();
const MOCK_DOMAIN = 'test.domain';

const { snapId, close: closeServer } = await getMockServer({
sourceCode: `
module.exports.onNameLookup = async (request) => {
return {
resolvedAddress: '0xc0ffee254729296a45a3885639AC7E10F9d54979',
protocol: 'test protocol',
domainName: request.domain,
};
};
`,
});

const { onNameLookup, close } = await installSnap(snapId);
const response = await onNameLookup({
chainId: 'eip155:1',
domain: MOCK_DOMAIN,
});

expect(response).toStrictEqual(
expect.objectContaining({
response: {
result: {
resolvedAddress: '0xc0ffee254729296a45a3885639AC7E10F9d54979',
protocol: 'test protocol',
domainName: MOCK_DOMAIN,
},
},
}),
);

// `close` is deprecated because the Jest environment will automatically
// close the Snap when the test finishes. However, we still need to close
// the Snap in this test because it's run outside the Jest environment.
await close();
await closeServer();
});
});

describe('runCronjob', () => {
it('runs a cronjob and returns the result', async () => {
jest.spyOn(console, 'log').mockImplementation();
Expand Down
39 changes: 39 additions & 0 deletions packages/snaps-simulation/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import { addJsonRpcMock, removeJsonRpcMock } from './store';
import {
assertIsResponseWithInterface,
JsonRpcMockOptionsStruct,
NameLookupOptionsStruct,
SignatureOptionsStruct,
TransactionOptionsStruct,
} from './structs';
import type {
CronjobOptions,
JsonRpcMockOptions,
KeyringOptions,
NameLookupOptions,
RequestOptions,
SignatureOptions,
SnapRequest,
Expand Down Expand Up @@ -140,6 +142,15 @@ export type SnapHelpers = {
*/
onUpdate(request?: Pick<RequestOptions, 'origin'>): SnapRequest;

/**
* Get the response from the Snap's `onNameLookup` handler.
*
* @returns The response.
*/
onNameLookup(
request: NameLookupOptions,
): Promise<SnapResponseWithoutInterface>;

/**
* Mock a JSON-RPC request. This will cause the snap to respond with the
* specified response when a request with the specified method is sent.
Expand Down Expand Up @@ -314,6 +325,34 @@ export function getHelpers({
});
},

onNameLookup: async (
nameLookupOptions: NameLookupOptions,
): Promise<SnapResponseWithoutInterface> => {
log('Requesting name lookup %o.', nameLookupOptions);

const { ...requestParams } = create(
nameLookupOptions,
NameLookupOptionsStruct,
);

const response = await handleRequest({
snapId,
store,
executionService,
controllerMessenger,
runSaga,
handler: HandlerType.OnNameLookup,
request: {
method: '',
params: {
...requestParams,
},
},
});

return response;
},

onSignature: async (
request: unknown,
): Promise<SnapResponseWithInterface> => {
Expand Down
17 changes: 17 additions & 0 deletions packages/snaps-simulation/src/structs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,23 @@ export const SignatureOptionsStruct = object({
),
});

export const NameLookupOptionsStruct = object({
/**
* The CAIP-2 chain ID. Defaults to `eip155:1`.
*/
chainId: defaulted(string(), 'eip155:1'),

/**
* Domain name to lookup.
*/
domain: optional(string()),

/**
* Address to lookup.
*/
address: optional(string()),
});

export const SnapOptionsStruct = object({
/**
* The timeout in milliseconds to use for requests to the snap. Defaults to
Expand Down
20 changes: 20 additions & 0 deletions packages/snaps-simulation/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Infer } from '@metamask/superstruct';
import type { Json, JsonRpcId, JsonRpcParams } from '@metamask/utils';

import type {
NameLookupOptionsStruct,
SignatureOptionsStruct,
SnapOptionsStruct,
SnapResponseStruct,
Expand Down Expand Up @@ -67,6 +68,16 @@ export type TransactionOptions = Infer<typeof TransactionOptionsStruct>;
*/
export type KeyringOptions = RequestOptions;

/**
* The options to use for name lookup requests.
*
* @property origin - The origin of the name lookup request (optional).`.
* @property chainId - Chain ID.
* @property domain - Domain name to lookup and resolve.
* @property address - Address to lookup and resolve.
*/
export type NameLookupOptions = Infer<typeof NameLookupOptionsStruct>;

/**
* The options to use for signature requests.
*
Expand Down Expand Up @@ -434,6 +445,15 @@ export type Snap = {
*/
onUpdate(request?: Pick<RequestOptions, 'origin'>): SnapRequest;

/**
* Get the response from the Snap's `onNameLookup` handler.
*
* @returns The response.
*/
onNameLookup(
nameLookupRequest: NameLookupOptions,
): Promise<SnapResponseWithoutInterface>;

/**
* Mock a JSON-RPC request. This will cause the snap to respond with the
* specified response when a request with the specified method is sent.
Expand Down

0 comments on commit 1432970

Please sign in to comment.