Skip to content

Commit 7f182fc

Browse files
phishing 0.19.1
1 parent 7312156 commit 7f182fc

File tree

6 files changed

+123
-83
lines changed

6 files changed

+123
-83
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## master
44

5+
- phishing 0.19.1
56
- api, api-{augment, base, contract, derive}, rpc-{augment, core, provider}, types, types-{augment, codec, create, known} 9.13.1
67
- hw-{ledger, ledger-transports}, keyring, networks, util, util-crypto, x-{bigint, fetch, global, randomvalues, textdecoder, textencoder, ws} 10.3.1
78

phishing/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
To check for sites that are on the list -
44

55
```js
6-
import { checkIfDenied } from 'https://deno.land/x/polkadot@0.2.23/phishing/mod.ts';
6+
import { checkIfDenied } from 'https://deno.land/x/polkadot/phishing/mod.ts';
77

88
const isOnDeny = await checkIfDenied(window.location.host);
99

@@ -13,7 +13,7 @@ console.log(`isOnDeny=${isOnDeny}`);
1313
To check for addresses that are on the list -
1414

1515
```js
16-
import { checkAddress } from 'https://deno.land/x/polkadot@0.2.23/phishing/mod.ts';
16+
import { checkAddress } from 'https://deno.land/x/polkadot/phishing/mod.ts';
1717

1818
const info = await checkAddress('1b....');
1919

phishing/bundle.ts

Lines changed: 117 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -3,105 +3,145 @@
33

44
import type { AddressList, HostList } from './types.ts';
55

6-
import { u8aEq } from 'https://deno.land/x/polkadot@0.2.23/util/mod.ts';
7-
import { decodeAddress } from 'https://deno.land/x/polkadot@0.2.23/util-crypto/mod.ts';
6+
import { u8aEq } from 'https://deno.land/x/polkadot/util/mod.ts';
7+
import { decodeAddress } from 'https://deno.land/x/polkadot/util-crypto/mod.ts';
88

99
import { fetchJson } from './fetch.ts';
1010

1111
export { packageInfo } from './packageInfo.ts';
1212

13+
interface Cache<T> {
14+
end: number;
15+
list: T;
16+
}
17+
18+
interface CacheAddrList extends Cache<AddressList> {
19+
u8a: [string, Uint8Array[]][];
20+
}
21+
22+
interface CacheHostList extends Cache<HostList> {
23+
parts: string[][];
24+
}
25+
1326
// Equivalent to https://raw.githubusercontent.com/polkadot-js/phishing/master/{address,all}.json
14-
const ADDRESS_JSON = 'https://polkadot.js.org/phishing/address.json';
15-
const ALL_JSON = 'https://polkadot.js.org/phishing/all.json';
27+
const PHISHING = 'https://polkadot.js.org/phishing';
28+
const ADDRESS_JSON = `${PHISHING}/address.json`;
1629
// 45 minutes cache refresh
1730
const CACHE_TIMEOUT = 45 * 60 * 1000;
1831

