diff --git a/package.json b/package.json index 907c78f..3995eaf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "token-lists", - "version": "1.13.0", + "version": "1.14.0", "description": "Manages custom token lists for Brave Wallet", "dependencies": { "@metamask/contract-metadata": "git+https://git@github.com/MetaMask/contract-metadata.git", diff --git a/scripts/index.js b/scripts/index.js index dc49185..ebc5df9 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -253,6 +253,12 @@ async function stageOnRampLists(stagingDir) { await fsPromises.writeFile(dstOnRampCurrenciesPath, JSON.stringify(onRampCurrencies, null, 2)); } +async function stageOFACLists(stagingDir) { + const ofacLists = await util.fetchGitHubRepoTopLevelFiles('brave-intl', 'ofac-sanctioned-digital-currency-addresses', 'lists'); + const dstOfacListsPath = path.join(stagingDir, 'ofac-sanctioned-digital-currency-addresses.json'); + await fsPromises.writeFile(dstOfacListsPath, JSON.stringify(ofacLists, null, 2)); +} + async function stageTokenPackage() { const stagingDir = 'build' if (!fs.existsSync(stagingDir)) { @@ -291,6 +297,9 @@ async function stageTokenPackage() { // Add on ramp JSON files await stageOnRampLists(stagingDir) + // Add OFAC banned address lists + await stageOFACLists(stagingDir) + stagePackageJson(stagingDir) stageManifest(stagingDir) } diff --git a/scripts/util.cjs b/scripts/util.cjs index 1c6d298..936844a 100644 --- a/scripts/util.cjs +++ b/scripts/util.cjs @@ -673,6 +673,58 @@ const injectCoingeckoIds = (tokensListMap, coingeckoIds) => return acc }, {}) +const fetchGitHubFileContent = async (repoOwner, repoName, branch, filePath, githubHeaders) => { + const contentApiUrl = `https://api.github.com/repos/${repoOwner}/${repoName}/contents/${filePath}?ref=${branch}`; + + const contentResponse = await fetch(contentApiUrl, { headers: githubHeaders }); + const contentData = await contentResponse.json(); + + if (!contentData.content) { + console.error('Failed to fetch content for file:', filePath, contentData.message || 'Unknown error'); + return ''; + } + + return Buffer.from(contentData.content, 'base64').toString('utf-8'); +}; + +const fetchGitHubRepoTopLevelFiles = async (repoOwner, repoName, branch) => { + const githubToken = process.env.API_AUTH_TOKEN_GITHUB; + const githubHeaders = { + "Accept": "application/vnd.github.v3+json", + "Authorization": `token ${githubToken}` + }; + + const apiUrl = `https://api.github.com/repos/${repoOwner}/${repoName}/git/trees/${branch}?recursive=1`; + const response = await fetch(apiUrl, { headers: githubHeaders }); + const data = await response.json(); + + if (!data.tree) { + console.error('Failed to fetch files:', data.message); + return; + } + + const jsonFiles = []; + for (const item of data.tree) { + if (item.type === 'blob' && + !item.path.includes('/') && + item.path.endsWith('.json') && + item.path !== 'README.md') { + jsonFiles.push(item); + } + } + + let bannedAddresses = [] + for (const file of jsonFiles) { + const content = await fetchGitHubFileContent(repoOwner, repoName, branch, file.path, githubHeaders); + const bannedAddressesForFile = JSON.parse(content); + bannedAddresses = [...bannedAddressesForFile, ...bannedAddresses] + } + bannedAddresses = [...new Set(bannedAddresses)] + + return {"addresses": bannedAddresses} +} + + module.exports = { contractReplaceSvgToPng, contractAddExtraMainnetAssets, @@ -685,5 +737,6 @@ module.exports = { addSupportedSardineCurrencies, generateCoingeckoIds, generateChainList, - injectCoingeckoIds + injectCoingeckoIds, + fetchGitHubRepoTopLevelFiles }