solana-risk-engine 0.4.4 → 0.4.6
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/base.js +28 -28
- package/src/client.js +157 -157
- package/src/constants.js +183 -93
- package/src/holders.js +274 -274
- package/src/i18n/en.js +114 -114
- package/src/i18n/es.js +117 -117
- package/src/index.js +60 -60
- package/src/markets.js +141 -136
- package/src/risk.js +302 -293
- package/src/tokens.js +123 -123
- package/src/wallet.js +94 -94
package/src/i18n/en.js
CHANGED
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
function usd(n) {
|
|
2
|
-
if (!n) return "$0";
|
|
3
|
-
if (n < 0.01) return "<$0.01";
|
|
4
|
-
return "$" + n.toLocaleString("en-US", { minimumFractionDigits: n < 1000 ? 2 : 0, maximumFractionDigits: n < 1000 ? 2 : 0 });
|
|
5
|
-
}
|
|
6
|
-
function pct(n) { return Math.round(n) + "%"; }
|
|
7
|
-
function short(a) { return a.slice(0, 4) + "…" + a.slice(-4); }
|
|
8
|
-
function prog(d) { return d && d.prog >= 20 ? ". Pools and programs hold " + pct(d.prog) : ""; }
|
|
9
|
-
|
|
10
|
-
const EXT = {
|
|
11
|
-
permanentDelegate: "The issuer can move or burn your tokens (permanent delegate). Normal for tokenized stocks, but you have to trust the issuer",
|
|
12
|
-
transferHook: "Has a transfer hook: runs external code on every transfer",
|
|
13
|
-
transferFeeConfig: "Charges a fee on every transfer",
|
|
14
|
-
nonTransferable: "Cannot be transferred",
|
|
15
|
-
defaultAccountState: "New accounts can be created frozen"
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export default {
|
|
19
|
-
fmt: { usd: usd, pct: pct, short: short },
|
|
20
|
-
signals: {
|
|
21
|
-
NO_INFO: () => "Could not read the token's information",
|
|
22
|
-
MINT_BY_PROGRAM: () => "A program controls the mint (usually a bridge or protocol): you have to trust that code",
|
|
23
|
-
MINT_ACTIVE: (d) => "The creator can still mint more tokens (mint authority active" + (d && d.byWallet ? ", held by a wallet" : "") + ")",
|
|
24
|
-
FREEZE_BY_PROGRAM: () => "A program controls freezing: it can freeze accounts according to its code",
|
|
25
|
-
FREEZE_ACTIVE: (d) => "The creator can freeze accounts (freeze authority active" + (d && d.byWallet ? ", held by a wallet" : "") + ")",
|
|
26
|
-
EXTENSION: (d) => EXT[d.ext] || ("Extension " + d.ext),
|
|
27
|
-
NO_MARKET: () => "No market on DexScreener (no price or liquidity)",
|
|
28
|
-
MARKET_UNCHECKED: () => "Could not check this token's market (network error reaching DexScreener): analyse it again to check",
|
|
29
|
-
KNOWN_TOKEN: () => "Well-known token",
|
|
30
|
-
|
|
31
|
-
CTL_MINT_ACTIVE: () => "The creator can mint more tokens (mint authority active)",
|
|
32
|
-
CTL_FREEZE_ACTIVE: () => "The creator can freeze accounts (freeze authority active)",
|
|
33
|
-
CTL_TRANSFER_HOOK: () => "Runs external code on every transfer",
|
|
34
|
-
CTL_TRANSFER_FEE: () => "Charges a fee on every transfer",
|
|
35
|
-
CTL_NON_TRANSFERABLE: () => "Cannot be transferred",
|
|
36
|
-
CTL_DEFAULT_FROZEN: () => "New accounts can be created frozen",
|
|
37
|
-
CTL_ONLY_PROGRAMS: () => "Only program-controlled authorities (see dependency)",
|
|
38
|
-
CTL_KNOWN_ISSUER: (d) => "Controlled by its issuer, " + d.issuer + " (see dependency)",
|
|
39
|
-
CTL_NONE: () => "No active authorities: nobody can mint more or freeze",
|
|
40
|
-
CTL_SERIAL_CREATOR: (d) => "The creator launched " + d.n + " other tokens in the last 24 h (per RugCheck): a serial launcher, who usually drops each token as soon as buyers arrive",
|
|
41
|
-
BRAND_COPY: (d) => "Uses the name of " + d.brand + ", a real company with no token on Solana: it is not official, almost certainly an imitation to draw buyers",
|
|
42
|
-
BRAND_NAME: (d) => "Uses the name of " + d.brand + ", a real company: it is not an official " + d.brand + " token",
|
|
43
|
-
COPYCAT: (d) => "There " + (d.n === 1 ? "is another token" : "are " + d.n + " more tokens") + " with the same name and ticker; the oldest one (" + short(d.original) + ", " + d.days + (d.days === 1 ? " day" : " days") + " old) is not this one: check you have the right address",
|
|
44
|
-
HOLD_GROUP: (d) => d.n + " holders got their first SOL from the same wallet and together hold " + pct(d.pct) + " of the supply: most likely one person or team",
|
|
45
|
-
CTL_CREATOR_HISTORY: (d) => "Of the " + d.old + " tokens the creator launched before (over 24 h ago), " + d.dead + " stayed under $10,000 market cap (per RugCheck): their launches rarely take off",
|
|
46
|
-
IMPOSTOR: (d) => "Impersonates " + d.symbol + ": the real " + d.symbol + " has another address (" + short(d.real) + "). It is a copy, almost certainly a scam",
|
|
47
|
-
|
|
48
|
-
CON_SKIPPED: () => "Holder concentration not checked",
|
|
49
|
-
CON_UNAVAILABLE: () => "Could not check holder concentration (the service did not answer; try again in a while)",
|
|
50
|
-
CON_ALL_POOLS: (d) => "Almost all the supply is in pools or programs" + prog(d),
|
|
51
|
-
CON_OK: (d) => "No worrying concentration (largest individual wallet: " + pct(d.w1) + ")" + prog(d),
|
|
52
|
-
CON_HIGH: (d) => "The largest individual wallet holds " + pct(d.w1) + " and the top 10 hold " + pct(d.w10) + " of the supply" + prog(d),
|
|
53
|
-
CON_UNSPLIT: (d) => "Could not separate pools from people. The largest account holds " + pct(d.top1) + " of the supply",
|
|
54
|
-
|
|
55
|
-
MKT_LIQ_INFLATED: (d) => "Inflated liquidity: DexScreener says " + usd(d.reported) + ", but the pool only has about " + usd(d.real) + " in real tokens (USDC, USDT or SOL). That is the most you could get out when selling" + (d.reported >= 100 * Math.max(d.real, 1) ? ". A gap like that is no accident: it is set up to make the token look established" : ""),
|
|
56
|
-
MKT_LIQ_VERY_LOW: (d) => "Very low liquidity (" + usd(d.liq) + ")",
|
|
57
|
-
MKT_LIQ_LOW: (d) => "Low liquidity (" + usd(d.liq) + ")",
|
|
58
|
-
MKT_VOLUME_LOW: (d) => "Almost no 24h volume (" + usd(d.vol) + ")",
|
|
59
|
-
MKT_NEW: (d) => "Very new market (" + (d.days < 1 ? "less than a day" : d.days + (d.days === 1 ? " day" : " days")) + ")",
|
|
60
|
-
MKT_POSITION_HEAVY: (d) => "This wallet's position equals " + pct(d.pct) + " of the liquidity: selling at once would move the price a lot",
|
|
61
|
-
MKT_LP_UNLOCKED: (d) => "Only " + pct(d.pct) + " of the liquidity is locked or burned (per RugCheck): the rest can be pulled at once",
|
|
62
|
-
MKT_LP_PARTLY_LOCKED: (d) => "Only " + pct(d.pct) + " of the liquidity is locked or burned (per RugCheck)",
|
|
63
|
-
MKT_OK: (d) => "Liquidity " + usd(d.liq) + " · 24h volume " + usd(d.vol),
|
|
64
|
-
|
|
65
|
-
DEP_PROGRAM_AUTHORITY: () => "A program controls the mint or freeze (bridge or protocol): you have to trust its code",
|
|
66
|
-
DEP_PERMANENT_DELEGATE: () => "The issuer can move or burn your tokens (permanent delegate): you trust the issuer",
|
|
67
|
-
DEP_STABLE_ISSUER: () => "Its value depends on whoever issues and backs it",
|
|
68
|
-
DEP_KNOWN_ISSUER: (d) => "Issued by " + d.issuer + ": it can mint, freeze or move tokens, like any regulated issuer. You trust the issuer",
|
|
69
|
-
DEP_NONE: () => "Does not depend on an issuer or a bridge"
|
|
70
|
-
},
|
|
71
|
-
offSolana: " and its main market may be outside Solana",
|
|
72
|
-
levels: {
|
|
73
|
-
HIGH: "High risk", MEDIUM: "Medium risk", LOW: "Low risk", SPAM: "Likely spam",
|
|
74
|
-
NO_DATA: "Not checked", NO_MARKET: "No market", MEDIUM_DATA_ONLY: "Medium due to missing data"
|
|
75
|
-
},
|
|
76
|
-
types: {
|
|
77
|
-
STABLE: { label: "Stablecoin", note: "Judged by its liquidity and trust in the issuer; concentration matters less." },
|
|
78
|
-
TOKENIZED: { label: "Tokenized or regulated", note: "The issuer normally keeps control (permanent delegate). The real risk is trusting the issuer and having liquidity to exit." },
|
|
79
|
-
BRIDGED: { label: "Bridged or protocol", note: "A program normally controls the mint. The real risk is trusting that bridge and its Solana market being small, since the main one may be on another chain." },
|
|
80
|
-
CREATOR: { label: "Creator-controlled", note: "A wallet can mint more or freeze accounts: the typical scam pattern, so it is judged more strictly." },
|
|
81
|
-
OPEN: { label: "Open token", note: "No creator authorities, typical of memecoins and new projects. Concentration in people and liquidity matter most." }
|
|
82
|
-
},
|
|
83
|
-
lights: { control: "Creator control", concentration: "Concentration", market: "Market and exit", dependency: "Dependency" },
|
|
84
|
-
missing: { control: "who controls the token", concentration: "holder concentration", market: "the market", dependency: "issuer dependency" },
|
|
85
|
-
steps: {
|
|
86
|
-
address: "Checking the address…", wallet: "Reading the wallet…", markets: "Fetching prices and liquidity…",
|
|
87
|
-
tokens: "Reviewing tokens…", token: "Reading the token…", owners: "Finding who owns each account…",
|
|
88
|
-
kinds: "Telling wallets from pools and programs…", bots: "Separating people from bots and exchanges…",
|
|
89
|
-
funders: "Looking for wallets funded from the same source…", exchangeSources: "Checking whether each group's source is an exchange…",
|
|
90
|
-
creator: "Looking up who created the token (RugCheck)…", creatorTokens: "Reviewing the creator's other tokens…",
|
|
91
|
-
networks: "Checking what wallet networks hold today…", wallets: "Reading wallets…",
|
|
92
|
-
pnl: "Estimating each wallet's result…", done: "Done"
|
|
93
|
-
},
|
|
94
|
-
notes: {
|
|
95
|
-
PNL_NO_HELIUS: "Wallet results were not estimated because there is no Helius key.",
|
|
96
|
-
PNL_PARTIAL: "Some wallets' history could not be read.",
|
|
97
|
-
PNL_APPROX: "SOL price history was unavailable: today's price was used and results may be far off."
|
|
98
|
-
},
|
|
99
|
-
errors: {
|
|
100
|
-
CANCELLED: () => "Cancelled.",
|
|
101
|
-
INVALID_ADDRESS: () => "That does not look like a Solana address. They are 32 to 44 letters and digits and do not start with 0x.",
|
|
102
|
-
NOT_A_TOKEN: () => "That address is not a token.",
|
|
103
|
-
IS_NFT: () => "That address is an NFT, not a token. The scanner does not review NFTs.",
|
|
104
|
-
NO_HOLDERS: () => "The RPC returned no holder data.",
|
|
105
|
-
HELIUS_REQUIRED: () => "Estimating results needs a Helius API key (or a Helius RPC URL with the key).",
|
|
106
|
-
SOL_PRICE: () => "Could not get the SOL price to compute the result. Try again in a while.",
|
|
107
|
-
DEX_UNREACHABLE: () => "Could not connect to DexScreener. Check your internet connection and try again.",
|
|
108
|
-
TOO_FEW_WALLETS: (d) => d && d.filter ? "Only " + d.n + (d.n === 1 ? " wallet passes" : " wallets pass") + " the result filter (of " + d.total + " read)." : "At least 2 readable wallets are needed.",
|
|
109
|
-
TOO_FEW_TOKENS: () => "Give at least 2 Solana token addresses.",
|
|
110
|
-
NETWORK_PUBLIC: () => "The free Solana services did not answer (they get saturated sometimes). Wait a minute and try again, or use your own RPC URL (Helius has a free plan).",
|
|
111
|
-
NETWORK_OWN: () => "Could not connect to your RPC URL. Check it was copied correctly (with the key at the end).",
|
|
112
|
-
UNKNOWN: (d) => "Something failed: " + d.message + ". Try again or use another RPC."
|
|
113
|
-
}
|
|
114
|
-
};
|
|
1
|
+
function usd(n) {
|
|
2
|
+
if (!n) return "$0";
|
|
3
|
+
if (n < 0.01) return "<$0.01";
|
|
4
|
+
return "$" + n.toLocaleString("en-US", { minimumFractionDigits: n < 1000 ? 2 : 0, maximumFractionDigits: n < 1000 ? 2 : 0 });
|
|
5
|
+
}
|
|
6
|
+
function pct(n) { return Math.round(n) + "%"; }
|
|
7
|
+
function short(a) { return a.slice(0, 4) + "…" + a.slice(-4); }
|
|
8
|
+
function prog(d) { return d && d.prog >= 20 ? ". Pools and programs hold " + pct(d.prog) : ""; }
|
|
9
|
+
|
|
10
|
+
const EXT = {
|
|
11
|
+
permanentDelegate: "The issuer can move or burn your tokens (permanent delegate). Normal for tokenized stocks, but you have to trust the issuer",
|
|
12
|
+
transferHook: "Has a transfer hook: runs external code on every transfer",
|
|
13
|
+
transferFeeConfig: "Charges a fee on every transfer",
|
|
14
|
+
nonTransferable: "Cannot be transferred",
|
|
15
|
+
defaultAccountState: "New accounts can be created frozen"
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
fmt: { usd: usd, pct: pct, short: short },
|
|
20
|
+
signals: {
|
|
21
|
+
NO_INFO: () => "Could not read the token's information",
|
|
22
|
+
MINT_BY_PROGRAM: () => "A program controls the mint (usually a bridge or protocol): you have to trust that code",
|
|
23
|
+
MINT_ACTIVE: (d) => "The creator can still mint more tokens (mint authority active" + (d && d.byWallet ? ", held by a wallet" : "") + ")",
|
|
24
|
+
FREEZE_BY_PROGRAM: () => "A program controls freezing: it can freeze accounts according to its code",
|
|
25
|
+
FREEZE_ACTIVE: (d) => "The creator can freeze accounts (freeze authority active" + (d && d.byWallet ? ", held by a wallet" : "") + ")",
|
|
26
|
+
EXTENSION: (d) => EXT[d.ext] || ("Extension " + d.ext),
|
|
27
|
+
NO_MARKET: () => "No market on DexScreener (no price or liquidity)",
|
|
28
|
+
MARKET_UNCHECKED: () => "Could not check this token's market (network error reaching DexScreener): analyse it again to check",
|
|
29
|
+
KNOWN_TOKEN: () => "Well-known token",
|
|
30
|
+
|
|
31
|
+
CTL_MINT_ACTIVE: () => "The creator can mint more tokens (mint authority active)",
|
|
32
|
+
CTL_FREEZE_ACTIVE: () => "The creator can freeze accounts (freeze authority active)",
|
|
33
|
+
CTL_TRANSFER_HOOK: () => "Runs external code on every transfer",
|
|
34
|
+
CTL_TRANSFER_FEE: () => "Charges a fee on every transfer",
|
|
35
|
+
CTL_NON_TRANSFERABLE: () => "Cannot be transferred",
|
|
36
|
+
CTL_DEFAULT_FROZEN: () => "New accounts can be created frozen",
|
|
37
|
+
CTL_ONLY_PROGRAMS: () => "Only program-controlled authorities (see dependency)",
|
|
38
|
+
CTL_KNOWN_ISSUER: (d) => "Controlled by its issuer, " + d.issuer + " (see dependency)",
|
|
39
|
+
CTL_NONE: () => "No active authorities: nobody can mint more or freeze",
|
|
40
|
+
CTL_SERIAL_CREATOR: (d) => "The creator launched " + d.n + " other tokens in the last 24 h (per RugCheck): a serial launcher, who usually drops each token as soon as buyers arrive",
|
|
41
|
+
BRAND_COPY: (d) => "Uses the name of " + d.brand + ", a real company with no token on Solana: it is not official, almost certainly an imitation to draw buyers",
|
|
42
|
+
BRAND_NAME: (d) => "Uses the name of " + d.brand + ", a real company: it is not an official " + d.brand + " token",
|
|
43
|
+
COPYCAT: (d) => "There " + (d.n === 1 ? "is another token" : "are " + d.n + " more tokens") + " with the same name and ticker; the oldest one with a real market (" + short(d.original) + ", " + d.days + (d.days === 1 ? " day" : " days") + " old) is not this one: check you have the right address",
|
|
44
|
+
HOLD_GROUP: (d) => d.n + " holders got their first SOL from the same wallet and together hold " + pct(d.pct) + " of the supply: most likely one person or team",
|
|
45
|
+
CTL_CREATOR_HISTORY: (d) => "Of the " + d.old + " tokens the creator launched before (over 24 h ago), " + d.dead + " stayed under $10,000 market cap (per RugCheck): their launches rarely take off",
|
|
46
|
+
IMPOSTOR: (d) => "Impersonates " + d.symbol + ": the real " + d.symbol + " has another address (" + short(d.real) + "). It is a copy, almost certainly a scam",
|
|
47
|
+
|
|
48
|
+
CON_SKIPPED: () => "Holder concentration not checked",
|
|
49
|
+
CON_UNAVAILABLE: () => "Could not check holder concentration (the service did not answer; try again in a while)",
|
|
50
|
+
CON_ALL_POOLS: (d) => "Almost all the supply is in pools or programs" + prog(d),
|
|
51
|
+
CON_OK: (d) => "No worrying concentration (largest individual wallet: " + pct(d.w1) + ")" + prog(d),
|
|
52
|
+
CON_HIGH: (d) => "The largest individual wallet holds " + pct(d.w1) + " and the top 10 hold " + pct(d.w10) + " of the supply" + prog(d),
|
|
53
|
+
CON_UNSPLIT: (d) => "Could not separate pools from people. The largest account holds " + pct(d.top1) + " of the supply",
|
|
54
|
+
|
|
55
|
+
MKT_LIQ_INFLATED: (d) => "Inflated liquidity: DexScreener says " + usd(d.reported) + ", but the pool only has about " + usd(d.real) + " in real tokens (USDC, USDT or SOL). That is the most you could get out when selling" + (d.reported >= 100 * Math.max(d.real, 1) ? ". A gap like that is no accident: it is set up to make the token look established" : ""),
|
|
56
|
+
MKT_LIQ_VERY_LOW: (d) => "Very low liquidity (" + usd(d.liq) + ")",
|
|
57
|
+
MKT_LIQ_LOW: (d) => "Low liquidity (" + usd(d.liq) + ")",
|
|
58
|
+
MKT_VOLUME_LOW: (d) => "Almost no 24h volume (" + usd(d.vol) + ")",
|
|
59
|
+
MKT_NEW: (d) => "Very new market (" + (d.days < 1 ? "less than a day" : d.days + (d.days === 1 ? " day" : " days")) + ")",
|
|
60
|
+
MKT_POSITION_HEAVY: (d) => "This wallet's position equals " + pct(d.pct) + " of the liquidity: selling at once would move the price a lot",
|
|
61
|
+
MKT_LP_UNLOCKED: (d) => "Only " + pct(d.pct) + " of the liquidity is locked or burned (per RugCheck): the rest can be pulled at once",
|
|
62
|
+
MKT_LP_PARTLY_LOCKED: (d) => "Only " + pct(d.pct) + " of the liquidity is locked or burned (per RugCheck)",
|
|
63
|
+
MKT_OK: (d) => "Liquidity " + usd(d.liq) + " · 24h volume " + usd(d.vol),
|
|
64
|
+
|
|
65
|
+
DEP_PROGRAM_AUTHORITY: () => "A program controls the mint or freeze (bridge or protocol): you have to trust its code",
|
|
66
|
+
DEP_PERMANENT_DELEGATE: () => "The issuer can move or burn your tokens (permanent delegate): you trust the issuer",
|
|
67
|
+
DEP_STABLE_ISSUER: () => "Its value depends on whoever issues and backs it",
|
|
68
|
+
DEP_KNOWN_ISSUER: (d) => "Issued by " + d.issuer + ": it can mint, freeze or move tokens, like any regulated issuer. You trust the issuer",
|
|
69
|
+
DEP_NONE: () => "Does not depend on an issuer or a bridge"
|
|
70
|
+
},
|
|
71
|
+
offSolana: " and its main market may be outside Solana",
|
|
72
|
+
levels: {
|
|
73
|
+
HIGH: "High risk", MEDIUM: "Medium risk", LOW: "Low risk", SPAM: "Likely spam",
|
|
74
|
+
NO_DATA: "Not checked", NO_MARKET: "No market", MEDIUM_DATA_ONLY: "Medium due to missing data"
|
|
75
|
+
},
|
|
76
|
+
types: {
|
|
77
|
+
STABLE: { label: "Stablecoin", note: "Judged by its liquidity and trust in the issuer; concentration matters less." },
|
|
78
|
+
TOKENIZED: { label: "Tokenized or regulated", note: "The issuer normally keeps control (permanent delegate). The real risk is trusting the issuer and having liquidity to exit." },
|
|
79
|
+
BRIDGED: { label: "Bridged or protocol", note: "A program normally controls the mint. The real risk is trusting that bridge and its Solana market being small, since the main one may be on another chain." },
|
|
80
|
+
CREATOR: { label: "Creator-controlled", note: "A wallet can mint more or freeze accounts: the typical scam pattern, so it is judged more strictly." },
|
|
81
|
+
OPEN: { label: "Open token", note: "No creator authorities, typical of memecoins and new projects. Concentration in people and liquidity matter most." }
|
|
82
|
+
},
|
|
83
|
+
lights: { control: "Creator control", concentration: "Concentration", market: "Market and exit", dependency: "Dependency" },
|
|
84
|
+
missing: { control: "who controls the token", concentration: "holder concentration", market: "the market", dependency: "issuer dependency" },
|
|
85
|
+
steps: {
|
|
86
|
+
address: "Checking the address…", wallet: "Reading the wallet…", markets: "Fetching prices and liquidity…",
|
|
87
|
+
tokens: "Reviewing tokens…", token: "Reading the token…", owners: "Finding who owns each account…",
|
|
88
|
+
kinds: "Telling wallets from pools and programs…", bots: "Separating people from bots and exchanges…",
|
|
89
|
+
funders: "Looking for wallets funded from the same source…", exchangeSources: "Checking whether each group's source is an exchange…",
|
|
90
|
+
creator: "Looking up who created the token (RugCheck)…", creatorTokens: "Reviewing the creator's other tokens…",
|
|
91
|
+
networks: "Checking what wallet networks hold today…", wallets: "Reading wallets…",
|
|
92
|
+
pnl: "Estimating each wallet's result…", done: "Done"
|
|
93
|
+
},
|
|
94
|
+
notes: {
|
|
95
|
+
PNL_NO_HELIUS: "Wallet results were not estimated because there is no Helius key.",
|
|
96
|
+
PNL_PARTIAL: "Some wallets' history could not be read.",
|
|
97
|
+
PNL_APPROX: "SOL price history was unavailable: today's price was used and results may be far off."
|
|
98
|
+
},
|
|
99
|
+
errors: {
|
|
100
|
+
CANCELLED: () => "Cancelled.",
|
|
101
|
+
INVALID_ADDRESS: () => "That does not look like a Solana address. They are 32 to 44 letters and digits and do not start with 0x.",
|
|
102
|
+
NOT_A_TOKEN: () => "That address is not a token.",
|
|
103
|
+
IS_NFT: () => "That address is an NFT, not a token. The scanner does not review NFTs.",
|
|
104
|
+
NO_HOLDERS: () => "The RPC returned no holder data.",
|
|
105
|
+
HELIUS_REQUIRED: () => "Estimating results needs a Helius API key (or a Helius RPC URL with the key).",
|
|
106
|
+
SOL_PRICE: () => "Could not get the SOL price to compute the result. Try again in a while.",
|
|
107
|
+
DEX_UNREACHABLE: () => "Could not connect to DexScreener. Check your internet connection and try again.",
|
|
108
|
+
TOO_FEW_WALLETS: (d) => d && d.filter ? "Only " + d.n + (d.n === 1 ? " wallet passes" : " wallets pass") + " the result filter (of " + d.total + " read)." : "At least 2 readable wallets are needed.",
|
|
109
|
+
TOO_FEW_TOKENS: () => "Give at least 2 Solana token addresses.",
|
|
110
|
+
NETWORK_PUBLIC: () => "The free Solana services did not answer (they get saturated sometimes). Wait a minute and try again, or use your own RPC URL (Helius has a free plan).",
|
|
111
|
+
NETWORK_OWN: () => "Could not connect to your RPC URL. Check it was copied correctly (with the key at the end).",
|
|
112
|
+
UNKNOWN: (d) => "Something failed: " + d.message + ". Try again or use another RPC."
|
|
113
|
+
}
|
|
114
|
+
};
|
package/src/i18n/es.js
CHANGED
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
// Spanish texts: the same wording the original single-file scanner used
|
|
2
|
-
function usd(n) {
|
|
3
|
-
if (!n) return "0 $";
|
|
4
|
-
if (n < 0.01) return "<0,01 $";
|
|
5
|
-
// de-DE instead of es-ES: same format (dot thousands, comma decimals), but es-ES does not group
|
|
6
|
-
// 4-digit numbers and "6494 $" showed next to "22.505 $"
|
|
7
|
-
return n.toLocaleString("de-DE", { minimumFractionDigits: n < 1000 ? 2 : 0, maximumFractionDigits: n < 1000 ? 2 : 0 }) + " $";
|
|
8
|
-
}
|
|
9
|
-
function pct(n) { return Math.round(n) + "%"; }
|
|
10
|
-
function short(a) { return a.slice(0, 4) + "…" + a.slice(-4); }
|
|
11
|
-
function prog(d) { return d && d.prog >= 20 ? ". Los pools y programas guardan el " + pct(d.prog) : ""; }
|
|
12
|
-
|
|
13
|
-
const EXT = {
|
|
14
|
-
permanentDelegate: "El emisor puede mover o quemar tus tokens (delegado permanente). Es normal en acciones tokenizadas, pero hay que confiar en el emisor",
|
|
15
|
-
transferHook: "Tiene transfer hook: ejecuta código externo en cada transferencia",
|
|
16
|
-
transferFeeConfig: "Cobra una comisión en cada transferencia",
|
|
17
|
-
nonTransferable: "No se puede transferir",
|
|
18
|
-
defaultAccountState: "Las cuentas nuevas pueden crearse congeladas"
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export default {
|
|
22
|
-
fmt: { usd: usd, pct: pct, short: short },
|
|
23
|
-
signals: {
|
|
24
|
-
NO_INFO: () => "No se pudo leer la información del token",
|
|
25
|
-
MINT_BY_PROGRAM: () => "El mint lo controla un programa (suele ser un puente o un protocolo): hay que confiar en ese código",
|
|
26
|
-
MINT_ACTIVE: (d) => "El creador todavía puede crear más tokens (mint activo" + (d && d.byWallet ? ", en manos de una wallet" : "") + ")",
|
|
27
|
-
FREEZE_BY_PROGRAM: () => "El freeze lo controla un programa: puede congelar cuentas según su código",
|
|
28
|
-
FREEZE_ACTIVE: (d) => "El creador puede congelar cuentas (freeze activo" + (d && d.byWallet ? ", en manos de una wallet" : "") + ")",
|
|
29
|
-
EXTENSION: (d) => EXT[d.ext] || ("Extensión " + d.ext),
|
|
30
|
-
NO_MARKET: () => "No hay mercado en DexScreener (sin precio ni liquidez)",
|
|
31
|
-
MARKET_UNCHECKED: () => "No se pudo consultar el mercado de este token (fallo de red al conectar con DexScreener): vuelve a analizarlo para comprobarlo",
|
|
32
|
-
KNOWN_TOKEN: () => "Token muy conocido",
|
|
33
|
-
|
|
34
|
-
CTL_MINT_ACTIVE: () => "El creador puede crear más tokens (mint activo)",
|
|
35
|
-
CTL_FREEZE_ACTIVE: () => "El creador puede congelar cuentas (freeze activo)",
|
|
36
|
-
CTL_TRANSFER_HOOK: () => "Ejecuta código externo en cada transferencia",
|
|
37
|
-
CTL_TRANSFER_FEE: () => "Cobra una comisión en cada transferencia",
|
|
38
|
-
CTL_NON_TRANSFERABLE: () => "No se puede transferir",
|
|
39
|
-
CTL_DEFAULT_FROZEN: () => "Las cuentas nuevas pueden crearse congeladas",
|
|
40
|
-
CTL_ONLY_PROGRAMS: () => "Solo hay autoridades controladas por un programa (ver dependencia)",
|
|
41
|
-
CTL_KNOWN_ISSUER: (d) => "Lo controla su emisor, " + d.issuer + " (ver dependencia)",
|
|
42
|
-
CTL_NONE: () => "Sin autoridades activas: nadie puede crear más ni congelar",
|
|
43
|
-
CTL_SERIAL_CREATOR: (d) => "El creador ha lanzado " + d.n + " tokens más en las últimas 24 h (según RugCheck): es un lanzador en serie, que suele abandonar cada token en cuanto llegan compradores",
|
|
44
|
-
BRAND_COPY: (d) => "Usa el nombre de " + d.brand + ", una empresa real que no tiene token en Solana: no es oficial, casi seguro una imitación para atraer compradores",
|
|
45
|
-
BRAND_NAME: (d) => "Usa el nombre de " + d.brand + ", una empresa real: no es un token oficial de " + d.brand,
|
|
46
|
-
COPYCAT: (d) => "Hay " + (d.n === 1 ? "otro token" : d.n + " tokens más") + " con el mismo nombre y ticker; el más antiguo (" + short(d.original) + ", de hace " + d.days + (d.days === 1 ? " día" : " días") + ") no es este: comprueba que tienes la dirección correcta",
|
|
47
|
-
HOLD_GROUP: (d) => d.n + " holders recibieron su primer SOL de la misma wallet y juntos tienen el " + pct(d.pct) + " del suministro: probablemente son la misma persona o equipo",
|
|
48
|
-
CTL_CREATOR_HISTORY: (d) => "De los " + d.old + " tokens que el creador lanzó antes (hace más de 24 h), " + d.dead + " se quedaron por debajo de 10.000 $ de capitalización (según RugCheck): sus lanzamientos no suelen despegar",
|
|
49
|
-
IMPOSTOR: (d) => "Se hace pasar por " + d.symbol + ": el " + d.symbol + " de verdad tiene otra dirección (" + short(d.real) + "). Es una copia, casi seguro una estafa",
|
|
50
|
-
|
|
51
|
-
CON_SKIPPED: () => "Sin comprobar la concentración de holders",
|
|
52
|
-
CON_UNAVAILABLE: () => "No se pudo comprobar la concentración de holders (el servicio no respondió; prueba otra vez en un rato)",
|
|
53
|
-
CON_ALL_POOLS: (d) => "Casi todo el supply está en pools o programas" + prog(d),
|
|
54
|
-
CON_OK: (d) => "Sin concentración preocupante (mayor wallet individual: " + pct(d.w1) + ")" + prog(d),
|
|
55
|
-
CON_HIGH: (d) => "La mayor wallet individual tiene el " + pct(d.w1) + " y las 10 mayores el " + pct(d.w10) + " del supply" + prog(d),
|
|
56
|
-
CON_UNSPLIT: (d) => "No se pudo separar pools de personas. La mayor cuenta tiene el " + pct(d.top1) + " del supply",
|
|
57
|
-
|
|
58
|
-
MKT_LIQ_INFLATED: (d) => "Liquidez inflada: DexScreener dice " + usd(d.reported) + ", pero el pool solo tiene unos " + usd(d.real) + " en tokens de verdad (USDC, USDT o SOL). Es lo máximo que podrías sacar al vender" + (d.reported >= 100 * Math.max(d.real, 1) ? ". Una diferencia así no es casual: está montada para que el token parezca establecido" : ""),
|
|
59
|
-
MKT_LIQ_VERY_LOW: (d) => "Liquidez muy baja (" + usd(d.liq) + ")",
|
|
60
|
-
MKT_LIQ_LOW: (d) => "Liquidez baja (" + usd(d.liq) + ")",
|
|
61
|
-
MKT_VOLUME_LOW: (d) => "Volumen de 24 h casi nulo (" + usd(d.vol) + ")",
|
|
62
|
-
MKT_NEW: (d) => "Mercado muy nuevo (" + (d.days < 1 ? "menos de un día" : d.days + (d.days === 1 ? " día" : " días")) + ")",
|
|
63
|
-
MKT_POSITION_HEAVY: (d) => "La posición de esta wallet equivale al " + pct(d.pct) + " de la liquidez: vender de golpe movería mucho el precio",
|
|
64
|
-
MKT_LP_UNLOCKED: (d) => "Solo el " + pct(d.pct) + " de la liquidez está bloqueada o quemada (según RugCheck): el resto se puede retirar de golpe",
|
|
65
|
-
MKT_LP_PARTLY_LOCKED: (d) => "Solo el " + pct(d.pct) + " de la liquidez está bloqueada o quemada (según RugCheck)",
|
|
66
|
-
MKT_OK: (d) => "Liquidez " + usd(d.liq) + " · volumen 24 h " + usd(d.vol),
|
|
67
|
-
|
|
68
|
-
DEP_PROGRAM_AUTHORITY: () => "Un programa controla el mint o el freeze (puente o protocolo): hay que confiar en su código",
|
|
69
|
-
DEP_PERMANENT_DELEGATE: () => "El emisor puede mover o quemar tus tokens (delegado permanente): confías en el emisor",
|
|
70
|
-
DEP_STABLE_ISSUER: () => "Su valor depende de quien la emite y la respalda",
|
|
71
|
-
DEP_KNOWN_ISSUER: (d) => "Lo emite " + d.issuer + ": puede crear, congelar o mover tokens, como cualquier emisor regulado. Confías en el emisor",
|
|
72
|
-
DEP_NONE: () => "No depende de un emisor ni de un puente"
|
|
73
|
-
},
|
|
74
|
-
offSolana: " y su mercado principal puede estar fuera de Solana",
|
|
75
|
-
levels: {
|
|
76
|
-
HIGH: "Riesgo alto", MEDIUM: "Riesgo medio", LOW: "Riesgo bajo", SPAM: "Probable spam",
|
|
77
|
-
NO_DATA: "Sin comprobar", NO_MARKET: "Sin mercado", MEDIUM_DATA_ONLY: "Medio por falta de datos"
|
|
78
|
-
},
|
|
79
|
-
types: {
|
|
80
|
-
STABLE: { label: "Stablecoin", note: "Se juzga por su liquidez y por la confianza en quien la emite; la concentración pesa menos." },
|
|
81
|
-
TOKENIZED: { label: "Tokenizado o regulado", note: "Lo normal es que el emisor tenga control (delegado permanente). El riesgo real es confiar en el emisor y que haya liquidez para salir." },
|
|
82
|
-
BRIDGED: { label: "Puenteado o de protocolo", note: "Lo normal es que un programa controle el mint. El riesgo real es confiar en ese puente y que su mercado en Solana sea pequeño, porque el principal puede estar en otra red." },
|
|
83
|
-
CREATOR: { label: "Con control del creador", note: "Una wallet puede crear más tokens o congelar cuentas: es el patrón típico de estafa, así que se juzga con más dureza." },
|
|
84
|
-
OPEN: { label: "Token abierto", note: "Sin autoridades del creador, típico de memecoins y proyectos nuevos. Pesan sobre todo la concentración en personas y la liquidez." }
|
|
85
|
-
},
|
|
86
|
-
lights: { control: "Control del creador", concentration: "Concentración", market: "Mercado y salida", dependency: "Dependencia" },
|
|
87
|
-
missing: { control: "quién controla el token", concentration: "la concentración de holders", market: "el mercado", dependency: "la dependencia de un emisor" },
|
|
88
|
-
steps: {
|
|
89
|
-
address: "Comprobando la dirección…", wallet: "Leyendo la wallet…", markets: "Consultando precios y liquidez…",
|
|
90
|
-
tokens: "Revisando tokens…", token: "Leyendo el token…", owners: "Buscando a quién pertenece cada cuenta…",
|
|
91
|
-
kinds: "Distinguiendo wallets de pools y programas…", bots: "Separando personas de bots y exchanges…",
|
|
92
|
-
funders: "Buscando wallets con el mismo origen de fondos…", exchangeSources: "Comprobando si el origen de cada grupo es un exchange…",
|
|
93
|
-
creator: "Mirando quién creó el token (RugCheck)…", creatorTokens: "Revisando otros tokens del creador…",
|
|
94
|
-
networks: "Comprobando cuánto tienen hoy las redes de wallets…", wallets: "Leyendo wallets…",
|
|
95
|
-
pnl: "Estimando el resultado de cada wallet…", done: "Listo"
|
|
96
|
-
},
|
|
97
|
-
notes: {
|
|
98
|
-
PNL_NO_HELIUS: "No se estimó el resultado de las wallets porque falta una clave de Helius.",
|
|
99
|
-
PNL_PARTIAL: "No se pudo leer el historial de algunas wallets.",
|
|
100
|
-
PNL_APPROX: "No se pudo obtener el histórico de precio de SOL: se usó el precio de hoy y los resultados pueden estar muy alejados de la realidad."
|
|
101
|
-
},
|
|
102
|
-
errors: {
|
|
103
|
-
CANCELLED: () => "Cancelado.",
|
|
104
|
-
INVALID_ADDRESS: () => "Esa dirección no parece de Solana. Son de 32 a 44 letras y números y no empiezan por 0x.",
|
|
105
|
-
NOT_A_TOKEN: () => "Esa dirección no es un token.",
|
|
106
|
-
IS_NFT: () => "Esa dirección es un NFT, no un token. El escáner no revisa NFTs.",
|
|
107
|
-
NO_HOLDERS: () => "El RPC no devolvió datos de holders.",
|
|
108
|
-
HELIUS_REQUIRED: () => "Para estimar el resultado hace falta una clave de Helius (o una URL de RPC de Helius con la clave).",
|
|
109
|
-
SOL_PRICE: () => "No se pudo obtener el precio de SOL para calcular el resultado. Prueba otra vez dentro de un rato.",
|
|
110
|
-
DEX_UNREACHABLE: () => "No se pudo conectar con DexScreener. Revisa tu conexión a internet y prueba otra vez.",
|
|
111
|
-
TOO_FEW_WALLETS: (d) => d && d.filter ? "Solo " + d.n + (d.n === 1 ? " wallet cumple" : " wallets cumplen") + " el filtro de resultado (de " + d.total + " leídas)." : "Hacen falta al menos 2 wallets que se puedan leer.",
|
|
112
|
-
TOO_FEW_TOKENS: () => "Pega al menos 2 direcciones de tokens de Solana.",
|
|
113
|
-
NETWORK_PUBLIC: () => "Los servicios gratuitos de Solana no han respondido (a veces se saturan). Espera un minuto y prueba otra vez, o usa tu propia URL de RPC (Helius tiene plan gratuito).",
|
|
114
|
-
NETWORK_OWN: () => "No se pudo conectar con tu URL de RPC. Revisa que esté bien copiada (con la clave al final).",
|
|
115
|
-
UNKNOWN: (d) => "Algo ha fallado: " + d.message + ". Prueba otra vez o usa otro RPC."
|
|
116
|
-
}
|
|
117
|
-
};
|
|
1
|
+
// Spanish texts: the same wording the original single-file scanner used
|
|
2
|
+
function usd(n) {
|
|
3
|
+
if (!n) return "0 $";
|
|
4
|
+
if (n < 0.01) return "<0,01 $";
|
|
5
|
+
// de-DE instead of es-ES: same format (dot thousands, comma decimals), but es-ES does not group
|
|
6
|
+
// 4-digit numbers and "6494 $" showed next to "22.505 $"
|
|
7
|
+
return n.toLocaleString("de-DE", { minimumFractionDigits: n < 1000 ? 2 : 0, maximumFractionDigits: n < 1000 ? 2 : 0 }) + " $";
|
|
8
|
+
}
|
|
9
|
+
function pct(n) { return Math.round(n) + "%"; }
|
|
10
|
+
function short(a) { return a.slice(0, 4) + "…" + a.slice(-4); }
|
|
11
|
+
function prog(d) { return d && d.prog >= 20 ? ". Los pools y programas guardan el " + pct(d.prog) : ""; }
|
|
12
|
+
|
|
13
|
+
const EXT = {
|
|
14
|
+
permanentDelegate: "El emisor puede mover o quemar tus tokens (delegado permanente). Es normal en acciones tokenizadas, pero hay que confiar en el emisor",
|
|
15
|
+
transferHook: "Tiene transfer hook: ejecuta código externo en cada transferencia",
|
|
16
|
+
transferFeeConfig: "Cobra una comisión en cada transferencia",
|
|
17
|
+
nonTransferable: "No se puede transferir",
|
|
18
|
+
defaultAccountState: "Las cuentas nuevas pueden crearse congeladas"
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
fmt: { usd: usd, pct: pct, short: short },
|
|
23
|
+
signals: {
|
|
24
|
+
NO_INFO: () => "No se pudo leer la información del token",
|
|
25
|
+
MINT_BY_PROGRAM: () => "El mint lo controla un programa (suele ser un puente o un protocolo): hay que confiar en ese código",
|
|
26
|
+
MINT_ACTIVE: (d) => "El creador todavía puede crear más tokens (mint activo" + (d && d.byWallet ? ", en manos de una wallet" : "") + ")",
|
|
27
|
+
FREEZE_BY_PROGRAM: () => "El freeze lo controla un programa: puede congelar cuentas según su código",
|
|
28
|
+
FREEZE_ACTIVE: (d) => "El creador puede congelar cuentas (freeze activo" + (d && d.byWallet ? ", en manos de una wallet" : "") + ")",
|
|
29
|
+
EXTENSION: (d) => EXT[d.ext] || ("Extensión " + d.ext),
|
|
30
|
+
NO_MARKET: () => "No hay mercado en DexScreener (sin precio ni liquidez)",
|
|
31
|
+
MARKET_UNCHECKED: () => "No se pudo consultar el mercado de este token (fallo de red al conectar con DexScreener): vuelve a analizarlo para comprobarlo",
|
|
32
|
+
KNOWN_TOKEN: () => "Token muy conocido",
|
|
33
|
+
|
|
34
|
+
CTL_MINT_ACTIVE: () => "El creador puede crear más tokens (mint activo)",
|
|
35
|
+
CTL_FREEZE_ACTIVE: () => "El creador puede congelar cuentas (freeze activo)",
|
|
36
|
+
CTL_TRANSFER_HOOK: () => "Ejecuta código externo en cada transferencia",
|
|
37
|
+
CTL_TRANSFER_FEE: () => "Cobra una comisión en cada transferencia",
|
|
38
|
+
CTL_NON_TRANSFERABLE: () => "No se puede transferir",
|
|
39
|
+
CTL_DEFAULT_FROZEN: () => "Las cuentas nuevas pueden crearse congeladas",
|
|
40
|
+
CTL_ONLY_PROGRAMS: () => "Solo hay autoridades controladas por un programa (ver dependencia)",
|
|
41
|
+
CTL_KNOWN_ISSUER: (d) => "Lo controla su emisor, " + d.issuer + " (ver dependencia)",
|
|
42
|
+
CTL_NONE: () => "Sin autoridades activas: nadie puede crear más ni congelar",
|
|
43
|
+
CTL_SERIAL_CREATOR: (d) => "El creador ha lanzado " + d.n + " tokens más en las últimas 24 h (según RugCheck): es un lanzador en serie, que suele abandonar cada token en cuanto llegan compradores",
|
|
44
|
+
BRAND_COPY: (d) => "Usa el nombre de " + d.brand + ", una empresa real que no tiene token en Solana: no es oficial, casi seguro una imitación para atraer compradores",
|
|
45
|
+
BRAND_NAME: (d) => "Usa el nombre de " + d.brand + ", una empresa real: no es un token oficial de " + d.brand,
|
|
46
|
+
COPYCAT: (d) => "Hay " + (d.n === 1 ? "otro token" : d.n + " tokens más") + " con el mismo nombre y ticker; el más antiguo con mercado real (" + short(d.original) + ", de hace " + d.days + (d.days === 1 ? " día" : " días") + ") no es este: comprueba que tienes la dirección correcta",
|
|
47
|
+
HOLD_GROUP: (d) => d.n + " holders recibieron su primer SOL de la misma wallet y juntos tienen el " + pct(d.pct) + " del suministro: probablemente son la misma persona o equipo",
|
|
48
|
+
CTL_CREATOR_HISTORY: (d) => "De los " + d.old + " tokens que el creador lanzó antes (hace más de 24 h), " + d.dead + " se quedaron por debajo de 10.000 $ de capitalización (según RugCheck): sus lanzamientos no suelen despegar",
|
|
49
|
+
IMPOSTOR: (d) => "Se hace pasar por " + d.symbol + ": el " + d.symbol + " de verdad tiene otra dirección (" + short(d.real) + "). Es una copia, casi seguro una estafa",
|
|
50
|
+
|
|
51
|
+
CON_SKIPPED: () => "Sin comprobar la concentración de holders",
|
|
52
|
+
CON_UNAVAILABLE: () => "No se pudo comprobar la concentración de holders (el servicio no respondió; prueba otra vez en un rato)",
|
|
53
|
+
CON_ALL_POOLS: (d) => "Casi todo el supply está en pools o programas" + prog(d),
|
|
54
|
+
CON_OK: (d) => "Sin concentración preocupante (mayor wallet individual: " + pct(d.w1) + ")" + prog(d),
|
|
55
|
+
CON_HIGH: (d) => "La mayor wallet individual tiene el " + pct(d.w1) + " y las 10 mayores el " + pct(d.w10) + " del supply" + prog(d),
|
|
56
|
+
CON_UNSPLIT: (d) => "No se pudo separar pools de personas. La mayor cuenta tiene el " + pct(d.top1) + " del supply",
|
|
57
|
+
|
|
58
|
+
MKT_LIQ_INFLATED: (d) => "Liquidez inflada: DexScreener dice " + usd(d.reported) + ", pero el pool solo tiene unos " + usd(d.real) + " en tokens de verdad (USDC, USDT o SOL). Es lo máximo que podrías sacar al vender" + (d.reported >= 100 * Math.max(d.real, 1) ? ". Una diferencia así no es casual: está montada para que el token parezca establecido" : ""),
|
|
59
|
+
MKT_LIQ_VERY_LOW: (d) => "Liquidez muy baja (" + usd(d.liq) + ")",
|
|
60
|
+
MKT_LIQ_LOW: (d) => "Liquidez baja (" + usd(d.liq) + ")",
|
|
61
|
+
MKT_VOLUME_LOW: (d) => "Volumen de 24 h casi nulo (" + usd(d.vol) + ")",
|
|
62
|
+
MKT_NEW: (d) => "Mercado muy nuevo (" + (d.days < 1 ? "menos de un día" : d.days + (d.days === 1 ? " día" : " días")) + ")",
|
|
63
|
+
MKT_POSITION_HEAVY: (d) => "La posición de esta wallet equivale al " + pct(d.pct) + " de la liquidez: vender de golpe movería mucho el precio",
|
|
64
|
+
MKT_LP_UNLOCKED: (d) => "Solo el " + pct(d.pct) + " de la liquidez está bloqueada o quemada (según RugCheck): el resto se puede retirar de golpe",
|
|
65
|
+
MKT_LP_PARTLY_LOCKED: (d) => "Solo el " + pct(d.pct) + " de la liquidez está bloqueada o quemada (según RugCheck)",
|
|
66
|
+
MKT_OK: (d) => "Liquidez " + usd(d.liq) + " · volumen 24 h " + usd(d.vol),
|
|
67
|
+
|
|
68
|
+
DEP_PROGRAM_AUTHORITY: () => "Un programa controla el mint o el freeze (puente o protocolo): hay que confiar en su código",
|
|
69
|
+
DEP_PERMANENT_DELEGATE: () => "El emisor puede mover o quemar tus tokens (delegado permanente): confías en el emisor",
|
|
70
|
+
DEP_STABLE_ISSUER: () => "Su valor depende de quien la emite y la respalda",
|
|
71
|
+
DEP_KNOWN_ISSUER: (d) => "Lo emite " + d.issuer + ": puede crear, congelar o mover tokens, como cualquier emisor regulado. Confías en el emisor",
|
|
72
|
+
DEP_NONE: () => "No depende de un emisor ni de un puente"
|
|
73
|
+
},
|
|
74
|
+
offSolana: " y su mercado principal puede estar fuera de Solana",
|
|
75
|
+
levels: {
|
|
76
|
+
HIGH: "Riesgo alto", MEDIUM: "Riesgo medio", LOW: "Riesgo bajo", SPAM: "Probable spam",
|
|
77
|
+
NO_DATA: "Sin comprobar", NO_MARKET: "Sin mercado", MEDIUM_DATA_ONLY: "Medio por falta de datos"
|
|
78
|
+
},
|
|
79
|
+
types: {
|
|
80
|
+
STABLE: { label: "Stablecoin", note: "Se juzga por su liquidez y por la confianza en quien la emite; la concentración pesa menos." },
|
|
81
|
+
TOKENIZED: { label: "Tokenizado o regulado", note: "Lo normal es que el emisor tenga control (delegado permanente). El riesgo real es confiar en el emisor y que haya liquidez para salir." },
|
|
82
|
+
BRIDGED: { label: "Puenteado o de protocolo", note: "Lo normal es que un programa controle el mint. El riesgo real es confiar en ese puente y que su mercado en Solana sea pequeño, porque el principal puede estar en otra red." },
|
|
83
|
+
CREATOR: { label: "Con control del creador", note: "Una wallet puede crear más tokens o congelar cuentas: es el patrón típico de estafa, así que se juzga con más dureza." },
|
|
84
|
+
OPEN: { label: "Token abierto", note: "Sin autoridades del creador, típico de memecoins y proyectos nuevos. Pesan sobre todo la concentración en personas y la liquidez." }
|
|
85
|
+
},
|
|
86
|
+
lights: { control: "Control del creador", concentration: "Concentración", market: "Mercado y salida", dependency: "Dependencia" },
|
|
87
|
+
missing: { control: "quién controla el token", concentration: "la concentración de holders", market: "el mercado", dependency: "la dependencia de un emisor" },
|
|
88
|
+
steps: {
|
|
89
|
+
address: "Comprobando la dirección…", wallet: "Leyendo la wallet…", markets: "Consultando precios y liquidez…",
|
|
90
|
+
tokens: "Revisando tokens…", token: "Leyendo el token…", owners: "Buscando a quién pertenece cada cuenta…",
|
|
91
|
+
kinds: "Distinguiendo wallets de pools y programas…", bots: "Separando personas de bots y exchanges…",
|
|
92
|
+
funders: "Buscando wallets con el mismo origen de fondos…", exchangeSources: "Comprobando si el origen de cada grupo es un exchange…",
|
|
93
|
+
creator: "Mirando quién creó el token (RugCheck)…", creatorTokens: "Revisando otros tokens del creador…",
|
|
94
|
+
networks: "Comprobando cuánto tienen hoy las redes de wallets…", wallets: "Leyendo wallets…",
|
|
95
|
+
pnl: "Estimando el resultado de cada wallet…", done: "Listo"
|
|
96
|
+
},
|
|
97
|
+
notes: {
|
|
98
|
+
PNL_NO_HELIUS: "No se estimó el resultado de las wallets porque falta una clave de Helius.",
|
|
99
|
+
PNL_PARTIAL: "No se pudo leer el historial de algunas wallets.",
|
|
100
|
+
PNL_APPROX: "No se pudo obtener el histórico de precio de SOL: se usó el precio de hoy y los resultados pueden estar muy alejados de la realidad."
|
|
101
|
+
},
|
|
102
|
+
errors: {
|
|
103
|
+
CANCELLED: () => "Cancelado.",
|
|
104
|
+
INVALID_ADDRESS: () => "Esa dirección no parece de Solana. Son de 32 a 44 letras y números y no empiezan por 0x.",
|
|
105
|
+
NOT_A_TOKEN: () => "Esa dirección no es un token.",
|
|
106
|
+
IS_NFT: () => "Esa dirección es un NFT, no un token. El escáner no revisa NFTs.",
|
|
107
|
+
NO_HOLDERS: () => "El RPC no devolvió datos de holders.",
|
|
108
|
+
HELIUS_REQUIRED: () => "Para estimar el resultado hace falta una clave de Helius (o una URL de RPC de Helius con la clave).",
|
|
109
|
+
SOL_PRICE: () => "No se pudo obtener el precio de SOL para calcular el resultado. Prueba otra vez dentro de un rato.",
|
|
110
|
+
DEX_UNREACHABLE: () => "No se pudo conectar con DexScreener. Revisa tu conexión a internet y prueba otra vez.",
|
|
111
|
+
TOO_FEW_WALLETS: (d) => d && d.filter ? "Solo " + d.n + (d.n === 1 ? " wallet cumple" : " wallets cumplen") + " el filtro de resultado (de " + d.total + " leídas)." : "Hacen falta al menos 2 wallets que se puedan leer.",
|
|
112
|
+
TOO_FEW_TOKENS: () => "Pega al menos 2 direcciones de tokens de Solana.",
|
|
113
|
+
NETWORK_PUBLIC: () => "Los servicios gratuitos de Solana no han respondido (a veces se saturan). Espera un minuto y prueba otra vez, o usa tu propia URL de RPC (Helius tiene plan gratuito).",
|
|
114
|
+
NETWORK_OWN: () => "No se pudo conectar con tu URL de RPC. Revisa que esté bien copiada (con la clave al final).",
|
|
115
|
+
UNKNOWN: (d) => "Algo ha fallado: " + d.message + ". Prueba otra vez o usa otro RPC."
|
|
116
|
+
}
|
|
117
|
+
};
|