Skip to content

Commit 5f44cc5

Browse files
committed
feat: add welcome message
fix: fc resolver in some cases, better twitter detection using .x and .twitter domains
1 parent d2572f9 commit 5f44cc5

File tree

10 files changed

+448
-335
lines changed

10 files changed

+448
-335
lines changed

packages/snap/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
},
3131
"dependencies": {
3232
"@lens-protocol/client": "^2.2.0",
33-
"@metamask/snaps-sdk": "^4.4.1",
33+
"@metamask/snaps-sdk": "^6.1.1",
3434
"@noble/hashes": "^1.4.0",
3535
"buffer": "^6.0.3",
3636
"ethers": "^6.12.1"
@@ -42,8 +42,8 @@
4242
"@metamask/eslint-config-jest": "^12.1.0",
4343
"@metamask/eslint-config-nodejs": "^12.1.0",
4444
"@metamask/eslint-config-typescript": "^12.1.0",
45-
"@metamask/snaps-cli": "^6.1.0",
46-
"@metamask/snaps-jest": "^7.0.0",
45+
"@metamask/snaps-cli": "^6.2.1",
46+
"@metamask/snaps-jest": "^8.2.0",
4747
"@typescript-eslint/eslint-plugin": "^5.42.1",
4848
"@typescript-eslint/parser": "^5.42.1",
4949
"eslint": "^8.45.0",
@@ -69,4 +69,4 @@
6969
"access": "public",
7070
"registry": "https://registry.npmjs.org/"
7171
}
72-
}
72+
}

packages/snap/snap.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { resolve } from 'path';
33

44
const config: SnapConfig = {
55
bundler: 'webpack',
6-
input: resolve(__dirname, 'src/index.ts'),
6+
input: resolve(__dirname, 'src/index.tsx'),
77
server: {
88
port: 8080,
99
},

packages/snap/snap.manifest.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "https://github.com/idriss-crypto/snap/tree/main/packages/snap"
88
},
99
"source": {
10-
"shasum": "9a+ZgF4hWDGgYEAjyEbg0hxTU/COftFoCfH7X3APF3A=",
10+
"shasum": "jQRz6xTMZkvAIKyiDhlg+jfSsGovfrwf5Dzz6YZTcUA=",
1111
"location": {
1212
"npm": {
1313
"filePath": "dist/bundle.js",
@@ -19,7 +19,9 @@
1919
},
2020
"initialPermissions": {
2121
"endowment:name-lookup": {},
22-
"endowment:network-access": {}
22+
"endowment:network-access": {},
23+
"endowment:lifecycle-hooks": {},
24+
"snap_dialog": {}
2325
},
2426
"manifestVersion": "0.1"
2527
}

packages/snap/src/constants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export const IDRISS_REGISTRY_RESOLVER =
1010
export const REG_PH =
1111
/^(\+\(?\d{1,4}\s?)\)?-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}/u;
1212
export const REG_M = /^[\w.-]+@[\d.A-Za-z-]+\.[A-Za-z]{2,}/u;
13-
export const REG_T = /^@\S+/u;
1413

