blumefi 2.2.0 → 2.3.0
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 +4 -2
- package/cli.js +130 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ blumefi pad launch <name> <symbol> [desc] # Launch a token on bonding curve
|
|
|
38
38
|
blumefi pad buy <token> <xrp_amount> # Buy tokens with XRP
|
|
39
39
|
blumefi pad sell <token> <amount|all> # Sell tokens for XRP
|
|
40
40
|
blumefi pad info <token> # View token info and progress
|
|
41
|
+
blumefi pad search <query> # Search tokens by name or symbol
|
|
41
42
|
blumefi pad tokens # List recent tokens
|
|
42
43
|
```
|
|
43
44
|
|
|
@@ -84,12 +85,13 @@ blumefi trade price # Get current XRP price
|
|
|
84
85
|
|
|
85
86
|
Collateral is in RLUSD. Default leverage is 2x if not specified.
|
|
86
87
|
|
|
87
|
-
### Wallet &
|
|
88
|
+
### Wallet & Account
|
|
88
89
|
|
|
89
90
|
```bash
|
|
90
91
|
blumefi wallet new # Generate a new wallet
|
|
92
|
+
blumefi balance [address] # Show XRP and token balances
|
|
91
93
|
blumefi faucet [address] # Get 25 testnet XRP
|
|
92
|
-
blumefi status # Show network info
|
|
94
|
+
blumefi status # Show network info and contracts
|
|
93
95
|
```
|
|
94
96
|
|
|
95
97
|
### Options
|
package/cli.js
CHANGED
|
@@ -403,8 +403,16 @@ async function cmdSwap(amountStr, fromToken, toToken) {
|
|
|
403
403
|
const amountOutMin = amountOut * 99n / 100n
|
|
404
404
|
|
|
405
405
|
const outFormatted = viem.formatUnits(amountOut, toDecimals)
|
|
406
|
-
|
|
407
|
-
|
|
406
|
+
|
|
407
|
+
// Resolve display labels — show symbol instead of raw address
|
|
408
|
+
let fromLabel = fromToken.toUpperCase()
|
|
409
|
+
let toLabel = toToken.toUpperCase()
|
|
410
|
+
if (fromToken.startsWith('0x')) {
|
|
411
|
+
try { fromLabel = await readContract({ address: from.address, abi: ERC20_ABI, functionName: 'symbol', args: [] }) } catch {}
|
|
412
|
+
}
|
|
413
|
+
if (toToken.startsWith('0x')) {
|
|
414
|
+
try { toLabel = await readContract({ address: to.address, abi: ERC20_ABI, functionName: 'symbol', args: [] }) } catch {}
|
|
415
|
+
}
|
|
408
416
|
|
|
409
417
|
console.log(`\n Swap: ${amount} ${fromLabel} -> ~${parseFloat(outFormatted).toFixed(6)} ${toLabel}`)
|
|
410
418
|
console.log(` Network: ${chain}`)
|
|
@@ -480,8 +488,17 @@ async function cmdSwapQuote(amountStr, fromToken, toToken) {
|
|
|
480
488
|
const outFormatted = viem.formatUnits(amountOut, toDecimals)
|
|
481
489
|
const rate = parseFloat(outFormatted) / parseFloat(amountStr)
|
|
482
490
|
|
|
483
|
-
|
|
484
|
-
|
|
491
|
+
let fromLabel = fromToken.toUpperCase()
|
|
492
|
+
let toLabel = toToken.toUpperCase()
|
|
493
|
+
if (fromToken.startsWith('0x')) {
|
|
494
|
+
try { fromLabel = await readContract({ address: from.address, abi: ERC20_ABI, functionName: 'symbol', args: [] }) } catch {}
|
|
495
|
+
}
|
|
496
|
+
if (toToken.startsWith('0x')) {
|
|
497
|
+
try { toLabel = await readContract({ address: to.address, abi: ERC20_ABI, functionName: 'symbol', args: [] }) } catch {}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
console.log(`\n Quote: ${amountStr} ${fromLabel} -> ${parseFloat(outFormatted).toFixed(6)} ${toLabel}`)
|
|
501
|
+
console.log(` Rate: 1 ${fromLabel} = ${rate.toFixed(6)} ${toLabel}`)
|
|
485
502
|
console.log(` Network: ${getChain()}`)
|
|
486
503
|
console.log(`\n Execute: blumefi swap ${amountStr} ${fromToken} ${toToken}`)
|
|
487
504
|
}
|
|
@@ -963,6 +980,44 @@ async function cmdPadInfo(tokenAddress) {
|
|
|
963
980
|
}
|
|
964
981
|
}
|
|
965
982
|
|
|
983
|
+
async function cmdPadSearch(query) {
|
|
984
|
+
if (!query) {
|
|
985
|
+
console.error('Usage: blumefi pad search <name or symbol>')
|
|
986
|
+
console.error(' blumefi pad search tulip')
|
|
987
|
+
process.exit(1)
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
const chain = getChain()
|
|
991
|
+
const q = query.toLowerCase()
|
|
992
|
+
|
|
993
|
+
try {
|
|
994
|
+
const data = await apiFetch(`/pad/tokens?chain=${chain}&limit=50&sort=recent`)
|
|
995
|
+
const tokens = data.data || data.tokens || data || []
|
|
996
|
+
if (!Array.isArray(tokens)) { console.log('No tokens found.'); return }
|
|
997
|
+
|
|
998
|
+
const matches = tokens.filter(t => {
|
|
999
|
+
const name = (t.name || '').toLowerCase()
|
|
1000
|
+
const symbol = (t.symbol || '').toLowerCase()
|
|
1001
|
+
return name.includes(q) || symbol.includes(q)
|
|
1002
|
+
})
|
|
1003
|
+
|
|
1004
|
+
if (!matches.length) { console.log(`\n No tokens matching "${query}" on ${chain}.`); return }
|
|
1005
|
+
|
|
1006
|
+
console.log(`\n Search: "${query}" on ${chain} — ${matches.length} match${matches.length === 1 ? '' : 'es'}\n`)
|
|
1007
|
+
for (const t of matches) {
|
|
1008
|
+
const name = t.name || '???'
|
|
1009
|
+
const symbol = t.symbol || '???'
|
|
1010
|
+
const graduated = t.graduated ? ' [GRADUATED]' : ''
|
|
1011
|
+
const reserve = t.reserveBalance ? ` ${parseFloat(t.reserveBalance).toFixed(1)} XRP` : ''
|
|
1012
|
+
console.log(` ${name} (${symbol})${graduated}${reserve}`)
|
|
1013
|
+
console.log(` ${t.address}`)
|
|
1014
|
+
console.log()
|
|
1015
|
+
}
|
|
1016
|
+
} catch {
|
|
1017
|
+
console.log(`\n Search not available. Browse: https://${chain === 'mainnet' ? '' : 'testnet.'}pad.blumefi.com`)
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
966
1021
|
async function cmdPadTokens() {
|
|
967
1022
|
const chain = getChain()
|
|
968
1023
|
try {
|
|
@@ -987,6 +1042,70 @@ async function cmdPadTokens() {
|
|
|
987
1042
|
}
|
|
988
1043
|
}
|
|
989
1044
|
|
|
1045
|
+
// ─── Balance command ─────────────────────────────────────────────────
|
|
1046
|
+
|
|
1047
|
+
async function cmdBalance(address) {
|
|
1048
|
+
const viem = await loadViem()
|
|
1049
|
+
const chain = getChain()
|
|
1050
|
+
const net = getNetwork()
|
|
1051
|
+
const pub = await getPublicClient()
|
|
1052
|
+
|
|
1053
|
+
if (!address) {
|
|
1054
|
+
const key = process.env.WALLET_PRIVATE_KEY || process.env.PRIVATE_KEY
|
|
1055
|
+
if (key) {
|
|
1056
|
+
const k = key.startsWith('0x') ? key : `0x${key}`
|
|
1057
|
+
address = viem.privateKeyToAccount(k).address
|
|
1058
|
+
} else { console.error('Usage: blumefi balance [address]'); process.exit(1) }
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
const xrpBalance = await pub.getBalance({ address })
|
|
1062
|
+
const xrpFormatted = parseFloat(viem.formatEther(xrpBalance)).toFixed(4)
|
|
1063
|
+
|
|
1064
|
+
console.log(`\n Balances for ${address}`)
|
|
1065
|
+
console.log(` Network: ${chain}`)
|
|
1066
|
+
console.log(` ─────────────────────────────────────`)
|
|
1067
|
+
console.log(` XRP: ${xrpFormatted}`)
|
|
1068
|
+
|
|
1069
|
+
// Check known tokens
|
|
1070
|
+
const tokens = []
|
|
1071
|
+
if (net.rlusd) tokens.push({ address: net.rlusd, name: 'RLUSD' })
|
|
1072
|
+
|
|
1073
|
+
// Check pad tokens the user might hold — query API for recent tokens
|
|
1074
|
+
try {
|
|
1075
|
+
const data = await apiFetch(`/pad/tokens?chain=${chain}&limit=50&sort=recent`)
|
|
1076
|
+
const padTokens = data.data || data.tokens || data || []
|
|
1077
|
+
if (Array.isArray(padTokens)) {
|
|
1078
|
+
for (const t of padTokens) {
|
|
1079
|
+
if (t.address) tokens.push({ address: t.address, name: t.symbol || t.name || '???' })
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
} catch {}
|
|
1083
|
+
|
|
1084
|
+
// Batch check balances
|
|
1085
|
+
const results = []
|
|
1086
|
+
for (const t of tokens) {
|
|
1087
|
+
try {
|
|
1088
|
+
const [bal, decimals] = await Promise.all([
|
|
1089
|
+
readContract({ address: t.address, abi: ERC20_ABI, functionName: 'balanceOf', args: [address] }),
|
|
1090
|
+
readContract({ address: t.address, abi: ERC20_ABI, functionName: 'decimals', args: [] }),
|
|
1091
|
+
])
|
|
1092
|
+
if (bal > 0n) {
|
|
1093
|
+
const formatted = parseFloat(viem.formatUnits(bal, decimals))
|
|
1094
|
+
results.push({ name: t.name, balance: formatted, address: t.address })
|
|
1095
|
+
}
|
|
1096
|
+
} catch {}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
if (results.length > 0) {
|
|
1100
|
+
for (const r of results) {
|
|
1101
|
+
const balStr = r.balance > 1000 ? r.balance.toLocaleString() : r.balance.toFixed(4)
|
|
1102
|
+
console.log(` ${r.name.padEnd(9)}${balStr}`)
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
console.log()
|
|
1107
|
+
}
|
|
1108
|
+
|
|
990
1109
|
// ─── Wallet & network commands ───────────────────────────────────────
|
|
991
1110
|
|
|
992
1111
|
async function cmdWalletNew() {
|
|
@@ -1089,6 +1208,7 @@ Pad (Launchpad):
|
|
|
1089
1208
|
pad buy <token> <xrp_amount> Buy tokens with XRP
|
|
1090
1209
|
pad sell <token> <amount|all> Sell tokens for XRP
|
|
1091
1210
|
pad info <token> View token info and progress
|
|
1211
|
+
pad search <query> Search tokens by name or symbol
|
|
1092
1212
|
pad tokens List recent tokens
|
|
1093
1213
|
|
|
1094
1214
|
Swap (DEX):
|
|
@@ -1103,12 +1223,11 @@ Trade (Perps — testnet):
|
|
|
1103
1223
|
trade position View your open positions
|
|
1104
1224
|
trade price Get current XRP price
|
|
1105
1225
|
|
|
1106
|
-
Wallet:
|
|
1226
|
+
Wallet & Account:
|
|
1107
1227
|
wallet new Generate a new wallet
|
|
1108
|
-
|
|
1109
|
-
Network:
|
|
1228
|
+
balance [address] Show XRP and token balances
|
|
1110
1229
|
faucet [address] Get 25 testnet XRP
|
|
1111
|
-
status Show network info, contracts
|
|
1230
|
+
status Show network info, contracts
|
|
1112
1231
|
|
|
1113
1232
|
Options:
|
|
1114
1233
|
--mainnet Use mainnet (default: testnet)
|
|
@@ -1145,6 +1264,7 @@ async function main() {
|
|
|
1145
1264
|
else if (sub === 'buy' || sub === 'b') await cmdPadBuy(args[2], args[3])
|
|
1146
1265
|
else if (sub === 'sell' || sub === 's') await cmdPadSell(args[2], args[3])
|
|
1147
1266
|
else if (sub === 'info' || sub === 'i') await cmdPadInfo(args[2])
|
|
1267
|
+
else if (sub === 'search' || sub === 'find') await cmdPadSearch(args[2])
|
|
1148
1268
|
else if (sub === 'tokens' || sub === 'list') await cmdPadTokens()
|
|
1149
1269
|
else { console.error(`Unknown: pad ${sub}. Try: launch, buy, sell, info, tokens`); process.exit(1) }
|
|
1150
1270
|
} else if (cmd === 'swap') {
|
|
@@ -1161,6 +1281,8 @@ async function main() {
|
|
|
1161
1281
|
} else if (cmd === 'wallet' || cmd === 'w') {
|
|
1162
1282
|
if (!sub || sub === 'new') await cmdWalletNew()
|
|
1163
1283
|
else { console.error(`Unknown: wallet ${sub}`); process.exit(1) }
|
|
1284
|
+
} else if (cmd === 'balance' || cmd === 'bal' || cmd === 'b') {
|
|
1285
|
+
await cmdBalance(args[1])
|
|
1164
1286
|
} else if (cmd === 'faucet') {
|
|
1165
1287
|
await cmdFaucet(args[1])
|
|
1166
1288
|
} else if (cmd === 'status' || cmd === 's') {
|
package/package.json
CHANGED