solana-risk-engine 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +147 -145
- package/package.json +1 -1
- package/src/constants.js +179 -93
- package/src/markets.js +11 -9
- package/src/risk.js +302 -293
package/src/constants.js
CHANGED
|
@@ -1,93 +1,179 @@
|
|
|
1
|
-
// api.mainnet-beta.solana.com answers 403 to anything coming from a browser. PublicNode serves almost
|
|
2
|
-
// everything (accounts, signatures, transactions) quickly, but blocks token-by-owner and largest-holder
|
|
3
|
-
// queries. Those go to Solana Vibe Station, which accepts them without a key but only at ~1 per second,
|
|
4
|
-
// so they go through a queue (see client.js). With your own RPC URL everything goes to that URL.
|
|
5
|
-
export const PUBLIC_RPC = "https://solana-rpc.publicnode.com";
|
|
6
|
-
export const VIBE_RPC = "https://public.rpc.solanavibestation.com";
|
|
7
|
-
export const DEX = "https://api.dexscreener.com/tokens/v1/solana/";
|
|
8
|
-
// SolFlag's wallet base (see base.js)
|
|
9
|
-
export const WALLET_BASE_URL = "https://solflag.com/datos/base.json";
|
|
10
|
-
export const DEX_SEARCH = "https://api.dexscreener.com/latest/dex/search?q=";
|
|
11
|
-
export const RUGCHECK = "https://api.rugcheck.xyz/v1/tokens/";
|
|
12
|
-
export const GECKO = "https://api.geckoterminal.com/api/v2/networks/solana/";
|
|
13
|
-
export const HELIUS_API = "https://api.helius.xyz/v0/addresses/";
|
|
14
|
-
export const COINGECKO_SOL = "https://api.coingecko.com/api/v3/coins/solana/market_chart?vs_currency=usd&days=365";
|
|
15
|
-
|
|
16
|
-
export const TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
17
|
-
export const TOKEN_2022 = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
|
|
18
|
-
export const SYSTEM_PROGRAM = "11111111111111111111111111111111";
|
|
19
|
-
export const PUMP_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
|
|
20
|
-
// dexId of a token still on Pump.fun's bonding curve: DexScreener says "pumpfun", GeckoTerminal "pump-fun"
|
|
21
|
-
export const PUMP_CURVE_DEXES = ["pumpfun", "pump-fun"];
|
|
22
|
-
|
|
23
|
-
export const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
24
|
-
export const USDT = "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB";
|
|
25
|
-
export const WSOL = "So11111111111111111111111111111111111111112";
|
|
26
|
-
|
|
27
|
-
export const KNOWN = {
|
|
28
|
-
[WSOL]: "SOL (wrapped)",
|
|
29
|
-
[USDC]: "USDC",
|
|
30
|
-
[USDT]: "USDT"
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// Symbols that scams usually copy, with their official address (checked on DexScreener)
|
|
34
|
-
export const FAMOUS = {
|
|
35
|
-
USDC, USDT, SOL: WSOL, WSOL,
|
|
36
|
-
JUP: "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN", BONK: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
|
|
37
|
-
WIF: "EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm", PYTH: "HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3",
|
|
38
|
-
JTO: "jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL", RAY: "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R",
|
|
39
|
-
PYUSD: "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo", MSOL: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
|
|
40
|
-
JITOSOL: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn", TRUMP: "6p6xgHyF7AeE6TZkSmFsko444wqoP15icUSqi2jfGiPN",
|
|
41
|
-
PUMP: "pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn", JLP: "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4",
|
|
42
|
-
POPCAT: "7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr", HNT: "hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux",
|
|
43
|
-
RENDER: "rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof", ORCA: "orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE",
|
|
44
|
-
DRIFT: "DriFtupJYLTosbwoN8koMbEYSx54aFAVLddWsbksjwg7",
|
|
45
|
-
// Bitcoin and Ether only exist on Solana bridged: a Pump.fun token called "BTC" is never the real one
|
|
46
|
-
BTC: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh", WBTC: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh",
|
|
47
|
-
ETH: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs", WETH: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// Real companies with no token of their own on Solana: a memecoin called "Spotify" is not Spotify.
|
|
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
|
-
|
|
1
|
+
// api.mainnet-beta.solana.com answers 403 to anything coming from a browser. PublicNode serves almost
|
|
2
|
+
// everything (accounts, signatures, transactions) quickly, but blocks token-by-owner and largest-holder
|
|
3
|
+
// queries. Those go to Solana Vibe Station, which accepts them without a key but only at ~1 per second,
|
|
4
|
+
// so they go through a queue (see client.js). With your own RPC URL everything goes to that URL.
|
|
5
|
+
export const PUBLIC_RPC = "https://solana-rpc.publicnode.com";
|
|
6
|
+
export const VIBE_RPC = "https://public.rpc.solanavibestation.com";
|
|
7
|
+
export const DEX = "https://api.dexscreener.com/tokens/v1/solana/";
|
|
8
|
+
// SolFlag's wallet base (see base.js)
|
|
9
|
+
export const WALLET_BASE_URL = "https://solflag.com/datos/base.json";
|
|
10
|
+
export const DEX_SEARCH = "https://api.dexscreener.com/latest/dex/search?q=";
|
|
11
|
+
export const RUGCHECK = "https://api.rugcheck.xyz/v1/tokens/";
|
|
12
|
+
export const GECKO = "https://api.geckoterminal.com/api/v2/networks/solana/";
|
|
13
|
+
export const HELIUS_API = "https://api.helius.xyz/v0/addresses/";
|
|
14
|
+
export const COINGECKO_SOL = "https://api.coingecko.com/api/v3/coins/solana/market_chart?vs_currency=usd&days=365";
|
|
15
|
+
|
|
16
|
+
export const TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
17
|
+
export const TOKEN_2022 = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
|
|
18
|
+
export const SYSTEM_PROGRAM = "11111111111111111111111111111111";
|
|
19
|
+
export const PUMP_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
|
|
20
|
+
// dexId of a token still on Pump.fun's bonding curve: DexScreener says "pumpfun", GeckoTerminal "pump-fun"
|
|
21
|
+
export const PUMP_CURVE_DEXES = ["pumpfun", "pump-fun"];
|
|
22
|
+
|
|
23
|
+
export const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
24
|
+
export const USDT = "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB";
|
|
25
|
+
export const WSOL = "So11111111111111111111111111111111111111112";
|
|
26
|
+
|
|
27
|
+
export const KNOWN = {
|
|
28
|
+
[WSOL]: "SOL (wrapped)",
|
|
29
|
+
[USDC]: "USDC",
|
|
30
|
+
[USDT]: "USDT"
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Symbols that scams usually copy, with their official address (checked on DexScreener)
|
|
34
|
+
export const FAMOUS = {
|
|
35
|
+
USDC, USDT, SOL: WSOL, WSOL,
|
|
36
|
+
JUP: "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN", BONK: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
|
|
37
|
+
WIF: "EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm", PYTH: "HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3",
|
|
38
|
+
JTO: "jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL", RAY: "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R",
|
|
39
|
+
PYUSD: "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo", MSOL: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
|
|
40
|
+
JITOSOL: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn", TRUMP: "6p6xgHyF7AeE6TZkSmFsko444wqoP15icUSqi2jfGiPN",
|
|
41
|
+
PUMP: "pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn", JLP: "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4",
|
|
42
|
+
POPCAT: "7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr", HNT: "hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux",
|
|
43
|
+
RENDER: "rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof", ORCA: "orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE",
|
|
44
|
+
DRIFT: "DriFtupJYLTosbwoN8koMbEYSx54aFAVLddWsbksjwg7",
|
|
45
|
+
// Bitcoin and Ether only exist on Solana bridged: a Pump.fun token called "BTC" is never the real one
|
|
46
|
+
BTC: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh", WBTC: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh",
|
|
47
|
+
ETH: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs", WETH: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Real companies with no token of their own on Solana: a memecoin called "Spotify" is not Spotify. Clubs
|
|
51
|
+
// with an official fan token on Solana (Barcelona, PSG, Juventus...) and Western Union (USDPT) are left out. Their
|
|
52
|
+
// genuine tokenized shares come from an issuer (xStocks, Backpack...) and are typed TOKENIZED, so they
|
|
53
|
+
// are never matched. Names only: stock tickers clash with real crypto symbols (META, COIN...). A name that
|
|
54
|
+
// is also an everyday word or a first name (Shell, Target, Puma, Mango, Oracle, Corona, Hermes...) is left
|
|
55
|
+
// out, since a token called just that would be marked HIGH. brandKey() normalises both sides
|
|
56
|
+
export function brandKey(s) {
|
|
57
|
+
return String(s || "").normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase()
|
|
58
|
+
.replace(/[$'’.\-_]/g, " ").replace(/\s+/g, " ").trim();
|
|
59
|
+
}
|
|
60
|
+
const BRAND_NAMES = [
|
|
61
|
+
// tech, internet and AI
|
|
62
|
+
"Apple", "Google", "Alphabet", "Microsoft", "Amazon", "Nvidia", "Facebook", "Instagram", "WhatsApp", "Netflix",
|
|
63
|
+
"Spotify", "Shopify", "TikTok", "YouTube", "OpenAI", "ChatGPT", "Anthropic", "DeepSeek", "Midjourney", "Samsung",
|
|
64
|
+
"Sony", "Nintendo", "PlayStation", "Xbox", "Intel", "Qualcomm", "Broadcom", "Salesforce", "Adobe", "IBM", "Cisco",
|
|
65
|
+
"Dell", "Lenovo", "Huawei", "Xiaomi", "OnePlus", "Motorola", "Nokia", "Snapchat", "Pinterest", "Reddit", "LinkedIn",
|
|
66
|
+
"Twitter", "Telegram", "Discord", "Twitch", "Dropbox", "Airbnb", "Uber", "Lyft", "DoorDash", "Expedia", "eBay",
|
|
67
|
+
"Alibaba", "AliExpress", "Temu", "Shein", "Tencent", "Baidu", "ByteDance", "Palantir", "SpaceX", "Starlink",
|
|
68
|
+
"Neuralink", "Roblox", "Fortnite", "Epic Games", "Minecraft", "Ubisoft", "Activision", "Rockstar Games",
|
|
69
|
+
"Electronic Arts", "Panasonic", "Philips", "Siemens", "Bosch", "Nikon", "GoPro", "Bose", "Dyson", "Garmin",
|
|
70
|
+
"Fitbit", "Peloton", "Logitech", "Razer", "Asus", "Xerox", "Vodafone", "Verizon", "AT&T", "T-Mobile", "Comcast",
|
|
71
|
+
"Movistar", "Telefonica", "Wikipedia", "Duolingo",
|
|
72
|
+
// finance and payments
|
|
73
|
+
"Visa", "Mastercard", "PayPal", "American Express", "JPMorgan", "Goldman Sachs", "Morgan Stanley", "BlackRock",
|
|
74
|
+
"Vanguard", "Fidelity", "Citibank", "Wells Fargo", "Bank of America", "HSBC", "Barclays", "Santander", "BBVA",
|
|
75
|
+
"CaixaBank", "Deutsche Bank", "Revolut", "Stripe", "Klarna", "Robinhood", "Charles Schwab", "Nasdaq", "NYSE",
|
|
76
|
+
"Berkshire Hathaway", "MoneyGram", "Venmo", "Cash App", "Zelle", "Monzo", "N26", "Nubank",
|
|
77
|
+
"Mapfre", "Bankinter",
|
|
78
|
+
// crypto companies with no token on Solana
|
|
79
|
+
"Coinbase", "Binance", "Bybit", "OKX", "KuCoin", "Bitget", "Upbit", "Bithumb", "Bitpanda", "eToro",
|
|
80
|
+
"MicroStrategy", "Grayscale", "MetaMask", "Trezor", "Solflare",
|
|
81
|
+
// fashion, retail and consumer goods
|
|
82
|
+
"Nike", "Adidas", "Reebok", "New Balance", "Under Armour", "Zara", "Inditex", "H&M", "Uniqlo", "Levi's", "Lacoste",
|
|
83
|
+
"Ralph Lauren", "Tommy Hilfiger", "Calvin Klein", "Gucci", "Louis Vuitton", "Chanel", "Prada", "Dior", "Versace",
|
|
84
|
+
"Balenciaga", "Burberry", "Fendi", "Givenchy", "Yves Saint Laurent", "Armani", "Dolce & Gabbana", "Rolex",
|
|
85
|
+
"Cartier", "Patek Philippe", "Audemars Piguet", "Swatch", "Ray-Ban", "Sephora", "L'Oreal", "Nivea", "Gillette",
|
|
86
|
+
"Colgate", "Pampers", "IKEA", "Lego", "Mattel", "Barbie", "Hot Wheels", "Hasbro", "Pokemon", "Hello Kitty",
|
|
87
|
+
"Sanrio", "Walmart", "Costco", "Carrefour", "Mercadona", "El Corte Ingles", "Lidl", "Aldi", "Tesco",
|
|
88
|
+
"Home Depot", "Best Buy", "7-Eleven", "Wallapop", "Glovo", "Cabify",
|
|
89
|
+
// food and drink
|
|
90
|
+
"Coca-Cola", "Pepsi", "Red Bull", "Monster Energy", "Starbucks", "McDonald's", "Burger King", "KFC", "Domino's",
|
|
91
|
+
"Pizza Hut", "Taco Bell", "Wendy's", "Chipotle", "Dunkin", "Krispy Kreme", "Nestle", "Nutella", "Ferrero",
|
|
92
|
+
"Doritos", "Pringles", "Cheetos", "Heinz", "Kellogg's", "Heineken", "Budweiser", "Guinness",
|
|
93
|
+
"Jack Daniel's", "Johnnie Walker", "Hennessy", "Moet", "Dom Perignon", "Smirnoff", "Bacardi", "Gatorade", "Fanta",
|
|
94
|
+
"Nespresso", "Haribo", "Snickers", "M&M's", "Hershey", "Cadbury", "Lindt",
|
|
95
|
+
// cars and motorbikes
|
|
96
|
+
"Tesla", "Ferrari", "Lamborghini", "Porsche", "Bugatti", "McLaren", "Bentley", "Rolls-Royce", "Aston Martin",
|
|
97
|
+
"Maserati", "BMW", "Mercedes-Benz", "Audi", "Volkswagen", "Toyota", "Honda", "Nissan", "Hyundai", "Chevrolet",
|
|
98
|
+
"Cadillac", "Volvo", "Peugeot", "Renault", "Harley-Davidson", "Ducati", "Yamaha", "Kawasaki", "Suzuki", "Rivian",
|
|
99
|
+
"Polestar",
|
|
100
|
+
// media, entertainment and sport
|
|
101
|
+
"Disney", "Pixar", "Marvel", "Warner Bros", "HBO", "Paramount", "Universal Studios", "DreamWorks", "Hulu",
|
|
102
|
+
"Fox News", "CNN", "ESPN", "National Geographic", "Playboy", "Nickelodeon", "Cartoon Network",
|
|
103
|
+
"Star Wars", "NBA", "NFL", "FIFA", "UEFA", "WWE", "Formula 1", "Real Madrid", "Manchester United",
|
|
104
|
+
"Bayern Munich",
|
|
105
|
+
// travel, transport, energy and health
|
|
106
|
+
"Emirates", "Qatar Airways", "Ryanair", "Lufthansa", "Boeing", "Airbus", "Marriott", "FedEx", "DHL",
|
|
107
|
+
"ExxonMobil", "Chevron", "Aramco", "Repsol", "Iberdrola", "Pfizer", "Moderna", "Johnson & Johnson",
|
|
108
|
+
"Procter & Gamble", "Unilever"
|
|
109
|
+
];
|
|
110
|
+
// Products that companies (or their partners) really put on Solana carry the name too: exchange staked SOL,
|
|
111
|
+
// fund shares, wrapped BTC. They trade for weeks with real liquidity, while copies are new and thin, so a
|
|
112
|
+
// market at least this old AND this deep is not checked for brand names
|
|
113
|
+
export const BRAND_MATURE_DAYS = 30;
|
|
114
|
+
export const BRAND_MATURE_LIQ = 100000;
|
|
115
|
+
export const BRANDS = Object.fromEntries(BRAND_NAMES.map(function (n) { return [brandKey(n), n]; }));
|
|
116
|
+
|
|
117
|
+
// Official tokens put on Solana by exchanges and by Socios.com, by mint address (a copy always has another
|
|
118
|
+
// address). They are bought and sold mostly on their exchange, so Solana pools are tiny and the issuer's
|
|
119
|
+
// custody wallet holds most of the supply: read as a stranger's token that gave HIGH (bnSOL, the Barcelona
|
|
120
|
+
// fan token). They are shown as dependency on the issuer, like ISSUERS below
|
|
121
|
+
export const OFFICIAL_TOKENS = {
|
|
122
|
+
BNso1VUJnh4zcfpZa6986Ea66P6TCp59hvtNJ8b1X85: "Binance", // Binance Staked SOL
|
|
123
|
+
Bybit2vBJGhPF52GBdNaQfUJ6ZpThSgHBobjWZpLPb4B: "Bybit", // Bybit Staked SOL
|
|
124
|
+
bgSoLfRx1wRPehwC9TyG568AGjnf1sQG1MYa8s3FbfY: "Bitget", // Bitget Staked SOL
|
|
125
|
+
"7cBuurYDdaqxnem7KyMTci6SWhjJKroZ6NUjqH2ewEPB": "MEXC", // MEXC Staked SOL
|
|
126
|
+
CDCSoLckzozyktpAp9FWT3w92KFJVEUxAU7cNu2Jn3aX: "Crypto.com", // Crypto.com Staked SOL
|
|
127
|
+
FDLkS4zH5rGmD7q7qGfzhmzPgQJ88jcX1JFT5nfdNTjg: "Socios.com (Chiliz)", // Olympique de Marseille Fan Token
|
|
128
|
+
BjXGwMnWWUkS9JrXEkkamszu4oX8oqo3kNqFr3ifNk1F: "Socios.com (Chiliz)", // Napoli Fan Token
|
|
129
|
+
BX8VbHBf8DUHeGJjJsSW2HCviGyQSF5SVCEnN7vXUkwM: "Socios.com (Chiliz)", // Argentine Football Association Fan Token
|
|
130
|
+
AiYi7HyVVXnDSuj8BoPirDsuuWgddeKkD5MQN35VpwNz: "Socios.com (Chiliz)", // Portugal National Team Fan Token
|
|
131
|
+
HD9i9C2Pw6hWXm354i3SWkYG8ZtfikUJn2bNPzwQZcEK: "Socios.com (Chiliz)", // SL Benfica Fan Token
|
|
132
|
+
cbbtcf3aa214zXHbiAZQwf4122FBYbraNdFqgw4iMij: "Coinbase", // Coinbase Wrapped BTC
|
|
133
|
+
gtBTCGWvSRYYoZpU9UZj6i3eUGUpgksXzzsbHk2K9So: "Gate", // Gate Wrapped BTC
|
|
134
|
+
CtzPWv73Sn1dMGVU3ZtLv9yWSyUAanBni19YWDaznnkn: "OKX", // OKX Wrapped BTC
|
|
135
|
+
BtjXf3LA7Z3jxAcQkKUqKYpLFS5B7GuB7pfjzeas1tdB: "Socios.com (Chiliz)", // OG Fan Token
|
|
136
|
+
"6VdpC1hcx7byFtJ5M6Xhspa6Uup5rZHruzXvuJhXAyXm": "Socios.com (Chiliz)", // Atletico Madrid Fan Token
|
|
137
|
+
EDzhmkPa5gToYGowjH66xycCRgPmfWNzfqpXdCzsYb8M: "Socios.com (Chiliz)", // Galatasaray Fan Token
|
|
138
|
+
"82DNsTK61ZrgCHP6pfP32Eubcsp9h38d64E6X9ETEBBe": "Socios.com (Chiliz)", // FC Barcelona Fan Token
|
|
139
|
+
"5eyib4qghYGHNh7VvxSFGYLFJSanjq9hug9fR52kksnm": "Socios.com (Chiliz)", // Paris Saint-Germain Fan Token
|
|
140
|
+
"3cVuTnMj8FeqK82PDgK4JzKnLP7LM6GauqTyqnxtcSk1": "Socios.com (Chiliz)", // AS Roma Fan Token
|
|
141
|
+
HE6bLNs16qgQo2jVSMXDSCnxQahjdVrww7qQPrHrZtEw: "Socios.com (Chiliz)", // Juventus Fan Token
|
|
142
|
+
"8WbNQtY7QmXMVKJFTSqFudierVZZtbuoyeepZEqJ1B2w": "Socios.com (Chiliz)", // Manchester City Fan Token
|
|
143
|
+
H5qGPniSX2uCNtAnxr7RpdfFAZcGkr6dknjgpa1AKHe1: "Socios.com (Chiliz)", // AC Milan Fan Token
|
|
144
|
+
Dst93spXQEXxFzwYbFrQRnFYBYpw7AzB2QyALEeP4NGQ: "Socios.com (Chiliz)", // Arsenal Fan Token
|
|
145
|
+
HagS3VmAuhx5QJnHcuMAJF4wwVDE58CiX5SFZCYFrVe: "Socios.com (Chiliz)", // Inter Milan Fan Token
|
|
146
|
+
AMnbxhGifp3gm2YsNwmfcF2ZCLsZN6iP3LdzBPZgGpzW: "Socios.com (Chiliz)", // Trabzonspor Fan Token
|
|
147
|
+
GDNoEjfSAUAvManoEaT3vStGcvwKkcUcSTvUwfvwhqXf: "Socios.com (Chiliz)", // Tottenham Hotspur FC Fan Token
|
|
148
|
+
FG44Jffowai8hqQifkwtNLbADkH3EjG5txMc54yaJ4cN: "Socios.com (Chiliz)", // UFC Fan Token
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Known issuers of tokenized assets: every key that controls their tokens (mint, freeze, permanent delegate,
|
|
152
|
+
// hook, pause, scaling). A token is theirs only if ALL its control keys are in the list, so copying one key
|
|
153
|
+
// (anyone can hand the mint authority to someone else's wallet) is not enough. Their control is the point of
|
|
154
|
+
// the product: it is shown as dependency on the issuer, not as a creator who can rug
|
|
155
|
+
export const ISSUERS = [
|
|
156
|
+
{ name: "xStocks (Backed)", keys: [
|
|
157
|
+
"7pt9tkctJPK7PPNQJ77GKg8ZffSF6QxoMiCFYHxrtaCj", // mint
|
|
158
|
+
"JDq14BWvqCRFNu1krb12bcRpbGtJZ1FLEakMw6FdxJNs", // freeze and pause (program)
|
|
159
|
+
"5aMNNLQJwAEeoemTEMkv5NVjqKwvvefRYCQ5Z67HFvEq", // permanent delegate, transfer hook, confidential transfers
|
|
160
|
+
"S7vYFFWH6BjJyEsdrPQpqpYTqLTrPRK6KW3VwsJuRaS" // share-split multiplier (scaled UI amount)
|
|
161
|
+
] }
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
// Token-2022 extensions that add risk, with the points they add to the no-market spam score
|
|
165
|
+
export const EXT_POINTS = {
|
|
166
|
+
permanentDelegate: 25,
|
|
167
|
+
transferHook: 15,
|
|
168
|
+
transferFeeConfig: 10,
|
|
169
|
+
nonTransferable: 10,
|
|
170
|
+
defaultAccountState: 10
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Risk levels, from worst to best (also the default sort order of results)
|
|
174
|
+
export const LEVELS = ["HIGH", "MEDIUM", "LOW", "SPAM", "NO_DATA", "NO_MARKET"];
|
|
175
|
+
export const TYPES = ["STABLE", "TOKENIZED", "BRIDGED", "CREATOR", "OPEN"];
|
|
176
|
+
export const LIGHTS = ["control", "concentration", "market", "dependency"];
|
|
177
|
+
export const RANKS = { ok: 0, na: 0, warn: 1, bad: 2 };
|
|
178
|
+
|
|
179
|
+
export const ADDRESS_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
package/src/markets.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEX, DEX_SEARCH, GECKO, USDC, USDT, WSOL, FAMOUS, BRANDS } from "./constants.js";
|
|
1
|
+
import { DEX, DEX_SEARCH, GECKO, USDC, USDT, WSOL, FAMOUS, BRANDS, brandKey, BRAND_MATURE_DAYS, BRAND_MATURE_LIQ } from "./constants.js";
|
|
2
2
|
import { ScanError, isCancel } from "./errors.js";
|
|
3
3
|
import { sleep } from "./util.js";
|
|
4
4
|
|
|
@@ -38,16 +38,18 @@ export function fakeLiquidity(pair) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
// A real company's name on a token that is not issued by anyone: {brand, exact}. exact = the name or the
|
|
41
|
-
// symbol is just the brand ("Spotify"); otherwise the brand is one word of a longer name ("Spotify Cat")
|
|
42
|
-
|
|
41
|
+
// symbol is just the brand ("Spotify"); otherwise the brand is one word of a longer name ("Spotify Cat").
|
|
42
|
+
// Established markets (see BRAND_MATURE_DAYS) are left alone
|
|
43
|
+
export function brandOf(pair, type, now) {
|
|
43
44
|
if (type === "TOKENIZED" || type === "BRIDGED" || type === "STABLE") return null;
|
|
45
|
+
const liq = (pair && pair.liquidity && pair.liquidity.usd) || 0;
|
|
46
|
+
const days = (pair && pair.pairCreatedAt) ? ((now || Date.now()) - pair.pairCreatedAt) / 86400000 : 0;
|
|
47
|
+
if (days >= BRAND_MATURE_DAYS && liq >= BRAND_MATURE_LIQ) return null;
|
|
44
48
|
const b = (pair && pair.baseToken) || {};
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (name === w || sym === w || name.replace(/ /g, "") === w.replace(/ /g, "")) return { brand: BRANDS[k], exact: true };
|
|
50
|
-
if ((" " + name + " ").indexOf(" " + w + " ") >= 0) return { brand: BRANDS[k], exact: false };
|
|
49
|
+
const name = brandKey(b.name), sym = brandKey(b.symbol);
|
|
50
|
+
for (const w of Object.keys(BRANDS)) {
|
|
51
|
+
if (name === w || sym === w || name.replace(/ /g, "") === w.replace(/ /g, "")) return { brand: BRANDS[w], exact: true };
|
|
52
|
+
if ((" " + name + " ").indexOf(" " + w + " ") >= 0) return { brand: BRANDS[w], exact: false };
|
|
51
53
|
}
|
|
52
54
|
return null;
|
|
53
55
|
}
|