forked from catchain/address-book
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.mjs
133 lines (111 loc) · 4.08 KB
/
index.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { readdir, readFile, writeFile } from 'node:fs/promises';
import { parseAllDocuments } from 'yaml'
import TonWeb from 'tonweb';
const CONTRACT_TYPES = [
'wallet',
'nft_collection',
'jetton',
'pool',
];
const YAML_DIRECTORY = './source/';
const BUILD_DIRECTORY = './build/';
/**
* @param {String} address
* @param {Boolean} options.bounceable
* @return {String}
*/
const canonizeAddress = function anyAddressToFriendly(address, { bounceable }) {
return new TonWeb.utils.Address(address).toString(true, true, bounceable, false);
};
/**
* @param {String} address
* @return {String}
*/
const canonizeAddressToRaw = function anyAddressToRaw(address) {
return new TonWeb.utils.Address(address).toString(false);
};
/**
* @param {Object} entry
* @return {Boolean}
*/
const validate = function checkThatEveryEntryHasValidAddressAndMetaFields(entry) {
try {
new TonWeb.utils.Address(entry.address);
} catch {
throw new Error(`[${entry.filename}] Invalid address: ${entry.address}`);
}
if (entry.filename !== 'scam.yaml' && (entry.name || '').length <= 2) {
throw new Error(
`[${entry.filename}] Name for ${entry.address} must be at least 2 symbols length, ` +
`given name: ${entry.name}`
);
}
if (entry.type !== undefined && !CONTRACT_TYPES.includes(entry.type)) {
throw new Error(
`[${entry.filename}] Contract type for ${entry.address} must be ` +
`either undefined or one of: ${CONTRACT_TYPES.join(', ')}, given: ${entry.type}`
);
}
return true;
};
/**
* @param {String} directory
* @return {Promise<Map>}
*/
const createAddressbook = async function parseDirectoryAndCreateAddressBookFromYamlFiles(directory = YAML_DIRECTORY) {
const yamls = (await readdir(directory))
.filter(file => file.endsWith('.yaml'))
.map(file => [ file, readFile(`${directory}${file}`, 'utf8') ]);
const addrbook = new Map;
const addresses = new Map;
for (const [filename, getContents] of yamls) {
parseAllDocuments(await getContents)
.flatMap(document => document.toJS())
.map(document => ({ ...document, filename }))
.filter(validate)
.forEach(({ address, name, tonIcon, isScam, type }) => {
const raw = canonizeAddressToRaw(address);
if (addresses.has(raw)) {
throw new Error(`[${filename}] Address ${address} is already defined in ${addresses.get(raw)}`);
}
addresses.set(raw, filename);
const canonicalAddress = canonizeAddress(address, {
bounceable: type !== 'wallet',
});
addrbook.set(canonicalAddress, {
name, tonIcon,
isScam: filename === 'scam.yaml' ? true : isScam,
});
// Remove this block after backend update:
if (type === 'wallet') {
addrbook.set(canonizeAddress(address, { bounceable: true }), addrbook.get(canonicalAddress));
}
});
}
return addrbook;
};
/**
* @return {Promise<Map>}
*/
const validateYamls = async function checkYamlsWithoutWritingAddressbook() {
return await createAddressbook();
};
/**
* @param {String} directory
* @return {Promise<Map>}
*/
const saveAddressbook = async function createAndWriteAddressbookJson(directory = BUILD_DIRECTORY) {
const addresses = await createAddressbook();
const addressbook = Object.fromEntries(addresses.entries());
await writeFile(`${directory}addresses.json`, JSON.stringify(addressbook, undefined, 2));
return addresses;
};
// Save addressbook if command line has build argument:
if (process.argv.slice(2).includes('build')) {
const addresses = await saveAddressbook();
console.log(`Successfully created addressbook with ${addresses.size} addresses`);
// Just test otherwise:
} else {
const addresses = await validateYamls();
console.log(`Success: all yaml files are valid, checked ${addresses.size} addresses`);
}