19-
let cacheAddrEnd = 0;
20-
let cacheAddrList: AddressList | null = null;
21-
let cacheAddrU8a: [string, Uint8Array[]][] | null = null;
22-
let cacheHostEnd = 0;
23-
let cacheHostList: HostList | null = null;
24-
25-
// gets the host-only part for a host
26-
function extractHost (path: string): string {
27-
return path
28-
.replace(/https:\/\/|http:\/\/|wss:\/\/|ws:\/\//, '')
29-
.split('/')[0];
32+
const cacheAddr: CacheAddrList = {
33+
end: 0,
34+
list: {},
35+
u8a: []
36+
};
37+
const cacheHost: Record<string, CacheHostList> = {};
38+
39+
function splitHostParts (host: string): string[] {
40+
return host
41+
// split domain
42+
.split('.')
43+
// reverse order
44+
.reverse();
3045
}
3146

32-
// logs an error in a consistent format
33-
function log (error: unknown, check: string): void {
34-
console.warn(`Error checking ${check}, assuming non-phishing`, (error as Error).message);
47+
function extractHostParts (host: string): string[] {
48+
return splitHostParts(
49+
host
50+
// remove protocol
51+
.replace(/https:\/\/|http:\/\/|wss:\/\/|ws:\/\//, '')
52+
// get the domain-only part
53+
.split('/')[0]
54+
);
3555
}
3656

37-
/**
38-
* Retrieve a list of known phishing addresses
39-
*/
40-
export async function retrieveAddrList (allowCached = true): Promise<AddressList> {
57+
async function retrieveAddrCache (allowCached = true): Promise<CacheAddrList> {
4158
const now = Date.now();
4259

43-
return (allowCached && cacheAddrList && (now < cacheAddrEnd))
44-
? cacheAddrList
45-
: fetchJson<AddressList>(ADDRESS_JSON).then((list) => {
46-
cacheAddrEnd = now + CACHE_TIMEOUT;
47-
cacheAddrList = list;
60+
if (allowCached && (now < cacheAddr.end)) {
61+
return cacheAddr;
62+
}
63+
64+
const list = await fetchJson<AddressList>(ADDRESS_JSON);
65+
66+
cacheAddr.end = now + CACHE_TIMEOUT;
67+
cacheAddr.list = list;
68+
cacheAddr.u8a = Object.entries(list).map(([key, addresses]): [string, Uint8Array[]] =>
69+
[key, addresses.map((a) => decodeAddress(a))]
70+
);
71+
72+
return cacheAddr;
73+
}
74+
75+
async function retrieveHostCache (allowCached = true, root = '*'): Promise<CacheHostList> {
76+
const now = Date.now();
77+
78+
if (allowCached && cacheHost[root] && (now < cacheHost[root].end)) {
79+
return cacheHost[root];
80+
}
81+
82+
let list: HostList;
83+
84+
try {
85+
list = root === '*'
86+
? await fetchJson<HostList>(`${PHISHING}/all.json`)
87+
: {
88+
allow: [],
89+
deny: await fetchJson<string[]>(`${PHISHING}/all/${root}/all.json`)
90+
};
91+
} catch {
92+
list = { allow: [], deny: [] };
93+
}
94+
95+
cacheHost[root] = {
96+
end: now + CACHE_TIMEOUT,
97+
list,
98+
parts: list.deny.map((h) => splitHostParts(h))
99+
};
48100

49-
return list;
50-
});
101+
return cacheHost[root];
102+
}
103+
104+
function checkHostParts (items: CacheHostList['parts'], hostParts: string[]): boolean {
105+
return items.some((parts) =>
106+
// out list entry needs to have the same (or less) parts
107+
(parts.length <= hostParts.length) &&
108+
// ensure each section matches
109+
parts.every((part, index) => hostParts[index] === part)
110+
);
51111
}
52112

53113
/**
54-
* Retrieve a list of known phishing addresses in raw Uint8Array format
114+
* Retrieve a list of known phishing addresses
115+
*
116+
* @deprecated While not due for removal, it is suggested to rather use the
117+
* checkAddress function (which is more optimal overall)
55118
*/
56-
async function retrieveAddrU8a (allowCached = true): Promise<[string, Uint8Array[]][]> {
57-
const now = Date.now();
119+
export async function retrieveAddrList (allowCached = true): Promise<AddressList> {
120+
const cache = await retrieveAddrCache(allowCached);
58121

59-
return (allowCached && cacheAddrU8a && (now < cacheAddrEnd))
60-
? cacheAddrU8a
61-
: retrieveAddrList(allowCached).then((all) => {
62-
cacheAddrU8a = Object
63-
.entries(all)
64-
.map(([key, addresses]): [string, Uint8Array[]] =>
65-
[key, addresses.map((a) => decodeAddress(a))]
66-
);
67-
68-
return cacheAddrU8a;
69-
});
122+
return cache.list;
70123
}
71124

72125
/**
73126
* Retrieve allow/deny from our list provider
127+
*
128+
* @deprecated While not due for removal, it is suggested to rather use the
129+
* checkIfDenied function (which is more optimal overall)
74130
*/
75-
export async function retrieveHostList (allowCached = true): Promise<HostList> {
76-
const now = Date.now();
77-
78-
return (allowCached && cacheHostList && (now < cacheHostEnd))
79-
? cacheHostList
80-
: fetchJson<HostList>(ALL_JSON).then((list) => {
81-
cacheHostEnd = now + CACHE_TIMEOUT;
82-
cacheHostList = list;
131+
export async function retrieveHostList (allowCached = true, root = '*'): Promise<HostList> {
132+
const cache = await retrieveHostCache(allowCached, root);
83133

84-
return list;
85-
});
134+
return cache.list;
86135
}
87136

88137
/**
89138
* Checks a host to see if it appears in the provided list
139+
*
140+
* @deprecated While not due for removal, it is suggested to rather use the
141+
* checkIfDenied function (which is more optimal overall)
90142
*/
91-
export function checkHost (items: string[], host: string): boolean {
92-
const hostParts = extractHost(host).split('.').reverse();
93-
94-
return items.some((item): boolean => {
95-
const checkParts = item.split('.').reverse();
96-
97-
// first we need to ensure it has less or equal parts to our source
98-
if (checkParts.length > hostParts.length) {
99-
return false;
100-
}
101-
102-
// ensure each section matches
103-
return checkParts.every((part, index) => hostParts[index] === part);
104-
});
143+
export function checkHost (list: string[], host: string): boolean {
144+
return checkHostParts(list.map((h) => splitHostParts(h)), extractHostParts(host));
105145
}
106146

107147
/**
@@ -111,13 +151,13 @@ export function checkHost (items: string[], host: string): boolean {
111151
export async function checkAddress (address: string | Uint8Array, allowCached = true): Promise<string | null> {
112152
try {
113153
const u8a = decodeAddress(address);
114-
const all = await retrieveAddrU8a(allowCached);
115-
const entry = all.find(([, all]) => all.some((a) => u8aEq(a, u8a))) || [null];
116-
117-
return entry[0];
118-
} catch (error) {
119-
log(error, 'address');
154+
const cache = await retrieveAddrCache(allowCached);
155+
const entry = cache.u8a.find(([, u8as]) =>
156+
u8as.some((a) => u8aEq(a, u8a))
157+
);
120158

159+
return (entry && entry[0]) || null;
160+
} catch {
121161
return null;
122162
}
123163
}
@@ -128,12 +168,11 @@ export async function checkAddress (address: string | Uint8Array, allowCached =
128168
*/
129169
export async function checkIfDenied (host: string, allowCached = true): Promise<boolean> {
130170
try {
131-
const { deny } = await retrieveHostList(allowCached);
132-
133-
return checkHost(deny, host);
134-
} catch (error) {
135-
log(error, host);
171+
const hostParts = extractHostParts(host);
172+
const cache = await retrieveHostCache(allowCached, hostParts[0]);
136173

174+
return checkHostParts(cache.parts, hostParts);
175+
} catch {
137176
return false;
138177
}
139178
}

phishing/detectPackage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
// Do not edit, auto-generated by @polkadot/dev
55

6-
import { detectPackage } from 'https://deno.land/x/polkadot@0.2.23/util/mod.ts';
6+
import { detectPackage } from 'https://deno.land/x/polkadot/util/mod.ts';
77

88
import others from './detectOther.ts';
99
import { packageInfo } from './packageInfo.ts';

phishing/fetch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2020-2023 @polkadot/phishing authors & contributors
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { fetch } from 'https://deno.land/x/polkadot@0.2.23/x-fetch/mod.ts';
4+
import { fetch } from 'https://deno.land/x/polkadot/x-fetch/mod.ts';
55

66
// this is also in @polkadot/apps-config - we may want to expose it
77
// inside x-fetch at some point in the future...

phishing/packageInfo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
// Do not edit, auto-generated by @polkadot/dev
55

6-
export const packageInfo = { name: '@polkadot/phishing', path: new URL(import.meta.url).pathname, type: 'deno', version: '0.2.23' };
6+
export const packageInfo = { name: '@polkadot/phishing', path: new URL(import.meta.url).pathname, type: 'deno', version: '0.19.1' };

0 commit comments

Comments
 (0)