1514
export const WALLET_TAGS = [
1615
{

packages/snap/src/index.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import type { ChainId } from '@metamask/snaps-sdk';
33

44
import { onNameLookup } from '.';
55

6-
const TWITTER_MOCK = '@IDriss_xyz';
6+
const TWITTER_MOCK = 'IDriss_xyz.twitter';
77
const TWITTER_ADDRESS_MOCK = '0x5ABca791C22E7f99237fCC04639E094Ffa0cCce9';
88
const MAIL_MOCK = '[email protected]';
99
const MAIL_ADDRESS_MOCK = '0x11E9F9344A9720d2B2B5F0753225bb805161139B';
10-
const TWITTER_MOCK_INVALID = '@vitalikbuterin';
10+
const TWITTER_MOCK_INVALID = 'vitalikbuterin.x';
1111

1212
const UD_DOMAIN_MOCK = 'matt.crypto';
1313
const UD_DOMAIN_MOCK_WRONG = 'mat.crypto';
@@ -19,7 +19,7 @@ const ENS_DOMAIN_MOCK_CONTRACT = 'gitcoin.eth';
1919
const ENS_ADDRESS_MOCK = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045';
2020
const ENS_CHAIN_ID_MOCK = 'eip155:137' as ChainId;
2121

22-
const FARCASTER_DOMAIN_MOCK = 'dwr.farcaster';
22+
const FARCASTER_DOMAIN_MOCK = 'dwr.eth.farcaster';
2323
const FARCASTER_DOMAIN_MOCK_NO_ADDRESS = 'nonexistantaccount.farcaster';
2424
const FARCASTER_ADDRESS_MOCK = '0xd7029bdea1c17493893aafe29aad69ef892b8ff2';
2525

@@ -40,7 +40,7 @@ describe('onNameLookup', () => {
4040
resolvedAddresses: [
4141
{
4242
resolvedAddress: TWITTER_ADDRESS_MOCK,
43-
protocol: 'IDriss',
43+
protocol: 'X (Twitter)',
4444
domainName: TWITTER_MOCK,
4545
},
4646
],
@@ -57,7 +57,7 @@ describe('onNameLookup', () => {
5757
resolvedAddresses: [
5858
{
5959
resolvedAddress: MAIL_ADDRESS_MOCK,
60-
protocol: 'IDriss',
60+
protocol: 'Email',
6161
domainName: MAIL_MOCK,
6262
},
6363
],

packages/snap/src/index.ts renamed to packages/snap/src/index.tsx

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
* @returns The result of `snap_dialog`.
99
* @throws If the request method is not valid for this snap.
1010
*/
11-
import type { OnNameLookupHandler } from '@metamask/snaps-sdk';
11+
import type {
12+
OnNameLookupHandler,
13+
OnInstallHandler,
14+
} from '@metamask/snaps-sdk';
15+
import { Box, Heading, Row, Divider, Text } from '@metamask/snaps-sdk/jsx';
1216

13-
import { REG_PH, REG_M, REG_T, UNSTOPPABLE_TLDS } from './constants';
17+
import { REG_M, REG_PH, UNSTOPPABLE_TLDS } from './constants';
1418
import { resolveENS } from './resolvers/ens';
1519
import { resolveFarcasterName } from './resolvers/farcaster';
1620
import { resolveIDriss } from './resolvers/idriss';
@@ -25,7 +29,12 @@ export const onNameLookup: OnNameLookupHandler = async (request: {
2529

2630
let customResolverAddress: any;
2731
if (domain) {
28-
if (REG_PH.test(domain) || REG_M.test(domain) || REG_T.test(domain)) {
32+
if (
33+
REG_PH.test(domain) ||
34+
REG_M.test(domain) ||
35+
domain?.endsWith('.twitter') ||
36+
domain?.endsWith('.x')
37+
) {
2938
const resolvedIDriss = await resolveIDriss(domain);
3039
customResolverAddress = resolvedIDriss;
3140
} else if (domain?.endsWith('.lens')) {
@@ -51,3 +60,49 @@ export const onNameLookup: OnNameLookupHandler = async (request: {
5160
}
5261
return { resolvedAddresses: customResolverAddress };
5362
};
63+
64+
export const onInstall: OnInstallHandler = async () => {
65+
await snap.request({
66+
method: 'snap_dialog',
67+
params: {
68+
type: 'alert',
69+
content: (
70+
<Box>
71+
<Heading>Installation successful 🎉</Heading>
72+
<Text>
73+
MetaMask can now send to a number of social handles and domans.
74+
</Text>
75+
<Divider />
76+
<Row label="IDriss">
77+
<Text>username.x</Text>
78+
</Row>
79+
<Row label="">
80+
<Text>username.twitter</Text>
81+
</Row>
82+
<Divider />
83+
<Row label="Farcaster">
84+
<Text>username.fc</Text>
85+
</Row>
86+
<Row label="">
87+
<Text>username.farcaster</Text>
88+
</Row>
89+
<Divider />
90+
<Row label="Lens">
91+
<Text>username.lens</Text>
92+
</Row>
93+
<Divider />
94+
<Row label="Unstoppable Domains">
95+
<Text>Valid UDs</Text>
96+
</Row>
97+
<Divider />
98+
<Row label="ENS">
99+
<Text>
100+
Valid ENS, given it does not resolve to a contract address on
101+
Mainnet
102+
</Text>
103+
</Row>
104+
</Box>
105+
),
106+
},
107+
});
108+
};

packages/snap/src/resolvers/idriss.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export async function resolveIDriss(
3232
): Promise<
3333
{ resolvedAddress: string; protocol: string; domainName: string }[]
3434
> {
35-
const identifier = await transformIdentifier(userInput);
35+
const { identifier, type } = await transformIdentifier(userInput);
3636
const filteredWalletTags = filterWalletTags(resolveOptions);
3737

3838
const digestPromises = filteredWalletTags.map(
@@ -77,7 +77,7 @@ export async function resolveIDriss(
7777
return [
7878
{
7979
resolvedAddress: resolvedIDriss,
80-
protocol: 'IDriss',
80+
protocol: type,
8181
domainName: userInput,
8282
},
8383
];

packages/snap/src/utils.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { sha256 } from '@noble/hashes/sha256';
22
import { bytesToHex } from '@noble/hashes/utils';
33

4-
import { REG_PH, REG_M, REG_T, BASE_API_URL, WALLET_TAGS } from './constants';
4+
import { REG_PH, REG_M, BASE_API_URL, WALLET_TAGS } from './constants';
55
import type { ResolveOptions } from './types';
66

77
const toTitleCase = (input: string) => {
@@ -10,13 +10,13 @@ const toTitleCase = (input: string) => {
1010

1111
const matchInput = (input: string) => {
1212
if (REG_PH.test(input)) {
13-
return 'phone';
13+
return 'Phone';
1414
}
1515
if (REG_M.test(input)) {
16-
return 'mail';
16+
return 'Email';
1717
}
18-
if (REG_T.test(input)) {
19-
return 'twitter';
18+
if (input.endsWith('.x') || input.endsWith('.twitter')) {
19+
return 'X (Twitter)';
2020
}
2121
return null;
2222
};
@@ -40,6 +40,7 @@ const getTwitterID = async (inputCombination: string): Promise<string> => {
4040
);
4141
}
4242
const json = await response.json();
43+
4344
return json.id;
4445
};
4546

@@ -53,19 +54,20 @@ export const transformIdentifier = async (input: string) => {
5354
);
5455
}
5556

56-
if (inputType === 'phone') {
57-
return convertPhone(identifier);
57+
if (inputType === 'Phone') {
58+
return { identifier: convertPhone(identifier), type: inputType };
5859
}
5960

60-
if (inputType === 'twitter') {
61-
const maybeTwitterIdentifier = await getTwitterID(identifier);
61+
if (inputType === 'X (Twitter)') {
62+
const cleanTwitter = identifier.replace('.x', '').replace('.twitter', '');
63+
const maybeTwitterIdentifier = await getTwitterID(cleanTwitter);
6264
if (maybeTwitterIdentifier === 'Not found') {
6365
throw new Error('Twitter handle not found.');
6466
}
65-
return maybeTwitterIdentifier;
67+
return { identifier: maybeTwitterIdentifier, type: inputType };
6668
}
6769

68-
return input;
70+
return { identifier: input, type: inputType };
6971
};
7072

7173
export const filterWalletTags = ({

packages/snap/tsconfig.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
{
22
"extends": "../../tsconfig.json",
33
"compilerOptions": {
4-
"baseUrl": "./"
4+
"jsx": "react-jsx",
5+
"baseUrl": "./",
6+
"jsxImportSource": "@metamask/snaps-sdk"
57
},
6-
"include": ["**/*.ts"]
8+
"include": ["**/*.ts", "src/index.tsx"]
79
}

0 commit comments

Comments
 (0)