diff --git a/.env.template b/.env.template
index 373544a53..5c156a6df 100644
--- a/.env.template
+++ b/.env.template
@@ -1,3 +1,7 @@
-INFURA_KEY=xxx
-ALCHEMY_KEY=xxx # For zkEVM
+# Blockchain API Keys for token metadata fetching
+INFURA_KEY=your_infura_key_here
+ALCHEMY_KEY=your_alchemy_key_here # For zkEVM
COINGECKO_API_KEY=xxx
+
+# GitHub Personal Access Token for creating PRs
+GITHUB_TOKEN=ghp_your_github_token_here
\ No newline at end of file
diff --git a/.github/workflows/tokenlist-fetch.yml b/.github/workflows/tokenlist-fetch.yml
new file mode 100644
index 000000000..cafb23c77
--- /dev/null
+++ b/.github/workflows/tokenlist-fetch.yml
@@ -0,0 +1,113 @@
+name: Token List Fetch
+
+on:
+ workflow_dispatch:
+ inputs:
+ source_url:
+ description: 'Source URL for token list'
+ required: false
+ default: 'https://raw.githubusercontent.com/burrbear-dev/default-lists/main/src/tokens/mainnet/defaultTokenList.json'
+ type: string
+ target_token_file:
+ description: 'Target token file path'
+ required: false
+ default: 'src/tokenlists/balancer/tokens/berachain.ts'
+ type: string
+ assets_dir:
+ description: 'Assets directory for logos'
+ required: false
+ default: 'src/assets/images/tokens'
+ type: string
+
+jobs:
+ update-tokenlist:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ fetch-depth: 0
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '18'
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Configure Git
+ run: |
+ git config --global user.name 'github-actions[bot]'
+ git config --global user.email 'github-actions[bot]@users.noreply.github.com'
+
+ - name: Fetch token list
+ run: |
+ # Set environment variables for the script
+ export SOURCE_URL="${{ inputs.source_url }}"
+ export TARGET_TOKEN_FILE="${{ inputs.target_token_file }}"
+ export ASSETS_DIR="${{ inputs.assets_dir }}"
+
+ # Run the fetch script
+ npm run tokenlist:fetch
+ env:
+ NODE_ENV: production
+
+ - name: Generate token list
+ run: |
+ # Run the generate script
+ npm run generate
+ env:
+ NODE_ENV: production
+ INFURA_KEY: ${{ secrets.INFURA_KEY }}
+ ALCHEMY_KEY: ${{ secrets.ALCHEMY_KEY }}
+
+ - name: Check for changes
+ id: check-changes
+ run: |
+ if git diff --quiet; then
+ echo "changes=false" >> $GITHUB_OUTPUT
+ echo "No changes detected"
+ else
+ echo "changes=true" >> $GITHUB_OUTPUT
+ echo "Changes detected"
+ fi
+
+ - name: Create PR
+ if: steps.check-changes.outputs.changes == 'true'
+ run: |
+ # Set environment variables for the PR script
+ export TARGET_TOKEN_FILE="${{ inputs.target_token_file }}"
+ export ASSETS_DIR="${{ inputs.assets_dir }}"
+
+ # Run the PR creation script
+ npm run tokenlist:pr
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Comment on PR
+ if: steps.check-changes.outputs.changes == 'true'
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const { data: pulls } = await github.rest.pulls.list({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ state: 'open',
+ head: `${context.repo.owner}:${context.payload.ref || 'feat/tokenlist-update-' + new Date().toISOString().slice(0, 19).replace(/[:.]/g, '-')}`
+ });
+
+ if (pulls.length > 0) {
+ const pr = pulls[0];
+ const commentBody = '🤖 **Automated Token List Update**\n\nThis PR was automatically generated by the GitHub Actions workflow.\n\n**Workflow Details:**\n- **Triggered by**: Manual workflow dispatch\n- **Run ID**: [' + context.runId + '](' + context.serverUrl + '/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId + ')\n- **Commit**: ' + context.sha + '\n\n**Changes:**\n- Updated token list with latest addresses\n- Downloaded new logo assets\n- Generated timestamped backups and logs\n\n---\n*This is an automated PR. Please review the changes before merging.*';
+
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: pr.number,
+ body: commentBody
+ });
+ }
diff --git a/.gitignore b/.gitignore
index 94e191f36..9b4f3a84a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,8 @@ dist
.DS_Store
.env
.idea/**
+
+# Log files generated by scripts
+fetch-tokenlist-*.log
+create-pr-*.log
+*.log
diff --git a/generated/balancer.tokenlist.json b/generated/balancer.tokenlist.json
index 79856e3e7..bf9ad178e 100644
--- a/generated/balancer.tokenlist.json
+++ b/generated/balancer.tokenlist.json
@@ -3,7 +3,7 @@
"version": {
"major": 1,
"minor": 0,
- "patch": 351
+ "patch": 352
},
"keywords": [
"Balancer",
@@ -17,7 +17,7 @@
"Swap"
],
"logoURI": "https://raw.githubusercontent.com/balancer/pebbles/master/images/pebbles-pad.256w.png",
- "timestamp": "2025-07-17T09:36:48.016Z",
+ "timestamp": "2025-07-18T09:04:46.281Z",
"tokens": [
{
"chainId": 999,
@@ -436,6 +436,486 @@
"address": "0x6969696969696969696969696969696969696969",
"name": "Wrapped Bera",
"symbol": "WBERA",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x6969696969696969696969696969696969696969.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0xD77552D3849ab4D8C3b189A9582d0ba4C1F4f912",
+ "name": "Wrapped gBERA",
+ "symbol": "wgBERA",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0xd77552d3849ab4d8c3b189a9582d0ba4c1f4f912.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590",
+ "name": "WETH",
+ "symbol": "WETH",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0xFCBD14DC51f0A4d49d5E53C2E0950e0bC26d0Dce",
+ "name": "Honey",
+ "symbol": "HONEY",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0xfcbd14dc51f0a4d49d5e53c2e0950e0bc26d0dce.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x28e0e3B9817012b356119dF9e217c25932D609c2",
+ "name": "Burr Governance Token",
+ "symbol": "BURR",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x28e0e3b9817012b356119df9e217c25932d609c2.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x1cE0a25D13CE4d52071aE7e02Cf1F6606F4C79d3",
+ "name": "Nectar",
+ "symbol": "NECT",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x1ce0a25d13ce4d52071ae7e02cf1f6606f4c79d3.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x549943e04f40284185054145c6E4e9568C1D3241",
+ "name": "Bridged USDC (Stargate)",
+ "symbol": "USDC.e",
+ "decimals": 6,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x549943e04f40284185054145c6e4e9568c1d3241.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x231A6BD8eB88Cfa42776B7Ac575CeCAf82bf1E21",
+ "name": "Beraplug",
+ "symbol": "PLUG",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x231a6bd8eb88cfa42776b7ac575cecaf82bf1e21.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0xBaadCC2962417C01Af99fb2B7C75706B9bd6Babe",
+ "name": "Liquid BGT",
+ "symbol": "LBGT",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0xbaadcc2962417c01af99fb2b7c75706b9bd6babe.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x656b95E550C07a9ffe548bd4085c72418Ceb1dba",
+ "name": "Bera Governance Token",
+ "symbol": "BGT",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x656b95e550c07a9ffe548bd4085c72418ceb1dba.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0xac03CABA51e17c86c921E1f6CBFBdC91F8BB2E6b",
+ "name": "Infrared BGT",
+ "symbol": "iBGT",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0xac03caba51e17c86c921e1f6cbfbdc91f8bb2e6b.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x8BF591Eae535f93a242D5A954d3Cde648b48A5A8",
+ "name": "Sumerian USD",
+ "symbol": "suUSD",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x8bf591eae535f93a242d5a954d3cde648b48a5a8.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0xe85411C030fB32A9D8b14Bbbc6CB19417391F711",
+ "name": "Sumerian BTC",
+ "symbol": "suBTC",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0xe85411c030fb32a9d8b14bbbc6cb19417391f711.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x30C8Cf6B46AA4DF3F9fbC2857aca92F10a6cAd7f",
+ "name": "Eliteness.Network",
+ "symbol": "ELITE",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x30c8cf6b46aa4df3f9fbc2857aca92f10a6cad7f.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0xD10E65A5F8cA6f835F2B1832e37cF150fb955f23",
+ "name": "NECT/USDC/HONEY",
+ "symbol": "NECT/USDC/HONEY",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0xd10e65a5f8ca6f835f2b1832e37cf150fb955f23.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x65967109401506222609BDc86e3039F910C4d08b",
+ "name": "TWIN ASSET TOKEN - COIN",
+ "symbol": "COIN",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x65967109401506222609bdc86e3039f910c4d08b.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x9EA30078bc52740F10812539E77B6502A2a5387a",
+ "name": "TWIN ASSET TOKEN - iCOIN",
+ "symbol": "iCOIN",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x9ea30078bc52740f10812539e77b6502a2a5387a.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x1De7EfAbfA656d077cFD961e4a83b061D351a83B",
+ "name": "TWIN ASSET TOKEN - NVDA",
+ "symbol": "NVDA",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x1de7efabfa656d077cfd961e4a83b061d351a83b.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x3A4B2d07c237C701c68238dA07E11302353A16F1",
+ "name": "TWIN ASSET TOKEN - iNVDA",
+ "symbol": "iNVDA",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x3a4b2d07c237c701c68238da07e11302353a16f1.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x0555E30da8f98308EdB960aa94C0Db47230d2B9c",
+ "name": "Wrapped BTC",
+ "symbol": "WBTC",
+ "decimals": 8,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x0555e30da8f98308edb960aa94c0db47230d2b9c.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x541FD749419CA806a8bc7da8ac23D346f2dF8B77",
+ "name": "Solv BTC",
+ "symbol": "SolvBTC",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x541fd749419ca806a8bc7da8ac23d346f2df8b77.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0xCC0966D8418d412c599A6421b760a847eB169A8c",
+ "name": "xSolvBTC",
+ "symbol": "xSolvBTC",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0xcc0966d8418d412c599a6421b760a847eb169a8c.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x439c84851bb1EDd8Db3DD94809ebBEA6670682F3",
+ "name": "Beracana NECT",
+ "symbol": "canaNECT",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x439c84851bb1edd8db3dd94809ebbea6670682f3.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
+ "name": "USDâ‚®0",
+ "symbol": "USDâ‚®0",
+ "decimals": 6,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x779ded0c9e1022225f8e0630b35a9b54be713736.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0x768670beAD85b4383940F60AfD8492AC76b2Ba28",
+ "name": "Beracana BERA",
+ "symbol": "canaBERA",
+ "decimals": 18,
+ "logoURI": "https://raw.githubusercontent.com/burrbear-dev/tokenlists/main/src/assets/images/tokens/0x768670bead85b4383940f60afd8492ac76b2ba28.png"
+ },
+ {
+ "chainId": 80094,
+ "address": "0xbdaB22CD9a4BcaB42Fe5Cf17e523A029cbe903Dc",
+ "name": "Boeing Company Tokenized by Sailing",
+ "symbol": "BAs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x69B88c116cb7cBBC5B0f85CBeA1Be91DF40b56E1",
+ "name": "Lockheed Martin Corporation Tokenized by Sailing",
+ "symbol": "LMTs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x24BC5c9a529024e2B670B5b8166993d4ECaefE22",
+ "name": "Coinbase Global Inc Tokenized by Sailing",
+ "symbol": "COINs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x4E0c8b91183374D3aB5eE691b0F59F1a4A671D80",
+ "name": "Warner Bros. Discovery Inc Tokenized by Sailing",
+ "symbol": "WBDs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xd9c5b692ed20fA4207f2da1a3db3450828d90a46",
+ "name": "YieldMax Universe Fund of Option Income ETFs Tokenized by Sailing",
+ "symbol": "YMAXs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x25f838Dc9DFC8F4Ac5bF957c475F90860Dde3460",
+ "name": "ARK Innovation ETF Tokenized By Sailing",
+ "symbol": "ARKKs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x17A238d9a31fFF2f1078C8e1E4b2aC6B84E3A068",
+ "name": "Paramount Global Tokenized by Sailing",
+ "symbol": "PARAs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x6379BB654aA1B63bC602DBC947f60305AB9d6467",
+ "name": "YieldMax Short COIN Option Income Strategy ETF Tokenized by Sailing",
+ "symbol": "FIATs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x39890d84ac4a0E94d486068486f6513470E541b4",
+ "name": "Roundhill S&P 500 0DTE Covered Call Strategy ETF Tokenized by Sailing",
+ "symbol": "XDTEs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x77D5cbfE85b3DfB6dB3e63d9392829f4C34FFA86",
+ "name": "Apple Inc Tokenized By Sailing",
+ "symbol": "AAPLs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xca72Cf92768bc1ABEF4b14cFD3E096c8B5f54696",
+ "name": "Tesla Inc Tokenized By Sailing",
+ "symbol": "TSLAs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x30F8a2fE5Ea2eb2E64b26CcbD33b690Ec4EFe723",
+ "name": "Amazon.com Inc Tokenized By Sailing",
+ "symbol": "AMZNs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xa8e8EFB06Ff91e8c5BEeD849417945d39F3f22Eb",
+ "name": "SPDR S&P 500 ETF Trust Tokenized By Sailing",
+ "symbol": "SPYs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x70fA06e485285B6873B0A93189B613E2d85dc5e2",
+ "name": "GameStop Corp Tokenized By Sailing",
+ "symbol": "GMEs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x59dEA303501B18c058882096b781B89B836aA12C",
+ "name": "Grupo Supervielle SA Tokenized By Sailing",
+ "symbol": "SUPVs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xbc2CeE93341C0e10d2fd5ED502F17AF88CFa1E7B",
+ "name": "YPF S.A. Tokenized by Sailing",
+ "symbol": "YPFs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xf79d63c21d7C69f1097114716dDB76844169B363",
+ "name": "YieldMax COIN Option Income Strategy ETF Tokenized by Sailing",
+ "symbol": "CONYs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xac894A14e3D2CE9E89AefD209b0a38c12AdcF624",
+ "name": "MercadoLibre Inc. Tokenized by Sailing",
+ "symbol": "MELIs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x9933Bb212C36860EF22915D44b74a8Cf1ffd45BB",
+ "name": "NVIDIA Corporation Tokenized by Sailing",
+ "symbol": "NVDAs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xB35ffDB091e2e4361d907d5AA7dB3C150846a3e1",
+ "name": "Meta Platforms Inc Tokenized By Sailing",
+ "symbol": "METAs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x849F0393632746AC5e8426b53d78266d1d8ac1cd",
+ "name": "Circle Internet Group Inc Tokenized by Sailing",
+ "symbol": "CRCLs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x8f7F14481a9c0943836898F825BFb5494b7828Db",
+ "name": "DLocal Ltd Tokenized By Sailing",
+ "symbol": "DLOs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x08bc8b0c234390a40Aa305277355fd1A1819f10E",
+ "name": "Upstart Holdings Inc Tokenized by Sailing",
+ "symbol": "UPSTs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x7542d8347913fA8eE3090fFf38544CDF694dd5F9",
+ "name": "NEOS S&P 500 High Income ETF Tokenized by Sailing",
+ "symbol": "SPYIs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x3a33A4Fa4443A5fd4aa89349BB3D2bc1D644478b",
+ "name": "AMC Entertainment Holdings Inc Tokenized By Sailing",
+ "symbol": "AMCs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x12855A68877A95482CEA16a39AaA25009ac6E396",
+ "name": "Invesco QQQ Trust Tokenized By Sailing",
+ "symbol": "QQQs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xB7ca08EEF00a58489A670a1E22D4c6D01579db2F",
+ "name": "Microstrategy Inc Tokenized By Sailing",
+ "symbol": "MSTRs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xe9C99da8395C57Bd08830c547a9c5d57A23C5cB3",
+ "name": "Ginkgo Bioworks Inc Tokenized By Sailing",
+ "symbol": "DNAs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x8dcCB687201955299E7bb1da47664313ff6759dd",
+ "name": "The Walt Disney Company Tokenized By Sailing",
+ "symbol": "DISs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x7195A0Bc1e8A8b29Cd426D545522d38e698120Bf",
+ "name": "Goldman Sachs Physical Gold ETF Tokenized By Sailing",
+ "symbol": "AAAUs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xD2A26cF1d3aB11799AFd3E2461eC7ea0D62eEC6C",
+ "name": "Airbnb Inc Tokenized By Sailing",
+ "symbol": "ABNBs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x42BECBE61383ce454db886e2A2802eC88ddC6beb",
+ "name": "Palantir Technologies Inc Tokenized by Sailing",
+ "symbol": "PLTRs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x4D9CeB1a0baA95b1Ae6198c152F44AB4e919824D",
+ "name": "Dynatrace Inc Tokenized By Sailing",
+ "symbol": "DTs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x43456286034E248EFC1471687fA7e7fF6aC4Bd5a",
+ "name": "McDonalds Tokenized By Sailing",
+ "symbol": "MCDs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xB1fef1bcf006604c382200168932f00812Ac9FF0",
+ "name": "The Goldman Sachs Group Inc Tokenized by Sailing",
+ "symbol": "GSs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x6C353a03d1177b5bA0C4Da63dA77341433015F86",
+ "name": "Uber Technologies Inc Tokenized by Sailing",
+ "symbol": "UBERs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x682BedD46D9d308eF35eaa7F92430e8A57c73792",
+ "name": "BlackRock Inc Tokenized by Sailing",
+ "symbol": "BLKs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0xB064c58a63EBf8D03CD7A063e9e5e1398CdeA138",
+ "name": "BYD Company Limited Tokenized by Sailing",
+ "symbol": "BYDs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x56b4930057bcF3Dc9b8f6F17FF64dD54698598e8",
+ "name": "Microsoft Corporation Tokenized by Sailing",
+ "symbol": "MSFTs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x23a9dfBc5f489311E891118a587C5367cc992a40",
+ "name": "United States Natural Gas Fund LP Tokenized by Sailing",
+ "symbol": "UNGs",
+ "decimals": 18
+ },
+ {
+ "chainId": 80094,
+ "address": "0x3e5D85dD846B4Ca5A12Eb19eBd21d2798b724c36",
+ "name": "Sailing",
+ "symbol": "SAIL",
"decimals": 18
}
]
diff --git a/package.json b/package.json
index 55c9cc711..0e610301c 100644
--- a/package.json
+++ b/package.json
@@ -5,6 +5,8 @@
"scripts": {
"generate": "ts-node src/generator.ts",
"tokenlist:create": "node src/lib/scripts/create-tokenlist.js",
+ "tokenlist:fetch": "node src/lib/scripts/fetch-tokenlist.js",
+ "tokenlist:pr": "node src/lib/scripts/create-pr.js",
"lint": "eslint . --ext .js,.ts --max-warnings 0",
"lint:fix": "npm run lint -- --fix",
"test": "vitest run",
diff --git a/src/assets/images/tokens/0x08bc8b0c234390a40aa305277355fd1a1819f10e.svg b/src/assets/images/tokens/0x08bc8b0c234390a40aa305277355fd1a1819f10e.svg
new file mode 100644
index 000000000..c865255c8
--- /dev/null
+++ b/src/assets/images/tokens/0x08bc8b0c234390a40aa305277355fd1a1819f10e.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x12855a68877a95482cea16a39aaa25009ac6e396.svg b/src/assets/images/tokens/0x12855a68877a95482cea16a39aaa25009ac6e396.svg
new file mode 100644
index 000000000..112a68098
--- /dev/null
+++ b/src/assets/images/tokens/0x12855a68877a95482cea16a39aaa25009ac6e396.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x17a238d9a31fff2f1078c8e1e4b2ac6b84e3a068.svg b/src/assets/images/tokens/0x17a238d9a31fff2f1078c8e1e4b2ac6b84e3a068.svg
new file mode 100644
index 000000000..6284034ae
--- /dev/null
+++ b/src/assets/images/tokens/0x17a238d9a31fff2f1078c8e1e4b2ac6b84e3a068.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x1ce0a25d13ce4d52071ae7e02cf1f6606f4c79d3.png b/src/assets/images/tokens/0x1ce0a25d13ce4d52071ae7e02cf1f6606f4c79d3.png
new file mode 100644
index 000000000..78f685c2f
Binary files /dev/null and b/src/assets/images/tokens/0x1ce0a25d13ce4d52071ae7e02cf1f6606f4c79d3.png differ
diff --git a/src/assets/images/tokens/0x1de7efabfa656d077cfd961e4a83b061d351a83b.png b/src/assets/images/tokens/0x1de7efabfa656d077cfd961e4a83b061d351a83b.png
new file mode 100644
index 000000000..634970adb
Binary files /dev/null and b/src/assets/images/tokens/0x1de7efabfa656d077cfd961e4a83b061d351a83b.png differ
diff --git a/src/assets/images/tokens/0x231a6bd8eb88cfa42776b7ac575cecaf82bf1e21.png b/src/assets/images/tokens/0x231a6bd8eb88cfa42776b7ac575cecaf82bf1e21.png
new file mode 100644
index 000000000..74d9fcab2
Binary files /dev/null and b/src/assets/images/tokens/0x231a6bd8eb88cfa42776b7ac575cecaf82bf1e21.png differ
diff --git a/src/assets/images/tokens/0x23a9dfbc5f489311e891118a587c5367cc992a40.svg b/src/assets/images/tokens/0x23a9dfbc5f489311e891118a587c5367cc992a40.svg
new file mode 100644
index 000000000..02bc5dcdf
--- /dev/null
+++ b/src/assets/images/tokens/0x23a9dfbc5f489311e891118a587c5367cc992a40.svg
@@ -0,0 +1,8464 @@
+
+
diff --git a/src/assets/images/tokens/0x24bc5c9a529024e2b670b5b8166993d4ecaefe22.svg b/src/assets/images/tokens/0x24bc5c9a529024e2b670b5b8166993d4ecaefe22.svg
new file mode 100644
index 000000000..76a5e531c
--- /dev/null
+++ b/src/assets/images/tokens/0x24bc5c9a529024e2b670b5b8166993d4ecaefe22.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x25f838dc9dfc8f4ac5bf957c475f90860dde3460.svg b/src/assets/images/tokens/0x25f838dc9dfc8f4ac5bf957c475f90860dde3460.svg
new file mode 100644
index 000000000..70a7d0ab2
--- /dev/null
+++ b/src/assets/images/tokens/0x25f838dc9dfc8f4ac5bf957c475f90860dde3460.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x28e0e3b9817012b356119df9e217c25932d609c2.png b/src/assets/images/tokens/0x28e0e3b9817012b356119df9e217c25932d609c2.png
new file mode 100644
index 000000000..36258e698
Binary files /dev/null and b/src/assets/images/tokens/0x28e0e3b9817012b356119df9e217c25932d609c2.png differ
diff --git a/src/assets/images/tokens/0x2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.png b/src/assets/images/tokens/0x2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.png
new file mode 100644
index 000000000..966044d04
Binary files /dev/null and b/src/assets/images/tokens/0x2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.png differ
diff --git a/src/assets/images/tokens/0x30c8cf6b46aa4df3f9fbc2857aca92f10a6cad7f.png b/src/assets/images/tokens/0x30c8cf6b46aa4df3f9fbc2857aca92f10a6cad7f.png
new file mode 100644
index 000000000..103ebe625
Binary files /dev/null and b/src/assets/images/tokens/0x30c8cf6b46aa4df3f9fbc2857aca92f10a6cad7f.png differ
diff --git a/src/assets/images/tokens/0x30f8a2fe5ea2eb2e64b26ccbd33b690ec4efe723.svg b/src/assets/images/tokens/0x30f8a2fe5ea2eb2e64b26ccbd33b690ec4efe723.svg
new file mode 100644
index 000000000..c10c16a34
--- /dev/null
+++ b/src/assets/images/tokens/0x30f8a2fe5ea2eb2e64b26ccbd33b690ec4efe723.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x39890d84ac4a0e94d486068486f6513470e541b4.svg b/src/assets/images/tokens/0x39890d84ac4a0e94d486068486f6513470e541b4.svg
new file mode 100644
index 000000000..5136d76ae
--- /dev/null
+++ b/src/assets/images/tokens/0x39890d84ac4a0e94d486068486f6513470e541b4.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x3a33a4fa4443a5fd4aa89349bb3d2bc1d644478b.svg b/src/assets/images/tokens/0x3a33a4fa4443a5fd4aa89349bb3d2bc1d644478b.svg
new file mode 100644
index 000000000..56588b21c
--- /dev/null
+++ b/src/assets/images/tokens/0x3a33a4fa4443a5fd4aa89349bb3d2bc1d644478b.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x3a4b2d07c237c701c68238da07e11302353a16f1.png b/src/assets/images/tokens/0x3a4b2d07c237c701c68238da07e11302353a16f1.png
new file mode 100644
index 000000000..08430450b
Binary files /dev/null and b/src/assets/images/tokens/0x3a4b2d07c237c701c68238da07e11302353a16f1.png differ
diff --git a/src/assets/images/tokens/0x3e5d85dd846b4ca5a12eb19ebd21d2798b724c36.svg b/src/assets/images/tokens/0x3e5d85dd846b4ca5a12eb19ebd21d2798b724c36.svg
new file mode 100644
index 000000000..2e7ab3ab1
--- /dev/null
+++ b/src/assets/images/tokens/0x3e5d85dd846b4ca5a12eb19ebd21d2798b724c36.svg
@@ -0,0 +1,13141 @@
+
+
diff --git a/src/assets/images/tokens/0x42becbe61383ce454db886e2a2802ec88ddc6beb.svg b/src/assets/images/tokens/0x42becbe61383ce454db886e2a2802ec88ddc6beb.svg
new file mode 100644
index 000000000..a1675c6c4
--- /dev/null
+++ b/src/assets/images/tokens/0x42becbe61383ce454db886e2a2802ec88ddc6beb.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x43456286034e248efc1471687fa7e7ff6ac4bd5a.svg b/src/assets/images/tokens/0x43456286034e248efc1471687fa7e7ff6ac4bd5a.svg
new file mode 100644
index 000000000..2cdf1c89e
--- /dev/null
+++ b/src/assets/images/tokens/0x43456286034e248efc1471687fa7e7ff6ac4bd5a.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x439c84851bb1edd8db3dd94809ebbea6670682f3.png b/src/assets/images/tokens/0x439c84851bb1edd8db3dd94809ebbea6670682f3.png
new file mode 100644
index 000000000..6ac7b5bf2
Binary files /dev/null and b/src/assets/images/tokens/0x439c84851bb1edd8db3dd94809ebbea6670682f3.png differ
diff --git a/src/assets/images/tokens/0x4d9ceb1a0baa95b1ae6198c152f44ab4e919824d.svg b/src/assets/images/tokens/0x4d9ceb1a0baa95b1ae6198c152f44ab4e919824d.svg
new file mode 100644
index 000000000..e1476eeca
--- /dev/null
+++ b/src/assets/images/tokens/0x4d9ceb1a0baa95b1ae6198c152f44ab4e919824d.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x4e0c8b91183374d3ab5ee691b0f59f1a4a671d80.svg b/src/assets/images/tokens/0x4e0c8b91183374d3ab5ee691b0f59f1a4a671d80.svg
new file mode 100644
index 000000000..7f8b08db6
--- /dev/null
+++ b/src/assets/images/tokens/0x4e0c8b91183374d3ab5ee691b0f59f1a4a671d80.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x541fd749419ca806a8bc7da8ac23d346f2df8b77.png b/src/assets/images/tokens/0x541fd749419ca806a8bc7da8ac23d346f2df8b77.png
new file mode 100644
index 000000000..d3a867e86
Binary files /dev/null and b/src/assets/images/tokens/0x541fd749419ca806a8bc7da8ac23d346f2df8b77.png differ
diff --git a/src/assets/images/tokens/0x549943e04f40284185054145c6e4e9568c1d3241.png b/src/assets/images/tokens/0x549943e04f40284185054145c6e4e9568c1d3241.png
new file mode 100644
index 000000000..c842b7430
Binary files /dev/null and b/src/assets/images/tokens/0x549943e04f40284185054145c6e4e9568c1d3241.png differ
diff --git a/src/assets/images/tokens/0x56b4930057bcf3dc9b8f6f17ff64dd54698598e8.svg b/src/assets/images/tokens/0x56b4930057bcf3dc9b8f6f17ff64dd54698598e8.svg
new file mode 100644
index 000000000..6b5cb76da
--- /dev/null
+++ b/src/assets/images/tokens/0x56b4930057bcf3dc9b8f6f17ff64dd54698598e8.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x59dea303501b18c058882096b781b89b836aa12c.svg b/src/assets/images/tokens/0x59dea303501b18c058882096b781b89b836aa12c.svg
new file mode 100644
index 000000000..bef5a1fcd
--- /dev/null
+++ b/src/assets/images/tokens/0x59dea303501b18c058882096b781b89b836aa12c.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x6379bb654aa1b63bc602dbc947f60305ab9d6467.svg b/src/assets/images/tokens/0x6379bb654aa1b63bc602dbc947f60305ab9d6467.svg
new file mode 100644
index 000000000..c5fc25bec
--- /dev/null
+++ b/src/assets/images/tokens/0x6379bb654aa1b63bc602dbc947f60305ab9d6467.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x656b95e550c07a9ffe548bd4085c72418ceb1dba.png b/src/assets/images/tokens/0x656b95e550c07a9ffe548bd4085c72418ceb1dba.png
new file mode 100644
index 000000000..13e9df87d
Binary files /dev/null and b/src/assets/images/tokens/0x656b95e550c07a9ffe548bd4085c72418ceb1dba.png differ
diff --git a/src/assets/images/tokens/0x65967109401506222609bdc86e3039f910c4d08b.png b/src/assets/images/tokens/0x65967109401506222609bdc86e3039f910c4d08b.png
new file mode 100644
index 000000000..9c580f513
Binary files /dev/null and b/src/assets/images/tokens/0x65967109401506222609bdc86e3039f910c4d08b.png differ
diff --git a/src/assets/images/tokens/0x682bedd46d9d308ef35eaa7f92430e8a57c73792.svg b/src/assets/images/tokens/0x682bedd46d9d308ef35eaa7f92430e8a57c73792.svg
new file mode 100644
index 000000000..7049c29ce
--- /dev/null
+++ b/src/assets/images/tokens/0x682bedd46d9d308ef35eaa7f92430e8a57c73792.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x6969696969696969696969696969696969696969.png b/src/assets/images/tokens/0x6969696969696969696969696969696969696969.png
new file mode 100644
index 000000000..bbede13d8
Binary files /dev/null and b/src/assets/images/tokens/0x6969696969696969696969696969696969696969.png differ
diff --git a/src/assets/images/tokens/0x69b88c116cb7cbbc5b0f85cbea1be91df40b56e1.svg b/src/assets/images/tokens/0x69b88c116cb7cbbc5b0f85cbea1be91df40b56e1.svg
new file mode 100644
index 000000000..6d4129fd5
--- /dev/null
+++ b/src/assets/images/tokens/0x69b88c116cb7cbbc5b0f85cbea1be91df40b56e1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x6c353a03d1177b5ba0c4da63da77341433015f86.svg b/src/assets/images/tokens/0x6c353a03d1177b5ba0c4da63da77341433015f86.svg
new file mode 100644
index 000000000..c47027ba0
--- /dev/null
+++ b/src/assets/images/tokens/0x6c353a03d1177b5ba0c4da63da77341433015f86.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x70fa06e485285b6873b0a93189b613e2d85dc5e2.svg b/src/assets/images/tokens/0x70fa06e485285b6873b0a93189b613e2d85dc5e2.svg
new file mode 100644
index 000000000..14c649478
--- /dev/null
+++ b/src/assets/images/tokens/0x70fa06e485285b6873b0a93189b613e2d85dc5e2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x7195a0bc1e8a8b29cd426d545522d38e698120bf.svg b/src/assets/images/tokens/0x7195a0bc1e8a8b29cd426d545522d38e698120bf.svg
new file mode 100644
index 000000000..22a34e397
--- /dev/null
+++ b/src/assets/images/tokens/0x7195a0bc1e8a8b29cd426d545522d38e698120bf.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/images/tokens/0x7542d8347913fa8ee3090fff38544cdf694dd5f9.svg b/src/assets/images/tokens/0x7542d8347913fa8ee3090fff38544cdf694dd5f9.svg
new file mode 100644
index 000000000..54e73e3c4
--- /dev/null
+++ b/src/assets/images/tokens/0x7542d8347913fa8ee3090fff38544cdf694dd5f9.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x768670bead85b4383940f60afd8492ac76b2ba28.png b/src/assets/images/tokens/0x768670bead85b4383940f60afd8492ac76b2ba28.png
new file mode 100644
index 000000000..39adac165
Binary files /dev/null and b/src/assets/images/tokens/0x768670bead85b4383940f60afd8492ac76b2ba28.png differ
diff --git a/src/assets/images/tokens/0x779ded0c9e1022225f8e0630b35a9b54be713736.png b/src/assets/images/tokens/0x779ded0c9e1022225f8e0630b35a9b54be713736.png
new file mode 100644
index 000000000..32bce844e
Binary files /dev/null and b/src/assets/images/tokens/0x779ded0c9e1022225f8e0630b35a9b54be713736.png differ
diff --git a/src/assets/images/tokens/0x77d5cbfe85b3dfb6db3e63d9392829f4c34ffa86.svg b/src/assets/images/tokens/0x77d5cbfe85b3dfb6db3e63d9392829f4c34ffa86.svg
new file mode 100644
index 000000000..8476c9f3b
--- /dev/null
+++ b/src/assets/images/tokens/0x77d5cbfe85b3dfb6db3e63d9392829f4c34ffa86.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x849f0393632746ac5e8426b53d78266d1d8ac1cd.svg b/src/assets/images/tokens/0x849f0393632746ac5e8426b53d78266d1d8ac1cd.svg
new file mode 100644
index 000000000..f6a362d5b
--- /dev/null
+++ b/src/assets/images/tokens/0x849f0393632746ac5e8426b53d78266d1d8ac1cd.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x8bf591eae535f93a242d5a954d3cde648b48a5a8.png b/src/assets/images/tokens/0x8bf591eae535f93a242d5a954d3cde648b48a5a8.png
new file mode 100644
index 000000000..5465c5439
Binary files /dev/null and b/src/assets/images/tokens/0x8bf591eae535f93a242d5a954d3cde648b48a5a8.png differ
diff --git a/src/assets/images/tokens/0x8dccb687201955299e7bb1da47664313ff6759dd.svg b/src/assets/images/tokens/0x8dccb687201955299e7bb1da47664313ff6759dd.svg
new file mode 100644
index 000000000..b4dfe417f
--- /dev/null
+++ b/src/assets/images/tokens/0x8dccb687201955299e7bb1da47664313ff6759dd.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x8f7f14481a9c0943836898f825bfb5494b7828db.svg b/src/assets/images/tokens/0x8f7f14481a9c0943836898f825bfb5494b7828db.svg
new file mode 100644
index 000000000..70bf98129
--- /dev/null
+++ b/src/assets/images/tokens/0x8f7f14481a9c0943836898f825bfb5494b7828db.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x9933bb212c36860ef22915d44b74a8cf1ffd45bb.svg b/src/assets/images/tokens/0x9933bb212c36860ef22915d44b74a8cf1ffd45bb.svg
new file mode 100644
index 000000000..218dc8f96
--- /dev/null
+++ b/src/assets/images/tokens/0x9933bb212c36860ef22915d44b74a8cf1ffd45bb.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0x9ea30078bc52740f10812539e77b6502a2a5387a.png b/src/assets/images/tokens/0x9ea30078bc52740f10812539e77b6502a2a5387a.png
new file mode 100644
index 000000000..84e763bab
Binary files /dev/null and b/src/assets/images/tokens/0x9ea30078bc52740f10812539e77b6502a2a5387a.png differ
diff --git a/src/assets/images/tokens/0xa8e8efb06ff91e8c5beed849417945d39f3f22eb.svg b/src/assets/images/tokens/0xa8e8efb06ff91e8c5beed849417945d39f3f22eb.svg
new file mode 100644
index 000000000..80c0eab20
--- /dev/null
+++ b/src/assets/images/tokens/0xa8e8efb06ff91e8c5beed849417945d39f3f22eb.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xac03caba51e17c86c921e1f6cbfbdc91f8bb2e6b.png b/src/assets/images/tokens/0xac03caba51e17c86c921e1f6cbfbdc91f8bb2e6b.png
new file mode 100644
index 000000000..9326b5223
Binary files /dev/null and b/src/assets/images/tokens/0xac03caba51e17c86c921e1f6cbfbdc91f8bb2e6b.png differ
diff --git a/src/assets/images/tokens/0xac894a14e3d2ce9e89aefd209b0a38c12adcf624.svg b/src/assets/images/tokens/0xac894a14e3d2ce9e89aefd209b0a38c12adcf624.svg
new file mode 100644
index 000000000..2c570d1c5
--- /dev/null
+++ b/src/assets/images/tokens/0xac894a14e3d2ce9e89aefd209b0a38c12adcf624.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xb064c58a63ebf8d03cd7a063e9e5e1398cdea138.svg b/src/assets/images/tokens/0xb064c58a63ebf8d03cd7a063e9e5e1398cdea138.svg
new file mode 100644
index 000000000..0743e6c10
--- /dev/null
+++ b/src/assets/images/tokens/0xb064c58a63ebf8d03cd7a063e9e5e1398cdea138.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xb1fef1bcf006604c382200168932f00812ac9ff0.svg b/src/assets/images/tokens/0xb1fef1bcf006604c382200168932f00812ac9ff0.svg
new file mode 100644
index 000000000..1c1f6e25b
--- /dev/null
+++ b/src/assets/images/tokens/0xb1fef1bcf006604c382200168932f00812ac9ff0.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xb35ffdb091e2e4361d907d5aa7db3c150846a3e1.svg b/src/assets/images/tokens/0xb35ffdb091e2e4361d907d5aa7db3c150846a3e1.svg
new file mode 100644
index 000000000..c25472e7e
--- /dev/null
+++ b/src/assets/images/tokens/0xb35ffdb091e2e4361d907d5aa7db3c150846a3e1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xb7ca08eef00a58489a670a1e22d4c6d01579db2f.svg b/src/assets/images/tokens/0xb7ca08eef00a58489a670a1e22d4c6d01579db2f.svg
new file mode 100644
index 000000000..a29321dfe
--- /dev/null
+++ b/src/assets/images/tokens/0xb7ca08eef00a58489a670a1e22d4c6d01579db2f.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xbaadcc2962417c01af99fb2b7c75706b9bd6babe.png b/src/assets/images/tokens/0xbaadcc2962417c01af99fb2b7c75706b9bd6babe.png
new file mode 100644
index 000000000..c9f36a5ce
Binary files /dev/null and b/src/assets/images/tokens/0xbaadcc2962417c01af99fb2b7c75706b9bd6babe.png differ
diff --git a/src/assets/images/tokens/0xbc2cee93341c0e10d2fd5ed502f17af88cfa1e7b.svg b/src/assets/images/tokens/0xbc2cee93341c0e10d2fd5ed502f17af88cfa1e7b.svg
new file mode 100644
index 000000000..9c08b864e
--- /dev/null
+++ b/src/assets/images/tokens/0xbc2cee93341c0e10d2fd5ed502f17af88cfa1e7b.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xbdab22cd9a4bcab42fe5cf17e523a029cbe903dc.svg b/src/assets/images/tokens/0xbdab22cd9a4bcab42fe5cf17e523a029cbe903dc.svg
new file mode 100644
index 000000000..f576a69ca
--- /dev/null
+++ b/src/assets/images/tokens/0xbdab22cd9a4bcab42fe5cf17e523a029cbe903dc.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xca72cf92768bc1abef4b14cfd3e096c8b5f54696.svg b/src/assets/images/tokens/0xca72cf92768bc1abef4b14cfd3e096c8b5f54696.svg
new file mode 100644
index 000000000..30e7444ee
--- /dev/null
+++ b/src/assets/images/tokens/0xca72cf92768bc1abef4b14cfd3e096c8b5f54696.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xcc0966d8418d412c599a6421b760a847eb169a8c.png b/src/assets/images/tokens/0xcc0966d8418d412c599a6421b760a847eb169a8c.png
new file mode 100644
index 000000000..97f42c71b
Binary files /dev/null and b/src/assets/images/tokens/0xcc0966d8418d412c599a6421b760a847eb169a8c.png differ
diff --git a/src/assets/images/tokens/0xd10e65a5f8ca6f835f2b1832e37cf150fb955f23.png b/src/assets/images/tokens/0xd10e65a5f8ca6f835f2b1832e37cf150fb955f23.png
new file mode 100644
index 000000000..4e413c491
Binary files /dev/null and b/src/assets/images/tokens/0xd10e65a5f8ca6f835f2b1832e37cf150fb955f23.png differ
diff --git a/src/assets/images/tokens/0xd2a26cf1d3ab11799afd3e2461ec7ea0d62eec6c.svg b/src/assets/images/tokens/0xd2a26cf1d3ab11799afd3e2461ec7ea0d62eec6c.svg
new file mode 100644
index 000000000..c83c592db
--- /dev/null
+++ b/src/assets/images/tokens/0xd2a26cf1d3ab11799afd3e2461ec7ea0d62eec6c.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xd77552d3849ab4d8c3b189a9582d0ba4c1f4f912.png b/src/assets/images/tokens/0xd77552d3849ab4d8c3b189a9582d0ba4c1f4f912.png
new file mode 100644
index 000000000..12050500f
Binary files /dev/null and b/src/assets/images/tokens/0xd77552d3849ab4d8c3b189a9582d0ba4c1f4f912.png differ
diff --git a/src/assets/images/tokens/0xd9c5b692ed20fa4207f2da1a3db3450828d90a46.svg b/src/assets/images/tokens/0xd9c5b692ed20fa4207f2da1a3db3450828d90a46.svg
new file mode 100644
index 000000000..c5fc25bec
--- /dev/null
+++ b/src/assets/images/tokens/0xd9c5b692ed20fa4207f2da1a3db3450828d90a46.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xe85411c030fb32a9d8b14bbbc6cb19417391f711.png b/src/assets/images/tokens/0xe85411c030fb32a9d8b14bbbc6cb19417391f711.png
new file mode 100644
index 000000000..9efc3c69e
Binary files /dev/null and b/src/assets/images/tokens/0xe85411c030fb32a9d8b14bbbc6cb19417391f711.png differ
diff --git a/src/assets/images/tokens/0xe9c99da8395c57bd08830c547a9c5d57a23c5cb3.svg b/src/assets/images/tokens/0xe9c99da8395c57bd08830c547a9c5d57a23c5cb3.svg
new file mode 100644
index 000000000..35e9319d5
--- /dev/null
+++ b/src/assets/images/tokens/0xe9c99da8395c57bd08830c547a9c5d57a23c5cb3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xf79d63c21d7c69f1097114716ddb76844169b363.svg b/src/assets/images/tokens/0xf79d63c21d7c69f1097114716ddb76844169b363.svg
new file mode 100644
index 000000000..c5fc25bec
--- /dev/null
+++ b/src/assets/images/tokens/0xf79d63c21d7c69f1097114716ddb76844169b363.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/tokens/0xfcbd14dc51f0a4d49d5e53c2e0950e0bc26d0dce.png b/src/assets/images/tokens/0xfcbd14dc51f0a4d49d5e53c2e0950e0bc26d0dce.png
new file mode 100644
index 000000000..97db27409
Binary files /dev/null and b/src/assets/images/tokens/0xfcbd14dc51f0a4d49d5e53c2e0950e0bc26d0dce.png differ
diff --git a/src/lib/scripts/create-pr.js b/src/lib/scripts/create-pr.js
new file mode 100644
index 000000000..cb03cfb7d
--- /dev/null
+++ b/src/lib/scripts/create-pr.js
@@ -0,0 +1,477 @@
+#! /usr/bin/env node
+/* eslint-disable @typescript-eslint/no-var-requires */
+const commander = require('commander')
+const chalk = require('chalk')
+const fs = require('fs-extra')
+const path = require('path')
+const { execSync } = require('child_process')
+
+// Load environment variables from .env file if it exists
+function loadEnvFile() {
+ try {
+ const envPath = path.resolve(process.cwd(), '.env')
+ if (fs.existsSync(envPath)) {
+ const envContent = fs.readFileSync(envPath, 'utf8')
+ const envVars = envContent
+ .split('\n')
+ .filter((line) => line.trim() && !line.startsWith('#'))
+ .map((line) => {
+ const [key, ...valueParts] = line.split('=')
+ const value = valueParts.join('=').trim()
+ return { key: key.trim(), value: value.replace(/^["']|["']$/g, '') }
+ })
+
+ envVars.forEach(({ key, value }) => {
+ if (!process.env[key]) {
+ process.env[key] = value
+ }
+ })
+
+ console.log(
+ chalk.blue(
+ `[${new Date().toISOString()}] Loaded environment variables from .env file`
+ )
+ )
+ }
+ } catch (error) {
+ console.log(
+ chalk.yellow(
+ `[${new Date().toISOString()}] Warning: Could not load .env file: ${
+ error.message
+ }`
+ )
+ )
+ }
+}
+
+// Load .env file when running locally
+loadEnvFile()
+
+// Configuration
+const CONFIG = {
+ TARGET_TOKEN_FILE:
+ process.env.TARGET_TOKEN_FILE ||
+ 'src/tokenlists/balancer/tokens/berachain.ts',
+ ASSETS_DIR: process.env.ASSETS_DIR || 'src/assets/images/tokens',
+ LOG_FILE: `create-pr-${new Date()
+ .toISOString()
+ .replace(/[:.]/g, '-')
+ .slice(0, 19)}.log`,
+}
+
+// Statistics tracking
+const stats = {
+ newTokens: 0,
+ newLogos: 0,
+ changesDetected: false,
+ prCreated: false,
+ errors: [],
+}
+
+/**
+ * Log message with timestamp
+ */
+function log(message, type = 'info') {
+ const timestamp = new Date().toISOString()
+ const logMessage = `[${timestamp}] ${message}`
+
+ switch (type) {
+ case 'error':
+ console.error(chalk.red(logMessage))
+ stats.errors.push(logMessage)
+ break
+ case 'success':
+ console.log(chalk.green(logMessage))
+ break
+ case 'warning':
+ console.log(chalk.yellow(logMessage))
+ break
+ default:
+ console.log(chalk.blue(logMessage))
+ }
+
+ // Append to log file
+ fs.appendFileSync(CONFIG.LOG_FILE, logMessage + '\n')
+}
+
+/**
+ * Check if running in CI environment
+ */
+function isCI() {
+ return process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true'
+}
+
+/**
+ * Configure git for CI environment
+ */
+function configureGitForCI() {
+ if (isCI()) {
+ try {
+ // Set git user for CI
+ execSync('git config --global user.name "github-actions[bot]"', {
+ stdio: 'inherit',
+ })
+ execSync(
+ 'git config --global user.email "github-actions[bot]@users.noreply.github.com"',
+ { stdio: 'inherit' }
+ )
+ log('Git configured for CI environment')
+ } catch (error) {
+ log(
+ `Warning: Failed to configure git for CI: ${error.message}`,
+ 'warning'
+ )
+ }
+ }
+}
+
+/**
+ * Check if there are any changes to commit
+ */
+function hasChanges() {
+ try {
+ const result = execSync('git status --porcelain', { encoding: 'utf8' })
+ return result.trim().length > 0
+ } catch (error) {
+ log(`Failed to check git status: ${error.message}`, 'error')
+ return false
+ }
+}
+
+/**
+ * Get current branch name
+ */
+function getCurrentBranch() {
+ try {
+ return execSync('git branch --show-current', { encoding: 'utf8' }).trim()
+ } catch (error) {
+ log(`Failed to get current branch: ${error.message}`, 'error')
+ return null
+ }
+}
+
+/**
+ * Create a new branch with timestamp
+ */
+function createNewBranch() {
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)
+ const branchName = `feat/tokenlist-update-${timestamp}`
+
+ try {
+ execSync(`git checkout -b ${branchName}`, { stdio: 'inherit' })
+ log(`Created new branch: ${branchName}`)
+ return branchName
+ } catch (error) {
+ log(`Failed to create branch: ${error.message}`, 'error')
+ return null
+ }
+}
+
+/**
+ * Add and commit changes
+ */
+function commitChanges() {
+ try {
+ // Add all changes
+ execSync('git add .', { stdio: 'inherit' })
+
+ // Get list of changed files for commit message
+ const changedFiles = execSync('git diff --cached --name-only', {
+ encoding: 'utf8',
+ })
+ .trim()
+ .split('\n')
+ .filter((file) => file.length > 0)
+
+ const commitMessage = `feat: update token list and assets
+
+- Updated berachain token list
+- Added new token logos
+- Generated timestamped backup and logs
+
+Changed files:
+${changedFiles.map((file) => `- ${file}`).join('\n')}`
+
+ execSync(`git commit -m "${commitMessage}"`, { stdio: 'inherit' })
+ log('Changes committed successfully')
+ return true
+ } catch (error) {
+ log(`Failed to commit changes: ${error.message}`, 'error')
+ return false
+ }
+}
+
+/**
+ * Get repository information from various sources
+ */
+function getRepositoryInfo() {
+ // Try to get from GitHub Actions context first
+ if (process.env.GITHUB_REPOSITORY) {
+ const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
+ log(`Using repository info from GITHUB_REPOSITORY: ${owner}/${repo}`)
+ return { owner, repo }
+ }
+
+ // Try to get from git remote
+ try {
+ const remoteUrl = execSync('git config --get remote.origin.url', {
+ encoding: 'utf8',
+ }).trim()
+
+ log(`Remote URL: ${remoteUrl}`)
+
+ // Handle HTTPS format (https://github.com/owner/repo.git)
+ let repoMatch = remoteUrl.match(
+ /github\.com[:/]([^/]+)\/([^/]+?)(?:\.git)?$/
+ )
+
+ // If no match, try SSH format (git@host:owner/repo.git)
+ if (!repoMatch) {
+ repoMatch = remoteUrl.match(/git@([^:]+):([^/]+)\/([^/]+?)(?:\.git)?$/)
+ if (repoMatch) {
+ // SSH format: [host, owner, repo]
+ const [, host, owner, repo] = repoMatch
+ log(`Parsed SSH URL: ${owner}/${repo}`)
+ return { owner, repo }
+ }
+ }
+
+ if (repoMatch) {
+ const [, owner, repo] = repoMatch
+ log(`Parsed HTTPS URL: ${owner}/${repo}`)
+ return { owner, repo }
+ }
+
+ log('Could not parse repository information from git remote.', 'error')
+ return null
+ } catch (error) {
+ log(
+ `Failed to get repository info from git remote: ${error.message}`,
+ 'error'
+ )
+ return null
+ }
+}
+
+/**
+ * Push branch and create PR
+ */
+function pushAndCreatePR(branchName) {
+ try {
+ // Push the branch
+ execSync(`git push -u origin ${branchName}`, { stdio: 'inherit' })
+ log(`Pushed branch ${branchName} to remote`)
+
+ // Get GitHub token from environment
+ const githubToken = process.env.GITHUB_TOKEN
+ if (!githubToken) {
+ log('GITHUB_TOKEN environment variable not found.', 'warning')
+ log('Please set GITHUB_TOKEN to create PRs automatically.')
+ log(`Branch pushed: ${branchName}`)
+ log('Please create the PR manually using the GitHub web interface')
+ return false
+ }
+
+ // Get repository info
+ const repoInfo = getRepositoryInfo()
+ if (!repoInfo) {
+ log('Could not determine repository information.', 'error')
+ log(`Branch pushed: ${branchName}`)
+ log('Please create the PR manually using the GitHub web interface')
+ return false
+ }
+
+ const { owner, repo } = repoInfo
+ const apiUrl = `https://api.github.com/repos/${owner}/${repo}/pulls`
+
+ const prTitle = `feat: Update token list and assets - ${new Date().toLocaleDateString()}`
+ const prBody = `## Token List Update
+
+This PR updates the berachain token list and associated logo assets.
+
+### Changes:
+- Updated token list with new addresses
+- Added new token logo images
+- Generated timestamped backups and logs
+
+### Files Changed:
+- \`src/tokenlists/balancer/tokens/berachain.ts\` - Updated token addresses
+- \`src/assets/images/tokens/\` - New logo assets
+- Generated backup files and logs
+
+### Summary:
+- New tokens added: ${stats.newTokens}
+- New logos downloaded: ${stats.newLogos}
+- All changes have been tested and validated
+
+---
+*Auto-generated by tokenlist update workflow*`
+
+ const prData = {
+ title: prTitle,
+ body: prBody,
+ head: branchName,
+ base: 'main',
+ }
+
+ const curlCommand = `curl -X POST "${apiUrl}" \
+ -H "Authorization: token ${githubToken}" \
+ -H "Accept: application/vnd.github.v3+json" \
+ -H "Content-Type: application/json" \
+ -d '${JSON.stringify(prData)}'`
+
+ const result = execSync(curlCommand, { encoding: 'utf8' })
+ const prResponse = JSON.parse(result)
+
+ if (prResponse.html_url) {
+ log(`Pull request created successfully: ${prResponse.html_url}`)
+ stats.prCreated = true
+ return true
+ } else {
+ log(`Failed to create PR: ${result}`, 'error')
+ return false
+ }
+ } catch (error) {
+ log(`Failed to create PR via API: ${error.message}`, 'error')
+ log(`Branch pushed: ${branchName}`)
+ log('Please create the PR manually using the GitHub web interface')
+ return false
+ }
+}
+
+/**
+ * Analyze changes to provide better commit messages
+ */
+function analyzeChanges() {
+ try {
+ // Check for new tokens in berachain.ts
+ if (fs.existsSync(CONFIG.TARGET_TOKEN_FILE)) {
+ const content = fs.readFileSync(CONFIG.TARGET_TOKEN_FILE, 'utf8')
+ const addresses = content.match(/'0x[a-fA-F0-9]{40}'/g) || []
+ stats.newTokens = addresses.length
+ }
+
+ // Check for new logo files
+ if (fs.existsSync(CONFIG.ASSETS_DIR)) {
+ const files = fs.readdirSync(CONFIG.ASSETS_DIR)
+ stats.newLogos = files.length
+ }
+
+ log(`Analysis: ${stats.newTokens} tokens, ${stats.newLogos} logo files`)
+ } catch (error) {
+ log(`Failed to analyze changes: ${error.message}`, 'warning')
+ }
+}
+
+/**
+ * Main workflow function
+ */
+async function createPRWorkflow() {
+ log('Starting PR creation workflow...')
+
+ // Configure git for CI if needed
+ configureGitForCI()
+
+ // Clear log file
+ fs.writeFileSync(CONFIG.LOG_FILE, '')
+
+ try {
+ // Step 1: Check if there are changes
+ if (!hasChanges()) {
+ log('No changes detected. Nothing to commit.', 'warning')
+ return
+ }
+
+ stats.changesDetected = true
+ log('Changes detected, proceeding with PR creation...')
+
+ // Step 2: Analyze changes
+ analyzeChanges()
+
+ // Step 3: Create new branch
+ const branchName = createNewBranch()
+ if (!branchName) {
+ throw new Error('Failed to create new branch')
+ }
+
+ // Step 4: Commit changes
+ if (!commitChanges()) {
+ throw new Error('Failed to commit changes')
+ }
+
+ // Step 5: Push and create PR
+ if (!pushAndCreatePR(branchName)) {
+ log('PR creation workflow completed with warnings', 'warning')
+ return
+ }
+
+ log('PR creation workflow completed successfully!', 'success')
+ } catch (error) {
+ log(`Workflow failed: ${error.message}`, 'error')
+ process.exit(1)
+ }
+}
+
+/**
+ * Print summary report
+ */
+function printSummary() {
+ console.log('\n' + '='.repeat(50))
+ console.log(chalk.cyan('CREATE PR SUMMARY'))
+ console.log('='.repeat(50))
+
+ if (stats.changesDetected) {
+ console.log(`Changes detected: ${chalk.green('Yes')}`)
+ console.log(`New tokens: ${chalk.blue(stats.newTokens)}`)
+ console.log(`New logos: ${chalk.blue(stats.newLogos)}`)
+ console.log(
+ `PR created: ${
+ stats.prCreated
+ ? chalk.green('Yes')
+ : chalk.yellow('No - GITHUB_TOKEN not set')
+ }`
+ )
+ } else {
+ console.log(`Changes detected: ${chalk.yellow('No')}`)
+ console.log('No changes to commit')
+ }
+
+ if (stats.errors.length > 0) {
+ console.log(`\n${chalk.red('Errors:')}`)
+ stats.errors.forEach((error) => console.log(` ${error}`))
+ }
+
+ console.log(`\nLog file: ${CONFIG.LOG_FILE}`)
+ console.log('='.repeat(50))
+}
+
+/**
+ * CLI setup
+ */
+async function init() {
+ const program = new commander.Command()
+ .version('1.0.0')
+ .name('npm run git:pr')
+ .description('Create a new branch and PR for token list changes')
+ .option('-f, --force', 'Force PR creation even if no changes detected')
+ .option('-v, --verbose', 'Enable verbose logging')
+ .parse(process.argv)
+
+ const options = program.opts()
+
+ if (options.force) {
+ log('Force mode enabled')
+ }
+
+ if (options.verbose) {
+ log('Verbose mode enabled')
+ }
+
+ await createPRWorkflow()
+ printSummary()
+}
+
+// Run the script
+;(async () => {
+ await init()
+})()
diff --git a/src/lib/scripts/create-tokenlist.js b/src/lib/scripts/create-tokenlist.js
index a32ae1347..efdd98e07 100644
--- a/src/lib/scripts/create-tokenlist.js
+++ b/src/lib/scripts/create-tokenlist.js
@@ -12,24 +12,16 @@ async function init() {
const program = new commander.Command()
.version(pkgJson.version)
.name('npm run tokenlist:create')
- .arguments('')
- .usage(`${chalk.green('')} [options]`)
+ .arguments('[tokenlist-name]')
+ .usage(`${chalk.green('[tokenlist-name]')} [options]`)
.action((name) => {
tokenlistName = name
})
.parse(process.argv)
+ // Use environment variable or default to 'balancer'
if (typeof tokenlistName === 'undefined') {
- console.error('Please specify the tokenlist name:')
- console.log(
- ` ${chalk.cyan(program.name())} ${chalk.green('')}`
- )
- console.log()
- console.log('For example:')
- console.log(
- ` ${chalk.cyan(program.name())} ${chalk.green('my-new-tokenlist')}`
- )
- process.exit(1)
+ tokenlistName = process.env.TOKENLIST_NAME || 'balancer'
}
await createTokenlist(tokenlistName)
diff --git a/src/lib/scripts/fetch-tokenlist.js b/src/lib/scripts/fetch-tokenlist.js
new file mode 100755
index 000000000..74ec1e851
--- /dev/null
+++ b/src/lib/scripts/fetch-tokenlist.js
@@ -0,0 +1,368 @@
+#! /usr/bin/env node
+/* eslint-disable @typescript-eslint/no-var-requires */
+const commander = require('commander')
+const chalk = require('chalk')
+const fs = require('fs-extra')
+const path = require('path')
+const { execSync } = require('child_process')
+
+// Configuration
+const CONFIG = {
+ SOURCE_URL:
+ process.env.SOURCE_URL ||
+ 'https://raw.githubusercontent.com/burrbear-dev/default-lists/main/src/tokens/mainnet/defaultTokenList.json',
+ TARGET_TOKEN_FILE:
+ process.env.TARGET_TOKEN_FILE ||
+ 'src/tokenlists/balancer/tokens/berachain.ts',
+ ASSETS_DIR: process.env.ASSETS_DIR || 'src/assets/images/tokens',
+ LOG_FILE: `fetch-tokenlist-${new Date()
+ .toISOString()
+ .replace(/[:.]/g, '-')
+ .slice(0, 19)}.log`,
+}
+
+// Statistics tracking
+const stats = {
+ totalTokens: 0,
+ successfulDownloads: 0,
+ failedDownloads: 0,
+ skippedDownloads: 0,
+ errors: [],
+}
+
+/**
+ * Execute curl command and return result
+ */
+function curlGet(url, options = {}) {
+ try {
+ const curlOptions = [
+ '-s', // silent mode
+ '-L', // follow redirects
+ '--max-time',
+ '30', // 30 second timeout
+ '--retry',
+ '3', // retry 3 times
+ '--retry-delay',
+ '2', // wait 2 seconds between retries
+ ]
+
+ if (options.output) {
+ curlOptions.push('-o', options.output)
+ }
+
+ // Build command with proper escaping
+ const command = `curl ${curlOptions.join(' ')} "${url}"`
+ const result = execSync(command, { encoding: 'utf8', shell: true })
+
+ return { success: true, data: result }
+ } catch (error) {
+ return {
+ success: false,
+ error: error.message,
+ command: `curl ${options.output ? '-o ' + options.output : ''} "${url}"`,
+ }
+ }
+}
+
+/**
+ * Extract filename from URL
+ */
+function extractFilenameFromUrl(url) {
+ try {
+ const urlObj = new URL(url)
+ const pathname = urlObj.pathname
+ return path.basename(pathname)
+ } catch (error) {
+ console.error(chalk.red(`Failed to parse URL: ${url}`))
+ return null
+ }
+}
+
+/**
+ * Validate Ethereum address format
+ */
+function isValidEthereumAddress(address) {
+ return /^0x[a-fA-F0-9]{40}$/.test(address)
+}
+
+/**
+ * Log message with timestamp
+ */
+function log(message, type = 'info') {
+ const timestamp = new Date().toISOString()
+ const logMessage = `[${timestamp}] ${message}`
+
+ switch (type) {
+ case 'error':
+ console.error(chalk.red(logMessage))
+ stats.errors.push(logMessage)
+ break
+ case 'success':
+ console.log(chalk.green(logMessage))
+ break
+ case 'warning':
+ console.log(chalk.yellow(logMessage))
+ break
+ default:
+ console.log(chalk.blue(logMessage))
+ }
+
+ // Append to log file
+ fs.appendFileSync(CONFIG.LOG_FILE, logMessage + '\n')
+}
+
+/**
+ * Download and parse the source token list using curl
+ */
+async function fetchTokenList() {
+ log('Fetching token list from source using curl...')
+
+ try {
+ const result = curlGet(CONFIG.SOURCE_URL)
+
+ if (!result.success) {
+ throw new Error(`Failed to fetch token list: ${result.error}`)
+ }
+
+ const tokenList = JSON.parse(result.data)
+
+ if (!tokenList.tokens || !Array.isArray(tokenList.tokens)) {
+ throw new Error(
+ 'Invalid token list format: missing or invalid tokens array'
+ )
+ }
+
+ stats.totalTokens = tokenList.tokens.length
+ log(`Successfully fetched ${stats.totalTokens} tokens using curl`)
+
+ return tokenList.tokens
+ } catch (error) {
+ log(`Failed to fetch token list: ${error.message}`, 'error')
+ throw error
+ }
+}
+
+/**
+ * Process tokens and extract addresses
+ */
+function processTokens(tokens) {
+ log('Processing tokens...')
+
+ const tokenAddresses = []
+ const validTokens = []
+
+ for (const token of tokens) {
+ if (!token.address) {
+ log(`Token missing address: ${token.symbol || 'unknown'}`, 'warning')
+ continue
+ }
+
+ if (!isValidEthereumAddress(token.address)) {
+ log(`Invalid address format: ${token.address}`, 'warning')
+ continue
+ }
+
+ tokenAddresses.push(token.address)
+ validTokens.push(token)
+ }
+
+ // Remove duplicates
+ const uniqueAddresses = [...new Set(tokenAddresses)]
+ log(`Found ${uniqueAddresses.length} unique valid addresses`)
+
+ return { tokenAddresses: uniqueAddresses, validTokens }
+}
+
+/**
+ * Update the berachain token list file
+ */
+async function updateTokenList(tokenAddresses) {
+ log('Updating berachain token list...')
+
+ try {
+ const targetFile = path.resolve(CONFIG.TARGET_TOKEN_FILE)
+
+ // Read existing content
+ let existingContent = ''
+ let existingAddresses = []
+
+ if (fs.existsSync(targetFile)) {
+ existingContent = fs.readFileSync(targetFile, 'utf8')
+
+ // Extract existing addresses from array format
+ const existingMatch = existingContent.match(/export default \[(.*)\]/s)
+
+ if (existingMatch) {
+ existingAddresses = existingMatch[1]
+ .split(',')
+ .map((addr) => addr.trim().replace(/['"]/g, ''))
+ .filter((addr) => addr && addr.length > 0)
+ }
+ }
+
+ // Merge addresses using Set to ensure uniqueness
+ const allAddresses = [...new Set([...existingAddresses, ...tokenAddresses])]
+
+ // Create new content
+ const newContent = `export default [\n${allAddresses
+ .map((addr) => ` '${addr}'`)
+ .join(',\n')}\n]`
+
+ // Backup original file BEFORE any changes
+ if (fs.existsSync(targetFile)) {
+ const timestamp = new Date()
+ .toISOString()
+ .replace(/[:.]/g, '-')
+ .slice(0, 19)
+ const backupFile = `${targetFile}.backup-${timestamp}`
+ fs.copyFileSync(targetFile, backupFile)
+ log(`Backup created: ${path.basename(backupFile)}`)
+ }
+
+ // Write new content
+ fs.writeFileSync(targetFile, newContent)
+
+ log(
+ `Successfully updated token list with ${allAddresses.length} addresses (${existingAddresses.length} existing + ${tokenAddresses.length} new)`
+ )
+ } catch (error) {
+ log(`Failed to update token list: ${error.message}`, 'error')
+ throw error
+ }
+}
+
+/**
+ * Download logo assets using curl with better path handling
+ */
+async function downloadAssets(tokens) {
+ log('Starting asset downloads using curl...')
+
+ // Ensure assets directory exists
+ fs.ensureDirSync(path.resolve(CONFIG.ASSETS_DIR))
+
+ for (const token of tokens) {
+ if (!token.logoURI) {
+ log(`Token ${token.symbol || token.address} missing logoURI`, 'warning')
+ continue
+ }
+
+ // Extract file extension from original URL
+ const originalFilename = extractFilenameFromUrl(token.logoURI)
+ if (!originalFilename) {
+ log(`Could not extract filename from URL: ${token.logoURI}`, 'warning')
+ continue
+ }
+
+ // Get file extension from original filename
+ const fileExtension = path.extname(originalFilename)
+
+ // Use token address as filename with original extension (lowercase)
+ const filename = `${token.address.toLowerCase()}${fileExtension}`
+ const targetPath = path.resolve(CONFIG.ASSETS_DIR, filename)
+
+ // Skip if file already exists
+ if (fs.existsSync(targetPath)) {
+ log(`Skipping existing file: ${filename}`)
+ stats.skippedDownloads++
+ continue
+ }
+
+ try {
+ // Use curl with proper path escaping
+ const curlCommand = `curl -s -L --max-time 30 --retry 3 --retry-delay 2 -o "${targetPath}" "${token.logoURI}"`
+ execSync(curlCommand, { shell: true })
+
+ log(`Downloaded: ${originalFilename} -> ${filename}`)
+ stats.successfulDownloads++
+ } catch (error) {
+ log(`Failed to download ${filename}: ${error.message}`, 'error')
+ stats.failedDownloads++
+ }
+ }
+}
+
+/**
+ * Print summary report
+ */
+function printSummary() {
+ console.log('\n' + '='.repeat(50))
+ console.log(chalk.cyan('FETCH TOKENLIST SUMMARY'))
+ console.log('='.repeat(50))
+ console.log(`Total tokens processed: ${stats.totalTokens}`)
+ console.log(`Successful downloads: ${chalk.green(stats.successfulDownloads)}`)
+ console.log(`Failed downloads: ${chalk.red(stats.failedDownloads)}`)
+ console.log(`Skipped downloads: ${chalk.yellow(stats.skippedDownloads)}`)
+ console.log(`Token list updated successfully!`)
+
+ if (stats.errors.length > 0) {
+ console.log(`\n${chalk.red('Errors:')}`)
+ stats.errors.forEach((error) => console.log(` ${error}`))
+ }
+
+ console.log(`\nLog file: ${CONFIG.LOG_FILE}`)
+ console.log('='.repeat(50))
+}
+
+/**
+ * Main workflow function
+ */
+async function integrateTokenList() {
+ log('Starting token list integration workflow...')
+
+ try {
+ // Clear log file
+ fs.writeFileSync(CONFIG.LOG_FILE, '')
+
+ // Step 1: Fetch token list using curl
+ const tokens = await fetchTokenList()
+
+ // Step 2: Process tokens
+ const { tokenAddresses, validTokens } = processTokens(tokens)
+
+ // Step 3: Update token list file
+ await updateTokenList(tokenAddresses)
+
+ // Step 4: Download logo assets
+ await downloadAssets(validTokens)
+
+ // Step 5: Print summary
+ printSummary()
+
+ log('Token list integration completed successfully!', 'success')
+ } catch (error) {
+ log(`Workflow failed: ${error.message}`, 'error')
+ process.exit(1)
+ }
+}
+
+/**
+ * CLI setup
+ */
+async function init() {
+ const program = new commander.Command()
+ .version('1.0.0')
+ .name('npm run tokenlist:fetch')
+ .description(
+ 'Fetch and integrate tokens from default-lists repository using curl'
+ )
+ .option('-f, --force', 'Force download even if files exist')
+ .option('-v, --verbose', 'Enable verbose logging')
+ .parse(process.argv)
+
+ const options = program.opts()
+
+ if (options.force) {
+ log('Force mode enabled - will overwrite existing files')
+ }
+
+ if (options.verbose) {
+ log('Verbose mode enabled')
+ }
+
+ await integrateTokenList()
+}
+
+// Run the script
+;(async () => {
+ await init()
+})()
diff --git a/src/tokenlists/balancer/tokens/berachain.ts b/src/tokenlists/balancer/tokens/berachain.ts
index 1a2214d9e..bda17db00 100644
--- a/src/tokenlists/balancer/tokens/berachain.ts
+++ b/src/tokenlists/balancer/tokens/berachain.ts
@@ -1 +1,68 @@
-export default ['0x6969696969696969696969696969696969696969']
+export default [
+ '0x6969696969696969696969696969696969696969',
+ '0xD77552D3849ab4D8C3b189A9582d0ba4C1F4f912',
+ '0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590',
+ '0xFCBD14DC51f0A4d49d5E53C2E0950e0bC26d0Dce',
+ '0x28e0e3B9817012b356119dF9e217c25932D609c2',
+ '0x1cE0a25D13CE4d52071aE7e02Cf1F6606F4C79d3',
+ '0x549943e04f40284185054145c6E4e9568C1D3241',
+ '0x231A6BD8eB88Cfa42776B7Ac575CeCAf82bf1E21',
+ '0xBaadCC2962417C01Af99fb2B7C75706B9bd6Babe',
+ '0x656b95E550C07a9ffe548bd4085c72418Ceb1dba',
+ '0xac03CABA51e17c86c921E1f6CBFBdC91F8BB2E6b',
+ '0x8bf591eae535f93a242d5a954d3cde648b48a5a8',
+ '0xe85411C030fB32A9D8b14Bbbc6CB19417391F711',
+ '0x30c8cf6b46aa4df3f9fbc2857aca92f10a6cad7f',
+ '0xD10E65A5F8cA6f835F2B1832e37cF150fb955f23',
+ '0x65967109401506222609BDc86e3039F910C4d08b',
+ '0x9EA30078bc52740F10812539E77B6502A2a5387a',
+ '0x1De7EfAbfA656d077cFD961e4a83b061D351a83B',
+ '0x3A4B2d07c237C701c68238dA07E11302353A16F1',
+ '0x0555E30da8f98308EdB960aa94C0Db47230d2B9c',
+ '0x541FD749419CA806a8bc7da8ac23D346f2dF8B77',
+ '0xCC0966D8418d412c599A6421b760a847eB169A8c',
+ '0x439c84851bb1EDd8Db3DD94809ebBEA6670682F3',
+ '0x779Ded0c9e1022225f8E0630b35a9b54bE713736',
+ '0x768670beAD85b4383940F60AfD8492AC76b2Ba28',
+ '0xbdaB22CD9a4BcaB42Fe5Cf17e523A029cbe903Dc',
+ '0x69B88c116cb7cBBC5B0f85CBeA1Be91DF40b56E1',
+ '0x24BC5c9a529024e2B670B5b8166993d4ECaefE22',
+ '0x4E0c8b91183374D3aB5eE691b0F59F1a4A671D80',
+ '0xd9c5b692ed20fA4207f2da1a3db3450828d90a46',
+ '0x25f838Dc9DFC8F4Ac5bF957c475F90860Dde3460',
+ '0x17A238d9a31fFF2f1078C8e1E4b2aC6B84E3A068',
+ '0x6379BB654aA1B63bC602DBC947f60305AB9d6467',
+ '0x39890d84ac4a0E94d486068486f6513470E541b4',
+ '0x77D5cbfE85b3DfB6dB3e63d9392829f4C34FFA86',
+ '0xca72Cf92768bc1ABEF4b14cFD3E096c8B5f54696',
+ '0x30F8a2fE5Ea2eb2E64b26CcbD33b690Ec4EFe723',
+ '0xa8e8EFB06Ff91e8c5BEeD849417945d39F3f22Eb',
+ '0x70fA06e485285B6873B0A93189B613E2d85dc5e2',
+ '0x59dEA303501B18c058882096b781B89B836aA12C',
+ '0xbc2CeE93341C0e10d2fd5ED502F17AF88CFa1E7B',
+ '0xf79d63c21d7C69f1097114716dDB76844169B363',
+ '0xac894A14e3D2CE9E89AefD209b0a38c12AdcF624',
+ '0x9933Bb212C36860EF22915D44b74a8Cf1ffd45BB',
+ '0xB35ffDB091e2e4361d907d5AA7dB3C150846a3e1',
+ '0x849F0393632746AC5e8426b53d78266d1d8ac1cd',
+ '0x8f7F14481a9c0943836898F825BFb5494b7828Db',
+ '0x08bc8b0c234390a40Aa305277355fd1A1819f10E',
+ '0x7542d8347913fA8eE3090fFf38544CDF694dd5F9',
+ '0x3a33A4Fa4443A5fd4aa89349BB3D2bc1D644478b',
+ '0x12855A68877A95482CEA16a39AaA25009ac6E396',
+ '0xB7ca08EEF00a58489A670a1E22D4c6D01579db2F',
+ '0xe9C99da8395C57Bd08830c547a9c5d57A23C5cB3',
+ '0x8dcCB687201955299E7bb1da47664313ff6759dd',
+ '0x7195A0Bc1e8A8b29Cd426D545522d38e698120Bf',
+ '0xD2A26cF1d3aB11799AFd3E2461eC7ea0D62eEC6C',
+ '0x42BECBE61383ce454db886e2A2802eC88ddC6beb',
+ '0x4D9CeB1a0baA95b1Ae6198c152F44AB4e919824D',
+ '0x43456286034E248EFC1471687fA7e7fF6aC4Bd5a',
+ '0xB1fef1bcf006604c382200168932f00812Ac9FF0',
+ '0x6C353a03d1177b5bA0C4Da63dA77341433015F86',
+ '0x682BedD46D9d308eF35eaa7F92430e8A57c73792',
+ '0xB064c58a63EBf8D03CD7A063e9e5e1398CdeA138',
+ '0x56b4930057bcF3Dc9b8f6F17FF64dD54698598e8',
+ '0x23a9dfBc5f489311E891118a587C5367cc992a40',
+ '0x3e5D85dD846B4Ca5A12Eb19eBd21d2798b724c36'
+]
\ No newline at end of file
diff --git a/src/tokenlists/balancer/tokens/berachain.ts.backup-2025-07-18T09-04-18 b/src/tokenlists/balancer/tokens/berachain.ts.backup-2025-07-18T09-04-18
new file mode 100644
index 000000000..1a2214d9e
--- /dev/null
+++ b/src/tokenlists/balancer/tokens/berachain.ts.backup-2025-07-18T09-04-18
@@ -0,0 +1 @@
+export default ['0x6969696969696969696969696969696969696969']