forked from ice-blockchain/ion-address-book
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.mjs
More file actions
141 lines (117 loc) · 4.29 KB
/
index.mjs
File metadata and controls
141 lines (117 loc) · 4.29 KB
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
134
135
136
137
138
139
140
141
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));
// CORS headers for Cloudflare Pages
await writeFile(`${directory}_headers`, `/*
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Content-Type: application/json
`);
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`);
}