mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-09 16:28:06 +00:00
Compare commits
190
Commits
release/lighter
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d80518853e | ||
|
|
422ee6f465 | ||
|
|
bee7bdd8fe | ||
|
|
3f67b99291 | ||
|
|
61e6e4cdde | ||
|
|
858b2f304b | ||
|
|
6998afebb1 | ||
|
|
b8942c18e6 | ||
|
|
6f85e609f8 | ||
|
|
a851257149 | ||
|
|
9355ec5019 | ||
|
|
fa82d45bfb | ||
|
|
d0154e5721 | ||
|
|
52b6a8a076 | ||
|
|
db6a9cfc68 | ||
|
|
03b8e53d30 | ||
|
|
8d79ace8b3 | ||
|
|
1fb6d3d62d | ||
|
|
c4559cb0d7 | ||
|
|
1d88ddefb5 | ||
|
|
683352f737 | ||
|
|
a629bc940c | ||
|
|
fe7b8eb6f3 | ||
|
|
24339929dc | ||
|
|
ed855f6859 | ||
|
|
e144c1822f | ||
|
|
69271d33ca | ||
|
|
f1140f106a | ||
|
|
3b935b7979 | ||
|
|
00388f9166 | ||
|
|
a32efa2ba0 | ||
|
|
76704b6bdd | ||
|
|
168d8cbb08 | ||
|
|
9629c22496 | ||
|
|
a34d06f9b4 | ||
|
|
2ba3e80ad9 | ||
|
|
12e8e3e064 | ||
|
|
aa24995d28 | ||
|
|
d493642935 | ||
|
|
86670486a6 | ||
|
|
6496011d8f | ||
|
|
792351ab8a | ||
|
|
4915dc574e | ||
|
|
9866e8068f | ||
|
|
099af3ce01 | ||
|
|
445e634aa1 | ||
|
|
4bb1fee995 | ||
|
|
aad14395e0 | ||
|
|
598f2a0eb6 | ||
|
|
cb1cef6f1b | ||
|
|
fd034d493f | ||
|
|
2551670874 | ||
|
|
3ec7e9b8d6 | ||
|
|
499ee692da | ||
|
|
de13142950 | ||
|
|
597e41f053 | ||
|
|
b0a33a58d1 | ||
|
|
65b9f21981 | ||
|
|
33b5407245 | ||
|
|
7aafc3b69d | ||
|
|
9a093459bc | ||
|
|
aa36b0cfdc | ||
|
|
93c6409688 | ||
|
|
84d5e1f3d7 | ||
|
|
6e5413ec1e | ||
|
|
84e8ce1d43 | ||
|
|
c69ea72860 | ||
|
|
624fecfa70 | ||
|
|
6dcf13481d | ||
|
|
3fd0f715a1 | ||
|
|
85e7f245c0 | ||
|
|
03df1006cc | ||
|
|
3099cb1319 | ||
|
|
49b8f0bcf1 | ||
|
|
a23eb91f04 | ||
|
|
974d3017e0 | ||
|
|
668c3a57d3 | ||
|
|
819ce93a90 | ||
|
|
061a8dd8f1 | ||
|
|
49df78c075 | ||
|
|
6a6b61c491 | ||
|
|
7612e25dd1 | ||
|
|
705e489c17 | ||
|
|
9a418aba41 | ||
|
|
2cb6c4fef1 | ||
|
|
180f47b6e0 | ||
|
|
5f79b134f2 | ||
|
|
85705dd27c | ||
|
|
59ccd1fea8 | ||
|
|
a9fa7f2e19 | ||
|
|
7529de334f | ||
|
|
1bfe4d58c0 | ||
|
|
4ce2b07e21 | ||
|
|
6bb0994cae | ||
|
|
486b911bed | ||
|
|
f48371ccd8 | ||
|
|
9ca35584b5 | ||
|
|
01e5ab9997 | ||
|
|
28bc1d5210 | ||
|
|
870fe2b8d7 | ||
|
|
e7f6341961 | ||
|
|
1baee3a207 | ||
|
|
e94cf1bda2 | ||
|
|
274e2f3d75 | ||
|
|
a91e87534b | ||
|
|
d0d1afa0ea | ||
|
|
0f70c6b6aa | ||
|
|
078b201d15 | ||
|
|
1832c4c13e | ||
|
|
73a88a8a0f | ||
|
|
265cb6df50 | ||
|
|
5bba8169b5 | ||
|
|
295c6a47b7 | ||
|
|
e7dedbba2c | ||
|
|
6196912cf4 | ||
|
|
f1ebfacaa2 | ||
|
|
ea5da20311 | ||
|
|
fabc8af679 | ||
|
|
189fed0f6e | ||
|
|
09ff4dc296 | ||
|
|
2627fa9db8 | ||
|
|
8b20e60753 | ||
|
|
f991215d86 | ||
|
|
6a3b842a3b | ||
|
|
b36c1dce0f | ||
|
|
dbe8df6934 | ||
|
|
400c7ad4b7 | ||
|
|
e96cbb6ff4 | ||
|
|
aa3d5e8c6c | ||
|
|
96cf4ea47b | ||
|
|
45061ed748 | ||
|
|
da3dacb549 | ||
|
|
51e0ce2bea | ||
|
|
8c13d20cb7 | ||
|
|
3d959ae579 | ||
|
|
4240cc6901 | ||
|
|
8d0e9578c4 | ||
|
|
95f07145a9 | ||
|
|
e3411c6791 | ||
|
|
640f1bfb4e | ||
|
|
f973fe433d | ||
|
|
730a75df93 | ||
|
|
de8a793bd5 | ||
|
|
bb072b2d1d | ||
|
|
95426e222b | ||
|
|
4365d73562 | ||
|
|
6067f759a0 | ||
|
|
b31b98f816 | ||
|
|
801543488e | ||
|
|
20c73eba21 | ||
|
|
ed49dca2a6 | ||
|
|
ca559d0f82 | ||
|
|
fef7604490 | ||
|
|
e524c225f2 | ||
|
|
39a97110dd | ||
|
|
8ad19b007b | ||
|
|
2e2990369b | ||
|
|
24f93fa8a7 | ||
|
|
d778e20c23 | ||
|
|
58f5de4a48 | ||
|
|
ad46635e20 | ||
|
|
6dde78f799 | ||
|
|
6b70aa0936 | ||
|
|
66e1b3e6f5 | ||
|
|
c6f279c51b | ||
|
|
9bad7f180e | ||
|
|
88292c9c49 | ||
|
|
5878a3dc0b | ||
|
|
ccb23ecf44 | ||
|
|
b6a6515677 | ||
|
|
5e65c7025d | ||
|
|
d7a95ceb36 | ||
|
|
1bd3e7edc6 | ||
|
|
28ba0613ca | ||
|
|
1dce3dfcfb | ||
|
|
732525b394 | ||
|
|
d829e451cd | ||
|
|
0d2aa84b84 | ||
|
|
d2867ba98c | ||
|
|
e28240e799 | ||
|
|
cfd5f4309d | ||
|
|
627ed36de4 | ||
|
|
ccc3a2bf89 | ||
|
|
f8a87f4557 | ||
|
|
263cbd7c21 | ||
|
|
d328758074 | ||
|
|
971a2a6adb | ||
|
|
fcb83bd16b | ||
|
|
d5c4b04746 | ||
|
|
65aaf26879 |
+124
-2
@@ -1,14 +1,36 @@
|
|||||||
|
# UI language (zh | en)
|
||||||
|
LANG=zh
|
||||||
|
|
||||||
# Exchange selection
|
# Exchange selection
|
||||||
EXCHANGE=aster # Pick aster (default) or grvt
|
EXCHANGE=aster # Pick aster (default) or standx/grvt/lighter/backpack/paradex/nado
|
||||||
|
|
||||||
# Aster API credentials
|
# Aster API credentials
|
||||||
ASTER_API_KEY=
|
ASTER_API_KEY=
|
||||||
ASTER_API_SECRET=
|
ASTER_API_SECRET=
|
||||||
|
|
||||||
|
# StandX authentication (set when EXCHANGE=standx)
|
||||||
|
STANDX_TOKEN=
|
||||||
|
STANDX_SYMBOL=BTC-USD
|
||||||
|
# STANDX_BASE_URL=https://perps.standx.com
|
||||||
|
# STANDX_WS_URL=wss://perps.standx.com/ws-stream/v1
|
||||||
|
# STANDX_SESSION_ID=
|
||||||
|
# Optional: request signing key (ed25519 private key, supports hex or base58 format)
|
||||||
|
# STANDX_REQUEST_PRIVATE_KEY=
|
||||||
|
# Token expiry configuration (recommended method: creation date + validity days)
|
||||||
|
# Get these values when generating API token at https://standx.com/user/session
|
||||||
|
# STANDX_TOKEN_CREATE_DATE=2026-01-15 # Token creation date (YYYY-MM-DD format)
|
||||||
|
# STANDX_TOKEN_VALIDITY_DAYS=30 # Token validity period in days
|
||||||
|
# Legacy method: direct expiry timestamp (Unix seconds)
|
||||||
|
# STANDX_TOKEN_EXPIRY=1737092800
|
||||||
|
|
||||||
# Core trading symbol and sizing
|
# Core trading symbol and sizing
|
||||||
TRADE_SYMBOL=BTCUSDT # Trading pair symbol
|
TRADE_SYMBOL=BTCUSDT # Trading pair symbol
|
||||||
TRADE_AMOUNT=0.001 # Base order quantity (base asset, e.g. BTC)
|
TRADE_AMOUNT=0.001 # Base order quantity (base asset, e.g. BTC)
|
||||||
|
|
||||||
|
# Swing Trading
|
||||||
|
SWING_DIRECTION=short # short | long | both
|
||||||
|
SWING_STOP_LOSS_PCT=0.05 # 0.05 = 5%
|
||||||
|
|
||||||
# Risk management (USD amounts unless noted)
|
# Risk management (USD amounts unless noted)
|
||||||
LOSS_LIMIT=0.04 # Max loss per trade in USDT before forced close
|
LOSS_LIMIT=0.04 # Max loss per trade in USDT before forced close
|
||||||
TRAILING_PROFIT=0.2 # Trailing stop activation profit (USDT)
|
TRAILING_PROFIT=0.2 # Trailing stop activation profit (USDT)
|
||||||
@@ -33,10 +55,30 @@ MAX_CLOSE_SLIPPAGE_PCT=0.05 # Max allowed deviation vs mark when clo
|
|||||||
MAKER_LOSS_LIMIT=0.05 # Maker loss cap (USDT). Defaults to LOSS_LIMIT if unset
|
MAKER_LOSS_LIMIT=0.05 # Maker loss cap (USDT). Defaults to LOSS_LIMIT if unset
|
||||||
MAKER_BID_OFFSET=0 # Bid quote offset from top bid (USDT)
|
MAKER_BID_OFFSET=0 # Bid quote offset from top bid (USDT)
|
||||||
MAKER_ASK_OFFSET=0 # Ask quote offset from top ask (USDT)
|
MAKER_ASK_OFFSET=0 # Ask quote offset from top ask (USDT)
|
||||||
MAKER_REFRESH_INTERVAL_MS=1500 # Maker refresh cadence (ms)
|
MAKER_REFRESH_INTERVAL_MS=500 # Maker refresh cadence (ms)
|
||||||
MAKER_MAX_CLOSE_SLIPPAGE_PCT=0.05 # Maker close slippage guard (fallbacks to MAX_CLOSE_SLIPPAGE_PCT)
|
MAKER_MAX_CLOSE_SLIPPAGE_PCT=0.05 # Maker close slippage guard (fallbacks to MAX_CLOSE_SLIPPAGE_PCT)
|
||||||
MAKER_PRICE_TICK=0.1 # Maker price tick size (defaults to PRICE_TICK)
|
MAKER_PRICE_TICK=0.1 # Maker price tick size (defaults to PRICE_TICK)
|
||||||
|
|
||||||
|
# Maker-points Binance depth imbalance monitor
|
||||||
|
MAKER_POINTS_BINANCE_DEPTH_WINDOW_BPS=3 # Binance depth monitor window around best bid/ask (bps)
|
||||||
|
MAKER_POINTS_BINANCE_DEPTH_IMBALANCE_RATIO=9 # Imbalance threshold ratio (e.g. 9 => one side >= 9x)
|
||||||
|
|
||||||
|
# Grid strategy defaults
|
||||||
|
GRID_LOWER_PRICE=25000 # Grid lower bound price (quote currency)
|
||||||
|
GRID_UPPER_PRICE=35000 # Grid upper bound price
|
||||||
|
GRID_LEVELS=10 # Number of grid levels between bounds (>=2)
|
||||||
|
GRID_ORDER_SIZE=0.001 # Quantity per grid order (base asset units)
|
||||||
|
GRID_MAX_POSITION_SIZE=0.01 # Max inventory the grid may hold (base units)
|
||||||
|
GRID_REFRESH_INTERVAL_MS=1000 # Grid evaluation cadence (ms)
|
||||||
|
GRID_MAX_LOG_ENTRIES=200 # Grid trade log length (defaults to MAX_LOG_ENTRIES when unset)
|
||||||
|
GRID_DIRECTION=both # Order direction: both | long | short
|
||||||
|
GRID_STOP_LOSS_PCT=0.01 # Stop loss trigger percentage beyond bounds (0.01 => 1%)
|
||||||
|
GRID_RESTART_TRIGGER_PCT=0.01 # Restart buffer percentage inside bounds
|
||||||
|
GRID_AUTO_RESTART_ENABLED=true # Automatically resume grid when price re-enters range
|
||||||
|
GRID_MAX_CLOSE_SLIPPAGE_PCT=0.05 # Close-order slippage guard relative to mark price
|
||||||
|
# GRID_PRICE_TICK=0.1 # Optional override for grid price tick (falls back to PRICE_TICK)
|
||||||
|
# GRID_QTY_STEP=0.001 # Optional override for grid quantity step (falls back to QTY_STEP)
|
||||||
|
|
||||||
# GRVT authentication (set when EXCHANGE=grvt)
|
# GRVT authentication (set when EXCHANGE=grvt)
|
||||||
GRVT_API_KEY=
|
GRVT_API_KEY=
|
||||||
GRVT_API_SECRET=
|
GRVT_API_SECRET=
|
||||||
@@ -61,3 +103,83 @@ LIGHTER_ENV=testnet # mainnet | testnet | staging | dev
|
|||||||
# LIGHTER_MARKET_ID=1 # Prefer explicit market id when symbols differ
|
# LIGHTER_MARKET_ID=1 # Prefer explicit market id when symbols differ
|
||||||
# LIGHTER_PRICE_DECIMALS=3 # Manual override for price decimals (optional)
|
# LIGHTER_PRICE_DECIMALS=3 # Manual override for price decimals (optional)
|
||||||
# LIGHTER_SIZE_DECIMALS=3 # Manual override for size decimals (optional)
|
# LIGHTER_SIZE_DECIMALS=3 # Manual override for size decimals (optional)
|
||||||
|
|
||||||
|
# Backpack exchange configuration
|
||||||
|
# Fill these with your Backpack API credentials and preferences
|
||||||
|
|
||||||
|
BACKPACK_API_KEY=
|
||||||
|
BACKPACK_API_SECRET=
|
||||||
|
BACKPACK_PASSWORD=
|
||||||
|
BACKPACK_SUBACCOUNT=
|
||||||
|
|
||||||
|
# Use sandbox environment: "true" to enable, otherwise leave as false
|
||||||
|
BACKPACK_SANDBOX=false
|
||||||
|
|
||||||
|
# Default trading symbol (falls back to TRADE_SYMBOL or BTCUSDC)
|
||||||
|
BACKPACK_SYMBOL=BTC_USD_PERP
|
||||||
|
|
||||||
|
# Enable verbose adapter logging: set to "1" or "true"
|
||||||
|
BACKPACK_DEBUG=false
|
||||||
|
|
||||||
|
# EdgeX exchange configuration
|
||||||
|
EDGEX_ACCOUNT_ID=
|
||||||
|
EDGEX_PRIVATE_KEY=
|
||||||
|
# EDGEX_POSITION_ID= # Defaults to EDGEX_ACCOUNT_ID when omitted
|
||||||
|
# EDGEX_BASE_URL=https://pro.edgex.exchange
|
||||||
|
# EDGEX_WS_PUBLIC_URL=wss://quote.edgex.exchange
|
||||||
|
# EDGEX_WS_PRIVATE_URL=wss://quote.edgex.exchange
|
||||||
|
# EDGEX_ORDER_TTL_MS=21600000 # Order expiration window (ms), default 6 hours
|
||||||
|
|
||||||
|
|
||||||
|
# Paradex exchange configuration
|
||||||
|
# Provide the EVM private key & wallet address for onboarded accounts.
|
||||||
|
# When EXCHANGE=paradex these values are used automatically.
|
||||||
|
|
||||||
|
PARADEX_SYMBOL=BTC-USD-PERP
|
||||||
|
PARADEX_PRIVATE_KEY=
|
||||||
|
PARADEX_WALLET_ADDRESS=
|
||||||
|
|
||||||
|
# Enable testnet endpoints by setting to "true"; defaults to false (mainnet).
|
||||||
|
# PARADEX_SANDBOX=false
|
||||||
|
|
||||||
|
# Force disabling ccxt.pro websocket usage by setting to "false" (pro is preferred when installed).
|
||||||
|
# PARADEX_USE_PRO=true
|
||||||
|
|
||||||
|
# Optional reconnect delay override (milliseconds, e.g., 2000). Leave blank for default.
|
||||||
|
# PARADEX_RECONNECT_DELAY_MS=
|
||||||
|
|
||||||
|
# Enable verbose adapter logging: set to "1" or "true"
|
||||||
|
# PARADEX_DEBUG=false
|
||||||
|
|
||||||
|
# Nado exchange configuration (Ink mainnet)
|
||||||
|
# Requires a linked signer private key + your original subaccount owner EVM address.
|
||||||
|
# When EXCHANGE=nado these values are used automatically.
|
||||||
|
|
||||||
|
NADO_ENV=inkMainnet # inkMainnet | inkTestnet
|
||||||
|
NADO_SYMBOL=BTC-PERP # Trading product symbol (e.g., BTC-PERP / ETH-PERP)
|
||||||
|
NADO_SIGNER_PRIVATE_KEY= # 32-byte 0x-prefixed private key (0x...)
|
||||||
|
NADO_SUBACCOUNT_OWNER= # EVM address of the subaccount owner (0x...)
|
||||||
|
NADO_SUBACCOUNT_NAME=default # Subaccount name (bytes12, default "default")
|
||||||
|
|
||||||
|
# Optional: market-order slippage buffer (used for IOC limit-as-market, e.g. 0.01 => 1%)
|
||||||
|
NADO_MARKET_SLIPPAGE_PCT=0.01
|
||||||
|
|
||||||
|
# Optional: stop trigger source for STOP_MARKET orders (oracle | last | mid)
|
||||||
|
NADO_STOP_TRIGGER_SOURCE=oracle
|
||||||
|
|
||||||
|
# Optional: how to handle orders smaller than Nado min_size (USDT0 notional)
|
||||||
|
# - adjust: round quantity up to the minimum allowed size (default)
|
||||||
|
# - reject: throw an error instead of auto-adjusting
|
||||||
|
NADO_MIN_SIZE_POLICY=adjust
|
||||||
|
|
||||||
|
# Optional endpoint overrides
|
||||||
|
# NADO_GATEWAY_WS_URL=wss://gateway.prod.nado.xyz/v1/ws
|
||||||
|
# NADO_SUBSCRIPTIONS_WS_URL=wss://gateway.prod.nado.xyz/v1/subscribe
|
||||||
|
# NADO_ARCHIVE_URL=https://archive.prod.nado.xyz/v1
|
||||||
|
# NADO_TRIGGER_URL=https://trigger.prod.nado.xyz/v1
|
||||||
|
# NADO_DEBUG=false
|
||||||
|
|
||||||
|
# Telegram notification configuration
|
||||||
|
# TELEGRAM_BOT_TOKEN= # Telegram bot token from @BotFather
|
||||||
|
# TELEGRAM_CHAT_ID= # Chat ID to receive notifications
|
||||||
|
# TELEGRAM_ACCOUNT_LABEL= # Account label to distinguish multiple bot instances (e.g., "Account-A")
|
||||||
|
|||||||
@@ -33,3 +33,6 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
|||||||
|
|
||||||
# Finder (MacOS) folder config
|
# Finder (MacOS) folder config
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
.tmp
|
||||||
|
.tmp/*
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# RitMEX Bot - Claude Instructions
|
||||||
|
|
||||||
|
## Package Manager
|
||||||
|
|
||||||
|
**必须使用 Bun** - 这个项目使用 Bun 作为包管理器和运行时。所有能用 bun 执行的命令都必须使用 bun:
|
||||||
|
|
||||||
|
- 安装依赖: `bun install`
|
||||||
|
- 运行脚本: `bun run <script>`
|
||||||
|
- 执行测试: `bun test`
|
||||||
|
- 类型检查: `bun run typecheck`
|
||||||
|
|
||||||
|
**不要使用 npm、yarn 或 npx**
|
||||||
@@ -1,42 +1,71 @@
|
|||||||
# ritmex-bot
|
# ritmex-bot
|
||||||
|
|
||||||
基于 Bun 的 Aster 永续合约量化终端,内置趋势跟随(SMA30)与做市策略,支持快速恢复、实时行情订阅与日志追踪。
|
> For English users, please see [README_en.md](README_en.md).
|
||||||
|
|
||||||
* [Aster 30% 手续费优惠注册链接](https://www.asterdex.com/zh-CN/referral/4665f3)
|
Please set `LANG=en` in `.env` for English interface.
|
||||||
|
|
||||||
|
A Bun-powered multi-exchange perpetuals workstation that ships an SMA30 trend engine, a Guardian stop sentinel, and two market-making modes. It offers instant restarts, realtime market data, structured logging, and an Ink-based CLI dashboard.
|
||||||
|
|
||||||
|
基于 Bun 的多交易所永续合约量化终端,内置趋势跟随(SMA30)、Guardian 防守与做市策略,支持快速恢复、实时行情订阅、日志追踪与 CLI 仪表盘。
|
||||||
|
|
||||||
|
如果您希望获取优惠并支持本项目,请考虑使用以下注册链接:
|
||||||
|
|
||||||
|
* [Lighter 手续费优惠注册链接](https://app.lighter.xyz/?referral=111909FA)
|
||||||
|
* [Aster 手续费优惠注册链接](https://www.asterdex.com/zh-CN/referral/4665f3)
|
||||||
|
* [StandX 手续费优惠注册链接](https://standx.com/referral?code=xingxingjun)
|
||||||
|
* [Binance 手续费优惠注册链接](https://www.binance.com/join?ref=KNKCA9XC)
|
||||||
* [GRVT 手续费优惠注册链接](https://grvt.io/exchange/sign-up?ref=sea)
|
* [GRVT 手续费优惠注册链接](https://grvt.io/exchange/sign-up?ref=sea)
|
||||||
|
* [Nado 手续费优惠注册链接](https://app.nado.xyz?join=LKbIUs5)
|
||||||
|
* [Backpack 手续费优惠注册链接](https://backpack.exchange/join/ritmex)
|
||||||
|
* [edgex 手续费优惠注册链接](https://pro.edgex.exchange/referral/BULL)
|
||||||
|
* [Paradex 手续费优惠注册链接](https://paradex.io/ref/xingxingjun)
|
||||||
|
* [Apex 手续费优惠注册链接](https://join.omni.apex.exchange/SEA)
|
||||||
|
|
||||||
## 文档索引
|
## 文档索引
|
||||||
- [English README](README_en.md)
|
|
||||||
- [简明上手指南(零基础)](simple-readme.md)
|
- [简明上手指南(零基础)](simple-readme.md)
|
||||||
|
- [基础网格策略使用教程](grid-trading.md)
|
||||||
|
|
||||||
## 项目亮点
|
## 核心特性
|
||||||
- **实时行情与风控**:Websocket + REST 自动同步账户、挂单与仓位。
|
- **实时行情与风控**:Websocket + REST 自动同步账户、挂单与仓位,断线后自动恢复。
|
||||||
- **趋势策略**:SMA30 穿越入场,内置止损、移动止盈、布林带带宽过滤与步进锁盈。
|
- **趋势策略**:SMA30 穿越入场,内置止损、移动止盈、布林带带宽过滤与步进锁盈。
|
||||||
- **做市策略**:支持双边追价、风险阈值与订单自愈。
|
- **Guardian 策略**:不主动开单,实时监听账户仓位并强制补挂/移动止损与动态止盈,防止裸奔。
|
||||||
- **模块化设计**:适配器、策略引擎与 CLI 解耦,方便扩展新交易所或策略。
|
- **做市策略**:支持双边追价、风险阈值控制与订单自愈。
|
||||||
|
- **模块化架构**:策略引擎、交易所适配器与 Ink CLI 相互解耦,新增交易所或策略更容易。
|
||||||
|
|
||||||
## 环境要求
|
## 支持的交易所
|
||||||
- Bun ≥ 1.2(含 `bun`、`bunx` 命令)
|
| 交易所 | 合约类型 | 必填环境变量 | 备注 |
|
||||||
- macOS、Linux 或 Windows (WSL 推荐)
|
| --- | --- | --- | --- |
|
||||||
- Node.js 仅在某些安装路径需要,可选
|
| Aster | USDT 永续 | `ASTER_API_KEY`, `ASTER_API_SECRET` | 默认交易所;兼容脚本引导
|
||||||
|
| StandX | USD 永续 | `STANDX_TOKEN` | 使用 JWT Token 登录,优先走 WebSocket 推送
|
||||||
|
| GRVT | USDT 永续 | `GRVT_API_KEY`, `GRVT_API_SECRET`, `GRVT_SUB_ACCOUNT_ID` | `GRVT_ENV` 可切换 `prod`/`testnet`
|
||||||
|
| Lighter | zkLighter 永续 | `LIGHTER_ACCOUNT_INDEX`, `LIGHTER_API_PRIVATE_KEY` | 默认 `LIGHTER_ENV=testnet`
|
||||||
|
| Backpack | USDC 永续 | `BACKPACK_API_KEY`, `BACKPACK_API_SECRET`, `BACKPACK_PASSWORD` | `BACKPACK_SANDBOX=true` 启用沙盒
|
||||||
|
| Paradex | StarkEx 永续 | `PARADEX_PRIVATE_KEY`, `PARADEX_WALLET_ADDRESS` | `PARADEX_SANDBOX=true` 使用测试网
|
||||||
|
| Nado | USDC 永续 | `NADO_SIGNER_PRIVATE_KEY`, `NADO_SUBACCOUNT_OWNER` | `NADO_ENV` 可切换 `inkMainnet`/`inkTestnet`
|
||||||
|
|
||||||
## 快速启动脚本(macOS / Linux / WSL)
|
## 系统要求
|
||||||
|
- Bun ≥ 1.2(需同时包含 `bun`、`bunx` 命令)
|
||||||
|
- macOS、Linux 或 Windows (推荐 WSL)
|
||||||
|
- Node.js 仅在部分工具链场景需要,可选
|
||||||
|
|
||||||
|
## 快速上手
|
||||||
|
### 一键脚本(macOS / Linux / WSL)
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://github.com/discountry/ritmex-bot/raw/refs/heads/main/setup.sh | bash
|
curl -fsSL https://github.com/discountry/ritmex-bot/raw/refs/heads/main/setup.sh | bash
|
||||||
```
|
```
|
||||||
脚本会安装 Bun、依赖,收集 Aster API Key/Secret,生成 `.env` 并启动 CLI。运行前请准备好 API 凭证。
|
脚本会安装 Bun、项目依赖,收集 Aster API 凭证,生成 `.env` 并启动 CLI。运行前请准备好对应交易所的 API Key/Secret。
|
||||||
|
|
||||||
## 手动安装步骤
|
### 手动安装
|
||||||
1. **获取代码**
|
1. **获取代码**
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/discountry/ritmex-bot.git
|
git clone https://github.com/discountry/ritmex-bot.git
|
||||||
cd ritmex-bot
|
cd ritmex-bot
|
||||||
```
|
```
|
||||||
不方便使用 Git 时,可在仓库页面下载 ZIP 并手动解压。
|
不便使用 Git 时,可在仓库页面下载 ZIP 后手动解压。
|
||||||
2. **安装 Bun**
|
2. **安装 Bun**
|
||||||
- macOS / Linux:`curl -fsSL https://bun.sh/install | bash`
|
- macOS / Linux:`curl -fsSL https://bun.sh/install | bash`
|
||||||
- Windows PowerShell:`powershell -c "irm bun.sh/install.ps1 | iex"`
|
- Windows PowerShell:`powershell -c "irm bun.sh/install.ps1 | iex"`
|
||||||
安装后重新打开终端,确认 `bun -v` 正常输出版本号。
|
安装完成后重新打开终端,确认 `bun -v` 正常输出版本号。
|
||||||
3. **安装依赖**
|
3. **安装依赖**
|
||||||
```bash
|
```bash
|
||||||
bun install
|
bun install
|
||||||
@@ -45,67 +74,124 @@ curl -fsSL https://github.com/discountry/ritmex-bot/raw/refs/heads/main/setup.sh
|
|||||||
```bash
|
```bash
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
```
|
```
|
||||||
按下文说明修改 `.env`,至少需要正确配置 Aster 或 GRVT 的 API。
|
按下文指南修改 `.env`,至少需要正确配置一个交易所的凭证。
|
||||||
5. **运行 CLI**
|
5. **运行 CLI**
|
||||||
```bash
|
```bash
|
||||||
bun run index.ts
|
bun run index.ts
|
||||||
```
|
```
|
||||||
方向键选择策略,回车启动;`Esc` 返回菜单,`Ctrl+C` 退出。
|
方向键选择策略并回车启动;`Esc` 返回菜单,`Ctrl+C` 退出。
|
||||||
|
|
||||||
## 环境变量配置指南
|
## 通用环境变量
|
||||||
核心变量在 `.env.example` 中给出默认值:
|
`.env.example` 提供了所有默认键值,下表概括最常用参数:
|
||||||
|
|
||||||
| 变量 | 说明 |
|
| 变量 | 说明 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `ASTER_API_KEY` / `ASTER_API_SECRET` | Aster API 凭证,运行策略必填 |
|
| `EXCHANGE` | 选择交易所(`aster`/`standx`/`grvt`/`lighter`/`backpack`/`paradex`/`nado`) |
|
||||||
| `TRADE_SYMBOL` | 交易对(默认 `BTCUSDT`) |
|
| `TRADE_SYMBOL` | 交易对(默认 `BTCUSDT`) |
|
||||||
| `TRADE_AMOUNT` | 单笔下单数量(标的资产计) |
|
| `TRADE_AMOUNT` | 单笔下单数量(标的资产计) |
|
||||||
| `LOSS_LIMIT` | 单笔最大亏损触发的强平额度(USDT) |
|
| `LOSS_LIMIT` | 单笔最大亏损触发的强平额度(USDT) |
|
||||||
| `TRAILING_PROFIT` / `TRAILING_CALLBACK_RATE` | 动态止盈触发值(USDT)与回撤百分比 |
|
| `TRAILING_PROFIT` / `TRAILING_CALLBACK_RATE` | 动态止盈触发值(USDT)与回撤百分比 |
|
||||||
| `PROFIT_LOCK_TRIGGER_USD` / `PROFIT_LOCK_OFFSET_USD` | 浮盈超过阈值后上调止损的触发金额与偏移 |
|
| `PROFIT_LOCK_TRIGGER_USD` / `PROFIT_LOCK_OFFSET_USD` | 浮盈超过阈值后上调止损的触发金额与偏移 |
|
||||||
| `BOLLINGER_LENGTH` / `BOLLINGER_STD_MULTIPLIER` | 布林带宽度判定的窗口长度与标准差倍数 |
|
| `BOLLINGER_*` | 趋势策略布林带过滤参数 |
|
||||||
| `MIN_BOLLINGER_BANDWIDTH` | 仅当带宽 ≥ 此比例时才触发入场信号 |
|
|
||||||
| `PRICE_TICK` / `QTY_STEP` | 交易所要求的最小报价与数量精度 |
|
| `PRICE_TICK` / `QTY_STEP` | 交易所要求的最小报价与数量精度 |
|
||||||
| `POLL_INTERVAL_MS` | 趋势策略循环间隔(毫秒) |
|
| `POLL_INTERVAL_MS` | 趋势策略循环间隔(毫秒) |
|
||||||
| `MAX_CLOSE_SLIPPAGE_PCT` | 平仓时相对标记价允许的最大偏差 |
|
| `MAX_CLOSE_SLIPPAGE_PCT` | 平仓时相对标记价允许的最大偏差 |
|
||||||
| `MAKER_*` 系列 | 做市策略独有参数(追价阈值、报价偏移、刷新频率等) |
|
| `MAKER_*` | 做市策略专属参数(追价阈值、报价偏移、刷新频率等) |
|
||||||
|
|
||||||
切换到 GRVT 时,将 `EXCHANGE=grvt` 并补齐 `GRVT_API_KEY`、`GRVT_API_SECRET`、`GRVT_SUB_ACCOUNT_ID` 等变量;详情见 `.env.example`。
|
> 可通过命令行临时覆盖交易所与策略(优先级高于 `.env`):
|
||||||
|
|
||||||
> 提示:你也可以通过命令行参数临时指定交易所(优先级高于环境变量):
|
|
||||||
> ```bash
|
> ```bash
|
||||||
> bun run index.ts --exchange grvt
|
> bun run index.ts --exchange grvt --strategy maker
|
||||||
> bun run index.ts -e lighter
|
> bun run index.ts -e lighter -s offset-maker --silent
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
## 常用命令
|
## 交易所配置指南
|
||||||
|
### Aster
|
||||||
|
1. 将 `EXCHANGE` 保持为 `aster`(默认值)。
|
||||||
|
2. 填写 `ASTER_API_KEY` 与 `ASTER_API_SECRET`。
|
||||||
|
3. 根据交易对调整 `TRADE_SYMBOL`、`PRICE_TICK`、`QTY_STEP` 等精度参数。
|
||||||
|
4. 一键脚本会自动写入这些变量,手动部署时需自行维护。
|
||||||
|
|
||||||
|
### StandX
|
||||||
|
|
||||||
|
* [StandX 做市策略教程](docs/standx/maker-points-guide.md)
|
||||||
|
|
||||||
|
策略需要 StandX 的 API Token 和签名私钥才能下单。
|
||||||
|
|
||||||
|
**获取方式(使用 StandX 官方 API 生成功能):**
|
||||||
|
1. 打开 StandX 官方 API 创建页面:https://standx.com/user/session
|
||||||
|
2. 连接钱包并登录
|
||||||
|
3. 点击 **"Generate API Token"** 按钮
|
||||||
|
4. 页面会显示以下信息:
|
||||||
|
- **Token**(以 `eyJ` 开头的 JWT 字符串)→ 填入 `STANDX_TOKEN`
|
||||||
|
- **Ed25519 Private Key**(Base58 格式私钥,类似 `HdsyJD7oWgT...`)→ 填入 `STANDX_REQUEST_PRIVATE_KEY`
|
||||||
|
- **创建日期** 和 **有效期天数** → 用于配置 Token 过期提醒
|
||||||
|
|
||||||
|
> Ed25519 Private Key 是系统自动生成的签名私钥,仅用于交易请求签名,你的资产仍在主钱包中,非常安全。
|
||||||
|
|
||||||
|
请妥善保存这些凭证,不要分享给他人。
|
||||||
|
|
||||||
|
**配置步骤:**
|
||||||
|
1. 设置 `EXCHANGE=standx`。
|
||||||
|
2. 填写 `STANDX_TOKEN`(Perps API 的 JWT Token)。
|
||||||
|
3. 填写 `STANDX_REQUEST_PRIVATE_KEY`(Ed25519 签名私钥,Base58 格式)。
|
||||||
|
4. 设置 `STANDX_SYMBOL`(默认 `BTC-USD`),并校准 `PRICE_TICK` / `QTY_STEP`。
|
||||||
|
5. 推荐配置 Token 过期时间:
|
||||||
|
- `STANDX_TOKEN_CREATE_DATE`(创建日期,格式 `YYYY-MM-DD`)
|
||||||
|
- `STANDX_TOKEN_VALIDITY_DAYS`(有效期天数)
|
||||||
|
6. 可选:`STANDX_BASE_URL`、`STANDX_WS_URL`、`STANDX_SESSION_ID` 用于自定义环境。
|
||||||
|
|
||||||
|
|
||||||
|
### GRVT
|
||||||
|
1. 在 `.env` 中设置 `EXCHANGE=grvt`。
|
||||||
|
2. 填写 `GRVT_API_KEY`、`GRVT_API_SECRET`、`GRVT_SUB_ACCOUNT_ID`。
|
||||||
|
3. 若使用测试网,可将 `GRVT_ENV=testnet` 并调整 `GRVT_INSTRUMENT`/`GRVT_SYMBOL`。
|
||||||
|
4. 可选:提供 `GRVT_COOKIE` 或自定义 `GRVT_SIGNER_PATH` 以复用已有登录态。
|
||||||
|
|
||||||
|
### Lighter
|
||||||
|
1. 设置 `EXCHANGE=lighter`。
|
||||||
|
2. 填写 `LIGHTER_ACCOUNT_INDEX` 与 `LIGHTER_API_PRIVATE_KEY`(40 字节十六进制私钥),其中`LIGHTER_ACCOUNT_INDEX`是你的账户索引,需要你在官网按F12观察接口请求获取,`LIGHTER_API_PRIVATE_KEY`是你的API私钥。
|
||||||
|
3. 如需切换环境,将 `LIGHTER_ENV` 改为 `mainnet`/`staging`/`dev`;必要时指定 `LIGHTER_BASE_URL`。
|
||||||
|
4. 交易对默认为 `LIGHTER_SYMBOL=BTCUSDT`,也可按需重写价格与数量小数位。
|
||||||
|
|
||||||
|
### Backpack
|
||||||
|
1. 设置 `EXCHANGE=backpack`。
|
||||||
|
2. 填写 `BACKPACK_API_KEY`、`BACKPACK_API_SECRET`、`BACKPACK_PASSWORD`;如有分账户,补充 `BACKPACK_SUBACCOUNT`,默认填写主账户ID。
|
||||||
|
3. 使用测试环境时将 `BACKPACK_SANDBOX=true`,并确认 `BACKPACK_SYMBOL` 与实际符号一致(默认 `BTC_USD_PERP`)。
|
||||||
|
4. 可通过 `BACKPACK_DEBUG=true` 观察适配器详细日志。
|
||||||
|
|
||||||
|
### Paradex
|
||||||
|
1. 设置 `EXCHANGE=paradex`。
|
||||||
|
2. 提供 `PARADEX_PRIVATE_KEY`(EVM 私钥)与 `PARADEX_WALLET_ADDRESS` 注意这是你EVM钱包的地址和私钥,建议创建全新钱包,不要放置无关资产。
|
||||||
|
3. 默认连接主网,若需测试网,将 `PARADEX_SANDBOX=true` 并根据需要调整 `PARADEX_SYMBOL`。
|
||||||
|
4. 复杂环境可额外设置 `PARADEX_USE_PRO`、`PARADEX_RECONNECT_DELAY_MS` 或调试开关。
|
||||||
|
|
||||||
|
### Nado
|
||||||
|
1. 设置 `EXCHANGE=nado`。
|
||||||
|
2. 在 Nado 官网(交易界面)打开开发者工具(F12)→ 切换到 `Application` → `Local Storage`,找到 `nado.userSettings`,在其内容中取出 `privateKey` 字段并填入 `.env` 的 `NADO_SIGNER_PRIVATE_KEY`。
|
||||||
|
3. 提供 `NADO_SUBACCOUNT_OWNER`(或 `NADO_EVM_ADDRESS`)。
|
||||||
|
4. 选择网络 `NADO_ENV=inkMainnet`(主网)或 `inkTestnet`(测试网)。
|
||||||
|
5. 设置交易品种 `NADO_SYMBOL`(交易对格式类似 `BTC-PERP`;也支持输入 `BTCUSDT0`,会自动映射为 `BTC-PERP`)。
|
||||||
|
|
||||||
|
## 命令速查
|
||||||
```bash
|
```bash
|
||||||
bun run index.ts # 启动 CLI(默认)
|
bun run index.ts # 启动 CLI(默认入口)
|
||||||
bun run start # 同上
|
bun run start # 等价于运行 index.ts
|
||||||
bun run dev # 调试模式,等价于运行 index.ts
|
bun run dev # 调试模式
|
||||||
bun x vitest run # 执行单元测试
|
bun x vitest run # 执行全部测试
|
||||||
```
|
```
|
||||||
|
|
||||||
## 静默启动与后台运行
|
## 静默启动与后台运行
|
||||||
### 直接静默启动
|
### 直接静默启动
|
||||||
无需进入 Ink 菜单,可用命令行直接拉起指定策略:
|
无需进入 Ink 菜单,可用命令行直接拉起指定策略:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run index.ts --strategy trend --silent # 启动趋势策略
|
bun run index.ts --strategy trend --silent
|
||||||
bun run index.ts --strategy maker --silent # 启动做市策略
|
bun run index.ts --strategy maker --silent
|
||||||
bun run index.ts --strategy offset-maker --silent # 启动偏移做市策略
|
bun run index.ts --strategy offset-maker --silent
|
||||||
```
|
|
||||||
|
|
||||||
如需同时指定交易所,可叠加 `--exchange/-e`(将覆盖 `.env` 中的 `EXCHANGE`/`TRADE_EXCHANGE`):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bun run index.ts --exchange grvt --strategy maker --silent
|
|
||||||
bun run index.ts -e lighter -s offset-maker --silent
|
|
||||||
```
|
```
|
||||||
|
如需同时指定交易所,可叠加 `--exchange/-e` 参数。
|
||||||
|
|
||||||
### 项目内置脚本
|
### 项目内置脚本
|
||||||
`package.json` 提供了便捷脚本:
|
`package.json` 提供了便捷脚本:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run start:trend:silent
|
bun run start:trend:silent
|
||||||
bun run start:maker:silent
|
bun run start:maker:silent
|
||||||
@@ -113,43 +199,38 @@ bun run start:offset:silent
|
|||||||
```
|
```
|
||||||
|
|
||||||
### 使用 pm2 守护并自动重启
|
### 使用 pm2 守护并自动重启
|
||||||
将 `pm2` 安装到项目中(示例:`bun add -d pm2`),之后即可在不安装全局 pm2 的情况下运行:
|
安装 `pm2`(示例:`bun add -d pm2`)后,可在项目内直接运行:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bunx pm2 start bun --name ritmex-trend --cwd . --restart-delay 5000 -- run index.ts --strategy trend --silent
|
bunx pm2 start bun --name ritmex-trend --cwd . --restart-delay 5000 -- run index.ts --strategy trend --silent
|
||||||
```
|
```
|
||||||
|
或调用预置脚本:
|
||||||
亦可直接调用脚本:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run pm2:start:trend
|
bun run pm2:start:trend
|
||||||
bun run pm2:start:maker
|
bun run pm2:start:maker
|
||||||
bun run pm2:start:offset
|
bun run pm2:start:offset
|
||||||
```
|
```
|
||||||
|
完成配置后可执行 `pm2 save` 持久化进程列表。
|
||||||
根据需要调整 `--name`、`--cwd`、`--restart-delay` 等参数,完成后可执行 `pm2 save` 持久化进程列表。
|
|
||||||
|
|
||||||
## 测试
|
## 测试
|
||||||
项目使用 Vitest:
|
项目使用 Vitest:
|
||||||
```bash
|
```bash
|
||||||
bun run test # 运行全部测试
|
bun run test
|
||||||
bun x vitest --watch
|
bun x vitest --watch
|
||||||
```
|
```
|
||||||
|
|
||||||
## 常见问题
|
## 常见问题
|
||||||
|
- 至少准备 50–100 USDT 资金以覆盖策略运行需求。
|
||||||
- 你需要至少 50-100 USDT 的资金才能运行策略
|
- 杠杆需在交易所提前设置(建议 ~50 倍),程序不会自动调整。
|
||||||
- 请在交易所自行设置 50 倍左右的杠杆,本策略不包含杠杆设置
|
- 请确保服务器/电脑时间同步真实世界时间,避免签名过期。
|
||||||
- 请确保你电脑/服务器的时间是准确的真实世界时间
|
- 账户需保持单向持仓模式。
|
||||||
- 持仓方式需要保持单向持仓
|
|
||||||
- `.env` 未读取:确认文件位于项目根目录且变量名无误。
|
- `.env` 未读取:确认文件位于项目根目录且变量名无误。
|
||||||
- API 拒绝访问:检查交易所后台权限,确保开启合约读写。
|
- API 拒绝访问:检查交易所后台权限,确保开启合约读写。
|
||||||
- 精度错误:同步交易对的最小价格与数量步长。
|
- 精度错误:同步交易对的最小价格与数量步长。
|
||||||
更多排查步骤可参考 [简明上手指南](simple-readme.md)。
|
更多排查细节可参见 [简明上手指南](simple-readme.md)。
|
||||||
|
|
||||||
## 社区与支持
|
## 社区与支持
|
||||||
- Telegram 交流群:[https://t.me/+4fdo0quY87o4Mjhh](https://t.me/+4fdo0quY87o4Mjhh)
|
- Telegram 交流群:[https://t.me/+4fdo0quY87o4Mjhh](https://t.me/+4fdo0quY87o4Mjhh)
|
||||||
- 反馈或新特性建议请提交 Issue 或 PR
|
- 欢迎通过 Issue 或 PR 提交反馈、特性建议
|
||||||
|
|
||||||
## 风险提示
|
## 风险提示
|
||||||
量化交易具备风险。建议在仿真或小额账户中验证策略表现,妥善保管 API 密钥,仅开启必要权限。
|
量化交易具备风险。请先在仿真或小额账户中验证策略表现,妥善保管 API 密钥,仅开启必要权限。
|
||||||
|
|||||||
+148
-67
@@ -1,39 +1,67 @@
|
|||||||
# ritmex-bot
|
# ritmex-bot
|
||||||
|
|
||||||
A Bun-powered trading workstation for Aster perpetual contracts that ships two production-ready agents: an SMA30 trend follower and a dual-sided market maker. The CLI is built with Ink, synchronises risk state from the exchange, and automatically recovers from restarts or disconnects.
|
**Language Setting**: Set `LANG=en` in your `.env` file to display the CLI interface in English.
|
||||||
|
|
||||||
|
A Bun-powered multi-exchange perpetuals workstation that ships an SMA30 trend engine, a Guardian stop sentinel, and two market-making modes. It offers instant restarts, realtime market data, structured logging, and an Ink-based CLI dashboard.
|
||||||
|
|
||||||
|
If you'd like to support this project and get fee discounts, please consider using these referral links:
|
||||||
|
|
||||||
|
* [Lighter referral link](https://app.lighter.xyz/?referral=111909FA)
|
||||||
|
* [Aster referral link](https://www.asterdex.com/en/referral/4665f3)
|
||||||
|
* [StandX referral link](https://standx.com/referral?code=xingxingjun)
|
||||||
|
* [Binance referral link](https://www.binance.com/join?ref=KNKCA9XC)
|
||||||
|
* [GRVT referral link](https://grvt.io/exchange/sign-up?ref=sea)
|
||||||
|
* [Nado referral link](https://app.nado.xyz?join=LKbIUs5)
|
||||||
|
* [Backpack referral link](https://backpack.exchange/join/ritmex)
|
||||||
|
* [edgex referral link](https://pro.edgex.exchange/referral/BULL)
|
||||||
|
* [Paradex referral link](https://paradex.io/ref/xingxingjun)
|
||||||
|
* [Apex referral link](https://join.omni.apex.exchange/SEA)
|
||||||
|
|
||||||
## Documentation Map
|
## Documentation Map
|
||||||
- [中文 README](README.md)
|
|
||||||
- [Beginner-friendly Quick Start](simple-readme.md)
|
- [Beginner-friendly Quick Start](simple-readme.md)
|
||||||
|
- [Grid Trading Strategy Guide](grid-trading.md)
|
||||||
|
|
||||||
## Highlights
|
## Highlights
|
||||||
- **Live market data & risk sync** via websocket feeds with REST fallbacks, full reconciliation on restart.
|
- **Live data & risk sync** via websockets with REST fallbacks and full reconciliation on restart.
|
||||||
- **Trend engine** featuring SMA30 entries, fixed stop loss, trailing stop, Bollinger bandwidth gate, and profit-lock stepping.
|
- **Trend strategy** featuring SMA30 entries, fixed stop loss, trailing stop, Bollinger bandwidth gate, and profit-lock stepping.
|
||||||
- **Market-making loop** with adaptive quote chasing, loss caps, and automatic order healing.
|
- **Guardian strategy** that never opens trades but mirrors your live exposure, ensuring every position has a synced stop loss and trailing stop.
|
||||||
- **Extensible architecture** decoupling exchange adapters, engines, and the Ink CLI for easy venue or strategy additions.
|
- **Market-making loop** with dual-sided quote chasing, loss caps, and automatic order healing.
|
||||||
|
- **Modular architecture** decoupling engines, exchange adapters, and the Ink CLI for easy venue or strategy extensions.
|
||||||
|
|
||||||
|
## Supported Exchanges
|
||||||
|
| Exchange | Contract Type | Required Environment Variables | Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Aster | USDT perpetuals | `ASTER_API_KEY`, `ASTER_API_SECRET` | Default venue; works with the bootstrap script |
|
||||||
|
| StandX | USD perpetuals | `STANDX_TOKEN` | Uses JWT token auth; prefer websocket streams |
|
||||||
|
| GRVT | USDT perpetuals | `GRVT_API_KEY`, `GRVT_API_SECRET`, `GRVT_SUB_ACCOUNT_ID` | Switch `GRVT_ENV` between `prod` and `testnet` |
|
||||||
|
| Lighter | zkLighter perpetuals | `LIGHTER_ACCOUNT_INDEX`, `LIGHTER_API_PRIVATE_KEY` | Defaults to `LIGHTER_ENV=testnet` |
|
||||||
|
| Backpack | USDC perpetuals | `BACKPACK_API_KEY`, `BACKPACK_API_SECRET`, `BACKPACK_PASSWORD` | Set `BACKPACK_SANDBOX=true` for the sandbox |
|
||||||
|
| Paradex | StarkEx perpetuals | `PARADEX_PRIVATE_KEY`, `PARADEX_WALLET_ADDRESS` | Toggle `PARADEX_SANDBOX=true` for the testnet |
|
||||||
|
| Nado | USDC perpetuals | `NADO_SIGNER_PRIVATE_KEY`, `NADO_SUBACCOUNT_OWNER` | Switch `NADO_ENV` between `inkMainnet` and `inkTestnet` |
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- Bun ≥ 1.2 (`bun`, `bunx` available on PATH)
|
- Bun >= 1.2 (both `bun` and `bunx` on PATH)
|
||||||
- macOS, Linux, or Windows via WSL (native Windows works but WSL is recommended)
|
- macOS, Linux, or Windows via WSL (native Windows works but WSL is recommended)
|
||||||
- Node.js is optional unless your environment requires it for tooling
|
- Node.js is optional unless your tooling requires it
|
||||||
|
|
||||||
## One-Line Bootstrap (macOS / Linux / WSL)
|
## Quick Start
|
||||||
|
### One-line bootstrap (macOS / Linux / WSL)
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://github.com/discountry/ritmex-bot/raw/refs/heads/main/setup.sh | bash
|
curl -fsSL https://github.com/discountry/ritmex-bot/raw/refs/heads/main/setup.sh | bash
|
||||||
```
|
```
|
||||||
The script installs Bun, project dependencies, collects Aster API credentials, generates `.env`, and launches the CLI. Prepare your API Key/Secret before running.
|
The script installs Bun, project dependencies, collects Aster API credentials, generates `.env`, and launches the CLI. Prepare the relevant exchange API keys before running it.
|
||||||
|
|
||||||
## Manual Installation
|
### Manual installation
|
||||||
1. **Clone the repository**
|
1. **Clone the repository**
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/discountry/ritmex-bot.git
|
git clone https://github.com/discountry/ritmex-bot.git
|
||||||
cd ritmex-bot
|
cd ritmex-bot
|
||||||
```
|
```
|
||||||
Alternatively download the ZIP from GitHub and extract it manually.
|
Alternatively, download the ZIP from GitHub and extract it manually.
|
||||||
2. **Install Bun**
|
2. **Install Bun**
|
||||||
- macOS / Linux: `curl -fsSL https://bun.sh/install | bash`
|
- macOS / Linux: `curl -fsSL https://bun.sh/install | bash`
|
||||||
- Windows PowerShell: `powershell -c "irm bun.sh/install.ps1 | iex"`
|
- Windows PowerShell: `powershell -c "irm bun.sh/install.ps1 | iex"`
|
||||||
Re-open the terminal and confirm `bun -v` prints a version.
|
Re-open the terminal and verify `bun -v` prints a version.
|
||||||
3. **Install dependencies**
|
3. **Install dependencies**
|
||||||
```bash
|
```bash
|
||||||
bun install
|
bun install
|
||||||
@@ -42,67 +70,124 @@ The script installs Bun, project dependencies, collects Aster API credentials, g
|
|||||||
```bash
|
```bash
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
```
|
```
|
||||||
Edit `.env` with your exchange credentials and overrides.
|
Edit `.env` with the exchange credentials and overrides you plan to use.
|
||||||
5. **Launch the CLI**
|
5. **Launch the CLI**
|
||||||
```bash
|
```bash
|
||||||
bun run index.ts
|
bun run index.ts
|
||||||
```
|
```
|
||||||
Use the arrow keys to pick a strategy, `Enter` to start, `Esc` to return to the menu, and `Ctrl+C` to exit.
|
Use the arrow keys to pick a strategy, `Enter` to start, `Esc` to go back, and `Ctrl+C` to exit.
|
||||||
|
|
||||||
## Environment Variables
|
## Shared Configuration
|
||||||
The most important settings shipped in `.env.example` are summarised below:
|
`.env.example` captures all defaults; the most common settings are summarised below.
|
||||||
|
|
||||||
| Variable | Purpose |
|
| Variable | Purpose |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `ASTER_API_KEY` / `ASTER_API_SECRET` | Required Aster exchange credentials |
|
| `EXCHANGE` | Choose the venue (`aster` / `standx` / `grvt` / `lighter` / `backpack` / `paradex` / `nado`) |
|
||||||
| `TRADE_SYMBOL` | Contract symbol, defaults to `BTCUSDT` |
|
| `TRADE_SYMBOL` | Contract symbol (defaults to `BTCUSDT`) |
|
||||||
| `TRADE_AMOUNT` | Order size in base asset units |
|
| `TRADE_AMOUNT` | Order size in base asset units |
|
||||||
| `LOSS_LIMIT` | Max per-trade loss (USDT) before forced close |
|
| `LOSS_LIMIT` | Max per-trade loss in USDT before forced close |
|
||||||
| `TRAILING_PROFIT` / `TRAILING_CALLBACK_RATE` | Trailing stop trigger amount (USDT) and pullback percentage |
|
| `TRAILING_PROFIT` / `TRAILING_CALLBACK_RATE` | Trailing stop trigger (USDT) and pullback percentage |
|
||||||
| `PROFIT_LOCK_TRIGGER_USD` / `PROFIT_LOCK_OFFSET_USD` | Move the base stop once unrealised PnL exceeds this trigger |
|
| `PROFIT_LOCK_TRIGGER_USD` / `PROFIT_LOCK_OFFSET_USD` | Profit lock trigger and offset thresholds |
|
||||||
| `BOLLINGER_LENGTH` / `BOLLINGER_STD_MULTIPLIER` | Window size and std-dev multiplier for bandwidth filtering |
|
| `BOLLINGER_*` | Bollinger bandwidth filters for the trend engine |
|
||||||
| `MIN_BOLLINGER_BANDWIDTH` | Minimum bandwidth ratio required before opening a new position |
|
|
||||||
| `PRICE_TICK` / `QTY_STEP` | Exchange precision filters for price and quantity |
|
| `PRICE_TICK` / `QTY_STEP` | Exchange precision filters for price and quantity |
|
||||||
| `POLL_INTERVAL_MS` | Trend engine polling cadence in milliseconds |
|
| `POLL_INTERVAL_MS` | Trend engine polling cadence in milliseconds |
|
||||||
| `MAX_CLOSE_SLIPPAGE_PCT` | Allowed deviation vs mark price when closing |
|
| `MAX_CLOSE_SLIPPAGE_PCT` | Allowed deviation vs mark price when closing |
|
||||||
| `MAKER_*` | Maker strategy knobs: chase threshold, quote offsets, refresh cadence, etc. |
|
| `MAKER_*` | Maker-specific knobs (quote offsets, refresh cadence, slippage guard, etc.) |
|
||||||
|
|
||||||
To trade on GRVT, set `EXCHANGE=grvt` and populate `GRVT_API_KEY`, `GRVT_API_SECRET`, `GRVT_SUB_ACCOUNT_ID`, plus any optional overrides documented in `.env.example`.
|
> CLI flags override environment variables at runtime:
|
||||||
|
|
||||||
> Tip: you can temporarily override the exchange via CLI flags (takes precedence over environment):
|
|
||||||
> ```bash
|
> ```bash
|
||||||
> bun run index.ts --exchange grvt
|
> bun run index.ts --exchange grvt --strategy maker
|
||||||
> bun run index.ts -e lighter
|
> bun run index.ts -e lighter -s offset-maker --silent
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
## Common Commands
|
## Exchange Setup Guides
|
||||||
|
|
||||||
|
### Aster
|
||||||
|
1. Keep `EXCHANGE=aster` (default value).
|
||||||
|
2. Supply `ASTER_API_KEY` and `ASTER_API_SECRET`.
|
||||||
|
3. Adjust `TRADE_SYMBOL`, `PRICE_TICK`, and `QTY_STEP` to match the requested market.
|
||||||
|
4. The bootstrap script auto-populates these variables; manual installs must maintain them.
|
||||||
|
|
||||||
|
### StandX
|
||||||
|
|
||||||
|
* [StandX Maker Points Strategy Guide](docs/standx/maker-points-guide.md)
|
||||||
|
|
||||||
|
The strategy requires a StandX API Token and signing private key to place orders.
|
||||||
|
|
||||||
|
**How to obtain (using StandX's official API generation feature):**
|
||||||
|
1. Open the StandX official API creation page: https://standx.com/user/session
|
||||||
|
2. Connect your wallet and log in
|
||||||
|
3. Click the **"Generate API Token"** button
|
||||||
|
4. The page will display the following information:
|
||||||
|
- **Token** (JWT string starting with `eyJ`) → Fill in `STANDX_TOKEN`
|
||||||
|
- **Ed25519 Private Key** (Base58 format, like `HdsyJD7oWgT...`) → Fill in `STANDX_REQUEST_PRIVATE_KEY`
|
||||||
|
- **Creation date** and **Validity days** → Used to configure token expiry reminders
|
||||||
|
|
||||||
|
> The Ed25519 Private Key is an auto-generated signing key used only for trade request signatures. Your assets remain in your main wallet and are completely safe.
|
||||||
|
|
||||||
|
Please keep these credentials safe and do not share them with anyone.
|
||||||
|
|
||||||
|
**Configuration steps:**
|
||||||
|
1. Set `EXCHANGE=standx`.
|
||||||
|
2. Provide `STANDX_TOKEN` (JWT token for perps API).
|
||||||
|
3. Provide `STANDX_REQUEST_PRIVATE_KEY` (Ed25519 signing private key, Base58 format).
|
||||||
|
4. Set `STANDX_SYMBOL` (defaults to `BTC-USD`) and align `PRICE_TICK` / `QTY_STEP`.
|
||||||
|
5. Recommended: configure token expiry settings:
|
||||||
|
- `STANDX_TOKEN_CREATE_DATE` (creation date, format `YYYY-MM-DD`)
|
||||||
|
- `STANDX_TOKEN_VALIDITY_DAYS` (validity days)
|
||||||
|
6. Optional: `STANDX_BASE_URL`, `STANDX_WS_URL`, or `STANDX_SESSION_ID` for custom endpoints.
|
||||||
|
|
||||||
|
### GRVT
|
||||||
|
1. Set `EXCHANGE=grvt` inside `.env`.
|
||||||
|
2. Fill `GRVT_API_KEY`, `GRVT_API_SECRET`, and `GRVT_SUB_ACCOUNT_ID`.
|
||||||
|
3. Use `GRVT_ENV=testnet` when targeting the test environment, and align `GRVT_INSTRUMENT` / `GRVT_SYMBOL`.
|
||||||
|
4. Optional: provide `GRVT_COOKIE` or a custom `GRVT_SIGNER_PATH` when reusing an existing session.
|
||||||
|
|
||||||
|
### Lighter
|
||||||
|
1. Set `EXCHANGE=lighter`.
|
||||||
|
2. Provide `LIGHTER_ACCOUNT_INDEX` and `LIGHTER_API_PRIVATE_KEY` (40-byte hex private key). `LIGHTER_ACCOUNT_INDEX` is your account index, which you can find by opening DevTools (F12) on the official website and observing API requests. `LIGHTER_API_PRIVATE_KEY` is your API private key.
|
||||||
|
3. Switch `LIGHTER_ENV` to `mainnet`, `staging`, or `dev` when necessary; override `LIGHTER_BASE_URL` if endpoints differ.
|
||||||
|
4. `LIGHTER_SYMBOL` defaults to `BTCUSDT`; override price/size decimals when markets differ.
|
||||||
|
|
||||||
|
### Backpack
|
||||||
|
1. Set `EXCHANGE=backpack`.
|
||||||
|
2. Populate `BACKPACK_API_KEY`, `BACKPACK_API_SECRET`, and `BACKPACK_PASSWORD`; add `BACKPACK_SUBACCOUNT` if you trade from a subaccount (defaults to main account ID).
|
||||||
|
3. Toggle `BACKPACK_SANDBOX=true` for the sandbox environment and verify `BACKPACK_SYMBOL` matches the contract (defaults to `BTC_USD_PERP`).
|
||||||
|
4. Enable `BACKPACK_DEBUG=true` for verbose adapter logging.
|
||||||
|
|
||||||
|
### Paradex
|
||||||
|
1. Set `EXCHANGE=paradex`.
|
||||||
|
2. Provide `PARADEX_PRIVATE_KEY` (EVM private key) and `PARADEX_WALLET_ADDRESS`. Note: These are your EVM wallet address and private key. It is recommended to create a brand new wallet and avoid storing unrelated assets in it.
|
||||||
|
3. The adapter connects to mainnet by default; enable `PARADEX_SANDBOX=true` and adjust `PARADEX_SYMBOL` for testnet usage.
|
||||||
|
4. Advanced tuning: use `PARADEX_USE_PRO`, `PARADEX_RECONNECT_DELAY_MS`, or debug flags as needed.
|
||||||
|
|
||||||
|
### Nado
|
||||||
|
1. Set `EXCHANGE=nado`.
|
||||||
|
2. On the Nado web app (trading interface), open DevTools (F12) -> switch to the `Application` tab -> `Local Storage`, locate `nado.userSettings`, then grab the `privateKey` field from its JSON value and paste it into `.env` as `NADO_SIGNER_PRIVATE_KEY`.
|
||||||
|
3. Provide `NADO_SUBACCOUNT_OWNER` (or `NADO_EVM_ADDRESS`).
|
||||||
|
4. Select network via `NADO_ENV=inkMainnet` (mainnet) or `inkTestnet` (testnet).
|
||||||
|
5. Set `NADO_SYMBOL` using Nado product symbols like `BTC-PERP` (it also accepts `BTCUSDT0` and maps it to `BTC-PERP`).
|
||||||
|
|
||||||
|
## Command Cheatsheet
|
||||||
```bash
|
```bash
|
||||||
bun run index.ts # Launch the CLI
|
bun run index.ts # Launch the CLI (default entrypoint)
|
||||||
bun run start # Same as above
|
bun run start # Alias for bun run index.ts
|
||||||
bun run dev # Development entry point
|
bun run dev # Development entrypoint
|
||||||
bun x vitest run # Execute the Vitest suite
|
bun x vitest run # Execute the full Vitest suite
|
||||||
```
|
```
|
||||||
|
|
||||||
## Silent & Background Execution
|
## Silent & Background Execution
|
||||||
### Direct silent launch
|
### Direct silent launch
|
||||||
Skip the Ink menu and start a strategy straight from the CLI:
|
Skip the Ink menu and start a strategy directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run index.ts --strategy trend --silent # Trend engine
|
bun run index.ts --strategy trend --silent
|
||||||
bun run index.ts --strategy maker --silent # Maker engine
|
bun run index.ts --strategy maker --silent
|
||||||
bun run index.ts --strategy offset-maker --silent # Offset maker engine
|
bun run index.ts --strategy offset-maker --silent
|
||||||
```
|
|
||||||
|
|
||||||
Combine with `--exchange/-e` to explicitly choose the venue (overrides `EXCHANGE`/`TRADE_EXCHANGE` from `.env`):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bun run index.ts --exchange grvt --strategy maker --silent
|
|
||||||
bun run index.ts -e lighter -s offset-maker --silent
|
|
||||||
```
|
```
|
||||||
|
Combine with `--exchange/-e` to pin the venue for that run.
|
||||||
|
|
||||||
### Package scripts
|
### Package scripts
|
||||||
Convenience aliases are exposed in `package.json`:
|
Convenience aliases exposed via `package.json`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run start:trend:silent
|
bun run start:trend:silent
|
||||||
bun run start:maker:silent
|
bun run start:maker:silent
|
||||||
@@ -110,42 +195,38 @@ bun run start:offset:silent
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Daemonising with pm2
|
### Daemonising with pm2
|
||||||
Install `pm2` locally (e.g. `bun add -d pm2`) and launch without a global install:
|
Install `pm2` locally (e.g. `bun add -d pm2`) and launch the process:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bunx pm2 start bun --name ritmex-trend --cwd . --restart-delay 5000 -- run index.ts --strategy trend --silent
|
bunx pm2 start bun --name ritmex-trend --cwd . --restart-delay 5000 -- run index.ts --strategy trend --silent
|
||||||
```
|
```
|
||||||
|
You can also call the bundled scripts:
|
||||||
You can also reuse the bundled scripts:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run pm2:start:trend
|
bun run pm2:start:trend
|
||||||
bun run pm2:start:maker
|
bun run pm2:start:maker
|
||||||
bun run pm2:start:offset
|
bun run pm2:start:offset
|
||||||
```
|
```
|
||||||
|
Run `pm2 save` afterwards if you want the process list to survive reboots.
|
||||||
Adjust `--name`, `--cwd`, or `--restart-delay` to suit your environment and run `pm2 save` if you want the process to auto-start after reboot.
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
Vitest powers the unit tests:
|
Powered by Vitest:
|
||||||
```bash
|
```bash
|
||||||
bun run test
|
bun run test
|
||||||
bun x vitest --watch
|
bun x vitest --watch
|
||||||
```
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
- You need at least 50–100 USDT of capital before deploying a live strategy.
|
- Keep at least 50-100 USDT in the account before deploying a live strategy.
|
||||||
- Set leverage on the exchange beforehand (around 50x is recommended); the bot does not change it for you.
|
- Configure leverage on the exchange manually (~50x is recommended); the bot will not change it.
|
||||||
- Keep server/desktop time in sync with real-world time to avoid signature errors.
|
- Ensure your server or workstation clock is in sync to avoid signature errors.
|
||||||
- Make sure the exchange account is in one-way position mode.
|
- Accounts must run in one-way position mode.
|
||||||
- **Env not loading**: ensure `.env` resides in the repository root and variable names are spelled correctly.
|
- **Env not loading**: make sure `.env` lives in the repo root and variable names are spelled correctly.
|
||||||
- **Order rejected for precision**: align `PRICE_TICK`, `QTY_STEP`, and `TRADE_SYMBOL` with the exchange filters.
|
- **Permission rejected**: confirm the API key has perpetual trading scopes enabled.
|
||||||
- **Permission or auth errors**: double-check exchange API scopes.
|
- **Precision errors**: align `PRICE_TICK`, `QTY_STEP`, and `TRADE_SYMBOL` with the exchange filters.
|
||||||
More step-by-step guidance is available in [simple-readme.md](simple-readme.md).
|
See [simple-readme.md](simple-readme.md) for more detailed walkthroughs.
|
||||||
|
|
||||||
## Community & Support
|
## Community & Support
|
||||||
- Telegram: [https://t.me/+4fdo0quY87o4Mjhh](https://t.me/+4fdo0quY87o4Mjhh)
|
- Telegram: [https://t.me/+4fdo0quY87o4Mjhh](https://t.me/+4fdo0quY87o4Mjhh)
|
||||||
- Issues and PRs are welcome for bug reports and feature ideas
|
- Issues and PRs are welcome for bug reports and feature requests
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
Algorithmic trading carries risk. Validate strategies with paper accounts or small capital first, safeguard your API keys, and only grant the minimum required permissions.
|
Algorithmic trading carries risk. Validate strategies with paper trading or small capital first, safeguard your API keys, and only grant the minimum required permissions.
|
||||||
|
|||||||
@@ -1,133 +1,162 @@
|
|||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ritmex-bot",
|
"name": "ritmex-bot",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@grvt/client": "^1.6.4",
|
"@grvt/client": "^1.6.25",
|
||||||
"axios": "^1.12.2",
|
"@nadohq/client": "^0.1.0-alpha.45",
|
||||||
"ccxt": "^4.5.5",
|
"@noble/ed25519": "^3.0.0",
|
||||||
"dotenv": "^17.2.2",
|
"@starkware-industries/starkware-crypto-utils": "^0.2.1",
|
||||||
"ethereum-cryptography": "^2.1.3",
|
"axios": "^1.13.4",
|
||||||
"ink": "^6.3.1",
|
"bignumber.js": "^9.3.1",
|
||||||
"react": "^19.1.1",
|
"ccxt": "^4.5.35",
|
||||||
"ws": "^8.18.3",
|
"dotenv": "^17.2.3",
|
||||||
|
"ethereum-cryptography": "^2.2.1",
|
||||||
|
"ink": "^6.6.0",
|
||||||
|
"react": "^19.2.4",
|
||||||
|
"trading-signals": "^7.4.3",
|
||||||
|
"viem": "^2.45.1",
|
||||||
|
"ws": "^8.19.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"vitest": "^3.2.4",
|
"vitest": "^3.2.4",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5",
|
"typescript": "^5.9.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.2.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-qI/5TaaaCZE4yeSZ83lu0+xi1r88JSxUjnH4OP/iZF7+KKZ75u3ee5isd0LxX+6N8U0npL61YrpbthILHB6BnA=="],
|
"@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.1", "", {}, "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ=="],
|
||||||
|
|
||||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.10", "", { "os": "aix", "cpu": "ppc64" }, "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw=="],
|
"@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.2.5", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-3NX/MpTdroi0aKz134A6RC2Gb2iXVECN4QaAXnvCIxxIm3C3AVB1mkUe8NaaiyvOpDfsrqWhYtj+Q6a62RrTsw=="],
|
||||||
|
|
||||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.10", "", { "os": "android", "cpu": "arm" }, "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w=="],
|
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
|
||||||
|
|
||||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.10", "", { "os": "android", "cpu": "arm64" }, "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg=="],
|
"@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
|
||||||
|
|
||||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.10", "", { "os": "android", "cpu": "x64" }, "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg=="],
|
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="],
|
||||||
|
|
||||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA=="],
|
"@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="],
|
||||||
|
|
||||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg=="],
|
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="],
|
||||||
|
|
||||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.10", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg=="],
|
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="],
|
||||||
|
|
||||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.10", "", { "os": "freebsd", "cpu": "x64" }, "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA=="],
|
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="],
|
||||||
|
|
||||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.10", "", { "os": "linux", "cpu": "arm" }, "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg=="],
|
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="],
|
||||||
|
|
||||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ=="],
|
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="],
|
||||||
|
|
||||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.10", "", { "os": "linux", "cpu": "ia32" }, "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ=="],
|
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="],
|
||||||
|
|
||||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg=="],
|
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="],
|
||||||
|
|
||||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA=="],
|
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="],
|
||||||
|
|
||||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.10", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA=="],
|
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="],
|
||||||
|
|
||||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA=="],
|
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="],
|
||||||
|
|
||||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.10", "", { "os": "linux", "cpu": "s390x" }, "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew=="],
|
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="],
|
||||||
|
|
||||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA=="],
|
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="],
|
||||||
|
|
||||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A=="],
|
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="],
|
||||||
|
|
||||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.10", "", { "os": "none", "cpu": "x64" }, "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig=="],
|
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="],
|
||||||
|
|
||||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.10", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw=="],
|
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="],
|
||||||
|
|
||||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.10", "", { "os": "openbsd", "cpu": "x64" }, "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw=="],
|
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="],
|
||||||
|
|
||||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag=="],
|
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="],
|
||||||
|
|
||||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.10", "", { "os": "sunos", "cpu": "x64" }, "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ=="],
|
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="],
|
||||||
|
|
||||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw=="],
|
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="],
|
||||||
|
|
||||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="],
|
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="],
|
||||||
|
|
||||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="],
|
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="],
|
||||||
|
|
||||||
"@grvt/client": ["@grvt/client@1.6.4", "", { "dependencies": { "axios": "^1.12.2" } }, "sha512-yZfEvsC/BtkcdMjoB7Eh6gshBraz/9810qCllvNXDx6OmdxR+NfxPO+ucNlPbyjEt1HfSVzHBWB1yGnVl1usNA=="],
|
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
|
||||||
|
|
||||||
|
"@grvt/client": ["@grvt/client@1.6.26", "", { "dependencies": { "axios": "^1.13.5" } }, "sha512-Y6uWa3rirdYPU0BgQS7vYKghscTR7AwykQYZVSjib2GGbMW4JZJc/XX/IcZq0aL59W/S7ISechw+DhU/Amw2SQ=="],
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||||
|
|
||||||
|
"@nadohq/client": ["@nadohq/client@0.1.0-alpha.50", "", { "dependencies": { "@nadohq/engine-client": "0.1.0-alpha.50", "@nadohq/indexer-client": "0.1.0-alpha.50", "@nadohq/shared": "0.1.0-alpha.50", "@nadohq/trigger-client": "0.1.0-alpha.50", "ts-mixer": "*" }, "peerDependencies": { "viem": "*" } }, "sha512-9A7I5pDuvdKJCGrhadxmORceaW3YVlrMTXoSQg+dYPBflsQpKLJQaEXZZyn1Hb9tz9K6rNUxdt33aXL0gb6IKw=="],
|
||||||
|
|
||||||
|
"@nadohq/engine-client": ["@nadohq/engine-client@0.1.0-alpha.50", "", { "dependencies": { "@nadohq/shared": "0.1.0-alpha.50", "axios": "*", "ts-mixer": "*" }, "peerDependencies": { "viem": "*" } }, "sha512-/mC0tH/h7oqmvj4lo+kWUTwDjGWtQl930WpvFdxQThIWJzXFxnb1eM0oGW5tCm2OxB05dwo5wHCmXH2fj+SO2Q=="],
|
||||||
|
|
||||||
|
"@nadohq/indexer-client": ["@nadohq/indexer-client@0.1.0-alpha.50", "", { "dependencies": { "@nadohq/engine-client": "0.1.0-alpha.50", "@nadohq/shared": "0.1.0-alpha.50", "axios": "*", "ts-mixer": "*" }, "peerDependencies": { "viem": "*" } }, "sha512-65+I8w/OWQBueUUwimhZf4QAYLH3pNOD19ZWNrkd9jdgigkDnqdra/620ZE1+RR1lUUSzvFy6Apus3M//uwxvw=="],
|
||||||
|
|
||||||
|
"@nadohq/shared": ["@nadohq/shared@0.1.0-alpha.50", "", { "dependencies": { "abitype": "^1.2.3" }, "peerDependencies": { "bignumber.js": "^9.3.0", "viem": "*" } }, "sha512-7WndVvF4M71yNiuuB8WNp61+QCN/J3Ke11xRQUO83hO6FZDd0Hc3NWINt2BUmgBnDDpmFkOopA59pYjxJX1v+A=="],
|
||||||
|
|
||||||
|
"@nadohq/trigger-client": ["@nadohq/trigger-client@0.1.0-alpha.50", "", { "dependencies": { "@nadohq/engine-client": "0.1.0-alpha.50", "@nadohq/shared": "0.1.0-alpha.50", "axios": "*", "ts-mixer": "*" }, "peerDependencies": { "viem": "*" } }, "sha512-kg5ytYVI/wszuGo6aG24iDoEk24ePygRl+Mq02OEz1CPbgt/S2aqRcTVmKLsw3R+6DK/zLFVSXo7odeJGXpZ3g=="],
|
||||||
|
|
||||||
|
"@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
|
||||||
|
|
||||||
"@noble/curves": ["@noble/curves@1.4.2", "", { "dependencies": { "@noble/hashes": "1.4.0" } }, "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw=="],
|
"@noble/curves": ["@noble/curves@1.4.2", "", { "dependencies": { "@noble/hashes": "1.4.0" } }, "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw=="],
|
||||||
|
|
||||||
|
"@noble/ed25519": ["@noble/ed25519@3.0.0", "", {}, "sha512-QyteqMNm0GLqfa5SoYbSC3+Pvykwpn95Zgth4MFVSMKBB75ELl9tX1LAVsN4c3HXOrakHsF2gL4zWDAYCcsnzg=="],
|
||||||
|
|
||||||
"@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="],
|
"@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="],
|
||||||
|
|
||||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.0", "", { "os": "android", "cpu": "arm" }, "sha512-VxDYCDqOaR7NXzAtvRx7G1u54d2kEHopb28YH/pKzY6y0qmogP3gG7CSiWsq9WvDFxOQMpNEyjVAHZFXfH3o/A=="],
|
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="],
|
||||||
|
|
||||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.0", "", { "os": "android", "cpu": "arm64" }, "sha512-pqDirm8koABIKvzL59YI9W9DWbRlTX7RWhN+auR8HXJxo89m4mjqbah7nJZjeKNTNYopqL+yGg+0mhCpf3xZtQ=="],
|
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="],
|
||||||
|
|
||||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YCdWlY/8ltN6H78HnMsRHYlPiKvqKagBP1r+D7SSylxX+HnsgXGCmLiV3Y4nSyY9hW8qr8U9LDUx/Lo7M6MfmQ=="],
|
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="],
|
||||||
|
|
||||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-z4nw6y1j+OOSGzuVbSWdIp1IUks9qNw4dc7z7lWuWDKojY38VMWBlEN7F9jk5UXOkUcp97vA1N213DF+Lz8BRg=="],
|
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="],
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-Q/dv9Yvyr5rKlK8WQJZVrp5g2SOYeZUs9u/t2f9cQ2E0gJjYB/BWoedXfUT0EcDJefi2zzVfhcOj8drWCzTviw=="],
|
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="],
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kdBsLs4Uile/fbjZVvCRcKB4q64R+1mUq0Yd7oU1CMm1Av336ajIFqNFovByipciuUQjBCPMxwJhCgfG2re3rg=="],
|
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.0", "", { "os": "linux", "cpu": "arm" }, "sha512-aL6hRwu0k7MTUESgkg7QHY6CoqPgr6gdQXRJI1/VbFlUMwsSzPGSR7sG5d+MCbYnJmJwThc2ol3nixj1fvI/zQ=="],
|
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.0", "", { "os": "linux", "cpu": "arm" }, "sha512-BTs0M5s1EJejgIBJhCeiFo7GZZ2IXWkFGcyZhxX4+8usnIo5Mti57108vjXFIQmmJaRyDwmV59Tw64Ap1dkwMw=="],
|
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-uj672IVOU9m08DBGvoPKPi/J8jlVgjh12C9GmjjBxCTQc3XtVmRkRKyeHSmIKQpvJ7fIm1EJieBUcnGSzDVFyw=="],
|
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-/+IVbeDMDCtB/HP/wiWsSzduD10SEGzIZX2945KSgZRNi4TSkjHqRJtNTVtVb8IRwhJ65ssI56krlLik+zFWkw=="],
|
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-U1vVzvSWtSMWKKrGoROPBXMh3Vwn93TA9V35PldokHGqiUbF6erSzox/5qrSMKp6SzakvyjcPiVF8yB1xKr9Pg=="],
|
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-X/4WfuBAdQRH8cK3DYl8zC00XEE6aM472W+QCycpQJeLWVnHfkv7RyBFVaTqNUMsTgIX8ihMjCvFF9OUgeABzw=="],
|
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-xIRYc58HfWDBZoLmWfWXg2Sq8VCa2iJ32B7mqfWnkx5mekekl0tMe7FHpY8I72RXEcUkaWawRvl3qA55og+cwQ=="],
|
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-mbsoUey05WJIOz8U1WzNdf+6UMYGwE3fZZnQqsM22FZ3wh1N887HT6jAOjXs6CNEK3Ntu2OBsyQDXfIjouI4dw=="],
|
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-qP6aP970bucEi5KKKR4AuPFd8aTx9EF6BvutvYxmZuWLJHmnq4LvBfp0U+yFDMGwJ+AIJEH5sIP+SNypauMWzg=="],
|
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.0", "", { "os": "linux", "cpu": "x64" }, "sha512-nmSVN+F2i1yKZ7rJNKO3G7ZzmxJgoQBQZ/6c4MuS553Grmr7WqR7LLDcYG53Z2m9409z3JLt4sCOhLdbKQ3HmA=="],
|
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2d0qRo33G6TfQVjaMR71P+yJVGODrt5V6+T0BDYH4EMfGgdC/2HWDVjSSFw888GSzAZUwuska3+zxNUCDco6rQ=="],
|
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="],
|
||||||
|
|
||||||
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.0", "", { "os": "none", "cpu": "arm64" }, "sha512-A1JalX4MOaFAAyGgpO7XP5khquv/7xKzLIyLmhNrbiCxWpMlnsTYr8dnsWM7sEeotNmxvSOEL7F65j0HXFcFsw=="],
|
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-YQugafP/rH0eOOHGjmNgDURrpYHrIX0yuojOI8bwCyXwxC9ZdTd3vYkmddPX0oHONLXu9Rb1dDmT0VNpjkzGGw=="],
|
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zYdUYhi3Qe2fndujBqL5FjAFzvNeLxtIqfzNEVKD1I7C37/chv1VxhscWSQHTNfjPCrBFQMnynwA3kpZpZ8w4A=="],
|
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.0", "", { "os": "win32", "cpu": "x64" }, "sha512-fGk03kQylNaCOQ96HDMeT7E2n91EqvCDd3RwvT5k+xNdFCeMGnj5b5hEgTGrQuyidqSsD3zJDQ21QIaxXqTBJw=="],
|
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.0", "", { "os": "win32", "cpu": "x64" }, "sha512-6iKDCVSIUQ8jPMoIV0OytRKniaYyy5EbY/RRydmLW8ZR3cEBhxbWl5ro0rkUNe0ef6sScvhbY79HrjRm8i3vDQ=="],
|
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="],
|
||||||
|
|
||||||
"@scure/base": ["@scure/base@1.1.9", "", {}, "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg=="],
|
"@scure/base": ["@scure/base@1.1.9", "", {}, "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg=="],
|
||||||
|
|
||||||
@@ -135,21 +164,23 @@
|
|||||||
|
|
||||||
"@scure/bip39": ["@scure/bip39@1.3.0", "", { "dependencies": { "@noble/hashes": "~1.4.0", "@scure/base": "~1.1.6" } }, "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ=="],
|
"@scure/bip39": ["@scure/bip39@1.3.0", "", { "dependencies": { "@noble/hashes": "~1.4.0", "@scure/base": "~1.1.6" } }, "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="],
|
"@starkware-industries/starkware-crypto-utils": ["@starkware-industries/starkware-crypto-utils@0.2.1", "", { "dependencies": { "assert": "^2.0.0", "bip39": "^3.0.4", "bn.js": "^4.12.0", "brorand": "^1.1.0", "buffer": "^6.0.3", "crypto-browserify": "^3.12.0", "elliptic": "^6.5.4", "enc-utils": "^3.0.0", "ethereumjs-wallet": "^1.0.2", "hash.js": "^1.1.7", "hmac-drbg": "^1.0.1", "inherits": "^2.0.4", "js-sha3": "^0.8.0", "minimalistic-assert": "^1.0.1", "minimalistic-crypto-utils": "^1.0.1", "stream-browserify": "^3.0.0" } }, "sha512-rA5O9b53zaoBOQwQxBd0cbumFbQoBm9NH/vfu+o0Cq3oouEbNPALneLlLjOmFEId2/WOJ5ecC64rFLI/PwuIPQ=="],
|
||||||
|
|
||||||
"@types/chai": ["@types/chai@5.2.2", "", { "dependencies": { "@types/deep-eql": "*" } }, "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg=="],
|
"@types/bn.js": ["@types/bn.js@5.2.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q=="],
|
||||||
|
|
||||||
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
|
"@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="],
|
||||||
|
|
||||||
|
"@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
|
||||||
|
|
||||||
"@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
|
"@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
"@types/node": ["@types/node@25.3.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-RpV6r/ij22zRRdyBPcxDeKAzH43phWVKEjL2iksqo1Vz3CuBUrgmPpPhALKiRfU7OMCmeeO9vECBMsV0hMTG8Q=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.5.2", "", { "dependencies": { "undici-types": "~7.12.0" } }, "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ=="],
|
"@types/pbkdf2": ["@types/pbkdf2@3.1.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.1.13", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ=="],
|
"@types/secp256k1": ["@types/secp256k1@4.0.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw=="],
|
||||||
|
|
||||||
"@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
|
"@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
|
||||||
|
|
||||||
@@ -165,39 +196,87 @@
|
|||||||
|
|
||||||
"@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="],
|
"@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="],
|
||||||
|
|
||||||
"ansi-escapes": ["ansi-escapes@7.1.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-YdhtCd19sKRKfAAUsrcC1wzm4JuzJoiX4pOJqIoW2qmKj5WzG/dL8uUJ0361zaXtHqK7gEhOwtAtz7t3Yq3X5g=="],
|
"abitype": ["abitype@1.2.3", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg=="],
|
||||||
|
|
||||||
|
"aes-js": ["aes-js@3.1.2", "", {}, "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ=="],
|
||||||
|
|
||||||
|
"ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="],
|
||||||
|
|
||||||
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||||
|
|
||||||
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||||
|
|
||||||
|
"asn1.js": ["asn1.js@4.10.1", "", { "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw=="],
|
||||||
|
|
||||||
|
"assert": ["assert@2.1.0", "", { "dependencies": { "call-bind": "^1.0.2", "is-nan": "^1.3.2", "object-is": "^1.1.5", "object.assign": "^4.1.4", "util": "^0.12.5" } }, "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw=="],
|
||||||
|
|
||||||
"assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
|
"assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
|
||||||
|
|
||||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||||
|
|
||||||
"auto-bind": ["auto-bind@5.0.1", "", {}, "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg=="],
|
"auto-bind": ["auto-bind@5.0.1", "", {}, "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg=="],
|
||||||
|
|
||||||
"axios": ["axios@1.12.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw=="],
|
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="],
|
"axios": ["axios@1.13.5", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q=="],
|
||||||
|
|
||||||
|
"base-x": ["base-x@3.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA=="],
|
||||||
|
|
||||||
|
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||||
|
|
||||||
|
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
|
||||||
|
|
||||||
|
"bip39": ["bip39@3.1.0", "", { "dependencies": { "@noble/hashes": "^1.2.0" } }, "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A=="],
|
||||||
|
|
||||||
|
"blakejs": ["blakejs@1.2.1", "", {}, "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ=="],
|
||||||
|
|
||||||
|
"bn.js": ["bn.js@4.12.3", "", {}, "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g=="],
|
||||||
|
|
||||||
|
"brorand": ["brorand@1.1.0", "", {}, "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="],
|
||||||
|
|
||||||
|
"browserify-aes": ["browserify-aes@1.2.0", "", { "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.3", "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA=="],
|
||||||
|
|
||||||
|
"browserify-cipher": ["browserify-cipher@1.0.1", "", { "dependencies": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", "evp_bytestokey": "^1.0.0" } }, "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w=="],
|
||||||
|
|
||||||
|
"browserify-des": ["browserify-des@1.0.2", "", { "dependencies": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A=="],
|
||||||
|
|
||||||
|
"browserify-rsa": ["browserify-rsa@4.1.1", "", { "dependencies": { "bn.js": "^5.2.1", "randombytes": "^2.1.0", "safe-buffer": "^5.2.1" } }, "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ=="],
|
||||||
|
|
||||||
|
"browserify-sign": ["browserify-sign@4.2.5", "", { "dependencies": { "bn.js": "^5.2.2", "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", "elliptic": "^6.6.1", "inherits": "^2.0.4", "parse-asn1": "^5.1.9", "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1" } }, "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw=="],
|
||||||
|
|
||||||
|
"bs58": ["bs58@4.0.1", "", { "dependencies": { "base-x": "^3.0.2" } }, "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw=="],
|
||||||
|
|
||||||
|
"bs58check": ["bs58check@2.1.2", "", { "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", "safe-buffer": "^5.1.2" } }, "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA=="],
|
||||||
|
|
||||||
|
"buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
|
||||||
|
|
||||||
|
"buffer-xor": ["buffer-xor@1.0.3", "", {}, "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
|
||||||
|
|
||||||
"cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
|
"cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
|
||||||
|
|
||||||
|
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
|
||||||
|
|
||||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||||
|
|
||||||
"ccxt": ["ccxt@4.5.5", "", { "dependencies": { "ws": "^8.8.1" } }, "sha512-AyhwTFLkx4sO985ImIOfumEBox7AHD/iqk5tPGICObUSZG6wTXg0aRzU8Hjz974aCMG4msFwLk3A/iXPKAU4wA=="],
|
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
||||||
|
|
||||||
|
"ccxt": ["ccxt@4.5.40", "", { "dependencies": { "ws": "^8.8.1" } }, "sha512-8nJhhNKft7+fELDNQuCV2AQZBxLJfYQaD2LpqxHrucSszosyVl0u6lCIFfcnDUbeUW925uhrsKevHf2fNbLjKw=="],
|
||||||
|
|
||||||
"chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="],
|
"chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="],
|
||||||
|
|
||||||
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||||
|
|
||||||
"check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="],
|
"check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],
|
||||||
|
|
||||||
|
"cipher-base": ["cipher-base@1.0.7", "", { "dependencies": { "inherits": "^2.0.4", "safe-buffer": "^5.2.1", "to-buffer": "^1.2.2" } }, "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA=="],
|
||||||
|
|
||||||
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
|
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
|
||||||
|
|
||||||
"cli-cursor": ["cli-cursor@4.0.0", "", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="],
|
"cli-cursor": ["cli-cursor@4.0.0", "", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="],
|
||||||
|
|
||||||
"cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="],
|
"cli-truncate": ["cli-truncate@5.1.1", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A=="],
|
||||||
|
|
||||||
"code-excerpt": ["code-excerpt@4.0.0", "", { "dependencies": { "convert-to-spaces": "^2.0.1" } }, "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA=="],
|
"code-excerpt": ["code-excerpt@4.0.0", "", { "dependencies": { "convert-to-spaces": "^2.0.1" } }, "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA=="],
|
||||||
|
|
||||||
@@ -205,19 +284,39 @@
|
|||||||
|
|
||||||
"convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
|
"convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
|
||||||
|
|
||||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
||||||
|
|
||||||
|
"create-ecdh": ["create-ecdh@4.0.4", "", { "dependencies": { "bn.js": "^4.1.0", "elliptic": "^6.5.3" } }, "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A=="],
|
||||||
|
|
||||||
|
"create-hash": ["create-hash@1.2.0", "", { "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", "md5.js": "^1.3.4", "ripemd160": "^2.0.1", "sha.js": "^2.4.0" } }, "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg=="],
|
||||||
|
|
||||||
|
"create-hmac": ["create-hmac@1.1.7", "", { "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", "inherits": "^2.0.1", "ripemd160": "^2.0.0", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" } }, "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg=="],
|
||||||
|
|
||||||
|
"crypto-browserify": ["crypto-browserify@3.12.1", "", { "dependencies": { "browserify-cipher": "^1.0.1", "browserify-sign": "^4.2.3", "create-ecdh": "^4.0.4", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", "diffie-hellman": "^5.0.3", "hash-base": "~3.0.4", "inherits": "^2.0.4", "pbkdf2": "^3.1.2", "public-encrypt": "^4.0.3", "randombytes": "^2.1.0", "randomfill": "^1.0.4" } }, "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ=="],
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
"deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
|
"deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
|
||||||
|
|
||||||
|
"define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
|
||||||
|
|
||||||
|
"define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
|
||||||
|
|
||||||
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||||
|
|
||||||
"dotenv": ["dotenv@17.2.2", "", {}, "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q=="],
|
"des.js": ["des.js@1.1.0", "", { "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg=="],
|
||||||
|
|
||||||
|
"diffie-hellman": ["diffie-hellman@5.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" } }, "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg=="],
|
||||||
|
|
||||||
|
"dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
|
||||||
|
|
||||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
"emoji-regex": ["emoji-regex@10.5.0", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="],
|
"elliptic": ["elliptic@6.6.1", "", { "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", "hash.js": "^1.0.0", "hmac-drbg": "^1.0.1", "inherits": "^2.0.4", "minimalistic-assert": "^1.0.1", "minimalistic-crypto-utils": "^1.0.1" } }, "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g=="],
|
||||||
|
|
||||||
|
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||||
|
|
||||||
|
"enc-utils": ["enc-utils@3.0.0", "", { "dependencies": { "is-typedarray": "1.0.0", "typedarray-to-buffer": "3.1.5" } }, "sha512-e57t/Z2HzWOLwOp7DZcV0VMEY8t7ptWwsxyp6kM2b2zrk6JqIpXxzkruHAMiBsy5wg9jp/183GdiRXCvBtzsYg=="],
|
||||||
|
|
||||||
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
||||||
|
|
||||||
@@ -231,9 +330,9 @@
|
|||||||
|
|
||||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||||
|
|
||||||
"es-toolkit": ["es-toolkit@1.39.10", "", {}, "sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w=="],
|
"es-toolkit": ["es-toolkit@1.44.0", "", {}, "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg=="],
|
||||||
|
|
||||||
"esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="],
|
"esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
|
||||||
|
|
||||||
"escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
|
"escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
|
||||||
|
|
||||||
@@ -241,19 +340,31 @@
|
|||||||
|
|
||||||
"ethereum-cryptography": ["ethereum-cryptography@2.2.1", "", { "dependencies": { "@noble/curves": "1.4.2", "@noble/hashes": "1.4.0", "@scure/bip32": "1.4.0", "@scure/bip39": "1.3.0" } }, "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg=="],
|
"ethereum-cryptography": ["ethereum-cryptography@2.2.1", "", { "dependencies": { "@noble/curves": "1.4.2", "@noble/hashes": "1.4.0", "@scure/bip32": "1.4.0", "@scure/bip39": "1.3.0" } }, "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg=="],
|
||||||
|
|
||||||
"expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="],
|
"ethereumjs-util": ["ethereumjs-util@7.1.5", "", { "dependencies": { "@types/bn.js": "^5.1.0", "bn.js": "^5.1.2", "create-hash": "^1.1.2", "ethereum-cryptography": "^0.1.3", "rlp": "^2.2.4" } }, "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg=="],
|
||||||
|
|
||||||
|
"ethereumjs-wallet": ["ethereumjs-wallet@1.0.2", "", { "dependencies": { "aes-js": "^3.1.2", "bs58check": "^2.1.2", "ethereum-cryptography": "^0.1.3", "ethereumjs-util": "^7.1.2", "randombytes": "^2.1.0", "scrypt-js": "^3.0.1", "utf8": "^3.0.0", "uuid": "^8.3.2" } }, "sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA=="],
|
||||||
|
|
||||||
|
"eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
|
||||||
|
|
||||||
|
"evp_bytestokey": ["evp_bytestokey@1.0.3", "", { "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" } }, "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA=="],
|
||||||
|
|
||||||
|
"expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
|
||||||
|
|
||||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||||
|
|
||||||
"follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
|
"follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
|
||||||
|
|
||||||
"form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
|
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
|
||||||
|
|
||||||
|
"form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
|
||||||
|
|
||||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||||
|
|
||||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||||
|
|
||||||
"get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
|
"generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
|
||||||
|
|
||||||
|
"get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="],
|
||||||
|
|
||||||
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||||
|
|
||||||
@@ -261,69 +372,157 @@
|
|||||||
|
|
||||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||||
|
|
||||||
|
"has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
|
||||||
|
|
||||||
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||||
|
|
||||||
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||||
|
|
||||||
|
"hash-base": ["hash-base@3.0.5", "", { "dependencies": { "inherits": "^2.0.4", "safe-buffer": "^5.2.1" } }, "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg=="],
|
||||||
|
|
||||||
|
"hash.js": ["hash.js@1.1.7", "", { "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA=="],
|
||||||
|
|
||||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||||
|
|
||||||
|
"hmac-drbg": ["hmac-drbg@1.0.1", "", { "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.1" } }, "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg=="],
|
||||||
|
|
||||||
|
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||||
|
|
||||||
"indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="],
|
"indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="],
|
||||||
|
|
||||||
"ink": ["ink@6.3.1", "", { "dependencies": { "@alcalzone/ansi-tokenize": "^0.2.0", "ansi-escapes": "^7.0.0", "ansi-styles": "^6.2.1", "auto-bind": "^5.0.1", "chalk": "^5.6.0", "cli-boxes": "^3.0.0", "cli-cursor": "^4.0.0", "cli-truncate": "^4.0.0", "code-excerpt": "^4.0.0", "es-toolkit": "^1.39.10", "indent-string": "^5.0.0", "is-in-ci": "^2.0.0", "patch-console": "^2.0.0", "react-reconciler": "^0.32.0", "signal-exit": "^3.0.7", "slice-ansi": "^7.1.0", "stack-utils": "^2.0.6", "string-width": "^7.2.0", "type-fest": "^4.27.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0", "ws": "^8.18.0", "yoga-layout": "~3.2.1" }, "peerDependencies": { "@types/react": ">=19.0.0", "react": ">=19.0.0", "react-devtools-core": "^6.1.2" }, "optionalPeers": ["@types/react", "react-devtools-core"] }, "sha512-3wGwITGrzL6rkWsi2gEKzgwdafGn4ZYd3u4oRp+sOPvfoxEHlnoB5Vnk9Uy5dMRUhDOqF3hqr4rLQ4lEzBc2sQ=="],
|
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||||
|
|
||||||
|
"ink": ["ink@6.8.0", "", { "dependencies": { "@alcalzone/ansi-tokenize": "^0.2.4", "ansi-escapes": "^7.3.0", "ansi-styles": "^6.2.1", "auto-bind": "^5.0.1", "chalk": "^5.6.0", "cli-boxes": "^3.0.0", "cli-cursor": "^4.0.0", "cli-truncate": "^5.1.1", "code-excerpt": "^4.0.0", "es-toolkit": "^1.39.10", "indent-string": "^5.0.0", "is-in-ci": "^2.0.0", "patch-console": "^2.0.0", "react-reconciler": "^0.33.0", "scheduler": "^0.27.0", "signal-exit": "^3.0.7", "slice-ansi": "^8.0.0", "stack-utils": "^2.0.6", "string-width": "^8.1.1", "terminal-size": "^4.0.1", "type-fest": "^5.4.1", "widest-line": "^6.0.0", "wrap-ansi": "^9.0.0", "ws": "^8.18.0", "yoga-layout": "~3.2.1" }, "peerDependencies": { "@types/react": ">=19.0.0", "react": ">=19.0.0", "react-devtools-core": ">=6.1.2" }, "optionalPeers": ["@types/react", "react-devtools-core"] }, "sha512-sbl1RdLOgkO9isK42WCZlJCFN9hb++sX9dsklOvfd1YQ3bQ2AiFu12Q6tFlr0HvEUvzraJntQCCpfEoUe9DSzA=="],
|
||||||
|
|
||||||
|
"is-arguments": ["is-arguments@1.2.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA=="],
|
||||||
|
|
||||||
|
"is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
|
||||||
|
|
||||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
|
"is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
|
||||||
|
|
||||||
|
"is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
|
||||||
|
|
||||||
"is-in-ci": ["is-in-ci@2.0.0", "", { "bin": { "is-in-ci": "cli.js" } }, "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w=="],
|
"is-in-ci": ["is-in-ci@2.0.0", "", { "bin": { "is-in-ci": "cli.js" } }, "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w=="],
|
||||||
|
|
||||||
|
"is-nan": ["is-nan@1.3.2", "", { "dependencies": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" } }, "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w=="],
|
||||||
|
|
||||||
|
"is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
|
||||||
|
|
||||||
|
"is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
|
||||||
|
|
||||||
|
"is-typedarray": ["is-typedarray@1.0.0", "", {}, "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="],
|
||||||
|
|
||||||
|
"isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
|
||||||
|
|
||||||
|
"isows": ["isows@1.0.7", "", { "peerDependencies": { "ws": "*" } }, "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg=="],
|
||||||
|
|
||||||
|
"js-sha3": ["js-sha3@0.8.0", "", {}, "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="],
|
||||||
|
|
||||||
"js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
|
"js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
|
||||||
|
|
||||||
|
"keccak": ["keccak@3.0.4", "", { "dependencies": { "node-addon-api": "^2.0.0", "node-gyp-build": "^4.2.0", "readable-stream": "^3.6.0" } }, "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q=="],
|
||||||
|
|
||||||
"loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
|
"loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||||
|
|
||||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||||
|
|
||||||
|
"md5.js": ["md5.js@1.3.5", "", { "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg=="],
|
||||||
|
|
||||||
|
"miller-rabin": ["miller-rabin@4.0.1", "", { "dependencies": { "bn.js": "^4.0.0", "brorand": "^1.0.1" }, "bin": { "miller-rabin": "bin/miller-rabin" } }, "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA=="],
|
||||||
|
|
||||||
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||||
|
|
||||||
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||||
|
|
||||||
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||||
|
|
||||||
|
"minimalistic-assert": ["minimalistic-assert@1.0.1", "", {}, "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="],
|
||||||
|
|
||||||
|
"minimalistic-crypto-utils": ["minimalistic-crypto-utils@1.0.1", "", {}, "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="],
|
||||||
|
|
||||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||||
|
|
||||||
|
"node-addon-api": ["node-addon-api@2.0.2", "", {}, "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA=="],
|
||||||
|
|
||||||
|
"node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="],
|
||||||
|
|
||||||
|
"object-is": ["object-is@1.1.6", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1" } }, "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q=="],
|
||||||
|
|
||||||
|
"object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
|
||||||
|
|
||||||
|
"object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
|
||||||
|
|
||||||
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
||||||
|
|
||||||
|
"ox": ["ox@0.12.4", "", { "dependencies": { "@adraffy/ens-normalize": "^1.11.0", "@noble/ciphers": "^1.3.0", "@noble/curves": "1.9.1", "@noble/hashes": "^1.8.0", "@scure/bip32": "^1.7.0", "@scure/bip39": "^1.6.0", "abitype": "^1.2.3", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-+P+C7QzuwPV8lu79dOwjBKfB2CbnbEXe/hfyyrff1drrO1nOOj3Hc87svHfcW1yneRr3WXaKr6nz11nq+/DF9Q=="],
|
||||||
|
|
||||||
|
"parse-asn1": ["parse-asn1@5.1.9", "", { "dependencies": { "asn1.js": "^4.10.1", "browserify-aes": "^1.2.0", "evp_bytestokey": "^1.0.3", "pbkdf2": "^3.1.5", "safe-buffer": "^5.2.1" } }, "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg=="],
|
||||||
|
|
||||||
"patch-console": ["patch-console@2.0.0", "", {}, "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA=="],
|
"patch-console": ["patch-console@2.0.0", "", {}, "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA=="],
|
||||||
|
|
||||||
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
"pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="],
|
"pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="],
|
||||||
|
|
||||||
|
"pbkdf2": ["pbkdf2@3.1.5", "", { "dependencies": { "create-hash": "^1.2.0", "create-hmac": "^1.1.7", "ripemd160": "^2.0.3", "safe-buffer": "^5.2.1", "sha.js": "^2.4.12", "to-buffer": "^1.2.1" } }, "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ=="],
|
||||||
|
|
||||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||||
|
|
||||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||||
|
|
||||||
|
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||||
|
|
||||||
|
"process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
|
||||||
|
|
||||||
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||||
|
|
||||||
"react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="],
|
"public-encrypt": ["public-encrypt@4.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q=="],
|
||||||
|
|
||||||
"react-reconciler": ["react-reconciler@0.32.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ=="],
|
"randombytes": ["randombytes@2.1.0", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="],
|
||||||
|
|
||||||
|
"randomfill": ["randomfill@1.0.4", "", { "dependencies": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" } }, "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw=="],
|
||||||
|
|
||||||
|
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
||||||
|
|
||||||
|
"react-reconciler": ["react-reconciler@0.33.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA=="],
|
||||||
|
|
||||||
|
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||||
|
|
||||||
"restore-cursor": ["restore-cursor@4.0.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="],
|
"restore-cursor": ["restore-cursor@4.0.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="],
|
||||||
|
|
||||||
"rollup": ["rollup@4.52.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.0", "@rollup/rollup-android-arm64": "4.52.0", "@rollup/rollup-darwin-arm64": "4.52.0", "@rollup/rollup-darwin-x64": "4.52.0", "@rollup/rollup-freebsd-arm64": "4.52.0", "@rollup/rollup-freebsd-x64": "4.52.0", "@rollup/rollup-linux-arm-gnueabihf": "4.52.0", "@rollup/rollup-linux-arm-musleabihf": "4.52.0", "@rollup/rollup-linux-arm64-gnu": "4.52.0", "@rollup/rollup-linux-arm64-musl": "4.52.0", "@rollup/rollup-linux-loong64-gnu": "4.52.0", "@rollup/rollup-linux-ppc64-gnu": "4.52.0", "@rollup/rollup-linux-riscv64-gnu": "4.52.0", "@rollup/rollup-linux-riscv64-musl": "4.52.0", "@rollup/rollup-linux-s390x-gnu": "4.52.0", "@rollup/rollup-linux-x64-gnu": "4.52.0", "@rollup/rollup-linux-x64-musl": "4.52.0", "@rollup/rollup-openharmony-arm64": "4.52.0", "@rollup/rollup-win32-arm64-msvc": "4.52.0", "@rollup/rollup-win32-ia32-msvc": "4.52.0", "@rollup/rollup-win32-x64-gnu": "4.52.0", "@rollup/rollup-win32-x64-msvc": "4.52.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-+IuescNkTJQgX7AkIDtITipZdIGcWF0pnVvZTWStiazUmcGA2ag8dfg0urest2XlXUi9kuhfQ+qmdc5Stc3z7g=="],
|
"ripemd160": ["ripemd160@2.0.3", "", { "dependencies": { "hash-base": "^3.1.2", "inherits": "^2.0.4" } }, "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA=="],
|
||||||
|
|
||||||
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
"rlp": ["rlp@2.2.7", "", { "dependencies": { "bn.js": "^5.2.0" }, "bin": { "rlp": "bin/rlp" } }, "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ=="],
|
||||||
|
|
||||||
|
"rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
|
||||||
|
|
||||||
|
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||||
|
|
||||||
|
"safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
|
||||||
|
|
||||||
|
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||||
|
|
||||||
|
"scrypt-js": ["scrypt-js@3.0.1", "", {}, "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA=="],
|
||||||
|
|
||||||
|
"secp256k1": ["secp256k1@4.0.4", "", { "dependencies": { "elliptic": "^6.5.7", "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" } }, "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw=="],
|
||||||
|
|
||||||
|
"set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
|
||||||
|
|
||||||
|
"setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="],
|
||||||
|
|
||||||
|
"sha.js": ["sha.js@2.4.12", "", { "dependencies": { "inherits": "^2.0.4", "safe-buffer": "^5.2.1", "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" } }, "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w=="],
|
||||||
|
|
||||||
"siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
|
"siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
|
||||||
|
|
||||||
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||||
|
|
||||||
"slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
|
"slice-ansi": ["slice-ansi@8.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" } }, "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg=="],
|
||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
||||||
@@ -331,13 +530,21 @@
|
|||||||
|
|
||||||
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
||||||
|
|
||||||
"std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="],
|
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
|
||||||
|
|
||||||
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
"stream-browserify": ["stream-browserify@3.0.0", "", { "dependencies": { "inherits": "~2.0.4", "readable-stream": "^3.5.0" } }, "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA=="],
|
||||||
|
|
||||||
"strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
|
"string-width": ["string-width@8.2.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw=="],
|
||||||
|
|
||||||
"strip-literal": ["strip-literal@3.0.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA=="],
|
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||||
|
|
||||||
|
"strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||||
|
|
||||||
|
"strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],
|
||||||
|
|
||||||
|
"tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
|
||||||
|
|
||||||
|
"terminal-size": ["terminal-size@4.0.1", "", {}, "sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ=="],
|
||||||
|
|
||||||
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
|
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
|
||||||
|
|
||||||
@@ -351,30 +558,118 @@
|
|||||||
|
|
||||||
"tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="],
|
"tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="],
|
||||||
|
|
||||||
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
"to-buffer": ["to-buffer@1.2.2", "", { "dependencies": { "isarray": "^2.0.5", "safe-buffer": "^5.2.1", "typed-array-buffer": "^1.0.3" } }, "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw=="],
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
"trading-signals": ["trading-signals@7.4.3", "", {}, "sha512-kOyzd85qhuhU7yGkB5z74MVP6j30xBCfZy5+bgBnvfxY1ZdvaQsdD+C5j+CoIRtCAgSOuxB7jmPpBrqO6h17sQ=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="],
|
"ts-mixer": ["ts-mixer@6.0.4", "", {}, "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="],
|
||||||
|
|
||||||
"vite": ["vite@7.1.7", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA=="],
|
"type-fest": ["type-fest@5.4.4", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw=="],
|
||||||
|
|
||||||
|
"typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
|
||||||
|
|
||||||
|
"typedarray-to-buffer": ["typedarray-to-buffer@3.1.5", "", { "dependencies": { "is-typedarray": "^1.0.0" } }, "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
|
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
||||||
|
|
||||||
|
"utf8": ["utf8@3.0.0", "", {}, "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ=="],
|
||||||
|
|
||||||
|
"util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="],
|
||||||
|
|
||||||
|
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||||
|
|
||||||
|
"uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
|
||||||
|
|
||||||
|
"viem": ["viem@2.46.3", "", { "dependencies": { "@noble/curves": "1.9.1", "@noble/hashes": "1.8.0", "@scure/bip32": "1.7.0", "@scure/bip39": "1.6.0", "abitype": "1.2.3", "isows": "1.0.7", "ox": "0.12.4", "ws": "8.18.3" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-2LJS+Hyh2sYjHXQtzfv1kU9pZx9dxFzvoU/ZKIcn0FNtOU0HQuIICuYdWtUDFHaGXbAdVo8J1eCvmjkL9JVGwg=="],
|
||||||
|
|
||||||
|
"vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
|
||||||
|
|
||||||
"vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
|
"vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
|
||||||
|
|
||||||
"vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="],
|
"vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="],
|
||||||
|
|
||||||
|
"which-typed-array": ["which-typed-array@1.1.20", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="],
|
||||||
|
|
||||||
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
|
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
|
||||||
|
|
||||||
"widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="],
|
"widest-line": ["widest-line@6.0.0", "", { "dependencies": { "string-width": "^8.1.0" } }, "sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA=="],
|
||||||
|
|
||||||
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
||||||
|
|
||||||
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
"ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
|
||||||
|
|
||||||
"yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="],
|
"yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="],
|
||||||
|
|
||||||
"cli-truncate/slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="],
|
"bip39/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||||
|
|
||||||
"cli-truncate/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="],
|
"browserify-rsa/bn.js": ["bn.js@5.2.3", "", {}, "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w=="],
|
||||||
|
|
||||||
|
"browserify-sign/bn.js": ["bn.js@5.2.3", "", {}, "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w=="],
|
||||||
|
|
||||||
|
"browserify-sign/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||||
|
|
||||||
|
"cli-truncate/slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
|
||||||
|
|
||||||
|
"ethereumjs-util/bn.js": ["bn.js@5.2.3", "", {}, "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w=="],
|
||||||
|
|
||||||
|
"ethereumjs-util/ethereum-cryptography": ["ethereum-cryptography@0.1.3", "", { "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", "blakejs": "^1.1.0", "browserify-aes": "^1.2.0", "bs58check": "^2.1.2", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", "hash.js": "^1.1.7", "keccak": "^3.0.0", "pbkdf2": "^3.0.17", "randombytes": "^2.1.0", "safe-buffer": "^5.1.2", "scrypt-js": "^3.0.0", "secp256k1": "^4.0.1", "setimmediate": "^1.0.5" } }, "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ=="],
|
||||||
|
|
||||||
|
"ethereumjs-wallet/ethereum-cryptography": ["ethereum-cryptography@0.1.3", "", { "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", "blakejs": "^1.1.0", "browserify-aes": "^1.2.0", "bs58check": "^2.1.2", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", "hash.js": "^1.1.7", "keccak": "^3.0.0", "pbkdf2": "^3.0.17", "randombytes": "^2.1.0", "safe-buffer": "^5.1.2", "scrypt-js": "^3.0.0", "secp256k1": "^4.0.1", "setimmediate": "^1.0.5" } }, "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ=="],
|
||||||
|
|
||||||
|
"md5.js/hash-base": ["hash-base@3.1.2", "", { "dependencies": { "inherits": "^2.0.4", "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1", "to-buffer": "^1.2.1" } }, "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg=="],
|
||||||
|
|
||||||
|
"ox/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="],
|
||||||
|
|
||||||
|
"ox/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||||
|
|
||||||
|
"ox/@scure/bip32": ["@scure/bip32@1.7.0", "", { "dependencies": { "@noble/curves": "~1.9.0", "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw=="],
|
||||||
|
|
||||||
|
"ox/@scure/bip39": ["@scure/bip39@1.6.0", "", { "dependencies": { "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A=="],
|
||||||
|
|
||||||
|
"ripemd160/hash-base": ["hash-base@3.1.2", "", { "dependencies": { "inherits": "^2.0.4", "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1", "to-buffer": "^1.2.1" } }, "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg=="],
|
||||||
|
|
||||||
|
"rlp/bn.js": ["bn.js@5.2.3", "", {}, "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w=="],
|
||||||
|
|
||||||
|
"secp256k1/node-addon-api": ["node-addon-api@5.1.0", "", {}, "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="],
|
||||||
|
|
||||||
|
"to-buffer/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
|
||||||
|
|
||||||
|
"viem/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="],
|
||||||
|
|
||||||
|
"viem/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||||
|
|
||||||
|
"viem/@scure/bip32": ["@scure/bip32@1.7.0", "", { "dependencies": { "@noble/curves": "~1.9.0", "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw=="],
|
||||||
|
|
||||||
|
"viem/@scure/bip39": ["@scure/bip39@1.6.0", "", { "dependencies": { "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A=="],
|
||||||
|
|
||||||
|
"viem/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
||||||
|
|
||||||
|
"wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||||
|
|
||||||
|
"browserify-sign/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||||
|
|
||||||
|
"browserify-sign/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
|
||||||
|
|
||||||
|
"md5.js/hash-base/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||||
|
|
||||||
|
"ox/@scure/bip32/@scure/base": ["@scure/base@1.2.6", "", {}, "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg=="],
|
||||||
|
|
||||||
|
"ox/@scure/bip39/@scure/base": ["@scure/base@1.2.6", "", {}, "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg=="],
|
||||||
|
|
||||||
|
"ripemd160/hash-base/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||||
|
|
||||||
|
"viem/@scure/bip32/@scure/base": ["@scure/base@1.2.6", "", {}, "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg=="],
|
||||||
|
|
||||||
|
"viem/@scure/bip39/@scure/base": ["@scure/base@1.2.6", "", {}, "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg=="],
|
||||||
|
|
||||||
|
"md5.js/hash-base/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||||
|
|
||||||
|
"md5.js/hash-base/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
|
||||||
|
|
||||||
|
"ripemd160/hash-base/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||||
|
|
||||||
|
"ripemd160/hash-base/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,51 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", function () {
|
||||||
|
|
||||||
|
const pollTickerContinuously = async function (exchange, symbol) {
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const ticker = await exchange.watchTicker (symbol)
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
exchange.id,
|
||||||
|
symbol,
|
||||||
|
JSON.stringify (ticker, undefined, '\n\t')
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ');
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
e.constructor.name,
|
||||||
|
e.message,
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.binance ({ enableRateLimit: true })
|
||||||
|
const symbol = 'ETH/BTC'
|
||||||
|
|
||||||
|
pollTickerContinuously (exchange, symbol)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, CCXT!</h1>
|
||||||
|
<p>This example uses websockets to watch changes in price of ETH/BTC</p>
|
||||||
|
<pre id="content"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import ccxt from '../../../js/ccxt.js';
|
||||||
|
|
||||||
|
// your version must be 0.7+
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
function handle (exchange, symbol, ticker) {
|
||||||
|
console.log (new Date (), exchange.id, symbol, ticker)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loop (exchange, symbol) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const ticker = await exchange.watchMyTrades ()
|
||||||
|
handle (exchange, symbol, ticker)
|
||||||
|
sleep( 10000 )
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
// do nothing and retry on next loop iteration
|
||||||
|
// throw e // uncomment to break all loops in case of an error in any one of them
|
||||||
|
// break // you can also break just this one loop if it fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.apex ({
|
||||||
|
'apiKey': 'your api Key',
|
||||||
|
'secret': 'your api secret',
|
||||||
|
'walletAddress': 'your eth address',
|
||||||
|
'options': {
|
||||||
|
'accountId': 'your account id',
|
||||||
|
'passphrase': 'your api passphrase',
|
||||||
|
'seeds': 'your zklink omni seed',
|
||||||
|
'brokerId': '',
|
||||||
|
},
|
||||||
|
}) // usd(s)-margined contracts
|
||||||
|
exchange.setSandboxMode(true)
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const exchange = new ccxt.pro.binance () // spot markets
|
||||||
|
//
|
||||||
|
// WARNING: when using the spot markets mind subscription limits!
|
||||||
|
// don't attempt to subscribe to all of them
|
||||||
|
// the exchanges will not allow that in general
|
||||||
|
// instead, specify a shorter list of symbols to subscribe to
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const exchange = new ccxt.pro.binancecoinm () // coin-margined contracts
|
||||||
|
|
||||||
|
if (exchange.has['watchTicker']) {
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
// many symbols
|
||||||
|
//await Promise.all (exchange.symbols.map (symbol => loop (exchange, symbol)))
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const symbols = [ 'BTC/USDT', 'ETH/USDT' ] // specific symbols
|
||||||
|
// await Promise.all (symbols.map (symbol => loop (exchange, symbol)))
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
await loop (exchange, ['BTC-USDT','ETH-USDT']) // one symbol
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log (exchange.id, 'does not support watchTicker yet')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt')
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
// This example will run silent and will return your balance only when the balance is updated.
|
||||||
|
//
|
||||||
|
// 1. launch the example with your keys and keep it running
|
||||||
|
// 2. go to the trading section on the website
|
||||||
|
// 3. place a order on a spot market
|
||||||
|
// 4. see your balance updated in the example
|
||||||
|
//
|
||||||
|
// Warning! This example might produce a lot of output to your screen
|
||||||
|
|
||||||
|
|
||||||
|
async function watchBalance (exchange) {
|
||||||
|
let balance = await exchange.fetchBalance ()
|
||||||
|
console.log ('---------------------------------------------------------')
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()))
|
||||||
|
console.log (balance, '\n')
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const update = await exchange.watchBalance ()
|
||||||
|
balance = exchange.deep_extend (balance, update)
|
||||||
|
// it will print the balance update when the balance changes
|
||||||
|
// if the balance remains unchanged the exchange will not send it
|
||||||
|
console.log ('---------------------------------------------------------')
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()))
|
||||||
|
console.log (balance, '\n')
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.binance ({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
})
|
||||||
|
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
|
||||||
|
// exchange.verbose = true // uncomment for debugging purposes if necessary
|
||||||
|
|
||||||
|
await watchBalance (exchange)
|
||||||
|
|
||||||
|
await exchange.close ()
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt')
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
let HttpsProxyAgent = undefined
|
||||||
|
|
||||||
|
try {
|
||||||
|
HttpsProxyAgent = require ('https-proxy-agent')
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
console.log ("\nCould not load the HTTPS proxy agent")
|
||||||
|
console.log ("\nPlease, run this command to make sure it's properly installed:")
|
||||||
|
console.log ("\nnpm install https-proxy-agent\n")
|
||||||
|
process.exit ()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
|
||||||
|
console.log ('Using proxy server', httpsProxyUrl);
|
||||||
|
|
||||||
|
// adjust for your HTTPS proxy URL
|
||||||
|
const httpsProxyUrl = process.env.https_proxy || 'https://username:password@your-proxy.com'
|
||||||
|
, httpsAgent = new HttpsProxyAgent (httpsProxyUrl)
|
||||||
|
, exchange = new ccxt.binance ({
|
||||||
|
httpsAgent: httpsAgent, // ←--------------------- httpsAgent here
|
||||||
|
options: {
|
||||||
|
'ws': {
|
||||||
|
'options': { agent: httpsAgent }, // ←--- httpsAgent here
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const symbol = 'BTC/USDT'
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
console.log ('Markets loaded')
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds()), symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt')
|
||||||
|
|
||||||
|
const ohlcvsBySymbol = {}
|
||||||
|
|
||||||
|
function handleAllOHLCVs (exchange, ohlcvs, symbol, timeframe) {
|
||||||
|
const now = exchange.iso8601 (exchange.milliseconds ())
|
||||||
|
const lastCandle = exchange.safeValue (ohlcvs, ohlcvs.length - 1)
|
||||||
|
const datetime = exchange.iso8601 (lastCandle[0])
|
||||||
|
console.log (now, datetime, symbol, timeframe, lastCandle.slice (1))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pollOHLCV (exchange, symbol, timeframe) {
|
||||||
|
await exchange.throttle (1000) // 1000ms delay between subscriptions
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const response = await exchange.watchOHLCV (symbol, timeframe)
|
||||||
|
ohlcvsBySymbol[symbol] = response
|
||||||
|
handleAllOHLCVs(exchange, response, symbol, timeframe)
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.binance()
|
||||||
|
const markets = await exchange.loadMarkets ()
|
||||||
|
const timeframe = '5m'
|
||||||
|
|
||||||
|
const firstOneHundredSymbols = exchange.symbols.slice (0, 100)
|
||||||
|
|
||||||
|
await Promise.all (firstOneHundredSymbols.map (symbol => pollOHLCV (exchange, symbol, timeframe)))
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt');
|
||||||
|
|
||||||
|
// your version must be 0.7+
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
function handle (exchange, symbol, timeframe, candles) {
|
||||||
|
const lastCandle = candles[candles.length - 1]
|
||||||
|
const lastClosingPrice = lastCandle[4]
|
||||||
|
console.log (new Date (), exchange.id, timeframe, symbol, '\t', lastClosingPrice)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loop (exchange, symbol, timeframe) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const candles = await exchange.watchOHLCV (symbol, timeframe)
|
||||||
|
handle (exchange, symbol, timeframe, candles)
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
// do nothing and retry on next loop iteration
|
||||||
|
// throw e // uncomment to break all loops in case of an error in any one of them
|
||||||
|
// break // you can also break just this one loop if it fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.binanceusdm () // usd(s)-margined contracts
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const exchange = new ccxt.pro.binance () // spot markets
|
||||||
|
//
|
||||||
|
// WARNING: when using the spot markets mind subscription limits!
|
||||||
|
// don't attempt to subscribe to all of them
|
||||||
|
// the exchanges will not allow that in general
|
||||||
|
// instead, specify a shorter list of symbols to subscribe to
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const exchange = new ccxt.pro.binancecoinm () // coin-margined contracts
|
||||||
|
|
||||||
|
if (exchange.has['watchOHLCV']) {
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
const timeframe = '15m'
|
||||||
|
// many symbols
|
||||||
|
await Promise.all (exchange.symbols.map (symbol => loop (exchange, symbol, timeframe)))
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const symbols = [ 'BTC/USDT', 'ETH/USDT' ] // specific symbols
|
||||||
|
// await Promise.all (symbols.map (symbol => loop (exchange, symbol, timeframe)))
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// await loop (exchange, 'BTC/USDT', timeframe) // one symbol
|
||||||
|
} else {
|
||||||
|
console.log (exchange.id, 'does not support watchOHLCV yet')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt');
|
||||||
|
|
||||||
|
// your version must be 0.7+
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
function handle (exchange, symbol, ticker) {
|
||||||
|
console.log (new Date (), exchange.id, symbol, ticker['last'])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loop (exchange, symbol) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const ticker = await exchange.watchTicker (symbol)
|
||||||
|
handle (exchange, symbol, ticker)
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
// do nothing and retry on next loop iteration
|
||||||
|
// throw e // uncomment to break all loops in case of an error in any one of them
|
||||||
|
// break // you can also break just this one loop if it fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.binanceusdm () // usd(s)-margined contracts
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const exchange = new ccxt.pro.binance () // spot markets
|
||||||
|
//
|
||||||
|
// WARNING: when using the spot markets mind subscription limits!
|
||||||
|
// don't attempt to subscribe to all of them
|
||||||
|
// the exchanges will not allow that in general
|
||||||
|
// instead, specify a shorter list of symbols to subscribe to
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const exchange = new ccxt.pro.binancecoinm () // coin-margined contracts
|
||||||
|
|
||||||
|
if (exchange.has['watchTicker']) {
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
// many symbols
|
||||||
|
await Promise.all (exchange.symbols.map (symbol => loop (exchange, symbol)))
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// const symbols = [ 'BTC/USDT', 'ETH/USDT' ] // specific symbols
|
||||||
|
// await Promise.all (symbols.map (symbol => loop (exchange, symbol)))
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// await loop (exchange, 'BTC/USDT') // one symbol
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log (exchange.id, 'does not support watchTicker yet')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt');
|
||||||
|
const asTable = require ('as-table').configure ({ delimiter: ' | ' })
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
|
||||||
|
async function loop (exchange, symbol, timeframe, completeCandlesOnly = false) {
|
||||||
|
const durationInSeconds = exchange.parseTimeframe (timeframe)
|
||||||
|
const durationInMs = durationInSeconds * 1000
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const trades = await exchange.watchTrades (symbol)
|
||||||
|
if (trades.length > 0) {
|
||||||
|
const currentMinute = parseInt (exchange.milliseconds () / durationInMs)
|
||||||
|
let ohlcvc = exchange.buildOHLCVC (trades, timeframe)
|
||||||
|
if (completeCandlesOnly) {
|
||||||
|
ohlcvc = ohlcvc.filter (candle => parseInt (candle[0] / durationInMs) < currentMinute)
|
||||||
|
}
|
||||||
|
if (ohlcvc.length > 0) {
|
||||||
|
console.log("Symbol:", symbol, "timeframe:", timeframe);
|
||||||
|
console.log ('-----------------------------------------------------------')
|
||||||
|
console.log (asTable (ohlcvc))
|
||||||
|
console.log ('-----------------------------------------------------------')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
// do nothing and retry on next loop iteration
|
||||||
|
// throw e // uncomment to break all loops in case of an error in any one of them
|
||||||
|
// break // you can also break just this one loop if it fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
// select the exchange
|
||||||
|
const exchange = new ccxt.pro.ftx ()
|
||||||
|
|
||||||
|
if (exchange.has['watchTrades']) {
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
// Change this value accordingly
|
||||||
|
const timeframe = '1m'
|
||||||
|
|
||||||
|
const allSymbols = exchange.symbols;
|
||||||
|
|
||||||
|
// arbitrary n symbols
|
||||||
|
const limit = 5;
|
||||||
|
// const selectedSymbols = allSymbols.slice(0, limit);
|
||||||
|
// you can also specify the symbols manually
|
||||||
|
// example:
|
||||||
|
// const selectedSymbols = ['BTC/USDT', 'LTC/USDT']
|
||||||
|
|
||||||
|
console.log(selectedSymbols);
|
||||||
|
|
||||||
|
// Use this variable to choose if only complete candles
|
||||||
|
// should be considered
|
||||||
|
const completeCandlesOnly = true
|
||||||
|
|
||||||
|
await Promise.all (selectedSymbols.map (symbol => loop (exchange, symbol, timeframe, completeCandlesOnly)))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log (exchange.id, 'does not support watchTrades yet')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
let ohlcvs = {}
|
||||||
|
|
||||||
|
async function log (exchange, symbol, timeframe) {
|
||||||
|
const market = exchange.market (symbol)
|
||||||
|
const duration = exchange.parseTimeframe (timeframe) * 1000
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), 'Warming up, waiting for at least one trade...')
|
||||||
|
while (!Object.keys (ohlcvs).length) {
|
||||||
|
await exchange.throttle (1)
|
||||||
|
}
|
||||||
|
let now = exchange.milliseconds ()
|
||||||
|
const start = (parseInt (now / duration) + 1) * duration
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), 'Trades started arriving, waiting till', exchange.iso8601 (start))
|
||||||
|
await exchange.sleep (start - now)
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), 'Done warming up')
|
||||||
|
for (let i = 0;; i++) {
|
||||||
|
now = exchange.milliseconds ()
|
||||||
|
let candle = Object.values (ohlcvs)[0]
|
||||||
|
console.log ('')
|
||||||
|
console.log (exchange.iso8601 (now), '------------------------------------------------------')
|
||||||
|
console.log ('Datetime ', 'Timestamp ', ... [ 'Open', 'High', 'Low', 'Close', market['base'], market['quote'] ].map (x => x.toString ().padEnd (10, ' ')))
|
||||||
|
for (let j = start; j < now; j += duration) {
|
||||||
|
if (!(j in ohlcvs)) {
|
||||||
|
ohlcvs[j] = [ j, candle[4], candle[4], candle[4], candle[4], 0, 0 ]
|
||||||
|
}
|
||||||
|
candle = exchange.safeValue (ohlcvs, j);
|
||||||
|
console.log (exchange.iso8601 (j), ... candle.map (x => x.toString ().padEnd (10, ' ')))
|
||||||
|
}
|
||||||
|
ohlcvs = exchange.indexBy (Object.values (ohlcvs).slice (-1000), 0)
|
||||||
|
await exchange.sleep(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function watch (exchange, symbol, timeframe) {
|
||||||
|
console.log ('Starting', exchange.id, symbol)
|
||||||
|
const duration = exchange.parseTimeframe (timeframe) * 1000
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const trades = await exchange.watchTrades(symbol)
|
||||||
|
for (const trade of trades) {
|
||||||
|
const timestamp = parseInt(trade['timestamp'] / duration) * duration
|
||||||
|
let candle = exchange.safe_value(ohlcvs, timestamp)
|
||||||
|
if (candle) {
|
||||||
|
candle[2] = Math.max(trade['price'], candle[2])
|
||||||
|
candle[3] = Math.min(trade['price'], candle[3])
|
||||||
|
candle[4] = trade['price']
|
||||||
|
candle[5] = exchange.parseNumber(exchange.amountToPrecision(symbol, trade['amount'] + candle[5]))
|
||||||
|
candle[6] = exchange.parseNumber(exchange.costToPrecision(symbol, trade['cost'] + candle[6]))
|
||||||
|
} else {
|
||||||
|
candle = [
|
||||||
|
timestamp,
|
||||||
|
trade['price'],
|
||||||
|
trade['price'],
|
||||||
|
trade['price'],
|
||||||
|
trade['price'],
|
||||||
|
exchange.parseNumber(exchange.amountToPrecision(symbol, trade['amount'])),
|
||||||
|
exchange.parseNumber(exchange.costToPrecision(symbol, trade['cost'])),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
ohlcvs[timestamp] = candle
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const symbol = 'BTC/USDT'
|
||||||
|
const exchange = new ccxt.pro.binance ({ 'newUpdates': true })
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
const timeframe = '1m'
|
||||||
|
await Promise.all ([ watch (exchange, symbol, timeframe), log (exchange, symbol, timeframe) ])
|
||||||
|
await exchange.close ()
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
let ohlcvs = {}
|
||||||
|
const symbol = 'BTC/USDT'
|
||||||
|
const exchange = new ccxt.pro.binance ({ 'newUpdates': true })
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
const market = exchange.market (symbol)
|
||||||
|
const timeframe = '1m'
|
||||||
|
const duration = exchange.parseTimeframe (timeframe) * 1000
|
||||||
|
console.log ('Starting', exchange.id, symbol)
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const trades = await exchange.watchTrades(symbol)
|
||||||
|
for (const trade of trades) {
|
||||||
|
const timestamp = parseInt(trade['timestamp'] / duration) * duration
|
||||||
|
let candle = exchange.safe_value(ohlcvs, timestamp)
|
||||||
|
if (candle) {
|
||||||
|
candle[2] = Math.max(trade['price'], candle[2])
|
||||||
|
candle[3] = Math.min(trade['price'], candle[3])
|
||||||
|
candle[4] = trade['price']
|
||||||
|
candle[5] = exchange.parseNumber(exchange.amountToPrecision(symbol, trade['amount'] + candle[5]))
|
||||||
|
candle[6] = exchange.parseNumber(exchange.costToPrecision(symbol, trade['cost'] + candle[6]))
|
||||||
|
} else {
|
||||||
|
candle = [
|
||||||
|
timestamp,
|
||||||
|
trade['price'],
|
||||||
|
trade['price'],
|
||||||
|
trade['price'],
|
||||||
|
trade['price'],
|
||||||
|
exchange.parseNumber(exchange.amountToPrecision(symbol, trade['amount'])),
|
||||||
|
exchange.parseNumber(exchange.costToPrecision(symbol, trade['cost'])),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
ohlcvs[timestamp] = candle
|
||||||
|
}
|
||||||
|
console.log ('')
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), '------------------------------------------------------')
|
||||||
|
const values = Object.values (ohlcvs).slice (-1000)
|
||||||
|
ohlcvs = exchange.indexBy (values, 0)
|
||||||
|
console.log ('Datetime ', 'Timestamp ', ... [ 'Open', 'High', 'Low', 'Close', market['base'], market['quote'] ].map (x => x.toString ().padEnd (10, ' ')))
|
||||||
|
for (let i = 0; i < values.length; i++) {
|
||||||
|
const candle = values[i]
|
||||||
|
console.log (exchange.iso8601 (candle[0]), ... candle.map (x => x.toString ().padEnd (10, ' ')))
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await exchange.close ()
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt.js').pro
|
||||||
|
, asTable = require ('as-table') // .configure ({ print: require ('string.ify').noPretty })
|
||||||
|
, log = require ('ololog').noLocate
|
||||||
|
, ansi = require ('ansicolor').nice
|
||||||
|
|
||||||
|
;(async function test () {
|
||||||
|
|
||||||
|
let total = 0
|
||||||
|
let missing = 0
|
||||||
|
let implemented = 0
|
||||||
|
let emulated = 0
|
||||||
|
|
||||||
|
const exchanges = ccxt.exchanges
|
||||||
|
.map (id => new ccxt[id]())
|
||||||
|
.filter (exchange => exchange.has.ws)
|
||||||
|
|
||||||
|
log (
|
||||||
|
asTable (
|
||||||
|
exchanges
|
||||||
|
.map (exchange => {
|
||||||
|
|
||||||
|
let result = {};
|
||||||
|
|
||||||
|
[
|
||||||
|
'ws',
|
||||||
|
'watchOrderBook',
|
||||||
|
'watchTicker',
|
||||||
|
'watchTrades',
|
||||||
|
'watchOHLCV',
|
||||||
|
'watchBalance',
|
||||||
|
'watchOrders',
|
||||||
|
'watchMyTrades',
|
||||||
|
|
||||||
|
].forEach (key => {
|
||||||
|
|
||||||
|
total += 1
|
||||||
|
|
||||||
|
let capability = (key in exchange.has) ?
|
||||||
|
exchange.has[key].toString () :
|
||||||
|
'undefined'
|
||||||
|
|
||||||
|
if (!exchange.has[key]) {
|
||||||
|
capability = exchange.id.red.dim
|
||||||
|
missing += 1
|
||||||
|
} else if (exchange.has[key] === 'emulated') {
|
||||||
|
capability = exchange.id.yellow
|
||||||
|
emulated += 1
|
||||||
|
} else {
|
||||||
|
capability = exchange.id.green
|
||||||
|
implemented += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
result[key] = capability
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
log ('Summary:',
|
||||||
|
exchanges.length.toString ().green, 'exchanges,',
|
||||||
|
implemented.toString ().green, 'methods implemented,',
|
||||||
|
emulated.toString ().yellow, 'emulated,',
|
||||||
|
missing.toString ().red, 'missing,',
|
||||||
|
total.toString (), 'total')
|
||||||
|
|
||||||
|
}) ()
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt')
|
||||||
|
|
||||||
|
console.log ("CCXT Pro Version:", ccxt.version)
|
||||||
|
|
||||||
|
const orderbooks = {}
|
||||||
|
|
||||||
|
let run = true
|
||||||
|
|
||||||
|
async function watchOrderBook (exchange, symbol) {
|
||||||
|
while (run) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
orderbooks[symbol] = orderbook
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), orderbook['datetime'], orderbook['nonce'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function stop (exchange) {
|
||||||
|
await exchange.sleep (10000)
|
||||||
|
run = false
|
||||||
|
await exchange.close ()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const exchange = new ccxt.pro.binance ()
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
exchange.verbose = true
|
||||||
|
const symbols = [
|
||||||
|
'BTC/USDT',
|
||||||
|
'ETH/USDT',
|
||||||
|
]
|
||||||
|
stop (exchange).then (() => {})
|
||||||
|
await Promise.all (symbols.map (symbol => watchOrderBook (exchange, symbol)))
|
||||||
|
console.log ('Sleeping for a moment...')
|
||||||
|
await exchange.sleep (10000)
|
||||||
|
console.log ('Done')
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt')
|
||||||
|
|
||||||
|
console.log ("CCXT Pro Version:", ccxt.version)
|
||||||
|
|
||||||
|
async function loop (exchange, method, symbol) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange[method] (symbol)
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), orderbook['datetime'], orderbook['nonce'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const exchange = new ccxt.pro.gateio ({
|
||||||
|
'options': {'defaultType':'swap'}
|
||||||
|
})
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
// exchange.verbose = true // uncomment for debugging purposes if necessary
|
||||||
|
const symbols = [
|
||||||
|
'ANC/USDT:USDT',
|
||||||
|
]
|
||||||
|
await Promise.all (symbols.map (symbol => loop (exchange, 'fetchOrderBook', symbol)))
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const ccxt = require ('../../../ccxt')
|
||||||
|
|
||||||
|
console.log ('CCXT Pro version:', ccxt.version)
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const exchange = new ccxt.pro.gateio ({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
})
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
exchange.verbose = true
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const response = await exchange.watchBalance ()
|
||||||
|
console.log (new Date (), response)
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
await exchange.sleep (1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt')
|
||||||
|
|
||||||
|
console.log ("CCXT Pro Version:", ccxt.version)
|
||||||
|
|
||||||
|
const orderbooks = {}
|
||||||
|
|
||||||
|
async function watchAllSymbols (exchange, symbols) {
|
||||||
|
while (true) {
|
||||||
|
const keys = Object.keys (orderbooks);
|
||||||
|
if (symbols.length === keys.length) {
|
||||||
|
console.log ('\n\n\n\n\n')
|
||||||
|
console.log ('----------------------------------------------------')
|
||||||
|
console.log ('All orderbooks received at least one update:');
|
||||||
|
for (let i = 0; i < symbols.length; i++) {
|
||||||
|
const symbol = symbols[i]
|
||||||
|
const orderbook = orderbooks[symbol]
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), orderbook['datetime'], orderbook['nonce'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
}
|
||||||
|
console.log ('----------------------------------------------------')
|
||||||
|
console.log ('\n\n\n\n\n')
|
||||||
|
// process.exit () // stop here if you want
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
await exchange.sleep (1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function watchOrderBook (exchange, symbol) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
orderbooks[symbol] = orderbook
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), orderbook['datetime'], orderbook['nonce'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const exchange = new ccxt.pro.gateio ({
|
||||||
|
'options': {
|
||||||
|
'defaultType': 'swap',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
// exchange.verbose = true // uncomment for debugging purposes if necessary
|
||||||
|
const symbols = [
|
||||||
|
// 'SOS/USDT:USDT',
|
||||||
|
// 'JASMY/USDT:USDT',
|
||||||
|
// 'SLP/USDT:USDT',
|
||||||
|
'ACH/USDT:USDT',
|
||||||
|
'MKISHU/USDT:USDT',
|
||||||
|
// 'GMT/USDT:USDT',
|
||||||
|
// 'ASTR/USDT:USDT',
|
||||||
|
'RAMP/USDT:USDT',
|
||||||
|
'RSR/USDT:USDT',
|
||||||
|
// 'RACA/USDT:USDT',
|
||||||
|
// 'ROOK/USDT:USDT',
|
||||||
|
// 'ROSE/USDT:USDT',
|
||||||
|
]
|
||||||
|
await Promise.all ([
|
||||||
|
watchAllSymbols (exchange, symbols),
|
||||||
|
... symbols.map (symbol => watchOrderBook (exchange, symbol))
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
let stop = false
|
||||||
|
|
||||||
|
async function shutdown (milliseconds) {
|
||||||
|
await ccxt.sleep (10000)
|
||||||
|
stop = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function watchOrderBook (exchangeId, symbol) {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro[exchangeId] ()
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
// exchange.verbose = true
|
||||||
|
while (!stop) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
console.log (new Date (), exchange.id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
stop = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await exchange.close ()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const streams = {
|
||||||
|
'binance': 'BTC/USDT',
|
||||||
|
'ftx': 'BTC/USDT',
|
||||||
|
};
|
||||||
|
|
||||||
|
await Promise.all ([
|
||||||
|
shutdown (10000),
|
||||||
|
... Object.entries (streams).map (([ exchangeId, symbol ]) => watchOrderBook (exchangeId, symbol))
|
||||||
|
])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
const streams = {
|
||||||
|
'binance': 'BTC/USDT',
|
||||||
|
'bittrex': 'BTC/USDT',
|
||||||
|
'poloniex': 'BTC/USDT',
|
||||||
|
'bitfinex': 'BTC/USDT',
|
||||||
|
'hitbtc': 'BTC/USDT',
|
||||||
|
'upbit': 'BTC/USDT',
|
||||||
|
'coinbasepro': 'BTC/USD',
|
||||||
|
'ftx': 'BTC/USDT',
|
||||||
|
'okex': 'BTC/USDT',
|
||||||
|
'gateio': 'BTC/USDT',
|
||||||
|
};
|
||||||
|
|
||||||
|
await Promise.all (Object.keys (streams).map (exchangeId =>
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro[exchangeId] ({ enableRateLimit: true })
|
||||||
|
const symbol = streams[exchangeId]
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
console.log (new Date (), exchange.id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}) ())
|
||||||
|
)
|
||||||
|
}) ()
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt')
|
||||||
|
, exchange = new ccxt.okex ({
|
||||||
|
apiKey: 'YOUR_API_KEY',
|
||||||
|
secret: 'YOUR_API_SECRET',
|
||||||
|
password: 'YOUR_API_PASSWORD',
|
||||||
|
enableRateLimit: true,
|
||||||
|
options: { defaultType: 'futures' },
|
||||||
|
})
|
||||||
|
, symbol = 'BTC/USDT:USDT-201225'
|
||||||
|
, amount = 1 // how may contracts
|
||||||
|
, price = undefined // or your limit price
|
||||||
|
, side = 'buy' // or 'sell'
|
||||||
|
, type = '1' // 1 open long, 2 open short, 3 close long, 4 close short for futures
|
||||||
|
, order_type = '4' // 0 = limit order, 4 = market order
|
||||||
|
|
||||||
|
console.log ('CCXT Pro Version: ', ccxt.version)
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
|
||||||
|
// exchange.verbose = true // uncomment for debugging
|
||||||
|
// open long market price order
|
||||||
|
const order = await exchange.createOrder(symbol, 'market', side, amount, price, { type });
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
// open long market price order
|
||||||
|
// const order = await exchange.createOrder(symbol, type, side, amount, price, { order_type });
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
// close short market price order
|
||||||
|
// const order = await exchange.createOrder(symbol, 'market', side, amount, price, { type, order_type });
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
// close short market price order
|
||||||
|
// const order = await exchange.createOrder(symbol, '4', side, amount, price, { order_type });
|
||||||
|
// ...
|
||||||
|
|
||||||
|
console.log (order)
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
const ccxt = require ('ccxt')
|
||||||
|
|
||||||
|
console.log ('Node.js:', process.version)
|
||||||
|
console.log ('CCXT Pro v' + ccxt.version)
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.okex ({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_API_SECRET',
|
||||||
|
'password': 'YOUR_API_PASWORD'
|
||||||
|
})
|
||||||
|
|
||||||
|
async function watchBalance (code) {
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const balance = await exchange.watchBalance ({
|
||||||
|
'code': code,
|
||||||
|
})
|
||||||
|
console.log ('New', code, 'balance is: ', balance[code])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
||||||
|
|
||||||
|
console.log ('Creating', symbol, type, 'order')
|
||||||
|
const order = await exchange.createOrder (symbol, type, side, amount, price, params);
|
||||||
|
console.log (symbol, type, side, 'order created')
|
||||||
|
console.log (order)
|
||||||
|
}
|
||||||
|
|
||||||
|
;(async () => {
|
||||||
|
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
console.log (exchange.id, 'markets loaded')
|
||||||
|
|
||||||
|
const symbol = 'ETH/USDT'
|
||||||
|
const market = exchange.market (symbol)
|
||||||
|
const quote = market['quote']
|
||||||
|
|
||||||
|
// run in parallel without await
|
||||||
|
console.log ('Watching', quote, 'balance')
|
||||||
|
watchBalance (quote)
|
||||||
|
|
||||||
|
// wait a bit to allow it to subscribe
|
||||||
|
await exchange.sleep (3000)
|
||||||
|
|
||||||
|
const ticker = await exchange.watchTicker (symbol)
|
||||||
|
const type = 'market'
|
||||||
|
const side = 'buy'
|
||||||
|
const amount = 0.1
|
||||||
|
const price = ticker['bid']
|
||||||
|
|
||||||
|
await createOrder (symbol, type, side, amount, price)
|
||||||
|
|
||||||
|
}) ()
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import ccxt from '../../../js/ccxt.js';
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const exchange = new ccxt.pro.okx()
|
||||||
|
await exchange.loadMarkets()
|
||||||
|
// exchange.verbose = true
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// don't do this, specify a list of symbols to watch for watchTickers
|
||||||
|
// or a very large subscription message will crash your WS connection
|
||||||
|
// const tickers = await exchange.watchTickers ()
|
||||||
|
|
||||||
|
// do this instead
|
||||||
|
const symbols = [
|
||||||
|
'ETH/BTC',
|
||||||
|
'BTC/USDT',
|
||||||
|
'ETH/USDT',
|
||||||
|
// ...
|
||||||
|
]
|
||||||
|
const tickers = await exchange.watchTickers (symbols)
|
||||||
|
symbols = Object.keys(tickers)
|
||||||
|
console.log (new Date(), 'received', symbols.length, 'symbols', ... symbols.slice(0,5).join(', '), '...')
|
||||||
|
} catch (e) {
|
||||||
|
console.log (new Date(), e.constructor.name, e.message)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt')
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
async function watchOrders(exchange) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orders = await exchange.watchOrders() // await here
|
||||||
|
console.log(orders)
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function watchBalance(exchange) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const balance = await exchange.watchBalance() // await here
|
||||||
|
console.log(balance)
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const exchange = new ccxt.pro.binance({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
'password': 'IF NECESSARY',
|
||||||
|
// etc...
|
||||||
|
})
|
||||||
|
await exchange.loadMarkets () // await here
|
||||||
|
|
||||||
|
// exchange.verbose = true // uncomment for debugging purposes if necessary
|
||||||
|
|
||||||
|
watchOrders(exchange) // no await
|
||||||
|
watchBalance(exchange) // no await
|
||||||
|
|
||||||
|
await exchange.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.binance ({ enableRateLimit: true })
|
||||||
|
const symbols = [ 'BTC/USDT', 'ETH/BTC', 'ETH/USDT' ]
|
||||||
|
|
||||||
|
const loop = async (symbol) => {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
console.log (new Date (), symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
// do nothing and retry on next loop iteration
|
||||||
|
// throw e // uncomment to break all loops in case of an error in any one of them
|
||||||
|
// break // you can also break just this one loop if it fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all (symbols.map (symbol => loop (symbol)))
|
||||||
|
|
||||||
|
}) ()
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.binance ({ enableRateLimit: true })
|
||||||
|
const symbols = [ 'BTC/USDT', 'ETH/BTC', 'ETH/USDT' ]
|
||||||
|
|
||||||
|
await Promise.all (symbols.map (symbol =>
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
console.log (new Date (), symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
// do nothing and retry on next loop iteration
|
||||||
|
// throw e // uncomment to break all loops in case of an error in any one of them
|
||||||
|
// break // you can also break just this one loop if it fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}) ())
|
||||||
|
)
|
||||||
|
}) ()
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt')
|
||||||
|
, SocksProxyAgent = require ('socks-proxy-agent')
|
||||||
|
, socks = 'socks://127.0.0.1:7000'
|
||||||
|
, socksAgent = new SocksProxyAgent (socks)
|
||||||
|
, exchange = new ccxt.binance ({
|
||||||
|
enableRatLimit: true,
|
||||||
|
httpsAgent: socksAgent, // ←--------------------- socksAgent here
|
||||||
|
options: {
|
||||||
|
'ws': {
|
||||||
|
'options': { agent: socksAgent }, // ←--- socksAgent here
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
;(async () => {
|
||||||
|
console.log (socks)
|
||||||
|
const symbol = 'BTC/USDT'
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
console.log ('Markets loaded')
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds()), symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) ()
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
async function watchOrderBook (exchange, symbol) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const method = exchange.has.watchOrderBook ? 'watchOrderBook' : 'fetchOrderBook'
|
||||||
|
const orderbook = await exchange[method](symbol)
|
||||||
|
console.log (new Date (), exchange.id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
process.exit ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function watchExchange (exchangeId, symbols) {
|
||||||
|
const exchange = new ccxt.pro[exchangeId] ()
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
await Promise.all (symbols.map (symbol => watchOrderBook (exchange, symbol)))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const streams = {
|
||||||
|
'ftx': [
|
||||||
|
'BTC/USDT',
|
||||||
|
'ETH/BTC',
|
||||||
|
],
|
||||||
|
'coinex': [
|
||||||
|
'BTC/USDT',
|
||||||
|
'ETH/BTC',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const entries = Object.entries (streams)
|
||||||
|
await Promise.all (entries.map (([ exchangeId, symbols ]) => watchExchange (exchangeId, symbols)))
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
async function watchOrderBook (exchange, symbol) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
console.log (new Date (), exchange.id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function watchExchange (exchangeId, symbols) {
|
||||||
|
const exchange = new ccxt.pro[exchangeId] ()
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
await Promise.all (symbols.map (symbol => watchOrderBook (exchange, symbol)))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const streams = {
|
||||||
|
'binance': [
|
||||||
|
'BTC/USDT',
|
||||||
|
'ETH/BTC',
|
||||||
|
],
|
||||||
|
'ftx': [
|
||||||
|
'BTC/USDT',
|
||||||
|
'ETH/BTC',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const entries = Object.entries (streams)
|
||||||
|
await Promise.all (entries.map (([ exchangeId, symbols ]) => watchExchange (exchangeId, symbols)))
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
|
||||||
|
async function watchTickerLoop (exchange, symbol) {
|
||||||
|
// exchange.verbose = true // uncomment for debugging purposes if necessary
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const ticker = await exchange.watchTicker (symbol)
|
||||||
|
console.log (new Date (), exchange.id, symbol, ticker['last'])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
// do nothing and retry on next loop iteration
|
||||||
|
// throw e // uncomment to break all loops in case of an error in any one of them
|
||||||
|
// break // you can also break just this one loop if it fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function exchangeLoop (exchangeId, symbols) {
|
||||||
|
const exchange = new ccxt.pro[exchangeId]()
|
||||||
|
await exchange.loadMarkets ()
|
||||||
|
const loops = symbols.map (symbol => watchTickerLoop (exchange, symbol))
|
||||||
|
await Promise.all (loops)
|
||||||
|
await exchange.close ()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const exchanges = {
|
||||||
|
'binance': [ 'BTC/USDT', 'ETH/USDT' ],
|
||||||
|
'ftx': [ 'BTC/USD', 'ETH/USD' ],
|
||||||
|
}
|
||||||
|
const loops = Object.entries (exchanges).map (([ exchangeId, symbols ]) => exchangeLoop (exchangeId, symbols))
|
||||||
|
await Promise.all (loops)
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt');
|
||||||
|
|
||||||
|
async function watchOrderBook (exchangeId, symbol) {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro[exchangeId] ()
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const orderbook = await exchange.watchOrderBook (symbol)
|
||||||
|
console.log (new Date (), exchange.id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const streams = {
|
||||||
|
'binance': 'BTC/USDT',
|
||||||
|
'ftx': 'BTC/USDT',
|
||||||
|
};
|
||||||
|
|
||||||
|
await Promise.all (Object.entries (streams).map (([ exchangeId, symbol ]) => watchOrderBook (exchangeId, symbol)))
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version);
|
||||||
|
|
||||||
|
async function watchExchange (exchangeId, symbol) {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro[exchangeId] ({
|
||||||
|
newUpdates: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await exchange.loadMarkets ();
|
||||||
|
|
||||||
|
// exchange.verbose = true // uncomment for debugging purposes if necessary
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const trades = await exchange.watchTrades (symbol)
|
||||||
|
for (let i = 0; i < trades.length; i++) {
|
||||||
|
const trade = trades[i]
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), exchange.id, trade['symbol'], trade['id'], trade['datetime'], trade['price'], trade['amount'])
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
|
||||||
|
const streams = {
|
||||||
|
'binance': 'BTC/USDT',
|
||||||
|
'okex': 'BTC/USDT',
|
||||||
|
'kraken': 'BTC/USD',
|
||||||
|
};
|
||||||
|
|
||||||
|
const values = Object.entries (streams)
|
||||||
|
const promises = values.map (([ exchangeId, symbol ]) => watchExchange (exchangeId, symbol))
|
||||||
|
await Promise.all (promises)
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('../../../ccxt');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
const streams = {
|
||||||
|
'binance': 'BTC/USDT',
|
||||||
|
'okex': 'BTC/USDT'
|
||||||
|
};
|
||||||
|
|
||||||
|
await Promise.all (Object.keys (streams).map (exchangeId =>
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro[exchangeId] ({
|
||||||
|
enableRateLimit: true,
|
||||||
|
options: {
|
||||||
|
tradesLimit: 100, // lower = better, 1000 by default
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const symbol = streams[exchangeId]
|
||||||
|
let lastId = ''
|
||||||
|
while (true) {
|
||||||
|
console.log ('---')
|
||||||
|
try {
|
||||||
|
const trades = await exchange.watchTrades (symbol)
|
||||||
|
for (let i = 0; i < trades.length; i++) {
|
||||||
|
const trade = trades[i]
|
||||||
|
if (trade['id'] > lastId) {
|
||||||
|
console.log (exchange.iso8601 (exchange.milliseconds ()), exchange.id, trade['symbol'], trade['id'], trade['datetime'], trade['price'], trade['amount'])
|
||||||
|
lastId = trade['id']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}) ())
|
||||||
|
)
|
||||||
|
}) ()
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt');
|
||||||
|
|
||||||
|
console.log ('CCXT Version:', ccxt.version)
|
||||||
|
|
||||||
|
async function watchTrades (exchange, symbol) {
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const trades = await exchange.watchTrades (symbol)
|
||||||
|
console.log (new Date (), exchange.id, symbol, trades.length, 'trades')
|
||||||
|
} catch (e) {
|
||||||
|
console.log (symbol, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const symbols = [ 'USDT/THB', 'BTC/THB', 'ETH/THB' ]
|
||||||
|
const exchange = new ccxt.pro.zipmex({
|
||||||
|
'newUpdates': true
|
||||||
|
})
|
||||||
|
const markets = await exchange.loadMarkets ()
|
||||||
|
exchange.verbose = true
|
||||||
|
await Promise.all (symbols.map ((symbol) => watchTrades (exchange, symbol)))
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// see this issue for details
|
||||||
|
// https://github.com/ccxt/ccxt/issues/6659
|
||||||
|
|
||||||
|
const ccxt = require ('ccxt')
|
||||||
|
|
||||||
|
const exchange = new ccxt.pro.kraken ()
|
||||||
|
|
||||||
|
function yellow (s) {
|
||||||
|
return '\x1b[33m' + s + '\x1b[0m'
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runWs () {
|
||||||
|
while (1) {
|
||||||
|
const book = await exchange.watchOrderBook ('ETH/BTC')
|
||||||
|
console.log (new Date (), 'WS ', book['datetime'], book['bids'][0][0], book['asks'][0][0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runRest () {
|
||||||
|
while (1) {
|
||||||
|
const book = await exchange.fetchOrderBook ('ETH/BTC')
|
||||||
|
const timestamp = new Date (exchange.last_response_headers['Date']).getTime ()
|
||||||
|
const datetime = exchange.iso8601 (timestamp)
|
||||||
|
console.log (new Date (), 'REST', yellow (datetime), book['bids'][0][0], book['asks'][0][0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runWs ()
|
||||||
|
runRest ()
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
$root = dirname(dirname(dirname(dirname(__FILE__))));
|
||||||
|
include $root . '/ccxt.php';
|
||||||
|
|
||||||
|
function create_exchange($exchange_id, $config) {
|
||||||
|
|
||||||
|
$keys = array(
|
||||||
|
'ids',
|
||||||
|
'markets',
|
||||||
|
'markets_by_id',
|
||||||
|
'currencies',
|
||||||
|
'currencies_by_id',
|
||||||
|
'base_currencies',
|
||||||
|
'quote_currencies',
|
||||||
|
'symbols',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$exchange_class = '\\ccxt\\pro\\' . $exchange_id;
|
||||||
|
$exchange = new $exchange_class($config);
|
||||||
|
$markets_on_disk = "./{$exchange_id}.markets.json";
|
||||||
|
|
||||||
|
$exchange->verbose = true; // this is a debug output to demonstrate which networking calls are being issued
|
||||||
|
|
||||||
|
if (file_exists($markets_on_disk)) {
|
||||||
|
|
||||||
|
$cache = json_decode(file_get_contents($markets_on_disk), true);
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$exchange->{$key} = $cache[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$markets = yield $exchange->load_markets();
|
||||||
|
$cache = array();
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$cache[$key] = $exchange->{$key};
|
||||||
|
}
|
||||||
|
file_put_contents($markets_on_disk, json_encode($cache));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $exchange;
|
||||||
|
}
|
||||||
|
|
||||||
|
$exchanges = array(
|
||||||
|
array('binance', array(
|
||||||
|
'id' => 'binance1',
|
||||||
|
'apiKey' => 'YOUR_API_KEY_HERE',
|
||||||
|
'secret' => 'YOUR_SECRET_HERE',
|
||||||
|
)),
|
||||||
|
array('binance', array(
|
||||||
|
'id' => 'binance2',
|
||||||
|
'apiKey' => 'YOUR_API_KEY_HERE',
|
||||||
|
'secret' => 'YOUR_SECRET_HERE',
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
$loop = function($exchange_id, $config) {
|
||||||
|
$exchange = yield create_exchange($exchange_id, $config);
|
||||||
|
$exchange->verbose = true;
|
||||||
|
while (true) {
|
||||||
|
$response = yield $exchange->watch_balance();
|
||||||
|
print('--------------------------------------------------------------');
|
||||||
|
print($exchange->id);
|
||||||
|
print($response);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($exchanges as $exchange) {
|
||||||
|
\React\Async\coroutine($loop, $exchange[0], $exchange[1]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$root = dirname(dirname(dirname(dirname(__FILE__))));
|
||||||
|
include $root . '/ccxt.php';
|
||||||
|
|
||||||
|
|
||||||
|
$config = array('enableRateLimit' => true);
|
||||||
|
$binance = new \ccxt\pro\binance($config);
|
||||||
|
$bittrex = new \ccxt\pro\bittrex($config);
|
||||||
|
$symbol = "BTC/USDT";
|
||||||
|
|
||||||
|
$loop = function($exchange, $symbol) {
|
||||||
|
echo 'got inside' . PHP_EOL;
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
$ticker = yield $exchange->watch_ticker($symbol);
|
||||||
|
print_ticker($ticker, $exchange->id, $symbol);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function print_ticker($ticker, $exchange_name, $symbol) {
|
||||||
|
$bid = $ticker['bid'];
|
||||||
|
$ask = $ticker['ask'];
|
||||||
|
echo "$exchange_name $symbol - bid: $bid <> ask: $ask" . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
\React\Async\coroutine($loop, $bittrex, $symbol);
|
||||||
|
\React\Async\coroutine($loop, $binance, $symbol);
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$root = dirname(dirname(dirname(dirname(__FILE__))));
|
||||||
|
include $root . '/ccxt.php';
|
||||||
|
|
||||||
|
$id = 'aax';
|
||||||
|
$exchange_class = '\\ccxt\\pro\\' . $id;
|
||||||
|
$exchange = new $exchange_class(array(
|
||||||
|
'enableRateLimit' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$symbols = array('BTC/USDT', 'ETH/USDT', 'ETH/BTC');
|
||||||
|
|
||||||
|
function print_orderbook($orderbook, $symbol) {
|
||||||
|
$id = isset($orderbook['nonce']) ? $orderbook['nonce'] : $orderbook['datetime'];
|
||||||
|
echo $id, ' ', $symbol, ' ',
|
||||||
|
count($orderbook['asks']), ' asks ', json_encode($orderbook['asks'][0]), ' ',
|
||||||
|
count($orderbook['bids']), ' bids ', json_encode($orderbook['bids'][0]), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$loop = function($exchange, $symbol) {
|
||||||
|
while (true) {
|
||||||
|
$orderbook = yield $exchange->watch_order_book($symbol);
|
||||||
|
print_orderbook($orderbook, $symbol);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach ($symbols as $symbol) {
|
||||||
|
\React\Async\coroutine($loop, $exchange, $symbol);
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
include dirname(dirname(dirname(dirname(__FILE__)))). '/ccxt.php';
|
||||||
|
|
||||||
|
$binance_id = '\\ccxt\\pro\\binance';
|
||||||
|
$binance_exchange = new $binance_id( /*[ 'apiKey' => _YOUR_APIKEY_HERE_, 'secret' => _YOUR_SECRET_HERE_ ]*/ );
|
||||||
|
|
||||||
|
$ftx_id = '\\ccxt\\pro\\ftx';
|
||||||
|
$ftx_exchange = new $ftx_id( /*['apiKey' => _YOUR_APIKEY_HERE_, 'secret' => _YOUR_SECRET_HERE_]*/ );
|
||||||
|
|
||||||
|
$wrapper_func = function($exchange, $symbol, $method_name) {
|
||||||
|
if ($exchange->has[$method_name]) {
|
||||||
|
print ("Starting $method_name for $exchange->id -> $symbol\n");
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
$orderbook = yield $exchange->$method_name($symbol);
|
||||||
|
print("$exchange->id -> $method_name -> $symbol : " . substr(json_encode($orderbook), 0 , 70) . "...\n");
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
print($ex->getMessage());
|
||||||
|
sleep(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print ($exchange->id . " API yet doesnt support $method_name");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function runAsync (...$args) {
|
||||||
|
\React\Async\coroutine(...$args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// *** uncomment whichever methods you want to test ***
|
||||||
|
// runAsync($wrapper_func, ...[$exchange, 'ETH/USDT', 'watchOrderBook']);
|
||||||
|
// runAsync($wrapper_func, ...[$exchange, 'ETH/USDT', 'watchTicker']);
|
||||||
|
// runAsync($wrapper_func, ...[$exchange, 'ETH/USDT', 'watchOrders']);
|
||||||
|
// runAsync($wrapper_func, ...[$exchange, 'ETH/USDT', 'watchMyTrades']);
|
||||||
|
|
||||||
|
runAsync($wrapper_func, ...[$binance_exchange, 'SOL/USDT', 'watchTrades']);
|
||||||
|
runAsync($wrapper_func, ...[$ftx_exchange, 'ETH/USDT', 'watchTrades']);
|
||||||
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from pprint import pprint
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
})
|
||||||
|
|
||||||
|
markets = await exchange.load_markets()
|
||||||
|
|
||||||
|
# exchange.verbose = True # uncomment for debugging purposes if necessary
|
||||||
|
|
||||||
|
symbol = 'ETH/BTC'
|
||||||
|
type = 'limit' # or 'market'
|
||||||
|
side = 'sell' # or 'buy'
|
||||||
|
amount = 1.0
|
||||||
|
price = 0.060154 # or None
|
||||||
|
|
||||||
|
order = await exchange.create_order(symbol, type, side, amount, price)
|
||||||
|
canceled = await exchange.cancel_order(order['id'], order['symbol'])
|
||||||
|
|
||||||
|
pprint(canceled)
|
||||||
|
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
|
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
# This example will run silent and will return your balance only when the balance is updated.
|
||||||
|
#
|
||||||
|
# 1. launch the example with your keys and keep it running
|
||||||
|
# 2. go to the trading section on the website
|
||||||
|
# 3. place a order on a spot market
|
||||||
|
# 4. see your balance updated in the example
|
||||||
|
#
|
||||||
|
# Warning! This example might produce a lot of output to your screen
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_balance(exchange):
|
||||||
|
await exchange.load_markets()
|
||||||
|
# exchange.verbose = True # uncomment for debugging purposes if necessary
|
||||||
|
balance = await exchange.fetch_balance()
|
||||||
|
print('---------------------------------------------------------')
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()))
|
||||||
|
print(balance)
|
||||||
|
print('')
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
update = await exchange.watch_balance()
|
||||||
|
balance = exchange.deep_extend(balance, update)
|
||||||
|
# it will print the balance update when the balance changes
|
||||||
|
# if the balance remains unchanged the exchange will not send it
|
||||||
|
print('---------------------------------------------------------')
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()))
|
||||||
|
print(balance)
|
||||||
|
print('')
|
||||||
|
except Exception as e:
|
||||||
|
print('watch_balance() failed')
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
})
|
||||||
|
await watch_balance(exchange)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import ccxt
|
||||||
|
import ccxt.pro
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
|
||||||
|
async def print_balance(exchange, market_type):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
balance = await exchange.watch_balance({'type': market_type})
|
||||||
|
pprint(balance)
|
||||||
|
print('balance of ' + market_type, balance)
|
||||||
|
print(exchange.options[market_type])
|
||||||
|
except ccxt.BaseError as e:
|
||||||
|
print(type(e), e)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e), e)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance({
|
||||||
|
"apiKey": "",
|
||||||
|
"secret": "",
|
||||||
|
'enableRateLimit': True,
|
||||||
|
'newUpdates': True,
|
||||||
|
})
|
||||||
|
# you must make an order a transfer first to the websocket to send updates
|
||||||
|
asyncio.ensure_future(print_balance(exchange, 'future'))
|
||||||
|
asyncio.ensure_future(print_balance(exchange, 'delivery')) # inverse futures settled in BTC
|
||||||
|
asyncio.ensure_future(print_balance(exchange, 'spot'))
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
|
asyncio.ensure_future(main())
|
||||||
|
loop.run_forever()
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance({
|
||||||
|
'options': {
|
||||||
|
'defaultType': 'future',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
print(orderbook['bids'][0], orderbook['asks'][0])
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import ccxt.pro as ccxt
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance({
|
||||||
|
'options': {
|
||||||
|
'defaultType': 'future', # spot, margin, future, delivery
|
||||||
|
},
|
||||||
|
})
|
||||||
|
# or
|
||||||
|
# exchange = ccxt.pro.binanceusdm()
|
||||||
|
# or
|
||||||
|
# exchange = ccxt.pro.binancecoinm()
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), exchange.id, symbol, 'ask:', orderbook['asks'][0], 'bid:', orderbook['bids'][0])
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run, gather
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Pro version', ccxt.pro.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_order_book(exchange, symbol):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
datetime = exchange.iso8601(exchange.milliseconds())
|
||||||
|
print(datetime, orderbook['nonce'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
async def reload_markets(exchange, delay):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
await exchange.sleep(delay)
|
||||||
|
markets = await exchange.load_markets(True)
|
||||||
|
datetime = exchange.iso8601(exchange.milliseconds())
|
||||||
|
print(datetime, 'Markets reloaded')
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance()
|
||||||
|
await exchange.load_markets()
|
||||||
|
# exchange.verbose = True
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
delay = 60000 # every minute = 60 seconds = 60000 milliseconds
|
||||||
|
loops = [watch_order_book(exchange, symbol), reload_markets(exchange, delay)]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import gather, run
|
||||||
|
|
||||||
|
|
||||||
|
orderbooks = {}
|
||||||
|
|
||||||
|
|
||||||
|
def handle_all_orderbooks(orderbooks):
|
||||||
|
print('We have the following orderbooks:')
|
||||||
|
for id, orderbooks_by_symbol in orderbooks.items():
|
||||||
|
for symbol in orderbooks_by_symbol.keys():
|
||||||
|
orderbook = orderbooks_by_symbol[symbol]
|
||||||
|
print(ccxt.pro.Exchange.iso8601(orderbook['timestamp']), id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, id, symbol):
|
||||||
|
print('Starting', id, symbol)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
orderbooks[id] = orderbooks.get(id, {})
|
||||||
|
orderbooks[id][symbol] = orderbook
|
||||||
|
print('===========================================================')
|
||||||
|
#
|
||||||
|
# here you can do what you want
|
||||||
|
# with the most recent versions of each orderbook you have so far
|
||||||
|
#
|
||||||
|
# you can also wait until all of them are available
|
||||||
|
# by just looking into all the orderbooks and counting them
|
||||||
|
#
|
||||||
|
# we just print them here to keep this example simple
|
||||||
|
#
|
||||||
|
handle_all_orderbooks(orderbooks)
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def exchange_loop(id, config):
|
||||||
|
print('Starting', id)
|
||||||
|
exchange = getattr(ccxt.pro, config['id'])({
|
||||||
|
'options': config['options'],
|
||||||
|
})
|
||||||
|
loops = [symbol_loop(exchange, id, symbol) for symbol in config['symbols']]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
configs = {
|
||||||
|
'Exchange A (Binance spot)': {
|
||||||
|
'id': 'binance',
|
||||||
|
'symbols': ['BTC/USDT', 'ETH/BTC','ETH/USDT'],
|
||||||
|
'options': {
|
||||||
|
'defaultType': 'spot',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'Exchange B (Binance futures)': {
|
||||||
|
'id': 'binance',
|
||||||
|
'symbols': ['BTC/USDT', 'ETH/USDT'],
|
||||||
|
'options': {
|
||||||
|
'defaultType': 'future',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
loops = [exchange_loop(id, config) for id, config in configs.items()]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import ccxt.pro as ccxt
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
orderbooks = {}
|
||||||
|
|
||||||
|
def when_orderbook_changed(exchange_spot, symbol, orderbook):
|
||||||
|
# this is a common handler function
|
||||||
|
# it is called when any of the orderbook is updated
|
||||||
|
# it has access to both the orderbook that was updated
|
||||||
|
# as well as the rest of the orderbooks
|
||||||
|
# ...................................................................
|
||||||
|
print('-------------------------------------------------------------')
|
||||||
|
print('Last updated:', exchange_spot.iso8601(exchange_spot.milliseconds()))
|
||||||
|
# ...................................................................
|
||||||
|
# print just one orderbook here
|
||||||
|
# print(orderbook['datetime'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
# ...................................................................
|
||||||
|
# or print all orderbooks that have been already subscribed-to
|
||||||
|
for symbol, orderbook in orderbooks.items():
|
||||||
|
print(orderbook['datetime'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_one_orderbook(exchange_spot, symbol):
|
||||||
|
# a call cost of 1 in the queue of subscriptions
|
||||||
|
# means one subscription per exchange.rateLimit milliseconds
|
||||||
|
your_delay = 1
|
||||||
|
await exchange_spot.throttle(your_delay)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange_spot.watch_order_book(symbol)
|
||||||
|
orderbooks[symbol] = orderbook
|
||||||
|
when_orderbook_changed(exchange_spot, symbol, orderbook)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_some_orderbooks(exchange_spot, symbol_list):
|
||||||
|
loops = [watch_one_orderbook(exchange_spot, symbol) for symbol in symbol_list]
|
||||||
|
# let them run, don't for all tasks cause they execute asynchronously
|
||||||
|
# don't print here
|
||||||
|
await asyncio.gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange_spot = ccxt.binance()
|
||||||
|
await exchange_spot.load_markets()
|
||||||
|
await watch_some_orderbooks(exchange_spot, ['ZEN/USDT', 'RUNE/USDT', 'AAVE/USDT', 'SNX/USDT'])
|
||||||
|
await exchange_spot.close()
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from asyncio import run
|
||||||
|
import ccxt.pro as ccxt
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
# This example will run silent and will return your balance only when the balance is updated.
|
||||||
|
|
||||||
|
# 1. launch the example with your keys and keep it running
|
||||||
|
# 2. go to the margin trading on the website
|
||||||
|
# 3. place a margin order on a spot market
|
||||||
|
# 4. see your balance updated in the example
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
'options': {
|
||||||
|
'defaultType': 'margin',
|
||||||
|
},
|
||||||
|
# comment it out if you don't want debug output
|
||||||
|
# this is for the demo purpose only (to show the communication)
|
||||||
|
'verbose': True,
|
||||||
|
})
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
balance = await exchange.watch_balance()
|
||||||
|
# it will print the balance update when the balance changes
|
||||||
|
# if the balance remains unchanged the exchange will not send it
|
||||||
|
pprint(balance)
|
||||||
|
except Exception as e:
|
||||||
|
print('watch_balance() failed')
|
||||||
|
print(e)
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
print('CCXT Pro version', ccxt.pro.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
def table(values):
|
||||||
|
first = values[0]
|
||||||
|
keys = list(first.keys()) if isinstance(first, dict) else range(0, len(first))
|
||||||
|
widths = [max([len(str(v[k])) for v in values]) for k in keys]
|
||||||
|
string = ' | '.join(['{:<' + str(w) + '}' for w in widths])
|
||||||
|
return "\n".join([string.format(*[str(v[k]) for k in keys]) for v in values])
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance({
|
||||||
|
# 'options': {
|
||||||
|
# 'OHLCVLimit': 1000, # how many candles to store in memory by default
|
||||||
|
# },
|
||||||
|
})
|
||||||
|
symbol = 'ETH/USDT' # or BNB/USDT, etc...
|
||||||
|
timeframe = '1m' # 5m, 1h, 1d
|
||||||
|
limit = 10 # how many candles to return max
|
||||||
|
method = 'watchOHLCV'
|
||||||
|
if (method in exchange.has) and exchange.has[method]:
|
||||||
|
max_iterations = 100000 # how many times to repeat the loop before exiting
|
||||||
|
for i in range(0, max_iterations):
|
||||||
|
try:
|
||||||
|
ohlcvs = await exchange.watch_ohlcv(symbol, timeframe, None, limit)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print('\n===============================================================================')
|
||||||
|
print('Loop iteration:', i, 'current time:', exchange.iso8601(now), symbol, timeframe)
|
||||||
|
print('-------------------------------------------------------------------------------')
|
||||||
|
print(table([[exchange.iso8601(o[0])] + o[1:] for o in ohlcvs]))
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
else:
|
||||||
|
print(exchange.id, method, 'is not supported or not implemented yet')
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from asyncio import run
|
||||||
|
import ccxt.pro as ccxt
|
||||||
|
|
||||||
|
|
||||||
|
class MyBinance(ccxt.binance):
|
||||||
|
def handle_order_book_message(self, client, message, orderbook):
|
||||||
|
asks = self.safe_value(message, 'a', [])
|
||||||
|
bids = self.safe_value(message, 'b', [])
|
||||||
|
# printing high-frequency updates is a resource-heavy task
|
||||||
|
# this print statement is here just to demonstrate the work of it
|
||||||
|
# replace it with you logic for processing individual updates
|
||||||
|
print('Updates:', {
|
||||||
|
'asks': asks,
|
||||||
|
'bids': bids,
|
||||||
|
})
|
||||||
|
return super(MyBinance, self).handle_order_book_message(client, message, orderbook);
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = MyBinance()
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
print('Watching', exchange.id, symbol)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
# break # you can also break just this one loop if it fails
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run, gather
|
||||||
|
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'orderbook': None,
|
||||||
|
'balance': None,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def common_handler(exchange, symbol):
|
||||||
|
market = exchange.market(symbol)
|
||||||
|
base = market['base']
|
||||||
|
quote = market['quote']
|
||||||
|
balance = data['balance']
|
||||||
|
orderbook = data['orderbook']
|
||||||
|
if balance and orderbook:
|
||||||
|
total = balance['total']
|
||||||
|
tip = [ orderbook['asks'][0], orderbook['bids'][0] ]
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), symbol, 'orderbook:', tip, 'balance:', total)
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_order_book(exchange, symbol):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data['orderbook'] = await exchange.watch_order_book(symbol)
|
||||||
|
common_handler(exchange, symbol)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break # break this loop
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_balance(exchange, symbol):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data['balance'] = await exchange.watch_balance()
|
||||||
|
common_handler(exchange, symbol)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break # break this loop
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binance({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
})
|
||||||
|
await exchange.load_markets()
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loops = [
|
||||||
|
watch_order_book(exchange, symbol),
|
||||||
|
watch_balance(exchange, symbol)
|
||||||
|
]
|
||||||
|
await gather(*loops)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Python
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run, gather
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
async def place_delayed_order(exchange, symbol, amount, price):
|
||||||
|
try:
|
||||||
|
await exchange.sleep(5000) # wait a bit
|
||||||
|
order = await exchange.create_limit_buy_order(symbol, amount, price)
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), 'place_delayed_order')
|
||||||
|
pprint(order)
|
||||||
|
print('---------------------------------------------------------------')
|
||||||
|
except Exception as e:
|
||||||
|
# break
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_orders_loop(exchange, symbol):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orders = await exchange.watch_orders(symbol)
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), 'watch_orders_loop', len(orders), ' last orders cached')
|
||||||
|
print('---------------------------------------------------------------')
|
||||||
|
except Exception as e:
|
||||||
|
# break
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_balance_loop(exchange):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
balance = await exchange.watch_balance()
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), 'watch_balance_loop')
|
||||||
|
pprint(balance)
|
||||||
|
print('---------------------------------------------------------------')
|
||||||
|
except Exception as e:
|
||||||
|
# break
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.binanceusdm({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
})
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
amount = 0.001
|
||||||
|
price = 11111
|
||||||
|
loops = [
|
||||||
|
watch_orders_loop(exchange, symbol),
|
||||||
|
watch_balance_loop(exchange),
|
||||||
|
place_delayed_order(exchange, symbol, amount, price)
|
||||||
|
]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from asyncio import run, gather
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
sys.path.append(root + '/python')
|
||||||
|
|
||||||
|
import ccxt.pro # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
async def print_balance_continuously(exchange):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
print('-----------------------------------------------------------')
|
||||||
|
await exchange.load_markets()
|
||||||
|
balance = await exchange.watch_balance()
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), exchange.id)
|
||||||
|
for currency, value in balance['total'].items():
|
||||||
|
print(value, currency)
|
||||||
|
except Exception as e:
|
||||||
|
print('-----------------------------------------------------------')
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), exchange.id, type(e), e)
|
||||||
|
await exchange.sleep(300000) # sleep 5 minutes and retry
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
config = {
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
}
|
||||||
|
exchange_ids = [
|
||||||
|
'binance',
|
||||||
|
'binanceusdm',
|
||||||
|
'binancecoinm',
|
||||||
|
]
|
||||||
|
exchanges = [getattr(ccxt.pro, exchange_id)(config) for exchange_id in exchange_ids]
|
||||||
|
printing_loops = [print_balance_continuously(exchange) for exchange in exchanges]
|
||||||
|
await gather(*printing_loops)
|
||||||
|
closing_tasks = [exchange.close() for exchange in exchanges]
|
||||||
|
await gather(*closing_tasks)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
|
||||||
|
def table(values):
|
||||||
|
first = values[0]
|
||||||
|
keys = list(first.keys()) if isinstance(first, dict) else range(0, len(first))
|
||||||
|
widths = [max([len(str(v[k])) for v in values]) for k in keys]
|
||||||
|
string = ' | '.join(['{:<' + str(w) + '}' for w in widths])
|
||||||
|
return "\n".join([string.format(*[str(v[k]) for k in keys]) for v in values])
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.bitmex({
|
||||||
|
# 'options': {
|
||||||
|
# 'OHLCVLimit': 1000, # how many candles to store in memory by default
|
||||||
|
# },
|
||||||
|
})
|
||||||
|
symbol = 'BTC/USD'
|
||||||
|
timeframe = '1m' # 5m, 1h, 1d
|
||||||
|
limit = 10 # how many candles to return max
|
||||||
|
method = 'watchOHLCV'
|
||||||
|
if (method in exchange.has) and exchange.has[method]:
|
||||||
|
max_iterations = 100 # how many times to repeat the loop before exiting
|
||||||
|
for i in range(0, max_iterations):
|
||||||
|
try:
|
||||||
|
ohlcvs = await exchange.watch_ohlcv(symbol, timeframe, None, limit)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print('\n===============================================================================')
|
||||||
|
print('Loop iteration:', i, 'current time:', exchange.iso8601(now), symbol, timeframe)
|
||||||
|
print('-------------------------------------------------------------------------------')
|
||||||
|
print(table([[exchange.iso8601(o[0])] + o[1:] for o in ohlcvs]))
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
else:
|
||||||
|
print(exchange.id, method, 'is not supported or not implemented yet')
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run, gather
|
||||||
|
|
||||||
|
|
||||||
|
def table(values):
|
||||||
|
first = values[0]
|
||||||
|
keys = list(first.keys()) if isinstance(first, dict) else range(0, len(first))
|
||||||
|
widths = [max([len(str(v[k])) for v in values]) for k in keys]
|
||||||
|
string = ' | '.join(['{:<' + str(w) + '}' for w in widths])
|
||||||
|
return "\n".join([string.format(*[str(v[k]) for k in keys]) for v in values])
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_ticker(color, duration, exchange, symbol):
|
||||||
|
method = 'watchTicker'
|
||||||
|
if (method in exchange.has) and exchange.has[method]:
|
||||||
|
start = exchange.milliseconds()
|
||||||
|
i = 1
|
||||||
|
while True:
|
||||||
|
ticker = await exchange.watch_ticker(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
# start color code
|
||||||
|
print(color, 'Ticker ========================================================================')
|
||||||
|
print(exchange.iso8601(now), symbol, 'iteration:', i, 'last price:', ticker['last'])
|
||||||
|
print('-------------------------------------------------------------------------------')
|
||||||
|
# pprint.pprint(ticker) # uncomment for a lengthy complete printout
|
||||||
|
print('\x1b[0m') # stop color code
|
||||||
|
i += 1
|
||||||
|
if (start + duration) < now:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise Exception(exchange.id + ' ' + method + ' is not supported or not implemented yet')
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_ohlcv(color, duration, exchange, symbol, timeframe, limit):
|
||||||
|
method = 'watchOHLCV'
|
||||||
|
if (method in exchange.has) and exchange.has[method]:
|
||||||
|
start = exchange.milliseconds()
|
||||||
|
i = 1
|
||||||
|
while True:
|
||||||
|
ohlcvs = await exchange.watch_ohlcv(symbol, timeframe, None, limit)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
# start color code
|
||||||
|
print(color, 'OHLCV =========================================================================')
|
||||||
|
print(exchange.iso8601(now), symbol, timeframe, 'iteration:', i)
|
||||||
|
print('-------------------------------------------------------------------------------')
|
||||||
|
print(table([[exchange.iso8601(o[0])] + o[1:] for o in ohlcvs]))
|
||||||
|
print('\x1b[0m') # stop color code
|
||||||
|
i += 1
|
||||||
|
if (start + duration) < now:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise Exception(exchange.id + ' ' + method + ' is not supported or not implemented yet')
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.bitmex()
|
||||||
|
await exchange.load_markets()
|
||||||
|
duration = 1200000 # run 20 minutes = 1200000 milliseconds
|
||||||
|
symbol = 'BTC/USD'
|
||||||
|
limit = 10
|
||||||
|
loops = [
|
||||||
|
watch_ticker('\033[35m', duration, exchange, symbol), # magenta
|
||||||
|
watch_ohlcv('\x1b[33m', duration, exchange, symbol, '1m', limit), # yellow
|
||||||
|
watch_ohlcv('\x1b[32m', duration, exchange, symbol, '5m', limit), # green
|
||||||
|
]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Pro version', ccxt.pro.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.bitvavo()
|
||||||
|
await exchange.load_markets()
|
||||||
|
exchange.verbose = True
|
||||||
|
symbol = 'BTC/EUR'
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
print(orderbook['nonce'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import asyncio
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
async def loop(exchange, symbol, timeframe, complete_candles_only=False):
|
||||||
|
duration_in_seconds = exchange.parse_timeframe(timeframe)
|
||||||
|
duration_in_ms = duration_in_seconds * 1000
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
trades = await exchange.watch_trades(symbol)
|
||||||
|
if len(trades) > 0:
|
||||||
|
current_minute = int(exchange.milliseconds() / duration_in_ms)
|
||||||
|
ohlcvc = exchange.build_ohlcvc(trades, timeframe)
|
||||||
|
if complete_candles_only:
|
||||||
|
ohlcvc = [candle for candle in ohlcvc if int(candle[0] / duration_in_ms) < current_minute]
|
||||||
|
if len(ohlcvc) > 0:
|
||||||
|
print('-----------------------------------------------------------')
|
||||||
|
print("Symbol:", symbol, "timeframe:", timeframe)
|
||||||
|
print(ohlcvc)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"{type(e).__name__}: {(str(e))}")
|
||||||
|
# raise type(e)(str(e)) # uncomment to break all loops in case of an error in any one of them
|
||||||
|
# break # you can also break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
# select the exchange
|
||||||
|
exchange = ccxt.pro.binance()
|
||||||
|
if exchange.has['watchTrades']:
|
||||||
|
markets = await exchange.load_markets()
|
||||||
|
# Change this value accordingly
|
||||||
|
timeframe = '1m'
|
||||||
|
limit = 5
|
||||||
|
selected_symbols = list(markets.values())[:limit]
|
||||||
|
# you can also specify the symbols manually
|
||||||
|
# selected_symbols = ['BTC/USDT', 'ETH/USDT']
|
||||||
|
|
||||||
|
# Use this variable to choose if only complete candles
|
||||||
|
# should be considered
|
||||||
|
complete_candles_only = True
|
||||||
|
await asyncio.gather(*[loop(exchange, symbol['symbol'], timeframe, complete_candles_only)
|
||||||
|
for symbol in selected_symbols])
|
||||||
|
await exchange.close()
|
||||||
|
else:
|
||||||
|
print(exchange.id, 'does not support watchTrades yet')
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.coinbase()
|
||||||
|
method = 'watchTrades'
|
||||||
|
print('CCXT Pro version', ccxt.pro.__version__)
|
||||||
|
if exchange.has[method]:
|
||||||
|
last_id = ''
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
trades = await exchange.watch_trades('BTC/USD')
|
||||||
|
for trade in trades:
|
||||||
|
if trade['id'] > last_id:
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), trade['symbol'], trade['datetime'], trade['price'], trade['amount'])
|
||||||
|
last_id = trade['id']
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# stop
|
||||||
|
await exchange.close()
|
||||||
|
raise e
|
||||||
|
# or retry
|
||||||
|
# pass
|
||||||
|
else:
|
||||||
|
raise Exception(exchange.id + ' ' + method + ' is not supported or not implemented yet')
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.coinbase()
|
||||||
|
method = 'watchTrades'
|
||||||
|
print('CCXT Pro version', ccxt.pro.__version__)
|
||||||
|
if exchange.has[method]:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
trades = await exchange.watch_trades('BTC/USD')
|
||||||
|
num_trades = len(trades)
|
||||||
|
trade = trades[-1]
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), trade['symbol'], trade['datetime'], trade['price'], trade['amount'], 'stored', num_trades, 'trades in cache')
|
||||||
|
except Exception as e:
|
||||||
|
# stop
|
||||||
|
await exchange.close()
|
||||||
|
raise e
|
||||||
|
# or retry
|
||||||
|
# pass
|
||||||
|
else:
|
||||||
|
raise Exception(exchange.id + ' ' + method + ' is not supported or not implemented yet')
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
|
||||||
|
async def consume_all_trades(exchange, symbol):
|
||||||
|
await exchange.load_markets()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
trades = await exchange.watch_trades(symbol)
|
||||||
|
print('----------------------------------------------------------------------')
|
||||||
|
print(exchange.iso8601(exchange.milliseconds()), 'received', len(trades), 'new', symbol, 'trades:')
|
||||||
|
for trade in trades:
|
||||||
|
print(exchange.id, symbol, trade['id'], trade['datetime'], trade['amount'], trade['price'])
|
||||||
|
exchange.trades[symbol].clear()
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
exchange = ccxt.pro.bitmex()
|
||||||
|
symbol = 'BTC/USD'
|
||||||
|
run(consume_all_trades(exchange, symbol))
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
async def loop(exchange, symbol):
|
||||||
|
since = datetime.utcnow()
|
||||||
|
timestamp = int(since.timestamp() * 1000)
|
||||||
|
while True:
|
||||||
|
trades = await exchange.watch_trades(symbol, since=timestamp)
|
||||||
|
print('--------------------------------------------------------------')
|
||||||
|
print('Received', len(trades), 'after', exchange.iso8601 (timestamp))
|
||||||
|
print('waiting for next update...')
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.gateio()
|
||||||
|
await loop(exchange, 'BTC/USDT')
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from asyncio import run
|
||||||
|
import ccxt.pro
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
class MyBinance(ccxt.pro.binance):
|
||||||
|
def handle_ohlcv(self, client, message):
|
||||||
|
# add your handling of the original message here
|
||||||
|
print('intercepted', message)
|
||||||
|
return super(MyBinance, self).handle_ohlcv(client, message)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = MyBinance()
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
print('Watching', exchange.id, symbol)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
ohlcv = await exchange.watch_ohlcv(symbol, '1m')
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
# break # you can also break just this one loop if it fails
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import gather, run
|
||||||
|
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, symbol):
|
||||||
|
print('Starting the', exchange.id, 'symbol loop with', symbol)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print(exchange.iso8601(now), exchange.id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.kucoin({
|
||||||
|
"apiKey": "YOUR_API_KEY",
|
||||||
|
"secret": "YOUR_API_SECRET",
|
||||||
|
"password": "YOUR_API_PASSWORD",
|
||||||
|
})
|
||||||
|
symbols = ['KDA/USDT', 'KDA/BTC', 'BTC/USDT']
|
||||||
|
loops = [symbol_loop(exchange, symbol) for symbol in symbols]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import gather, run
|
||||||
|
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, method, symbol):
|
||||||
|
print('Starting', exchange.id, method, symbol)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
response = await getattr(exchange, method)(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
iso8601 = exchange.iso8601(now)
|
||||||
|
if method == 'watchOrderBook':
|
||||||
|
print(iso8601, exchange.id, method, symbol, response['asks'][0], response['bids'][0])
|
||||||
|
elif method == 'watchTicker':
|
||||||
|
print(iso8601, exchange.id, method, symbol, response['high'], response['low'], response['bid'], response['ask'])
|
||||||
|
elif method == 'watchTrades':
|
||||||
|
print(iso8601, exchange.id, method, symbol, len(response), 'trades')
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def method_loop(exchange, method, symbols):
|
||||||
|
print('Starting', exchange.id, method, symbols)
|
||||||
|
loops = [symbol_loop(exchange, method, symbol) for symbol in symbols]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
async def exchange_loop(exchange_id, methods):
|
||||||
|
print('Starting', exchange_id, methods)
|
||||||
|
exchange = getattr(ccxt.pro, exchange_id)()
|
||||||
|
loops = [method_loop(exchange, method, symbols) for method, symbols in methods.items()]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchanges = {
|
||||||
|
'okex': {
|
||||||
|
'watchOrderBook': ['BTC/USDT', 'ETH/BTC', 'ETH/USDT'],
|
||||||
|
'watchTicker': ['BTC/USDT'],
|
||||||
|
},
|
||||||
|
'binance': {
|
||||||
|
'watchOrderBook': ['BTC/USDT', 'ETH/BTC'],
|
||||||
|
'watchTrades': [ 'ETH/BTC' ],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
loops = [exchange_loop(exchange_id, methods) for exchange_id, methods in exchanges.items()]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
|
||||||
|
orderbooks = {}
|
||||||
|
|
||||||
|
|
||||||
|
def handle_all_orderbooks(orderbooks):
|
||||||
|
print('We have the following orderbooks:')
|
||||||
|
for exchange_id, orderbooks_by_symbol in orderbooks.items():
|
||||||
|
for symbol in orderbooks_by_symbol.keys():
|
||||||
|
orderbook = orderbooks_by_symbol[symbol]
|
||||||
|
print(ccxt.pro.Exchange.iso8601(orderbook['timestamp']), exchange_id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, symbol):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
orderbooks[exchange.id] = orderbooks.get(exchange.id, {})
|
||||||
|
orderbooks[exchange.id][symbol] = orderbook
|
||||||
|
print('===========================================================')
|
||||||
|
#
|
||||||
|
# here you can do what you want
|
||||||
|
# with the most recent versions of each orderbook you have so far
|
||||||
|
#
|
||||||
|
# you can also wait until all of them are available
|
||||||
|
# by just looking into all the orderbooks and counting them
|
||||||
|
#
|
||||||
|
# we just print them here to keep this example simple
|
||||||
|
#
|
||||||
|
handle_all_orderbooks(orderbooks)
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def exchange_loop(exchange_id, symbols):
|
||||||
|
exchange = getattr(ccxt.pro, exchange_id)()
|
||||||
|
loops = [symbol_loop(exchange, symbol) for symbol in symbols]
|
||||||
|
await asyncio.gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
symbols = ['BTC/USDT', 'ETH/BTC']
|
||||||
|
# symbols = []
|
||||||
|
exchanges = {
|
||||||
|
'okex': symbols + ['ETH/USDT'],
|
||||||
|
'binance': symbols,
|
||||||
|
}
|
||||||
|
loops = [exchange_loop(exchange_id, symbols) for exchange_id, symbols in exchanges.items()]
|
||||||
|
await asyncio.gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run, gather, sleep
|
||||||
|
|
||||||
|
|
||||||
|
orderbooks = {}
|
||||||
|
|
||||||
|
|
||||||
|
def handle_all_orderbooks(orderbooks):
|
||||||
|
print('We have the following orderbooks:')
|
||||||
|
for exchange_id, orderbooks_by_symbol in orderbooks.items():
|
||||||
|
for symbol in orderbooks_by_symbol.keys():
|
||||||
|
orderbook = orderbooks_by_symbol[symbol]
|
||||||
|
print(ccxt.pro.Exchange.iso8601(orderbook['timestamp']), exchange_id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
|
||||||
|
|
||||||
|
async def handling_loop(orderbooks):
|
||||||
|
delay = 5
|
||||||
|
while True:
|
||||||
|
await sleep(delay)
|
||||||
|
handle_all_orderbooks(orderbooks)
|
||||||
|
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, symbol):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
orderbooks[exchange.id] = orderbooks.get(exchange.id, {})
|
||||||
|
orderbooks[exchange.id][symbol] = orderbook
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def exchange_loop(exchange_id, symbols):
|
||||||
|
exchange = getattr(ccxt.pro, exchange_id)()
|
||||||
|
loops = [symbol_loop(exchange, symbol) for symbol in symbols]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
symbols = ['BTC/USDT', 'ETH/BTC']
|
||||||
|
# symbols = []
|
||||||
|
exchanges = {
|
||||||
|
'okex': symbols + ['ETH/USDT'],
|
||||||
|
'binance': symbols,
|
||||||
|
}
|
||||||
|
loops = [exchange_loop(exchange_id, symbols) for exchange_id, symbols in exchanges.items()]
|
||||||
|
loops += [handling_loop(orderbooks)]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import gather, run
|
||||||
|
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, method, symbol):
|
||||||
|
print('Starting', exchange.id, method, symbol)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
response = await getattr(exchange, method)(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
iso8601 = exchange.iso8601(now)
|
||||||
|
if method == 'watchOrderBook':
|
||||||
|
print(iso8601, exchange.id, method, symbol, response['asks'][0], response['bids'][0])
|
||||||
|
elif method == 'watchTicker':
|
||||||
|
print(iso8601, exchange.id, method, symbol, response['high'], response['low'], response['bid'], response['ask'])
|
||||||
|
elif method == 'watchTrades':
|
||||||
|
print(iso8601, exchange.id, method, symbol, len(response), 'trades')
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def symbols_method_loop(exchange, method, symbols):
|
||||||
|
print('Starting', exchange.id, method, symbols)
|
||||||
|
loops = [symbol_loop(exchange, method, symbol) for symbol in symbols]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
async def method_loop(exchange, method):
|
||||||
|
print('Starting', exchange.id, method)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
response = await getattr(exchange, method)()
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
iso8601 = exchange.iso8601(now)
|
||||||
|
print(iso8601, exchange.id, method, response)
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def exchange_loop(exchange_id, methods, config={}):
|
||||||
|
print('Starting', exchange_id, methods)
|
||||||
|
exchange = getattr(ccxt.pro, exchange_id)()
|
||||||
|
for attr, value in config.items():
|
||||||
|
setattr(exchange, attr, value)
|
||||||
|
loops = [symbols_method_loop(exchange, method, symbols) if len(symbols) else method_loop(exchange, method) for method, symbols in methods.items()]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
keys = {
|
||||||
|
'okex': {
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
},
|
||||||
|
'binance': {
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
exchanges = {
|
||||||
|
'okex': {
|
||||||
|
'watchOrderBook': ['BTC/USDT', 'ETH/BTC', 'ETH/USDT'],
|
||||||
|
'watchTicker': ['BTC/USDT'],
|
||||||
|
'watchBalance': [],
|
||||||
|
},
|
||||||
|
'binance': {
|
||||||
|
'watchOrderBook': ['BTC/USDT', 'ETH/BTC'],
|
||||||
|
'watchTrades': [ 'ETH/BTC' ],
|
||||||
|
'watchBalance': [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
loops = [exchange_loop(exchange_id, methods, keys.get(exchange_id, {})) for exchange_id, methods in exchanges.items()]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import gather, run
|
||||||
|
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, symbol):
|
||||||
|
print('Starting the', exchange.id, 'symbol loop with', symbol)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print(exchange.iso8601(now), exchange.id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
async def exchange_loop(exchange_id, symbols):
|
||||||
|
print('Starting the', exchange_id, 'exchange loop with', symbols)
|
||||||
|
exchange = getattr(ccxt.pro, exchange_id)()
|
||||||
|
loops = [symbol_loop(exchange, symbol) for symbol in symbols]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchanges = {
|
||||||
|
'okex': ['BTC/USDT', 'ETH/BTC', 'ETH/USDT'],
|
||||||
|
'binance': ['BTC/USDT', 'ETH/BTC'],
|
||||||
|
}
|
||||||
|
loops = [exchange_loop(exchange_id, symbols) for exchange_id, symbols in exchanges.items()]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
from asyncio import gather, run
|
||||||
|
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, symbol):
|
||||||
|
print('Starting the', exchange.id, 'symbol loop with', symbol)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
trades = await exchange.watch_trades(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print(exchange.iso8601(now), exchange.id, symbol, len(trades), trades[-1]['price'])
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def exchange_loop(exchange_id, symbols):
|
||||||
|
print('Starting the', exchange_id, 'exchange loop with', symbols)
|
||||||
|
exchange = getattr(ccxt.pro, exchange_id)({
|
||||||
|
'newUpdates': True, # https://github.com/ccxt/ccxt/wiki/ccxt.pro.manual#incremental-data-structures
|
||||||
|
})
|
||||||
|
loops = [symbol_loop(exchange, symbol) for symbol in symbols]
|
||||||
|
await gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchanges = {
|
||||||
|
'okex': ['BTC/USDT', 'ETH/BTC', 'ETH/USDT'],
|
||||||
|
'binance': ['BTC/USDT', 'ETH/BTC'],
|
||||||
|
}
|
||||||
|
loops = [exchange_loop(exchange_id, symbols) for exchange_id, symbols in exchanges.items()]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
|
||||||
|
async def loop(exchange_id, symbol):
|
||||||
|
exchange = getattr(ccxt.pro, exchange_id)()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print(exchange.iso8601(now), exchange.id, symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
symbols = {
|
||||||
|
'kraken': 'BTC/USDT',
|
||||||
|
'binance': 'BTC/USDT',
|
||||||
|
'bitmex': 'XBT_USDT',
|
||||||
|
}
|
||||||
|
await asyncio.gather(*[loop(exchange_id, symbol) for exchange_id, symbol in symbols.items()])
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_book(exchange, ticker):
|
||||||
|
last = None
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(ticker)
|
||||||
|
# TODO add timeout within a minute
|
||||||
|
# TODO add last
|
||||||
|
top_bid = orderbook['bids'][0][0]
|
||||||
|
if last != top_bid:
|
||||||
|
print(f'{int(time.time() * 1000)} top bid for celo on {exchange.name} is {top_bid}')
|
||||||
|
last = top_bid
|
||||||
|
except Exception as e:
|
||||||
|
print(f'{exchange.name} failed {type(e)} {e}')
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange_ids = ['coinbasepro', 'okcoin', 'bittrex']
|
||||||
|
exchanges = [getattr(ccxt.pro, exchange_id)() for exchange_id in exchange_ids]
|
||||||
|
try:
|
||||||
|
done, pending = await asyncio.wait({watch_book(exchange, 'CELO/USD') for exchange in exchanges}, return_when=asyncio.FIRST_EXCEPTION)
|
||||||
|
for completed in done:
|
||||||
|
# trigger the exception here
|
||||||
|
completed.result()
|
||||||
|
except Exception as e:
|
||||||
|
print(f'closing all exchanges because of exception {type(e)} {e}')
|
||||||
|
await asyncio.gather(*[exchange.close() for exchange in exchanges])
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from asyncio import run
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Pro Version: ', ccxt.pro.__version__)
|
||||||
|
|
||||||
|
exchange = ccxt.pro.okex({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_API_SECRET',
|
||||||
|
'password': 'YOUR_API_PASSWORD',
|
||||||
|
'options': { 'defaultType': 'swap' },
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
await exchange.load_markets()
|
||||||
|
# exchange.verbose = True # uncomment for debugging
|
||||||
|
|
||||||
|
# https://github.com/ccxt/ccxt/wiki/Manual#overriding-unified-params
|
||||||
|
# https://www.okex.com/docs/en/#swap-swap---orders
|
||||||
|
|
||||||
|
symbol = 'BTC/USDT:USDT'
|
||||||
|
amount = 1 # how may contracts
|
||||||
|
price = None # or your limit price
|
||||||
|
side = 'buy' # or 'sell'
|
||||||
|
future_type = '1' # 1 open long, 2 open short, 3 close long, 4 close short for futures
|
||||||
|
order_type = '4' # 0 = limit order, 4 = market order
|
||||||
|
|
||||||
|
try:
|
||||||
|
# open long market price order
|
||||||
|
order = await exchange.create_order(symbol, 'market', side, amount, price, {'type': future_type})
|
||||||
|
# --------------------------------------------------------------------
|
||||||
|
# open long market price order
|
||||||
|
# const order = await exchange.create_order(symbol, type, side, amount, price, {'order_type': order_type})
|
||||||
|
# --------------------------------------------------------------------
|
||||||
|
# close short market price order
|
||||||
|
# const order = await exchange.create_order(symbol, 'market', side, amount, price, {'type': future_type, 'order_type': order_type})
|
||||||
|
# --------------------------------------------------------------------
|
||||||
|
# close short market price order
|
||||||
|
# const order = await exchange.create_order(symbol, '4', side, amount, price, {'order_type': order_type})
|
||||||
|
# ...
|
||||||
|
print(order)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import ccxt.pro as ccxt
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.okex({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
# okex requires this: https://github.com/ccxt/ccxt/wiki/Manual#authentication
|
||||||
|
'password': 'YOUR_API_PASSWORD',
|
||||||
|
# comment it out if you don't want debug output
|
||||||
|
# this is for the demo purpose only (to show the communication)
|
||||||
|
'verbose': True,
|
||||||
|
})
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
balance = await exchange.watch_balance({
|
||||||
|
# okex watch_balance requires a symbol or an instrument_id
|
||||||
|
'symbol': 'BTC/USDT',
|
||||||
|
'type': 'margin',
|
||||||
|
})
|
||||||
|
# it will print the balance update when the balance changes
|
||||||
|
# if the balance remains unchanged the exchange will not send it
|
||||||
|
pprint(balance)
|
||||||
|
except Exception as e:
|
||||||
|
print('watch_balance() failed')
|
||||||
|
print(e)
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import ccxt.pro as ccxt
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.okex({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
# okex requires this: https://github.com/ccxt/ccxt/wiki/Manual#authentication
|
||||||
|
'password': 'YOUR_API_PASSWORD',
|
||||||
|
'options': {
|
||||||
|
'watchBalance': 'margin',
|
||||||
|
},
|
||||||
|
# comment it out if you don't want debug output
|
||||||
|
# this is for the demo purpose only (to show the communication)
|
||||||
|
'verbose': True,
|
||||||
|
})
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
balance = await exchange.watch_balance({
|
||||||
|
# okex watch_balance requires a symbol or an instrument_id
|
||||||
|
'symbol': 'BTC/USDT',
|
||||||
|
})
|
||||||
|
# it will print the balance update when the balance changes
|
||||||
|
# if the balance remains unchanged the exchange will not send it
|
||||||
|
pprint(balance)
|
||||||
|
except Exception as e:
|
||||||
|
print('watch_balance() failed')
|
||||||
|
print(e)
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Pro version', ccxt.pro.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.okx({
|
||||||
|
'options': {
|
||||||
|
'watchOrderBook': {
|
||||||
|
'depth': 'bbo-tbt', # tick-by-tick best bidask
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
markets = await exchange.load_markets()
|
||||||
|
# exchange.verbose = True # uncomment for debugging purposes if necessary
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# use this:
|
||||||
|
# orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
# print(orderbook['datetime'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# or this:
|
||||||
|
ticker = await exchange.watch_ticker(symbol)
|
||||||
|
print(ticker['datetime'], symbol, [ticker['ask'], ticker['askVolume']], [ticker['bid'], ticker['bidVolume']])
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run, ensure_future
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
# on_connected() is called when a client connection is established
|
||||||
|
# note that the exchange will reuse the same client connection
|
||||||
|
# some exchanges might require two or more public/private connections
|
||||||
|
# therefore on_connected() may be called more than once
|
||||||
|
|
||||||
|
class MyBinance(ccxt.pro.binance):
|
||||||
|
def on_connected(self, client, message=None):
|
||||||
|
print('Connected to', client.url)
|
||||||
|
ensure_future(create_order(self))
|
||||||
|
|
||||||
|
|
||||||
|
async def create_order(exchange):
|
||||||
|
symbol = 'BTC/USDT'
|
||||||
|
type = 'limit'
|
||||||
|
side = 'buy'
|
||||||
|
amount = 123.45 # change for your values
|
||||||
|
price = 54.321 # change for your values
|
||||||
|
params = {}
|
||||||
|
try:
|
||||||
|
order = await exchange.create_order(symbol, type, side, amount, price, params)
|
||||||
|
print('--------------------------------------------------------------')
|
||||||
|
print('create_order():')
|
||||||
|
pprint(order)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_orders(exchange):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orders = await exchange.watch_orders()
|
||||||
|
print('--------------------------------------------------------------')
|
||||||
|
print('watch_orders():')
|
||||||
|
pprint(orders)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
exchange = MyBinance({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
run(watch_orders(exchange))
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_order_book(exchange, symbol):
|
||||||
|
while True:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
print(orderbook['datetime'], symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_trades(exchange, symbol):
|
||||||
|
while True:
|
||||||
|
trades = await exchange.watch_trades(symbol)
|
||||||
|
last = trades[-1]
|
||||||
|
print(last['datetime'], last['price'], last['amount'])
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.bitstamp()
|
||||||
|
await exchange.load_markets()
|
||||||
|
symbol = 'BTC/USD'
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loops = [
|
||||||
|
watch_order_book(exchange, symbol),
|
||||||
|
watch_trades(exchange, symbol)
|
||||||
|
]
|
||||||
|
await asyncio.gather(*loops)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
break
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from asyncio import run
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
async def loop(exchange, symbol):
|
||||||
|
await exchange.throttle(10)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print(exchange.iso8601(now), symbol, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
# break # you can also break just this one loop if it fails
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.ftx()
|
||||||
|
symbols = ['BTC/USDT', 'ETH/USDT', 'ETH/BTC']
|
||||||
|
await asyncio.gather(*[loop(exchange, symbol) for symbol in symbols])
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import ccxt.pro
|
||||||
|
from asyncio import run
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.phemex({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_SECRET',
|
||||||
|
})
|
||||||
|
markets = await exchange.load_markets()
|
||||||
|
# exchange.verbose = True # uncomment for debugging purposes if necessary
|
||||||
|
try:
|
||||||
|
symbol = 'UNI/USDT'
|
||||||
|
response = await exchange.cancel_all_orders(symbol)
|
||||||
|
pprint(response)
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||||
|
sys.path.append(root + '/python')
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.pro.__version__)
|
||||||
|
|
||||||
|
orderbooks = {}
|
||||||
|
|
||||||
|
def handle_all_orderbooks(exchange, orderbooks, spot, future):
|
||||||
|
if spot in orderbooks and future in orderbooks:
|
||||||
|
spot_order_book = orderbooks[spot]
|
||||||
|
future_order_book = orderbooks[future]
|
||||||
|
timestamp = exchange.milliseconds()
|
||||||
|
spot_lag = abs(timestamp - spot_order_book['timestamp']) if spot_order_book['timestamp'] else 10000
|
||||||
|
future_lag = abs(timestamp - future_order_book['timestamp']) if future_order_book['timestamp'] else 10000
|
||||||
|
if spot_lag >= 10000 or future_lag >= 10000:
|
||||||
|
print('Lag > 10 seconds')
|
||||||
|
|
||||||
|
async def symbol_loop(exchange, symbol, spot, future):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
orderbooks[symbol] = orderbook
|
||||||
|
print(exchange.id, '{:13s}'.format(symbol), orderbook['datetime'], orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
#
|
||||||
|
# here you can do what you want
|
||||||
|
# with the most recent versions of each orderbook you have so far
|
||||||
|
#
|
||||||
|
# you can also wait until all of them are available
|
||||||
|
# by just looking into all the orderbooks and counting them
|
||||||
|
#
|
||||||
|
# we just print them here to keep this example simple
|
||||||
|
#
|
||||||
|
handle_all_orderbooks(exchange, orderbooks, spot, future)
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
spot = 'BTC/USDT'
|
||||||
|
future = 'BTC/USDT:USDT'
|
||||||
|
symbols = [ spot, future ]
|
||||||
|
exchange = ccxt.pro.bitmart()
|
||||||
|
loops = [
|
||||||
|
symbol_loop(exchange, spot, spot, future),
|
||||||
|
symbol_loop(exchange, future, spot, future),
|
||||||
|
]
|
||||||
|
await asyncio.gather(*loops)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
|
||||||
|
async def loop(exchange, symbol, n):
|
||||||
|
i = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
orderbook = await exchange.watch_order_book(symbol)
|
||||||
|
# print every 100th bidask to avoid wasting CPU cycles on printing
|
||||||
|
if not i % 100:
|
||||||
|
# i = how many updates there were in total
|
||||||
|
# n = the number of the pair to count subscriptions
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print(exchange.iso8601(now), n, symbol, i, orderbook['asks'][0], orderbook['bids'][0])
|
||||||
|
i += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
# break # you can also break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = ccxt.pro.kraken()
|
||||||
|
await exchange.load_markets()
|
||||||
|
markets = list(exchange.markets.values())
|
||||||
|
symbols = [market['symbol'] for market in markets if not market['darkpool']]
|
||||||
|
await asyncio.gather(*[loop(exchange, symbol, n) for n, symbol in enumerate(symbols)])
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import asyncio
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
|
||||||
|
class MyBinance(ccxt.pro.binance):
|
||||||
|
|
||||||
|
def handle_mini_ticker(self, client, message):
|
||||||
|
market_id = self.safe_string_lower(message, 's')
|
||||||
|
message_hash = market_id + '@miniTicker'
|
||||||
|
client.resolve(message, message_hash)
|
||||||
|
|
||||||
|
def handle_message(self, client, message):
|
||||||
|
handlers = {
|
||||||
|
'24hrMiniTicker': self.handle_mini_ticker,
|
||||||
|
# add other custom handlers here
|
||||||
|
}
|
||||||
|
e = self.safe_string(message, 'e')
|
||||||
|
method = self.safe_value(handlers, e)
|
||||||
|
if method:
|
||||||
|
return method(client, message)
|
||||||
|
else:
|
||||||
|
return super(MyBinance, self).handle_message(client, message)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchange = MyBinance({
|
||||||
|
'enableRateLimit': False,
|
||||||
|
'options': {
|
||||||
|
'defaultType': 'future'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
await exchange.load_markets()
|
||||||
|
# exchange.verbose = True # uncomment for debugging purposes
|
||||||
|
market = exchange.market('BTC/USDT')
|
||||||
|
message_hash = market['lowercaseId'] + '@miniTicker'
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
print(await exchange.watch_public(message_hash))
|
||||||
|
except Exception as e:
|
||||||
|
print(type(e).__name__, str(e))
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
asyncio.run(main())
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from asyncio import run, gather
|
||||||
|
import ccxt.pro
|
||||||
|
|
||||||
|
|
||||||
|
print('CCXT Version:', ccxt.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
async def exchange_loop(exchange_id, symbols):
|
||||||
|
exchange = getattr(ccxt.pro, exchange_id)()
|
||||||
|
markets = await exchange.load_markets()
|
||||||
|
await gather(*[watch_ticker_loop(exchange, symbol) for symbol in symbols])
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_ticker_loop(exchange, symbol):
|
||||||
|
# exchange.verbose = True # uncomment for debugging purposes if necessary
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
ticker = await exchange.watch_ticker(symbol)
|
||||||
|
now = exchange.milliseconds()
|
||||||
|
print(exchange.iso8601(now), exchange.id, symbol, 'bid:', ticker['bid'], 'ask:', ticker['ask'], 'last:', ticker['last'], 'on', ticker['datetime'])
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
# raise e # uncomment to break all loops in case of an error in any one of them
|
||||||
|
break # you can break just this one loop if it fails
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchanges = {
|
||||||
|
'binance': [ 'BTC/USDT', 'ETH/USDT' ],
|
||||||
|
'ftx': [ 'BTC/USD', 'ETH/USD' ],
|
||||||
|
}
|
||||||
|
loops = [exchange_loop(exchange_id, symbols) for exchange_id, symbols in exchanges.items()]
|
||||||
|
await gather(*loops)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from asyncio import gather, run
|
||||||
|
import ccxt.pro
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_ticker_continuously(exchange, symbol):
|
||||||
|
filename = exchange.id + '-' + symbol.replace('/', '-') + '.csv'
|
||||||
|
print('Watching', exchange.id, symbol, filename)
|
||||||
|
keys = ['index', 'exchange', 'symbol', 'timestamp', 'open', 'high', 'low', 'close', 'baseVolume']
|
||||||
|
with open(filename, 'w') as file:
|
||||||
|
file.write(','.join(keys) + "\n")
|
||||||
|
index = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
ticker = await exchange.watch_ticker(symbol)
|
||||||
|
values = [str(index), exchange.id] + [str(ticker[key]) for key in keys[2:]]
|
||||||
|
print(*values)
|
||||||
|
with open(filename, 'a') as file:
|
||||||
|
file.write(','.join(values) + "\n")
|
||||||
|
index += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
|
async def watch_tickers_continuously(exchange_id, overrides, symbols):
|
||||||
|
exchange_class = getattr(ccxt.pro, exchange_id)
|
||||||
|
exchange = exchange_class(overrides)
|
||||||
|
coroutines = [watch_ticker_continuously(exchange, symbol) for symbol in symbols]
|
||||||
|
await gather(*coroutines)
|
||||||
|
await exchange.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
exchanges = {
|
||||||
|
'binance': {'options': {'defaultType': 'future'}},
|
||||||
|
'huobipro': {}
|
||||||
|
}
|
||||||
|
symbols = ['BTC/USDT', 'ETH/USDT', 'LTC/USDT', 'XRP/USDT', 'BCH/USDT']
|
||||||
|
coroutines = [watch_tickers_continuously(exchange_id, exchanges[exchange_id], symbols) for exchange_id in exchanges.keys()]
|
||||||
|
return await gather(*coroutines)
|
||||||
|
|
||||||
|
|
||||||
|
run(main())
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", function () {
|
||||||
|
|
||||||
|
alert ('ccxt version ' + ccxt.version);
|
||||||
|
|
||||||
|
const exchange = new ccxt.bittrex ({
|
||||||
|
'proxyUrl': 'https://cors-anywhere.herokuapp.com/'
|
||||||
|
})
|
||||||
|
|
||||||
|
const symbol = 'BTC/USDT'
|
||||||
|
|
||||||
|
exchange.fetchTicker (symbol).then (ticker => {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
exchange.id,
|
||||||
|
symbol,
|
||||||
|
JSON.stringify (ticker, undefined, '\n\t')
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ')
|
||||||
|
|
||||||
|
}).catch (e => {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
e.constructor.name,
|
||||||
|
e.message,
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ')
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, CCXT!</h1>
|
||||||
|
<pre id="content"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<style type="text/css">
|
||||||
|
#contentA { background-color: #ccccff; }
|
||||||
|
#contentB { background-color: #ffcccc; }
|
||||||
|
</style>
|
||||||
|
<script>'use strict'
|
||||||
|
|
||||||
|
class MyExchange extends ccxt.coinbasepro {
|
||||||
|
|
||||||
|
async fetchTicker (symbol, params = {}) {
|
||||||
|
alert ("I'm about to call the parent method from the overrided class, woohooo!")
|
||||||
|
// just call the parent method and that's it
|
||||||
|
return super.fetchTicker (symbol, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", function () {
|
||||||
|
|
||||||
|
const exchange = new MyExchange ()
|
||||||
|
|
||||||
|
const symbol = 'ETH/BTC'
|
||||||
|
|
||||||
|
const showFetchedTicker = function (ticker, elementId) {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
exchange.id,
|
||||||
|
symbol,
|
||||||
|
JSON.stringify (ticker, undefined, '\n\t')
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById (elementId).innerHTML = text.join (' ')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
exchange.fetchTicker (symbol).then (ticker => showFetchedTicker (ticker, 'content'))
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, CCXT!</h1>
|
||||||
|
<pre id="content"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", function () {
|
||||||
|
|
||||||
|
alert ('ccxt version ' + ccxt.version + ' supporting ');
|
||||||
|
|
||||||
|
const pollTickerContinuously = async function (exchange, symbol) {
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const ticker = await exchange.fetchTicker (symbol)
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
exchange.id,
|
||||||
|
symbol,
|
||||||
|
JSON.stringify (ticker, undefined, '\n\t')
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ');
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
e.constructor.name,
|
||||||
|
e.message,
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const exchange = new ccxt.binance ({ enableRateLimit: true })
|
||||||
|
const symbol = 'ETH/BTC'
|
||||||
|
|
||||||
|
pollTickerContinuously (exchange, symbol)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, CCXT!</h1>
|
||||||
|
<pre id="content"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", async function () {
|
||||||
|
|
||||||
|
alert ('ccxt version ' + ccxt.version);
|
||||||
|
|
||||||
|
const enableRateLimit = true
|
||||||
|
const exchange = new ccxt.poloniex ({ enableRateLimit })
|
||||||
|
const symbol = 'ETH/BTC'
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
let text = []
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const ticker = await exchange.fetchTicker (symbol)
|
||||||
|
|
||||||
|
text = [
|
||||||
|
exchange.id,
|
||||||
|
symbol,
|
||||||
|
JSON.stringify (exchange.omit (ticker, 'info'), undefined, '\t')
|
||||||
|
]
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
text = [
|
||||||
|
e.constructor.name,
|
||||||
|
e.message,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, CCXT!</h1>
|
||||||
|
<pre id="content"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", function () {
|
||||||
|
|
||||||
|
alert ('CCXT' + (ccxt.isBrowser ? ' browser' : '') + ' version ' + ccxt.version);
|
||||||
|
|
||||||
|
const exchange = new ccxt.coinbasepro ({ enableRateLimit: true })
|
||||||
|
const symbol = 'ETH/BTC'
|
||||||
|
|
||||||
|
exchange.fetchTicker (symbol).then (ticker => {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
exchange.id,
|
||||||
|
symbol,
|
||||||
|
JSON.stringify (ticker, undefined, '\n\t')
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ')
|
||||||
|
|
||||||
|
}).catch (e => {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
e.constructor.name,
|
||||||
|
e.message,
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ')
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, CCXT!</h1>
|
||||||
|
<pre id="content"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", function () {
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
const exchange = new ccxt.binance ({
|
||||||
|
'apiKey': 'YOUR_API_KEY',
|
||||||
|
'secret': 'YOUR_API_SECRET',
|
||||||
|
'proxyUrl': 'https://cors-anywhere.herokuapp.com/',
|
||||||
|
})
|
||||||
|
const response = await exchange.fetchBalance ()
|
||||||
|
console.log (response)
|
||||||
|
}
|
||||||
|
|
||||||
|
main ()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, CCXT!</h1>
|
||||||
|
<pre id="content"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// JavaScript CORS Proxy
|
||||||
|
// Save this in a file like cors.js and run with `node cors [port]`
|
||||||
|
// It will listen for your requests on the port you pass in command line or port 8080 by default
|
||||||
|
const port = (process.argv.length > 2) ? parseInt (process.argv[2]) : 8080 // default
|
||||||
|
require ('cors-anywhere').createServer ({
|
||||||
|
setHeaders: { 'origin': 'https://www.bitmex.com' }
|
||||||
|
}).listen (port, '0.0.0.0')
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", function () {
|
||||||
|
|
||||||
|
alert ('ccxt version ' + ccxt.version);
|
||||||
|
|
||||||
|
const exchange = new ccxt.bitmex ({
|
||||||
|
'proxyUrl': 'http://127.0.0.1:8080/',
|
||||||
|
})
|
||||||
|
|
||||||
|
const symbol = 'BTC/USDT'
|
||||||
|
|
||||||
|
exchange.fetchTicker (symbol).then (ticker => {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
exchange.id,
|
||||||
|
symbol,
|
||||||
|
JSON.stringify (ticker, undefined, '\n\t')
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ')
|
||||||
|
|
||||||
|
}).catch (e => {
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
e.constructor.name,
|
||||||
|
e.message,
|
||||||
|
]
|
||||||
|
|
||||||
|
document.getElementById ('content').innerHTML = text.join (' ')
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, CCXT!</h1>
|
||||||
|
<pre id="content"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CCXT Basic example for the browser</title>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/ccxt"></script>
|
||||||
|
<script type="text/javascript" src="https://unpkg.com/lightweight-charts@3.4.0/dist/lightweight-charts.standalone.production.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener ("DOMContentLoaded", async function () {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const exchange = new ccxt.coinbasepro ({ enableRateLimit: true });
|
||||||
|
const symbol = 'ETH/BTC';
|
||||||
|
const timeframe = '1d';
|
||||||
|
const since = undefined;
|
||||||
|
const limit = 600;
|
||||||
|
const config = {
|
||||||
|
width: 600,
|
||||||
|
height: 300,
|
||||||
|
priceScale: {
|
||||||
|
position: 'left',
|
||||||
|
mode: 1,
|
||||||
|
autoScale: true,
|
||||||
|
invertScale: false,
|
||||||
|
},
|
||||||
|
timeScale: {
|
||||||
|
fixLeftEdge: true,
|
||||||
|
lockVisibleTimeRangeOnResize: true,
|
||||||
|
rightBarStaysOnScroll: true,
|
||||||
|
visible: true,
|
||||||
|
timeVisible: true,
|
||||||
|
secondsVisible: true,
|
||||||
|
},
|
||||||
|
crosshair: {
|
||||||
|
mode: window.LightweightCharts.CrosshairMode.Normal,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const chart = window.LightweightCharts.createChart(document.body, config);
|
||||||
|
const candleSeries = chart.addCandlestickSeries();
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const response = await exchange.fetchOHLCV(symbol, timeframe, since, limit);
|
||||||
|
const last = response[response.length - 1]
|
||||||
|
const [ timestamp, open, high, low, close ] = last;
|
||||||
|
const data = response.map (([ timestamp, open, high, low, close ]) => ({ time: exchange.iso8601 (timestamp), open, high, low, close }));
|
||||||
|
candleSeries.setData(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.log (e.constructor.name, e.message);
|
||||||
|
}
|
||||||
|
await exchange.sleep (1000);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
alert (e.constructor.name + ' ' + e.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h2>CCXT running on a Webworker example</h2>
|
||||||
|
<p>This example uses a web worker to continuously call <b>fetchTicker</b> on a user-defined exchange, symbol and interval. Then, the web worker reaches back with the results.</p>
|
||||||
|
<h3>Parameters</h3>
|
||||||
|
<label for="exchange">Exchange:</label>
|
||||||
|
<input type="text" id="exchange" name="exchange" ><br><br>
|
||||||
|
<label for="symbol">Symbol: </label>
|
||||||
|
<input type="text" id="symbol" name="symbol"><br><br>
|
||||||
|
<label for="interval">Interval (ms): </label>
|
||||||
|
<input type="text" id="interval" name="interval"><br><br>
|
||||||
|
<button onclick="startWorker()">Start CCXT worker</button>
|
||||||
|
<button onclick="stopWorker()">Stop CCXT worker</button>
|
||||||
|
<h3> Received Results:</h3>
|
||||||
|
<output id="result"></output>
|
||||||
|
<table id="resultsTable" style="left:300px;width:400px; border:1px solid black;" >
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Symbol</th>
|
||||||
|
<th>Last Price</th>
|
||||||
|
<th>Base Volume</th>
|
||||||
|
<th>Exchange Ts</th>
|
||||||
|
<th>Local Ts</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody">
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
// fill in default values
|
||||||
|
document.addEventListener('DOMContentLoaded', function(event) {
|
||||||
|
document.getElementById('exchange').value = 'coinbasepro';
|
||||||
|
document.getElementById('symbol').value = 'BTC/USDT';
|
||||||
|
document.getElementById('interval').value = '1000';
|
||||||
|
});
|
||||||
|
|
||||||
|
var ccxtWorker;
|
||||||
|
function startWorker() {
|
||||||
|
|
||||||
|
if (typeof(Worker) !== "undefined") {
|
||||||
|
// if the worker does not exist yet, creates it
|
||||||
|
if (typeof(ccxtWorker) == "undefined") {
|
||||||
|
ccxtWorker = new Worker("worker.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads user-defined parameters
|
||||||
|
var exchange = document.getElementById('exchange').value
|
||||||
|
var symbol = document.getElementById('symbol').value
|
||||||
|
var interval = document.getElementById('interval').value
|
||||||
|
|
||||||
|
// send a message with those values
|
||||||
|
ccxtWorker.postMessage([exchange,symbol, interval]);
|
||||||
|
|
||||||
|
ccxtWorker.onmessage = function(event) {
|
||||||
|
// every time the ccxtworker posts a message
|
||||||
|
// this handler will be invoked
|
||||||
|
handleReceivedData(event.data)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
document.getElementById("result").innerHTML = "Sorry! No Web Worker support.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleReceivedData(data) {
|
||||||
|
var [symbol, last, baseVolume, timestamp, ourTimestamp] = data;
|
||||||
|
var tableRef = document.getElementById('resultsTable');
|
||||||
|
var tbody = document.getElementById('tbody');
|
||||||
|
row = tbody.insertRow(0);
|
||||||
|
|
||||||
|
cellSymbol = row.insertCell();
|
||||||
|
cellSymbol.innerHTML = symbol;
|
||||||
|
|
||||||
|
cellPrice = row.insertCell();
|
||||||
|
cellPrice.innerHTML = last;
|
||||||
|
|
||||||
|
cellPrice = row.insertCell();
|
||||||
|
cellPrice.innerHTML = baseVolume;
|
||||||
|
|
||||||
|
cellTimestamp = row.insertCell();
|
||||||
|
cellTimestamp.innerHTML = timestamp;
|
||||||
|
|
||||||
|
cellOurtimestamp = row.insertCell();
|
||||||
|
cellOurtimestamp.innerHTML = ourTimestamp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopWorker() {
|
||||||
|
if (ccxtWorker !== undefined) {
|
||||||
|
ccxtWorker.terminate();
|
||||||
|
ccxtWorker = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user