From e1b7f94aa7830bd1629a1e7808e034e9c4f6bca5 Mon Sep 17 00:00:00 2001 From: Definitive Prototype <5364018+graycraft@users.noreply.github.com> Date: Wed, 25 Sep 2024 20:25:07 +0500 Subject: [PATCH 1/3] fix: apply patch 8 --- collection/coinbase/currency_all.json | 994 ------------------ configuration/bybit.json | 2 +- configuration/coinbase.json | 29 +- jsconfig.json | 8 +- {lib => library}/array.mjs | 0 {lib => library}/authentication.mjs | 0 {lib => library}/boolean.mjs | 0 {lib => library}/constants.mjs | 0 {lib => library}/fetch.mjs | 0 {lib => library}/file_system.mjs | 0 {lib => library}/output.mjs | 0 {lib => library}/socket.mjs | 0 {lib => library}/string.mjs | 0 {lib => library}/template.mjs | 0 {lib => library}/utility.mjs | 20 +- {lib => library}/validation.mjs | 0 package.json | 10 +- request.mjs | 65 ++ request/bybit.js | 512 +++++---- request/bybit/account/information.mjs | 2 +- request/bybit/account/wallets.mjs | 2 +- request/bybit/balance/all.mjs | 2 +- request/bybit/balance/information.mjs | 2 +- request/bybit/balance/one.mjs | 2 +- request/bybit/currency/all.mjs | 2 +- request/bybit/currency/network-all.mjs | 2 +- request/bybit/currency/network-one.mjs | 2 +- request/bybit/currency/one.mjs | 2 +- request/bybit/deposit/all.mjs | 2 +- request/bybit/deposit/new-master.mjs | 2 +- request/bybit/deposit/new-sub.mjs | 2 +- request/bybit/deposit/one.mjs | 2 +- request/bybit/get.mjs | 16 +- request/bybit/key/information.mjs | 2 +- request/bybit/market/history.mjs | 2 +- request/bybit/market/information.mjs | 2 +- request/bybit/market/tickers.mjs | 2 +- request/bybit/order/all.mjs | 2 +- request/bybit/order/book.mjs | 2 +- request/bybit/order/cancel-all.mjs | 2 +- request/bybit/order/cancel-one.mjs | 2 +- request/bybit/order/history-all.mjs | 2 +- request/bybit/order/history-one.mjs | 2 +- request/bybit/order/limit-buy.mjs | 2 +- request/bybit/order/limit-sell.mjs | 2 +- request/bybit/order/market-buy.mjs | 2 +- request/bybit/order/market-sell.mjs | 2 +- request/bybit/order/one.mjs | 2 +- request/bybit/post.mjs | 16 +- request/bybit/sign.mjs | 4 +- request/bybit/trade/history-all.mjs | 2 +- request/bybit/trade/history-one.mjs | 2 +- request/bybit/trade/rates.mjs | 2 +- request/bybit/transfer/all.mjs | 2 +- request/bybit/transfer/internal.mjs | 4 +- request/bybit/transfer/one.mjs | 2 +- request/bybit/validate.mjs | 7 +- request/bybit/withdraw/all.mjs | 2 +- request/bybit/withdraw/new.mjs | 2 +- request/bybit/withdraw/one.mjs | 2 +- request/coinbase.js | 82 +- request/coinbase/address/all.mjs | 26 +- request/coinbase/address/new.mjs | 28 +- request/coinbase/address/one.mjs | 23 +- request/coinbase/address/transactions.mjs | 19 +- request/coinbase/currency/all.mjs | 14 +- request/coinbase/currency/one.mjs | 26 +- request/coinbase/get.mjs | 17 +- request/coinbase/market/all.mjs | 49 +- request/coinbase/market/one.mjs | 27 +- request/coinbase/market/tickers.mjs | 21 +- request/coinbase/order/all.mjs | 8 +- request/coinbase/order/book.mjs | 42 + request/coinbase/order/cancel.mjs | 14 +- request/coinbase/order/limit-buy.mjs | 47 +- request/coinbase/order/limit-sell.mjs | 47 +- request/coinbase/order/market-buy.mjs | 50 +- request/coinbase/order/market-sell.mjs | 74 +- request/coinbase/order/one.mjs | 8 +- request/coinbase/post.mjs | 38 +- request/coinbase/sign.mjs | 8 +- request/coinbase/transaction/all.mjs | 13 +- request/coinbase/transaction/one.mjs | 15 +- request/coinbase/user/account-all.mjs | 4 +- request/coinbase/user/account-one.mjs | 7 +- request/coinbase/user/portfolio-all.mjs | 4 +- request/coinbase/user/portfolio-one.mjs | 24 +- request/coinbase/validate.mjs | 115 +- request/get.mjs | 47 +- request/post.mjs | 47 +- request/validate.mjs | 22 +- response/aggregate.mjs | 18 +- response/analyze.mjs | 56 +- response/bybit.js | 9 +- response/bybit/aggregate.mjs | 4 +- response/bybit/currency/all.mjs | 4 +- response/bybit/currency/network-all.mjs | 4 +- response/bybit/network/all.mjs | 4 +- response/bybit/parse.mjs | 63 +- response/coinbase.js | 9 +- response/coinbase/address/all.mjs | 7 +- response/coinbase/address/schema.mjs | 43 +- response/coinbase/aggregate.mjs | 7 +- response/coinbase/currency/schema.mjs | 14 +- response/coinbase/market/schema.mjs | 25 +- response/coinbase/order/schema.mjs | 10 + response/coinbase/parse.mjs | 120 +-- response/coinbase/parse/find.mjs | 11 +- response/coinbase/parse/map.mjs | 12 +- response/coinbase/status.json | 14 +- response/coinbase/user/schema.mjs | 41 +- response/snapshot.mjs | 2 +- response/validate.mjs | 5 +- settings/bybit.json | 5 +- settings/coinbase.json | 43 +- socket/coinbase.js | 7 +- socket/coinbase.mjs | 13 +- socket/coinbase/subscribe.mjs | 12 +- socket/coinbase/unsubscribe.mjs | 10 +- socket/coinbase/validate.mjs | 2 +- socket/validate.mjs | 2 +- .../coinbase/address/transactions.d.js | 18 + 122 files changed, 1497 insertions(+), 1822 deletions(-) delete mode 100644 collection/coinbase/currency_all.json rename {lib => library}/array.mjs (100%) rename {lib => library}/authentication.mjs (100%) rename {lib => library}/boolean.mjs (100%) rename {lib => library}/constants.mjs (100%) rename {lib => library}/fetch.mjs (100%) rename {lib => library}/file_system.mjs (100%) rename {lib => library}/output.mjs (100%) rename {lib => library}/socket.mjs (100%) rename {lib => library}/string.mjs (100%) rename {lib => library}/template.mjs (100%) rename {lib => library}/utility.mjs (78%) rename {lib => library}/validation.mjs (100%) create mode 100644 request.mjs create mode 100644 request/coinbase/order/book.mjs create mode 100644 types/request/coinbase/address/transactions.d.js diff --git a/collection/coinbase/currency_all.json b/collection/coinbase/currency_all.json deleted file mode 100644 index dd15b02..0000000 --- a/collection/coinbase/currency_all.json +++ /dev/null @@ -1,994 +0,0 @@ -[ - { - "code": "00", - "name": "00 Token" - }, - { - "code": "1INCH", - "name": "1inch" - }, - { - "code": "AAVE", - "name": "Aave" - }, - { - "code": "ABT", - "name": "Arcblock" - }, - { - "code": "ACH", - "name": "Alchemy Pay" - }, - { - "code": "ACS", - "name": "Access" - }, - { - "code": "ADA", - "name": "Cardano" - }, - { - "code": "AERGO", - "name": "Aergo" - }, - { - "code": "AERO", - "name": "Aerodrome Finance" - }, - { - "code": "AGLD", - "name": "Adventure Gold" - }, - { - "code": "AIOZ", - "name": "AIOZ Network" - }, - { - "code": "AKT", - "name": "Akash Network" - }, - { - "code": "ALCX", - "name": "Alchemix" - }, - { - "code": "ALEPH", - "name": "Aleph.im" - }, - { - "code": "ALGO", - "name": "Algorand" - }, - { - "code": "ALICE", - "name": "MyNeighborAlice" - }, - { - "code": "AMP", - "name": "Amp" - }, - { - "code": "ANKR", - "name": "Ankr" - }, - { - "code": "APE", - "name": "ApeCoin" - }, - { - "code": "API3", - "name": "API3" - }, - { - "code": "APT", - "name": "Aptos" - }, - { - "code": "ARB", - "name": "Arbitrum" - }, - { - "code": "ARKM", - "name": "Arkham" - }, - { - "code": "ARPA", - "name": "ARPA Chain" - }, - { - "code": "ASM", - "name": "Assemble AI" - }, - { - "code": "AST", - "name": "AirSwap" - }, - { - "code": "ATOM", - "name": "Cosmos" - }, - { - "code": "AUCTION", - "name": "Bounce Token" - }, - { - "code": "AUDIO", - "name": "Audius" - }, - { - "code": "AURORA", - "name": "Aurora" - }, - { - "code": "AVAX", - "name": "Avalanche" - }, - { - "code": "AVT", - "name": "Aventus" - }, - { - "code": "AXL", - "name": "Axelar" - }, - { - "code": "AXS", - "name": "Axie Infinity" - }, - { - "code": "BADGER", - "name": "Badger DAO" - }, - { - "code": "BAL", - "name": "Balancer" - }, - { - "code": "BAND", - "name": "Band Protocol" - }, - { - "code": "BAT", - "name": "Basic Attention Token" - }, - { - "code": "BCH", - "name": "Bitcoin Cash" - }, - { - "code": "BICO", - "name": "BICONOMY (BICO)" - }, - { - "code": "BIGTIME", - "name": "Big Time" - }, - { - "code": "BIT", - "name": "BitDAO" - }, - { - "code": "BLAST", - "name": "Blast" - }, - { - "code": "BLUR", - "name": "Blur" - }, - { - "code": "BLZ", - "name": "Bluzelle" - }, - { - "code": "BNT", - "name": "Bancor Network Token" - }, - { - "code": "BOBA", - "name": "Boba Network" - }, - { - "code": "BONK", - "name": "Bonk" - }, - { - "code": "BTC", - "name": "Bitcoin" - }, - { - "code": "BTRST", - "name": "Braintrust" - }, - { - "code": "C98", - "name": "Coin98" - }, - { - "code": "CBETH", - "name": "Coinbase Wrapped Staked ETH" - }, - { - "code": "CELR", - "name": "Celer Network" - }, - { - "code": "CGLD", - "name": "Celo" - }, - { - "code": "CHZ", - "name": "Chiliz" - }, - { - "code": "CLV", - "name": "Clover Finance" - }, - { - "code": "COMP", - "name": "Compound" - }, - { - "code": "CORECHAIN", - "name": "Core" - }, - { - "code": "COTI", - "name": "COTI" - }, - { - "code": "CRO", - "name": "Crypto.com Coin" - }, - { - "code": "CRV", - "name": "Curve DAO Token" - }, - { - "code": "CTSI", - "name": "Cartesi" - }, - { - "code": "CTX", - "name": "Cryptex Finance" - }, - { - "code": "CVC", - "name": "Civic" - }, - { - "code": "CVX", - "name": "Convex Finance" - }, - { - "code": "DAI", - "name": "Dai" - }, - { - "code": "DAR", - "name": "Mines of Dalarnia" - }, - { - "code": "DASH", - "name": "Dash" - }, - { - "code": "DESO", - "name": "Decentralized Social" - }, - { - "code": "DEXT", - "name": "DEXTools" - }, - { - "code": "DIA", - "name": "DIA" - }, - { - "code": "DIMO", - "name": "DIMO" - }, - { - "code": "DNT", - "name": "district0x" - }, - { - "code": "DOGE", - "name": "Dogecoin" - }, - { - "code": "DOT", - "name": "Polkadot" - }, - { - "code": "DYP", - "name": "Dypius" - }, - { - "code": "EGLD", - "name": "MultiversX" - }, - { - "code": "ELA", - "name": "Elastos" - }, - { - "code": "ENS", - "name": "Ethereum Name Service" - }, - { - "code": "EOS", - "name": "EOS" - }, - { - "code": "ERN", - "name": "Ethernity Chain" - }, - { - "code": "ETC", - "name": "Ethereum Classic" - }, - { - "code": "ETH", - "name": "Ethereum" - }, - { - "code": "EURC", - "name": "EURC" - }, - { - "code": "FARM", - "name": "Harvest Finance" - }, - { - "code": "FET", - "name": "Fetch.ai" - }, - { - "code": "FIDA", - "name": "Bonfida" - }, - { - "code": "FIL", - "name": "Filecoin" - }, - { - "code": "FIS", - "name": "StaFi" - }, - { - "code": "FLOW", - "name": "Flow" - }, - { - "code": "FLR", - "name": "Flare" - }, - { - "code": "FORT", - "name": "Forta" - }, - { - "code": "FORTH", - "name": "Ampleforth Governance Token" - }, - { - "code": "FOX", - "name": "Shapeshift FOX Token" - }, - { - "code": "FX", - "name": "Function X" - }, - { - "code": "GAL", - "name": "Galxe" - }, - { - "code": "GFI", - "name": "Goldfinch Protocol" - }, - { - "code": "GHST", - "name": "Aavegotchi" - }, - { - "code": "GLM", - "name": "Golem" - }, - { - "code": "GMT", - "name": "STEPN" - }, - { - "code": "GNO", - "name": "Gnosis" - }, - { - "code": "GODS", - "name": "Gods Unchained" - }, - { - "code": "GRT", - "name": "The Graph" - }, - { - "code": "GST", - "name": "Green Satoshi Token" - }, - { - "code": "GTC", - "name": "Gitcoin" - }, - { - "code": "GUSD", - "name": "Gemini Dollar" - }, - { - "code": "GYEN", - "name": "GYEN" - }, - { - "code": "HBAR", - "name": "Hedera" - }, - { - "code": "HFT", - "name": "Hashflow" - }, - { - "code": "HIGH", - "name": "Highstreet" - }, - { - "code": "HNT", - "name": "Helium" - }, - { - "code": "HONEY", - "name": "Hivemapper" - }, - { - "code": "HOPR", - "name": "HOPR" - }, - { - "code": "ICP", - "name": "Internet Computer" - }, - { - "code": "IDEX", - "name": "IDEX" - }, - { - "code": "ILV", - "name": "Illuvium" - }, - { - "code": "IMX", - "name": "Immutable" - }, - { - "code": "INDEX", - "name": "Index Cooperative" - }, - { - "code": "INJ", - "name": "Injective" - }, - { - "code": "INV", - "name": "Inverse Finance" - }, - { - "code": "IOTX", - "name": "IoTeX" - }, - { - "code": "JASMY", - "name": "Jasmy" - }, - { - "code": "JTO", - "name": "Jito" - }, - { - "code": "KARRAT", - "name": "Karrat" - }, - { - "code": "KAVA", - "name": "Kava" - }, - { - "code": "KNC", - "name": "Kyber Network" - }, - { - "code": "KRL", - "name": "Kryll" - }, - { - "code": "KSM", - "name": "Kusama" - }, - { - "code": "LCX", - "name": "LCX" - }, - { - "code": "LDO", - "name": "Lido DAO Token" - }, - { - "code": "LINK", - "name": "Chainlink" - }, - { - "code": "LIT", - "name": "Litentry" - }, - { - "code": "LOKA", - "name": "League of Kingdoms Arena" - }, - { - "code": "LPT", - "name": "Livepeer" - }, - { - "code": "LQTY", - "name": "Liquity" - }, - { - "code": "LRC", - "name": "Loopring" - }, - { - "code": "LRDS", - "name": "Blocklords" - }, - { - "code": "LSETH", - "name": "Liquid Staked ETH" - }, - { - "code": "LTC", - "name": "Litecoin" - }, - { - "code": "MAGIC", - "name": "MAGIC" - }, - { - "code": "MANA", - "name": "Decentraland" - }, - { - "code": "MASK", - "name": "Mask Network" - }, - { - "code": "MATH", - "name": "MATH" - }, - { - "code": "MATIC", - "name": "Polygon" - }, - { - "code": "MDT", - "name": "Measurable Data Token" - }, - { - "code": "MEDIA", - "name": "Media Network" - }, - { - "code": "METIS", - "name": "Metis" - }, - { - "code": "MINA", - "name": "Mina" - }, - { - "code": "MKR", - "name": "Maker" - }, - { - "code": "MLN", - "name": "Enzyme" - }, - { - "code": "MNDE", - "name": "Marinade" - }, - { - "code": "MOBILE", - "name": "Helium Mobile" - }, - { - "code": "MPL", - "name": "Maple" - }, - { - "code": "MSOL", - "name": "Marinade Staked SOL" - }, - { - "code": "MUSE", - "name": "Muse" - }, - { - "code": "NCT", - "name": "PolySwarm" - }, - { - "code": "NEAR", - "name": "NEAR Protocol" - }, - { - "code": "NEON", - "name": "Neon EVM" - }, - { - "code": "NKN", - "name": "NKN" - }, - { - "code": "NMR", - "name": "Numeraire" - }, - { - "code": "OCEAN", - "name": "Ocean Protocol" - }, - { - "code": "OGN", - "name": "Origin Token" - }, - { - "code": "ONDO", - "name": "Ondo Finance" - }, - { - "code": "OP", - "name": "Optimism" - }, - { - "code": "ORCA", - "name": "Orca" - }, - { - "code": "ORN", - "name": "Orion Protocol" - }, - { - "code": "OSMO", - "name": "Osmosis" - }, - { - "code": "OXT", - "name": "Orchid" - }, - { - "code": "PAX", - "name": "Paxos Standard" - }, - { - "code": "PERP", - "name": "Perpetual Protocol" - }, - { - "code": "PLU", - "name": "Pluton" - }, - { - "code": "PNG", - "name": "Pangolin" - }, - { - "code": "POLS", - "name": "Polkastarter" - }, - { - "code": "POND", - "name": "Marlin" - }, - { - "code": "POWR", - "name": "Powerledger" - }, - { - "code": "PRIME", - "name": "Echelon Prime" - }, - { - "code": "PRO", - "name": "Propy" - }, - { - "code": "PRQ", - "name": "PARSIQ" - }, - { - "code": "PUNDIX", - "name": "Pundi X (New)" - }, - { - "code": "PYR", - "name": "Vulcan Forged PYR" - }, - { - "code": "PYUSD", - "name": "PayPal USD" - }, - { - "code": "QI", - "name": "BENQI" - }, - { - "code": "QNT", - "name": "Quant" - }, - { - "code": "RAD", - "name": "Radworks" - }, - { - "code": "RARE", - "name": "SuperRare" - }, - { - "code": "RARI", - "name": "Rarible" - }, - { - "code": "RBN", - "name": "Ribbon Finance" - }, - { - "code": "RENDER", - "name": "Render" - }, - { - "code": "REP", - "name": "Augur" - }, - { - "code": "REQ", - "name": "Request" - }, - { - "code": "RLC", - "name": "iExec RLC" - }, - { - "code": "RNDR", - "name": "Render (ERC-20)" - }, - { - "code": "RONIN", - "name": "Ronin" - }, - { - "code": "ROSE", - "name": "Oasis Network" - }, - { - "code": "RPL", - "name": "Rocket Pool" - }, - { - "code": "SAFE", - "name": "Safe" - }, - { - "code": "SAND", - "name": "The Sandbox" - }, - { - "code": "SD", - "name": "Stader" - }, - { - "code": "SEAM", - "name": "Seamless" - }, - { - "code": "SEI", - "name": "Sei" - }, - { - "code": "SHDW", - "name": "Shadow Token" - }, - { - "code": "SHIB", - "name": "SHIBA INU" - }, - { - "code": "SHPING", - "name": "SHPING" - }, - { - "code": "SKL", - "name": "SKALE" - }, - { - "code": "SNX", - "name": "Synthetix Network Token" - }, - { - "code": "SOL", - "name": "Solana" - }, - { - "code": "SPA", - "name": "Sperax" - }, - { - "code": "SPELL", - "name": "Spell Token" - }, - { - "code": "STG", - "name": "Stargate Finance" - }, - { - "code": "STORJ", - "name": "Storj" - }, - { - "code": "STRK", - "name": "Starknet Token" - }, - { - "code": "STX", - "name": "Stacks" - }, - { - "code": "SUI", - "name": "SUI" - }, - { - "code": "SUKU", - "name": "SUKU" - }, - { - "code": "SUPER", - "name": "SuperVerse" - }, - { - "code": "SUSHI", - "name": "SushiSwap" - }, - { - "code": "SWFTC", - "name": "SwftCoin" - }, - { - "code": "SYN", - "name": "Synapse" - }, - { - "code": "T", - "name": "Threshold" - }, - { - "code": "TIA", - "name": "Celestia" - }, - { - "code": "TIME", - "name": "Chrono.tech" - }, - { - "code": "TNSR", - "name": "Tensor" - }, - { - "code": "TRAC", - "name": "OriginTrail" - }, - { - "code": "TRB", - "name": "Tellor" - }, - { - "code": "TRU", - "name": "TrueFi" - }, - { - "code": "TVK", - "name": "Virtua" - }, - { - "code": "UMA", - "name": "UMA" - }, - { - "code": "UNI", - "name": "Uniswap" - }, - { - "code": "USDC", - "name": "USDC" - }, - { - "code": "USDT", - "name": "Tether" - }, - { - "code": "VARA", - "name": "Vara" - }, - { - "code": "VELO", - "name": "Velodrome Finance" - }, - { - "code": "VET", - "name": "vechain" - }, - { - "code": "VOXEL", - "name": "Voxies" - }, - { - "code": "VTHO", - "name": "VeThor Token" - }, - { - "code": "WAXL", - "name": "Wrapped Axelar" - }, - { - "code": "WBTC", - "name": "Wrapped Bitcoin" - }, - { - "code": "WCFG", - "name": "Wrapped Centrifuge" - }, - { - "code": "XCN", - "name": "Onyxcoin" - }, - { - "code": "XLM", - "name": "Stellar Lumens" - }, - { - "code": "XRP", - "name": "XRP" - }, - { - "code": "XTZ", - "name": "Tezos" - }, - { - "code": "XYO", - "name": "XYO" - }, - { - "code": "YFI", - "name": "yearn.finance" - }, - { - "code": "ZEC", - "name": "Zcash" - }, - { - "code": "ZEN", - "name": "Horizen" - }, - { - "code": "ZETA", - "name": "Zetachain" - }, - { - "code": "ZRX", - "name": "0x Protocol" - } -] \ No newline at end of file diff --git a/configuration/bybit.json b/configuration/bybit.json index 12591e2..e8301ae 100644 --- a/configuration/bybit.json +++ b/configuration/bybit.json @@ -76,7 +76,7 @@ "CODE": "retCode", "DESCRIPTION": "retMsg", "OK": 0, - "SUCCESS": "OK" + "SUCCESSFUL": "OK" }, "TRADE": { "EXEC": [ diff --git a/configuration/coinbase.json b/configuration/coinbase.json index 19b8fca..ee3a2cd 100644 --- a/configuration/coinbase.json +++ b/configuration/coinbase.json @@ -1,9 +1,19 @@ { + "CONTRACT": { + "EXPIRY": ["EXPIRING", "PERPETUAL", "UNKNOWN_CONTRACT_EXPIRY_TYPE"], + "STATUS": [ + "STATUS_ALL", + "STATUS_EXPIRED", + "STATUS_UNEXPIRED", + "UNKNOWN_EXPIRING_CONTRACT_STATUS" + ] + }, "ENCODING": "hex", "HOSTNAME": "api.coinbase.com", "ORDER": { "LIMIT": "limit_limit_gtc", "MARKET": "market_market_ioc", + "PLACEMENT": ["RETAIL_ADVANCED", "RETAIL_SIMPLE", "UNKNOWN_PLACEMENT_SOURCE"], "STATUS": [ "CANCEL_QUEUED", "CANCELLED", @@ -14,7 +24,15 @@ "PENDING", "QUEUED", "UNKNOWN_ORDER_STATUS" - ] + ], + "TIME_IN_FORCES": [ + "FILL_OR_KILL", + "GOOD_UNTIL_CANCELLED", + "GOOD_UNTIL_DATE_TIME", + "IMMEDIATE_OR_CANCEL", + "UNKNOWN_TIME_IN_FORCE" + ], + "TYPE": ["BRACKET", "LIMIT", "MARKET", "STOP", "STOP_LIMIT", "UNKNOWN_ORDER_TYPE"] }, "PATH": { "ADDRESS": "/v2/accounts/${account_uuid}/addresses", @@ -27,6 +45,7 @@ "MARKET_TICKERS": "/api/v3/brokerage/market/products/${product_id}/ticker", "NETWORK_ALL": "/api/v2/currencies/crypto?network", "ORDER_ALL": "/api/v3/brokerage/orders/historical/batch", + "ORDER_BOOK": "/api/v3/brokerage/market/product_book", "ORDER_CANCEL": "/api/v3/brokerage/orders/batch_cancel", "ORDER_ONE": "/api/v3/brokerage/orders/historical/${order_uuid}", "ORDER_PLACE": "/api/v3/brokerage/orders", @@ -40,7 +59,8 @@ "PREFIX": "", "PRODUCT": { "FUTURE": "FUTURE", - "SPOT": "SPOT" + "SPOT": "SPOT", + "UNKNOWN": "UNKNOWN_PRODUCT_TYPE" }, "SOCKET": { "CHANNEL": { @@ -58,11 +78,12 @@ "UNSUBSCRIBE": "unsubscribe", "URL": "wss://advanced-trade-ws.coinbase.com" }, + "SORT": ["LAST_FILL_TIME", "LIMIT_PRICE", "UNKNOWN_SORT_BY"], "RESPONSE": { "CODE": "error", "DESCRIPTION": "message", - "OK": "OK", - "SUCCESS": "OK" + "OK": "0", + "SUCCESSFUL": "Successful." }, "TRADE": { "SIDE": { diff --git a/jsconfig.json b/jsconfig.json index cf117ef..85a78c6 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -2,14 +2,18 @@ "compilerOptions": { "baseUrl": ".", "checkJs": true, + "esModuleInterop": true, "lib": ["es2021", "dom", "dom.iterable"], "module": "ESNext", "moduleResolution": "Node", "paths": { - "types/*": ["./types/*"] + "#config/*": ["./configuration/*"], + "#lib/*": ["./library/*"], + "#settings/*": ["./settings/*"], + "#res/*": ["./response/*"], + "#types/*": ["./types/*"] }, "resolveJsonModule": true, - "esModuleInterop": true, "target": "ES6" }, "exclude": ["node_modules"], diff --git a/lib/array.mjs b/library/array.mjs similarity index 100% rename from lib/array.mjs rename to library/array.mjs diff --git a/lib/authentication.mjs b/library/authentication.mjs similarity index 100% rename from lib/authentication.mjs rename to library/authentication.mjs diff --git a/lib/boolean.mjs b/library/boolean.mjs similarity index 100% rename from lib/boolean.mjs rename to library/boolean.mjs diff --git a/lib/constants.mjs b/library/constants.mjs similarity index 100% rename from lib/constants.mjs rename to library/constants.mjs diff --git a/lib/fetch.mjs b/library/fetch.mjs similarity index 100% rename from lib/fetch.mjs rename to library/fetch.mjs diff --git a/lib/file_system.mjs b/library/file_system.mjs similarity index 100% rename from lib/file_system.mjs rename to library/file_system.mjs diff --git a/lib/output.mjs b/library/output.mjs similarity index 100% rename from lib/output.mjs rename to library/output.mjs diff --git a/lib/socket.mjs b/library/socket.mjs similarity index 100% rename from lib/socket.mjs rename to library/socket.mjs diff --git a/lib/string.mjs b/library/string.mjs similarity index 100% rename from lib/string.mjs rename to library/string.mjs diff --git a/lib/template.mjs b/library/template.mjs similarity index 100% rename from lib/template.mjs rename to library/template.mjs diff --git a/lib/utility.mjs b/library/utility.mjs similarity index 78% rename from lib/utility.mjs rename to library/utility.mjs index 495bcc6..968ec3a 100644 --- a/lib/utility.mjs +++ b/library/utility.mjs @@ -21,15 +21,17 @@ export const obtainName = (path, PATH) => { /** * Parse process argument vectors to usable handler, parameters, options and flow. * @typedef Result - * @type {object} - * @property {string} handler API request handler. - * @property {object} options Options to apply while executing API request handler. - * @property {(string | { [key: string]: string; })[]} params Parameters to execute API request handler with. - * @property {string} flow flow for multiple API request handlers. + * @prop {string} handler API request handler. + * @prop {object} options Options to apply while executing API request handler. + * @prop {(string | { [key: string]: string; })[]} params Parameters to execute API request handler with. + * @prop {string} flow flow for multiple API request handlers. * @returns {Result} */ export const parseArguments = () => { - const options = {}, + const { + settings: { debug }, + } = global.apiTools, + options = {}, args = process.argv.slice(3).map((param) => { /** A param with defined value. */ if (param.includes('=')) { @@ -42,6 +44,9 @@ export const parseArguments = () => { return { [key]: value }; } /** Options. */ + if (param.includes('--debug')) { + options.isDebug = true; + } if (param.includes('--head')) { options.isHeaders = true; } @@ -65,6 +70,7 @@ export const parseArguments = () => { let handler = process.argv[2] ?? '', flow = ''; + /** Options. */ if (handler.includes('--flow')) { const value = handler.split('=')[1]; @@ -80,7 +86,7 @@ export const parseArguments = () => { params, }; - dirObject('arguments', result); + if (debug) dirObject('Arguments', { result }); return result; }; diff --git a/lib/validation.mjs b/library/validation.mjs similarity index 100% rename from lib/validation.mjs rename to library/validation.mjs diff --git a/package.json b/package.json index ee0e60b..99502df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "api-tools", - "version": "0.2.0-alpha", + "version": "0.2.1-alpha", "description": "Tools to work with a REST API.", "main": "request.mjs", "directories": { @@ -44,5 +44,11 @@ "node": "22.7.0", "npm": "10.8.3" }, - "type": "module" + "type": "module", + "imports": { + "#config/*": "./configuration/*", + "#lib/*": "./library/*", + "#res/*": "./response/*", + "#settings/*": "./settings/*" + } } diff --git a/request.mjs b/request.mjs new file mode 100644 index 0000000..bd49778 --- /dev/null +++ b/request.mjs @@ -0,0 +1,65 @@ +/** + * Request an API endpoint by the specified method. + * + * @module request + */ + +import { fetchData } from '#lib/fetch.mjs'; +import analyze from './response/analyze.mjs'; +import validate from './response/validate.mjs'; + +/** + * Analyze, validate, parse and snapshot response data. + * @param {"GET" | "POST"} method URL to send request. + * @param {string} url URL to send request. + * @param {string} template Path template to be interpolated. + * @param {object} headers Headers to send with request. + * @param {object} schema JSON-schema to validate response with. + * @param {{ + * parse: function, + * snapshot: function + * }} callback Utility callback functions to process response data. + * @param {object} [data] Data to send with request. + * @returns {Promise} JSON data from response. + */ +const request = async (method, url, template, headers, schema, callback, data = {}) => { + const response = await fetchData(method, url, data, headers), + responseParsed = callback.parse(response, template, data), + { json } = response, + { jsonParsed, statusText } = responseParsed, + { isKnown, isSaved, isSuccessful } = analyze(responseParsed), + isValid = validate(response.json, schema); + + global.apiTools.output[statusText] = { + headers: response.headers, + json: jsonParsed, + }; + if (isSuccessful) { + if (isValid) { + callback.snapshot( + { + ...global.apiTools.output, + [statusText]: { + ...global.apiTools.output[statusText], + json, + }, + }, + template, + ); + } else { + console.info('Snapshot:', 'response is not valid.'); + console.info('Parse:', 'response is not valid.'); + } + } else { + console.info( + 'Status:', + `code is${isKnown ? '' : ' not'} known, description is${isSaved ? '' : ' not'} saved.`, + ); + console.info('Snapshot:', 'response is not successful.'); + console.info('Parse:', 'response is not successful.'); + } + + return json; +}; + +export default request; diff --git a/request/bybit.js b/request/bybit.js index 361b0cb..425dae8 100644 --- a/request/bybit.js +++ b/request/bybit.js @@ -15,11 +15,12 @@ * @module request/bybit */ -import config from '../configuration/bybit.json' with { type: 'json' }; -import { NUMBER } from '../lib/constants.mjs'; -import { optional } from '../lib/template.mjs'; -import { parseArguments } from '../lib/utility.mjs'; -import settings from '../settings/bybit.json' with { type: 'json' }; +import config from '#config/bybit.json' with { type: 'json' }; +import { NUMBER } from '#lib/constants.mjs'; +import { optional } from '#lib/template.mjs'; +import { parseArguments } from '#lib/utility.mjs'; +import settings from '#settings/bybit.json' with { type: 'json' }; + import accountInformation from './bybit/account/information.mjs'; import accountWallets from './bybit/account/wallets.mjs'; import balanceAll from './bybit/balance/all.mjs'; @@ -60,220 +61,305 @@ import withdrawOne from './bybit/withdraw/one.mjs'; import status from '../response/bybit/status.json' with { type: 'json' }; const { + DATE: { DAY }, + } = NUMBER, + { account: { SPOT, UNIFIED }, address: { cursor, deposit }, } = settings, - requestBybit = () => { - const { flow, handler, options, params } = parseArguments(), - { - DATE: { DAY }, - } = NUMBER, - timestamp = Date.now(); + timestamp = Date.now(); + +const requestBybit = () => { + const { flow, handler, options, params } = parseArguments(); - global.apiTools = { config, options, output: {}, settings, status, timestamp }; - if (handler) { - switch (handler) { - case 'account': - case 'accountInfo': - case 'accountInformation': - return accountInformation(); - case 'accountWallets': - return accountWallets(...params); - case 'balanceAll': - return balanceAll(...params); - case 'balanceInfo': - case 'balanceInformation': - return balanceInformation(...params); - case 'balance': - case 'balanceOne': - return balanceOne(...params); - case 'currencyAll': - return currencyAll(...params); - case 'currencyNetworkAll': - return currencyNetworkAll(...params); - case 'currencyNetwork': - case 'currencyNetworkOne': - return currencyNetworkOne(...params); - case 'currency': - case 'currencyOne': - return currencyOne(...params); - case 'depositAll': - return depositAll(...params); - case 'depositNew': - case 'depositNewMaster': - return depositNewMaster(...params); - case 'depositNewSub': - return depositNewSub(...params); - case 'deposit': - case 'depositOne': - return depositOne(...params); - case 'key': - case 'keyInfo': - case 'keyInformation': - return keyInformation(...params); - case 'marketHistory': - return marketHistory(...params); - case 'market': - case 'marketInfo': - case 'marketInformation': - return marketInformation(...params); - case 'marketTickers': - return marketTickers(...params); - case 'orderAll': - return orderAll(...params); - case 'orderBook': - return orderBook(...params); - case 'orderCancelAll': - return orderCancelAll(...params); - case 'orderCancel': - case 'orderCancelOne': - return orderCancelOne(...params); - case 'orderHistoryAll': - return orderHistoryAll(...params); - case 'orderHistory': - case 'orderHistoryOne': - return orderHistoryOne(...params); - case 'order': - case 'orderOne': - return orderOne(...params); - case 'orderLimit': - case 'orderLimitBuy': - return orderLimitBuy(...params); - case 'orderLimitSell': - return orderLimitSell(...params); - case 'orderMarket': - case 'orderMarketBuy': - return orderMarketBuy(...params); - case 'orderMarketSell': - return orderMarketSell(...params); - case 'tradeRates': - return tradeRates(...params); - case 'tradeHistoryAll': - return tradeHistoryAll(...params); - case 'tradeHistory': - case 'tradeHistoryOne': - return tradeHistoryOne(...params); - case 'transferAll': - return transferAll(...params); - case 'transfer': - case 'transferOne': - return transferOne(...params); - case 'transferInternal': - return transferInternal(...params); - case 'withdrawAll': - return withdrawAll(...params); - case 'withdraw': - case 'withdrawOne': - return withdrawOne(...params); - case 'withdrawNew': - return withdrawNew(...params); - default: - throw new Error(requestBybit.name + ': ' + optional(handler)); - } - } else { - switch (flow) { - case 'orders': - Promise.resolve() - .then((response) => orderAll('NOTUSDT', 'Buy', '2')) - .then((response) => orderBook('NOTUSDT', 'inverse', '2')) - .then((response) => orderHistoryAll('NOTUSDT', '2')) - .then((response) => orderHistoryOne(response.result.list[0]?.orderId)) - .then((response) => orderLimitBuy('100', '0.002')) - .then((response) => orderOne(response.result.orderId)) - .then((response) => orderLimitSell('100', '2')) - .then((response) => orderCancelOne(response.result.orderId)) - .then((response) => orderMarketBuy('1')) - .then((response) => orderMarketSell('1')) - .then((response) => orderCancelAll('NOTUSDT')) - .catch(console.log.bind(console)); - break; - default: - Promise.resolve() - .then((response) => accountInformation()) - .then((response) => accountWallets([SPOT, UNIFIED].join())) - .then((response) => balanceAll('UNIFIED', UNIFIED, { coin: 'SHIB', withBonus: '1' })) - .then((response) => balanceInformation('UNIFIED', 'USDT')) - .then((response) => balanceOne('FUND', 'USDT', SPOT, { withBonus: '1' })) - .then((response) => currencyAll()) - .then((response) => currencyNetworkAll()) - .then((response) => currencyNetworkOne('AVAX', 'CAVAX')) - .then((response) => currencyOne('AVAX')) - .then((response) => - depositAll('USDC', { - cursor, - endTime: timestamp, - limit: 1, - startTime: timestamp - DAY * 30, - }), - ) - .then((response) => depositNewMaster('USDC', 'CAVAX')) - .then((response) => depositNewSub('219021948', 'USDC', 'CAVAX')) - .then((response) => - depositOne(deposit, { - coin: 'USDC', - cursor, - endTime: timestamp, - limit: 1, - startTime: timestamp - DAY * 30, - }), - ) - .then((response) => keyInformation()) - .then((response) => - marketHistory('SHIBUSDT', '2', { - baseCoin: 'SHIB', - category: 'option', - optionType: 'Call', - }), - ) - .then((response) => - marketInformation('linear', { - baseCoin: 'BTC', - cursor: 'first%3DBTC-04OCT24%26last%3DBTC-20SEP24', - limit: '2', - status: 'Trading', - symbol: 'BTC-25OCT24', - }), - ) - .then((response) => - marketTickers('BTC-25OCT24', { - baseCoin: 'BTC', - category: 'option', - expDate: '27DEC24', - }), - ) - .then((response) => orderAll('NOTUSDT', 'Buy', '2')) - .then((response) => orderBook('NOTUSDT', 'inverse', '2')) - .then((response) => orderHistoryAll('NOTUSDT', '2')) - .then((response) => - orderHistoryOne(response.result.list[0]?.orderId ?? '0000000000000000000'), - ) - .then((response) => orderCancelAll()) - .then((response) => orderMarketBuy('1000')) - .then((response) => orderMarketSell('100')) - .then((response) => orderOne(response.result.orderId)) - .then((response) => orderLimitBuy('100', '0.002')) - .then((response) => orderLimitSell('100', '2')) - .then((response) => orderCancelOne(response.result.orderId)) - .then((response) => orderCancelAll('NOTUSDT')) - .then((response) => tradeHistoryAll()) - .then((response) => tradeHistoryOne(response.result.list[0]?.orderId)) - .then((response) => tradeRates('NOTUSDT')) - .then((response) => transferAll('FUND')) - .then((response) => transferInternal('FUND', '1')) - .then((response) => transferOne('FUND', 'NOT')) - .then((response) => withdrawAll()) - .then((response) => - withdrawOne( - response.result.rows[0]?.txID ?? - '0x0000000000000000000000000000000000000000000000000000000000000000', - ), - ) - .then((response) => withdrawNew('1', 'NOT')) - .catch(console.log.bind(console)); - } + global.apiTools.options = options; + if (handler) { + switch (handler) { + case 'account': + case 'accountInfo': + case 'accountInformation': + return accountInformation(); + case 'accountWallets': + return accountWallets(...params); + case 'balanceAll': + return balanceAll(...params); + case 'balanceInfo': + case 'balanceInformation': + return balanceInformation(...params); + case 'balance': + case 'balanceOne': + return balanceOne(...params); + case 'currencyAll': + return currencyAll(...params); + case 'currencyNetworkAll': + return currencyNetworkAll(...params); + case 'currencyNetwork': + case 'currencyNetworkOne': + return currencyNetworkOne(...params); + case 'currency': + case 'currencyOne': + return currencyOne(...params); + case 'depositAll': + return depositAll(...params); + case 'depositNew': + case 'depositNewMaster': + return depositNewMaster(...params); + case 'depositNewSub': + return depositNewSub(...params); + case 'deposit': + case 'depositOne': + return depositOne(...params); + case 'key': + case 'keyInfo': + case 'keyInformation': + return keyInformation(...params); + case 'marketHistory': + return marketHistory(...params); + case 'market': + case 'marketInfo': + case 'marketInformation': + return marketInformation(...params); + case 'marketTickers': + return marketTickers(...params); + case 'orderAll': + return orderAll(...params); + case 'orderBook': + return orderBook(...params); + case 'orderCancelAll': + return orderCancelAll(...params); + case 'orderCancel': + case 'orderCancelOne': + return orderCancelOne(...params); + case 'orderHistoryAll': + return orderHistoryAll(...params); + case 'orderHistory': + case 'orderHistoryOne': + return orderHistoryOne(...params); + case 'order': + case 'orderOne': + return orderOne(...params); + case 'orderLimit': + case 'orderLimitBuy': + return orderLimitBuy(...params); + case 'orderLimitSell': + return orderLimitSell(...params); + case 'orderMarket': + case 'orderMarketBuy': + return orderMarketBuy(...params); + case 'orderMarketSell': + return orderMarketSell(...params); + case 'tradeRates': + return tradeRates(...params); + case 'tradeHistoryAll': + return tradeHistoryAll(...params); + case 'tradeHistory': + case 'tradeHistoryOne': + return tradeHistoryOne(...params); + case 'transferAll': + return transferAll(...params); + case 'transfer': + case 'transferOne': + return transferOne(...params); + case 'transferInternal': + return transferInternal(...params); + case 'withdrawAll': + return withdrawAll(...params); + case 'withdraw': + case 'withdrawOne': + return withdrawOne(...params); + case 'withdrawNew': + return withdrawNew(...params); + default: + throw new Error(requestBybit.name + ': ' + optional(handler)); } - }; + } else { + switch (flow) { + case 'account': + accountFlow(); + break; + case 'balance': + balanceFlow(); + break; + case 'currency': + currencyFlow(); + break; + case 'deposit': + depositFlow(); + break; + case 'key': + keyInformation(); + break; + case 'market': + marketFlow(); + break; + case 'order': + orderFlow(); + break; + case 'trade': + tradeFlow(); + break; + case 'transfer': + transferFlow(); + break; + case 'withdraw': + withdrawFlow(); + break; + default: + Promise.resolve() + .then((response) => accountFlow()) + .then((response) => balanceFlow()) + .then((response) => currencyFlow()) + .then((response) => depositFlow()) + .then((response) => keyInformation()) + .then((response) => marketFlow()) + .then((response) => orderFlow()) + .then((response) => tradeFlow()) + .then((response) => transferFlow()) + .then((response) => withdrawFlow()) + .catch(console.log.bind(console)); + } + } +}; + +/** + * @returns {Promise} + */ +const accountFlow = () => + Promise.resolve() + .then((response) => accountInformation()) + .then((response) => accountWallets([SPOT, UNIFIED].join())) + .catch(console.log.bind(console)); + +/** + * @returns {Promise} + */ +const balanceFlow = () => + Promise.resolve() + .then((response) => balanceAll('UNIFIED', UNIFIED, { coin: 'SHIB', withBonus: '1' })) + .then((response) => balanceInformation('UNIFIED', 'USDT')) + .then((response) => balanceOne('FUND', 'USDT', SPOT, { withBonus: '1' })) + .catch(console.log.bind(console)); + +/** + * @returns {Promise} + */ +const currencyFlow = () => + Promise.resolve() + .then((response) => currencyAll()) + .then((response) => currencyNetworkAll()) + .then((response) => currencyNetworkOne('AVAX', 'CAVAX')) + .then((response) => currencyOne('AVAX')) + .catch(console.log.bind(console)); + +/** + * @returns {Promise} + */ +const depositFlow = () => + Promise.resolve() + .then((response) => + depositAll('USDC', { + cursor, + endTime: timestamp, + limit: 1, + startTime: timestamp - DAY * 30, + }), + ) + .then((response) => depositNewMaster('USDC', 'CAVAX')) + .then((response) => depositNewSub('219021948', 'USDC', 'CAVAX')) + .then((response) => + depositOne(deposit, { + coin: 'USDC', + cursor, + endTime: timestamp, + limit: 1, + startTime: timestamp - DAY * 30, + }), + ) + .catch(console.log.bind(console)); + +/** + * @returns {Promise} + */ +const marketFlow = () => + Promise.resolve() + .then((response) => + marketHistory('SHIBUSDT', '2', { + baseCoin: 'SHIB', + category: 'spot', + optionType: 'Call', + }), + ) + .then((response) => + marketInformation('spot', { + baseCoin: 'BTC', + cursor: 'first%3DBTC-04OCT24%26last%3DBTC-20SEP24', + limit: '2', + status: 'Trading', + symbol: 'SHIBUSDT', + }), + ) + .then((response) => + marketTickers('BONKUSDT', { + baseCoin: 'BTC', + category: 'spot', + }), + ) + .catch(console.log.bind(console)); + +/** + * @returns {Promise} + */ +const orderFlow = () => + Promise.resolve() + .then((response) => orderAll('NOTUSDT', 'Buy', '2')) + .then((response) => orderBook('NOTUSDT', 'inverse', '2')) + .then((response) => orderHistoryAll('NOTUSDT', '2')) + .then((response) => orderHistoryOne(response.result.list[0]?.orderId ?? '0000000000000000000')) + .then((response) => orderCancelAll()) + .then((response) => orderMarketBuy('1000')) + .then((response) => orderMarketSell('100')) + .then((response) => orderLimitBuy('100', '0.002')) + .then((response) => orderOne(response.result.orderId)) + .then((response) => orderLimitSell('100', '2')) + .then((response) => orderCancelOne(response.result.orderId)) + .then((response) => orderCancelAll('NOTUSDT')) + .catch(console.log.bind(console)); + +/** + * @returns {Promise} + */ +const tradeFlow = () => + Promise.resolve() + .then((response) => tradeHistoryAll()) + .then((response) => tradeHistoryOne(response.result.list[0]?.orderId)) + .then((response) => tradeRates('NOTUSDT')) + .catch(console.log.bind(console)); + +/** + * @returns {Promise} + */ +const transferFlow = () => + Promise.resolve() + .then((response) => transferAll('FUND')) + .then((response) => transferInternal('FUND', '1')) + .then((response) => transferOne('FUND', 'NOT')) + .catch(console.log.bind(console)); +/** + * @returns {Promise} + */ +const withdrawFlow = () => + Promise.resolve() + .then((response) => withdrawAll()) + .then((response) => + withdrawOne( + response.result.rows[0]?.txID ?? + '0x0000000000000000000000000000000000000000000000000000000000000000', + ), + ) + .then((response) => withdrawNew('1', 'NOT')) + .catch(console.log.bind(console)); +global.apiTools = { config, output: {}, settings, status, timestamp }; requestBybit(); export default null; diff --git a/request/bybit/account/information.mjs b/request/bybit/account/information.mjs index 34931b4..5110e81 100644 --- a/request/bybit/account/information.mjs +++ b/request/bybit/account/information.mjs @@ -5,8 +5,8 @@ * @module request/bybit/account/information */ +import { accountInformation as schema } from '#res/bybit/account/schema.mjs'; import get from '../get.mjs'; -import { accountInformation as schema } from '../../../response/bybit/account/schema.mjs'; /** * @returns {Promise} JSON data from response. diff --git a/request/bybit/account/wallets.mjs b/request/bybit/account/wallets.mjs index 760bc65..d373a87 100644 --- a/request/bybit/account/wallets.mjs +++ b/request/bybit/account/wallets.mjs @@ -5,9 +5,9 @@ * @module request/bybit/account/wallets */ +import { accountWallets as schema } from '#res/bybit/account/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { accountWallets as schema } from '../../../response/bybit/account/schema.mjs'; /** * "FUND" - never deposited or transfered capital. This wallet type absent in the array, but account has this wallet. diff --git a/request/bybit/balance/all.mjs b/request/bybit/balance/all.mjs index 82d1437..3c36285 100644 --- a/request/bybit/balance/all.mjs +++ b/request/bybit/balance/all.mjs @@ -5,9 +5,9 @@ * @module request/bybit/balance/all */ +import { balanceAll as schema } from '#res/bybit/balance/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { balanceAll as schema } from '../../../response/bybit/balance/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#accounttype diff --git a/request/bybit/balance/information.mjs b/request/bybit/balance/information.mjs index 31f6ade..e8c635a 100644 --- a/request/bybit/balance/information.mjs +++ b/request/bybit/balance/information.mjs @@ -5,9 +5,9 @@ * @module request/bybit/balance/information */ +import { balanceInformation as schema } from '#res/bybit/balance/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { balanceInformation as schema } from '../../../response/bybit/balance/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#accounttype diff --git a/request/bybit/balance/one.mjs b/request/bybit/balance/one.mjs index e9014e9..b1b8709 100644 --- a/request/bybit/balance/one.mjs +++ b/request/bybit/balance/one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/balance/one */ +import { balanceOne as schema } from '#res/bybit/balance/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { balanceOne as schema } from '../../../response/bybit/balance/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#accounttype diff --git a/request/bybit/currency/all.mjs b/request/bybit/currency/all.mjs index ef983ed..7394f85 100644 --- a/request/bybit/currency/all.mjs +++ b/request/bybit/currency/all.mjs @@ -5,8 +5,8 @@ * @module request/bybit/currency/all */ +import { currencyAll as schema } from '#res/bybit/currency/schema.mjs'; import get from '../get.mjs'; -import { currencyAll as schema } from '../../../response/bybit/currency/schema.mjs'; /** * @returns {Promise} JSON data from response. diff --git a/request/bybit/currency/network-all.mjs b/request/bybit/currency/network-all.mjs index d29c220..1853cbd 100644 --- a/request/bybit/currency/network-all.mjs +++ b/request/bybit/currency/network-all.mjs @@ -5,8 +5,8 @@ * @module request/bybit/currency/network-all */ +import { currencyNetworkAll as schema } from '#res/bybit/currency/schema.mjs'; import get from '../get.mjs'; -import { currencyNetworkAll as schema } from '../../../response/bybit/currency/schema.mjs'; /** * Uses the same endpoint as `currencyAll`. diff --git a/request/bybit/currency/network-one.mjs b/request/bybit/currency/network-one.mjs index be7f971..f987566 100644 --- a/request/bybit/currency/network-one.mjs +++ b/request/bybit/currency/network-one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/currency/network-one */ +import { currencyNetworkOne as schema } from '#res/bybit/currency/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { currencyNetworkOne as schema } from '../../../response/bybit/currency/schema.mjs'; /** * Uses the same endpoint as `currencyOne`. diff --git a/request/bybit/currency/one.mjs b/request/bybit/currency/one.mjs index f5f1a5f..e2b79cb 100644 --- a/request/bybit/currency/one.mjs +++ b/request/bybit/currency/one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/currency/one */ +import { currencyOne as schema } from '#res/bybit/currency/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { currencyOne as schema } from '../../../response/bybit/currency/schema.mjs'; /** * @returns {Promise} JSON data from response. diff --git a/request/bybit/deposit/all.mjs b/request/bybit/deposit/all.mjs index e6488b9..0b323a9 100644 --- a/request/bybit/deposit/all.mjs +++ b/request/bybit/deposit/all.mjs @@ -5,9 +5,9 @@ * @module request/bybit/deposit/all */ +import { depositAll as schema } from '#res/bybit/deposit/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { depositAll as schema } from '../../../response/bybit/deposit/schema.mjs'; /** * Documentation do not describe `txID`, but another endpoint `WITHDRAW_ONE` also has this parameter. diff --git a/request/bybit/deposit/new-master.mjs b/request/bybit/deposit/new-master.mjs index 43a0dc5..69a96e4 100644 --- a/request/bybit/deposit/new-master.mjs +++ b/request/bybit/deposit/new-master.mjs @@ -5,9 +5,9 @@ * @module request/bybit/deposit/new-master */ +import { depositNewMaster as schema } from '#res/bybit/deposit/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { depositNewMaster as schema } from '../../../response/bybit/deposit/schema.mjs'; /** * @param {string} coin Currency name. diff --git a/request/bybit/deposit/new-sub.mjs b/request/bybit/deposit/new-sub.mjs index 45a846d..6c98a68 100644 --- a/request/bybit/deposit/new-sub.mjs +++ b/request/bybit/deposit/new-sub.mjs @@ -5,9 +5,9 @@ * @module request/bybit/new-sub */ +import { depositNewSub as schema } from '#res/bybit/deposit/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { depositNewSub as schema } from '../../../response/bybit/deposit/schema.mjs'; /** * Custodial sub account deposit address cannot be obtained. diff --git a/request/bybit/deposit/one.mjs b/request/bybit/deposit/one.mjs index 69de5aa..1d65d6b 100644 --- a/request/bybit/deposit/one.mjs +++ b/request/bybit/deposit/one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/deposit/one */ +import { depositOne as schema } from '#res/bybit/deposit/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { depositOne as schema } from '../../../response/bybit/deposit/schema.mjs'; /** * Documentation do not describe `txID`, but another endpoint `WITHDRAW_ONE` also has this parameter. diff --git a/request/bybit/get.mjs b/request/bybit/get.mjs index e95617f..da8bd1a 100644 --- a/request/bybit/get.mjs +++ b/request/bybit/get.mjs @@ -7,14 +7,15 @@ * @module request/bybit/get */ +import { HTTP } from '#lib/constants.mjs'; +import { endpointGet } from '#lib/fetch.mjs'; +import { dirObject } from '#lib/output.mjs'; +import { obtainName } from '#lib/utility.mjs'; +import parse from '#res/bybit/parse.mjs'; +import snapshot from '#res/bybit/snapshot.mjs'; + import { bybitKey, bybitSign } from './sign.mjs'; import get from '../get.mjs'; -import { HTTP } from '../../lib/constants.mjs'; -import { endpointGet } from '../../lib/fetch.mjs'; -import { dirObject } from '../../lib/output.mjs'; -import { obtainName } from '../../lib/utility.mjs'; -import parse from '../../response/bybit/parse.mjs'; -import snapshot from '../../response/bybit/snapshot.mjs'; /** * @param {string} template Path template to be interpolated. @@ -31,6 +32,7 @@ const bybitGet = async (template, schema, security, data = {}) => { { PATH } = config, { authentication: { delay }, + verbose, } = settings, { query, url } = endpointGet(template, data), { key, timestamp } = bybitKey(), @@ -51,7 +53,7 @@ const bybitGet = async (template, schema, security, data = {}) => { data, ); - dirObject('JSON', global.apiTools.output); + if (verbose) dirObject('Snapshot', global.apiTools.output); return json; }; diff --git a/request/bybit/key/information.mjs b/request/bybit/key/information.mjs index ba15856..bcc2af2 100644 --- a/request/bybit/key/information.mjs +++ b/request/bybit/key/information.mjs @@ -5,8 +5,8 @@ * @module request/bybit/key/information */ +import { keyInformation as schema } from '#res/bybit/key/schema.mjs'; import get from '../get.mjs'; -import { keyInformation as schema } from '../../../response/bybit/key/schema.mjs'; /** * @returns {Promise} JSON data from response. diff --git a/request/bybit/market/history.mjs b/request/bybit/market/history.mjs index c315781..aa0072d 100644 --- a/request/bybit/market/history.mjs +++ b/request/bybit/market/history.mjs @@ -5,9 +5,9 @@ * @module request/bybit/market/history */ +import { marketHistory as schema } from '#res/bybit/market/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { marketHistory as schema } from '../../../response/bybit/market/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/market/information.mjs b/request/bybit/market/information.mjs index f3ee7a2..ac2002b 100644 --- a/request/bybit/market/information.mjs +++ b/request/bybit/market/information.mjs @@ -5,9 +5,9 @@ * @module request/bybit/market/information */ +import { marketInformation as schema } from '#res/bybit/market/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { marketInformation as schema } from '../../../response/bybit/market/schema.mjs'; /** * Pagination is not supported for category spot, so `cursor` and `limit` cannot be used in this case. diff --git a/request/bybit/market/tickers.mjs b/request/bybit/market/tickers.mjs index 3185b3d..982790f 100644 --- a/request/bybit/market/tickers.mjs +++ b/request/bybit/market/tickers.mjs @@ -6,9 +6,9 @@ * @module request/bybit/market/tickers */ +import { marketTickers as schema } from '#res/bybit/market/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { marketTickers as schema } from '../../../response/bybit/market/schema.mjs'; /** * Parameter `limit` is not available for this endpoint. diff --git a/request/bybit/order/all.mjs b/request/bybit/order/all.mjs index 9060919..9d68fd5 100644 --- a/request/bybit/order/all.mjs +++ b/request/bybit/order/all.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/all */ +import { orderAll as schema } from '#res/bybit/order/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { orderAll as schema } from '../../../response/bybit/order/schema.mjs'; /** * Also supports querying recent 500 closed status (cancelled or filled) orders by `openOnly` parameter. diff --git a/request/bybit/order/book.mjs b/request/bybit/order/book.mjs index da4d2f4..7d41070 100644 --- a/request/bybit/order/book.mjs +++ b/request/bybit/order/book.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/book */ +import { orderBook as schema } from '#res/bybit/order/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { orderBook as schema } from '../../../response/bybit/order/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/order/cancel-all.mjs b/request/bybit/order/cancel-all.mjs index 2ced382..5e96cce 100644 --- a/request/bybit/order/cancel-all.mjs +++ b/request/bybit/order/cancel-all.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/cancel-all */ +import { orderCancelAll as schema } from '#res/bybit/order/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { orderCancelAll as schema } from '../../../response/bybit/order/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/order/cancel-one.mjs b/request/bybit/order/cancel-one.mjs index 5354872..499dd15 100644 --- a/request/bybit/order/cancel-one.mjs +++ b/request/bybit/order/cancel-one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/cancel-one */ +import { orderCancelOne as schema } from '#res/bybit/order/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { orderCancelOne as schema } from '../../../response/bybit/order/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/order/history-all.mjs b/request/bybit/order/history-all.mjs index 20c06f3..8fb25b9 100644 --- a/request/bybit/order/history-all.mjs +++ b/request/bybit/order/history-all.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/history-all */ +import { orderHistoryAll as schema } from '#res/bybit/order/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { orderHistoryAll as schema } from '../../../response/bybit/order/schema.mjs'; /** * Because order creation and cancellation is asynchronous, the data returned from this endpoint may delay. diff --git a/request/bybit/order/history-one.mjs b/request/bybit/order/history-one.mjs index 266ca70..1bd76fb 100644 --- a/request/bybit/order/history-one.mjs +++ b/request/bybit/order/history-one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/history-one */ +import { orderHistoryOne as schema } from '#res/bybit/order/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { orderHistoryOne as schema } from '../../../response/bybit/order/schema.mjs'; /** * Because order creation and cancellation is asynchronous, the data returned from this endpoint may delay. diff --git a/request/bybit/order/limit-buy.mjs b/request/bybit/order/limit-buy.mjs index 162b6a9..79ad018 100644 --- a/request/bybit/order/limit-buy.mjs +++ b/request/bybit/order/limit-buy.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/limit-buy */ +import { orderLimitBuy as schema } from '#res/bybit/order/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { orderLimitBuy as schema } from '../../../response/bybit/order/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/order/limit-sell.mjs b/request/bybit/order/limit-sell.mjs index a00fe3b..d13b758 100644 --- a/request/bybit/order/limit-sell.mjs +++ b/request/bybit/order/limit-sell.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/limit-sell */ +import { orderLimitSell as schema } from '#res/bybit/order/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { orderLimitSell as schema } from '../../../response/bybit/order/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/order/market-buy.mjs b/request/bybit/order/market-buy.mjs index 349b244..e6e8e12 100644 --- a/request/bybit/order/market-buy.mjs +++ b/request/bybit/order/market-buy.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/market-buy */ +import { orderMarketBuy as schema } from '#res/bybit/order/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { orderMarketBuy as schema } from '../../../response/bybit/order/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/order/market-sell.mjs b/request/bybit/order/market-sell.mjs index 3a2d0ba..ebdba25 100644 --- a/request/bybit/order/market-sell.mjs +++ b/request/bybit/order/market-sell.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/market-sell */ +import { orderMarketSell as schema } from '#res/bybit/order/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { orderMarketSell as schema } from '../../../response/bybit/order/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/order/one.mjs b/request/bybit/order/one.mjs index f9e55dd..b7d4a2c 100644 --- a/request/bybit/order/one.mjs +++ b/request/bybit/order/one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/order/one */ +import { orderOne as schema } from '#res/bybit/order/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { orderOne as schema } from '../../../response/bybit/order/schema.mjs'; /** * Also supports querying recent 500 closed status (cancelled or filled) orders by `openOnly` parameter. diff --git a/request/bybit/post.mjs b/request/bybit/post.mjs index b9aa4bf..c0e7e58 100644 --- a/request/bybit/post.mjs +++ b/request/bybit/post.mjs @@ -7,14 +7,15 @@ * @module request/bybit/post */ +import { HTTP } from '#lib/constants.mjs'; +import { endpointPost } from '#lib/fetch.mjs'; +import { dirObject } from '#lib/output.mjs'; +import { obtainName } from '#lib/utility.mjs'; +import parse from '#res/bybit/parse.mjs'; +import snapshot from '#res/bybit/snapshot.mjs'; + import { bybitKey, bybitSign } from './sign.mjs'; import post from '../post.mjs'; -import { HTTP } from '../../lib/constants.mjs'; -import { endpointPost } from '../../lib/fetch.mjs'; -import { dirObject } from '../../lib/output.mjs'; -import { obtainName } from '../../lib/utility.mjs'; -import parse from '../../response/bybit/parse.mjs'; -import snapshot from '../../response/bybit/snapshot.mjs'; /** * @param {string} template Path template to be interpolated. @@ -31,6 +32,7 @@ const bybitPost = async (template, schema, security, data = {}) => { { PATH } = config, { authentication: { delay }, + verbose, } = settings, { body, url } = endpointPost(template, data), { key, timestamp } = bybitKey(), @@ -51,7 +53,7 @@ const bybitPost = async (template, schema, security, data = {}) => { data, ); - dirObject('JSON', global.apiTools.output); + if (verbose) dirObject('Snapshot', global.apiTools.output); return json; }; diff --git a/request/bybit/sign.mjs b/request/bybit/sign.mjs index 3a6c140..b79fb78 100644 --- a/request/bybit/sign.mjs +++ b/request/bybit/sign.mjs @@ -7,8 +7,8 @@ * @module request/bybit/sign */ -import { blind, signHmac } from '../../lib/authentication.mjs'; -import { AUTH } from '../../lib/constants.mjs'; +import { blind, signHmac } from '#lib/authentication.mjs'; +import { AUTH } from '#lib/constants.mjs'; let timestamp; diff --git a/request/bybit/trade/history-all.mjs b/request/bybit/trade/history-all.mjs index 02665ac..03819f7 100644 --- a/request/bybit/trade/history-all.mjs +++ b/request/bybit/trade/history-all.mjs @@ -5,9 +5,9 @@ * @module request/bybit/trade/history-all */ +import { tradeHistoryAll as schema } from '#res/bybit/trade/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { tradeHistoryAll as schema } from '../../../response/bybit/trade/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/trade/history-one.mjs b/request/bybit/trade/history-one.mjs index 4e18834..5ae9dfe 100644 --- a/request/bybit/trade/history-one.mjs +++ b/request/bybit/trade/history-one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/trade/history-one */ +import { tradeHistoryOne as schema } from '#res/bybit/trade/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { tradeHistoryOne as schema } from '../../../response/bybit/trade/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/trade/rates.mjs b/request/bybit/trade/rates.mjs index d9583ec..9fe199c 100644 --- a/request/bybit/trade/rates.mjs +++ b/request/bybit/trade/rates.mjs @@ -5,9 +5,9 @@ * @module request/bybit/trade/rates */ +import { tradeRates as schema } from '#res/bybit/trade/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { tradeRates as schema } from '../../../response/bybit/trade/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#category diff --git a/request/bybit/transfer/all.mjs b/request/bybit/transfer/all.mjs index b8c664b..0ac73b0 100644 --- a/request/bybit/transfer/all.mjs +++ b/request/bybit/transfer/all.mjs @@ -5,9 +5,9 @@ * @module request/bybit/transfer/all */ +import { transferAll as schema } from '#res/bybit/transfer/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { transferAll as schema } from '../../../response/bybit/transfer/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#accounttype diff --git a/request/bybit/transfer/internal.mjs b/request/bybit/transfer/internal.mjs index 80dc460..4735cfa 100644 --- a/request/bybit/transfer/internal.mjs +++ b/request/bybit/transfer/internal.mjs @@ -6,13 +6,13 @@ */ import nodeCrypto from 'node:crypto'; +import { transferInternal as schema } from '#res/bybit/transfer/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { transferInternal as schema } from '../../../response/bybit/transfer/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#accounttype - * @param {string} toAccountType To account type. + * @param {string} toAccountType Account type to transfer. * @param {string} amount Currency amount to transfer. * @param {string} [coin] Currency name. * @param {{ fromAccountType?, transferId? }} rest diff --git a/request/bybit/transfer/one.mjs b/request/bybit/transfer/one.mjs index 3f5f061..22a9c77 100644 --- a/request/bybit/transfer/one.mjs +++ b/request/bybit/transfer/one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/transfer/one */ +import { transferOne as schema } from '#res/bybit/transfer/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { transferOne as schema } from '../../../response/bybit/transfer/schema.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/enum#accounttype diff --git a/request/bybit/validate.mjs b/request/bybit/validate.mjs index c0ea2bb..ecc730b 100644 --- a/request/bybit/validate.mjs +++ b/request/bybit/validate.mjs @@ -4,10 +4,11 @@ * @module request/bybit/validate */ +import { withinRange } from '#lib/boolean.mjs'; +import { NUMBER, REGEXP } from '#lib/constants.mjs'; +import { fileNameNewest, fileReadJson } from '#lib/file_system.mjs'; + import { hasSome, requestValidate } from '../validate.mjs'; -import { withinRange } from '../../lib/boolean.mjs'; -import { NUMBER, REGEXP } from '../../lib/constants.mjs'; -import { fileNameNewest, fileReadJson } from '../../lib/file_system.mjs'; /** * @param {string} path diff --git a/request/bybit/withdraw/all.mjs b/request/bybit/withdraw/all.mjs index 5b23dc6..3a5736f 100644 --- a/request/bybit/withdraw/all.mjs +++ b/request/bybit/withdraw/all.mjs @@ -5,9 +5,9 @@ * @module request/bybit/withdraw/all */ +import { withdrawAll as schema } from '#res/bybit/withdraw/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { withdrawAll as schema } from '../../../response/bybit/withdraw/schema.mjs'; /** * @param {{ coin?, cursor?, endTime?, limit?, startTime?, txID?, withdrawID?, withdrawType? }} rest diff --git a/request/bybit/withdraw/new.mjs b/request/bybit/withdraw/new.mjs index 5ab31f7..f95b9da 100644 --- a/request/bybit/withdraw/new.mjs +++ b/request/bybit/withdraw/new.mjs @@ -5,9 +5,9 @@ * @module request/bybit/withdraw/new */ +import { withdrawNew as schema } from '#res/bybit/withdraw/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { withdrawNew as schema } from '../../../response/bybit/withdraw/schema.mjs'; /** * API key pair must have "*Withdrawal" permission. diff --git a/request/bybit/withdraw/one.mjs b/request/bybit/withdraw/one.mjs index faa4c1e..33dfcb4 100644 --- a/request/bybit/withdraw/one.mjs +++ b/request/bybit/withdraw/one.mjs @@ -5,9 +5,9 @@ * @module request/bybit/withdraw/one */ +import { withdrawOne as schema } from '#res/bybit/withdraw/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { withdrawOne as schema } from '../../../response/bybit/withdraw/schema.mjs'; /** * @param {string} txID Transaction identifier. diff --git a/request/coinbase.js b/request/coinbase.js index 856f29f..d7aed3c 100644 --- a/request/coinbase.js +++ b/request/coinbase.js @@ -1,13 +1,16 @@ /** * Request Coinbase Advanced API spot endpoints. * + * @typedef {import('#types/request/coinbase/address/transactions.d').T} AddressTransactions * @module request/coinbase */ -import config from '../configuration/coinbase.json' with { type: 'json' }; -import { optional } from '../lib/template.mjs'; -import { parseArguments } from '../lib/utility.mjs'; -import settings from '../settings/coinbase.json' with { type: 'json' }; +import config from '#config/coinbase.json' with { type: 'json' }; +import { optional } from '#lib/template.mjs'; +import { parseArguments } from '#lib/utility.mjs'; +import status from '#res/coinbase/status.json' with { type: 'json' }; +import settings from '#settings/coinbase.json' with { type: 'json' }; + import addressAll from './coinbase/address/all.mjs'; import addressOne from './coinbase/address/one.mjs'; import addressNew from './coinbase/address/new.mjs'; @@ -18,6 +21,7 @@ import marketAll from './coinbase/market/all.mjs'; import marketOne from './coinbase/market/one.mjs'; import marketTickers from './coinbase/market/tickers.mjs'; import orderAll from './coinbase/order/all.mjs'; +import orderBook from './coinbase/order/book.mjs'; import orderCancel from './coinbase/order/cancel.mjs'; import orderLimitBuy from './coinbase/order/limit-buy.mjs'; import orderLimitSell from './coinbase/order/limit-sell.mjs'; @@ -30,23 +34,29 @@ import userAccountAll from './coinbase/user/account-all.mjs'; import userAccountOne from './coinbase/user/account-one.mjs'; import userPortfolioAll from './coinbase/user/portfolio-all.mjs'; import userPortfolioOne from './coinbase/user/portfolio-one.mjs'; -import status from '../response/coinbase/status.json' with { type: 'json' }; + +const { + user, + user: { portfolio }, + } = settings, + account = user[portfolio].account, + timestamp = Date.now(); const requestCoinbase = () => { - const { flow, handler, options, params } = parseArguments(), - { account } = settings, - timestamp = Date.now(); + const { flow, handler, options, params } = parseArguments(); - global.apiTools = { config, options, output: {}, settings, status, timestamp }; + global.apiTools.options = options; if (handler) { switch (handler) { case 'addressAll': return addressAll(...params); case 'addressNew': return addressNew(...params); + case 'address': case 'addressOne': return addressOne(...params); case 'addressTransactions': + case 'addressTxs': return addressTransactions(...params); case 'currencyAll': return currencyAll(...params); @@ -62,6 +72,8 @@ const requestCoinbase = () => { return marketTickers(...params); case 'orderAll': return orderAll(...params); + case 'orderBook': + return orderBook(...params); case 'orderCancel': return orderCancel(...params); case 'orderLimit': @@ -95,31 +107,31 @@ const requestCoinbase = () => { } else { switch (flow) { case 'address': - address(account); + addressFlow(account); break; case 'currency': - currency(); + currencyFlow(); break; case 'market': - market(); + marketFlow(); break; case 'order': - order(); + orderFlow(); break; case 'transaction': - transaction(account); + transactionFlow(account); break; case 'user': - user(); + userFlow(); break; default: Promise.resolve() - .then(() => address(account)) - .then(() => currency()) - .then(() => market()) - .then(() => order()) - .then(() => transaction(account)) - .then(() => user()) + .then(() => addressFlow(account)) + .then(() => currencyFlow()) + .then(() => marketFlow()) + .then(() => orderFlow()) + .then(() => transactionFlow(account)) + .then(() => userFlow()) .catch(console.log.bind(console)); } } @@ -127,20 +139,20 @@ const requestCoinbase = () => { /** * @param {{ uuid: string }} account - * @returns {Promise<{ data: { id: string; } }>} + * @returns {Promise} */ -const address = (account) => +const addressFlow = (account) => Promise.resolve() - .then((response) => addressNew(account.uuid)) + .then((response) => addressNew('abc', account.uuid)) .then((response) => addressOne(response.data.id, account.uuid)) - .then((response) => addressAll(account.uuid, '2')) - .then((response) => addressTransactions(response.data[0].id, account.uuid, '2')) + .then((response) => addressAll('2', account.uuid)) + .then((response) => addressTransactions(response.data[0].id, '2', account.uuid)) .catch(console.log.bind(console)); /** - * @returns {Promise<{ data: { asset_id: string; } }>} + * @returns {Promise<{ data: [{ asset_id: string; }] }>} */ -const currency = () => +const currencyFlow = () => Promise.resolve() .then((response) => currencyAll()) .then((response) => currencyOne(response.data[0].asset_id)) @@ -149,18 +161,19 @@ const currency = () => /** * @returns {Promise<{ data: { trades: [{ trade_id: string }] } }>} */ -const market = () => +const marketFlow = () => Promise.resolve() - .then((response) => marketAll('BTC-EUR', '2')) + .then((response) => marketAll('2')) .then((response) => marketOne(response.products[0].product_id)) - .then((response) => marketTickers('BTC-EUR', '2')) + .then((response) => marketTickers('BTC-USDT', '2')) .catch(console.log.bind(console)); /** * @returns {Promise<{ results: { order_id: string, success: boolean } }>} */ -const order = () => +const orderFlow = () => Promise.resolve() + .then((response) => orderBook('SHIB-USDT', '2')) .then((response) => orderMarketBuy('1')) .then((response) => orderMarketSell('0.0001')) .then((response) => orderLimitBuy('0.0001', '1000')) @@ -174,7 +187,7 @@ const order = () => * @param {{ uuid: string }} account * @returns {Promise<{ data: [{ id: string; }] }>} */ -const transaction = (account) => +const transactionFlow = (account) => Promise.resolve() .then((response) => transactionAll(account.uuid, '2')) .then((response) => transactionOne(account.uuid, response.data[0].id)) @@ -183,7 +196,7 @@ const transaction = (account) => /** * @returns {Promise<{ breakdown: object; }>} */ -const user = () => +const userFlow = () => Promise.resolve() .then((response) => userAccountAll('2')) .then((response) => userAccountOne(response.accounts[0].uuid)) @@ -191,6 +204,7 @@ const user = () => .then((response) => userPortfolioOne(response.portfolios[0].uuid)) .catch(console.log.bind(console)); +global.apiTools = { config, output: {}, settings, status, timestamp }; requestCoinbase(); export default null; diff --git a/request/coinbase/address/all.mjs b/request/coinbase/address/all.mjs index e6b67d4..8435aa7 100644 --- a/request/coinbase/address/all.mjs +++ b/request/coinbase/address/all.mjs @@ -1,31 +1,41 @@ /** - * Handle Coinbase Advanced API all account addresses endpoint. + * Handle Coinbase Advanced API all account addresses endpoint, listing all created addresses. * * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-addresses#list-addresses * @module request/coinbase/address/all */ +import { addressAll as schema } from '#res/coinbase/address/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { addressAll as schema } from '../../../response/coinbase/address/schema.mjs'; /** - * @param {string} account_uuid Account UUID. - * @param {string} [limit] Pagination limit (default is 25). Not described in documentation. - * @returns {Promise<{ data: [{ id: string }] }>} + * Latest generated address is the first item in the data array. + * @param {string} limit Pagination limit (default: 25, maximum: 300). Not described in documentation. + * @param {string} [account_uuid] Account UUID. + * @returns {Promise<{ + * data: [ + * { + * address: string, + * id: string, + * network: string + * } + * ] + * }>} JSON data from response. */ -const addressAll = async (account_uuid, limit) => { +const addressAll = async (limit = '1', account_uuid) => { const { config, settings } = global.apiTools, { PATH: { ADDRESS }, } = config, { - account: { uuid }, authentication: { security }, + user, + user: { portfolio }, } = settings, data = validate(ADDRESS, { defaults: { - account_uuid: uuid, + account_uuid: user[portfolio].account.uuid, }, optional: { account_uuid }, required: { limit }, diff --git a/request/coinbase/address/new.mjs b/request/coinbase/address/new.mjs index 75eb378..64983ed 100644 --- a/request/coinbase/address/new.mjs +++ b/request/coinbase/address/new.mjs @@ -1,34 +1,42 @@ /** - * Handle Coinbase Advanced API endpoint, with creating an address for an account. - * Addresses can be created for wallet account types. + * Handle Coinbase Advanced API new address endpoint, creating an address for an account. * * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-addresses#create-address * @module request/coinbase/address/new */ +import { addressNew as schema } from '#res/coinbase/address/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { addressNew as schema } from '../../../response/coinbase/address/schema.mjs'; /** - * @param {string} account_uuid Account UUID. - * @param {string} [name] Address label. - * @returns {Promise<{ data: { id: string } }>} + * Addresses can be created for wallet account types. + * @param {string} name Address label. + * @param {string} [account_uuid] Account UUID. + * @returns {Promise<{ + * data: { + * address: string, + * id: string, + * network: string + * } + * }>} JSON data from response. */ -const addressNew = async (account_uuid, name) => { +const addressNew = async (name, account_uuid) => { const { config, settings } = global.apiTools, { PATH: { ADDRESS }, } = config, { - account: { uuid }, authentication: { security }, + user, + user: { portfolio }, } = settings, data = validate(ADDRESS, { defaults: { - account_uuid: uuid, + account_uuid: user[portfolio].account.uuid, }, - optional: { account_uuid, name }, + optional: { account_uuid }, + required: { name }, }), json = await post(ADDRESS, schema, security, data); diff --git a/request/coinbase/address/one.mjs b/request/coinbase/address/one.mjs index 209c28e..2017844 100644 --- a/request/coinbase/address/one.mjs +++ b/request/coinbase/address/one.mjs @@ -1,18 +1,26 @@ /** - * Handle Coinbase Advanced API endpoint, with one address for an account. + * Handle Coinbase Advanced API one account addresses endpoint. * - * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-addresses#list-addresses + * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-addresses#show-address * @module request/coinbase/address/all */ +import { addressOne as schema } from '#res/coinbase/address/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { addressOne as schema } from '../../../response/coinbase/address/schema.mjs'; /** * @param {string} address_uuid Address UUID. Also regular cryptocurrency address can be used here. * @param {string} [account_uuid] Account UUID. - * @returns {Promise<{ data: { id: string } }>} + * @returns {Promise<{ + * data: [ + * { + * address: string, + * id: string, + * network: string + * } + * ] + * }>} JSON data from response. */ const addressOne = async (address_uuid, account_uuid) => { const { config, settings } = global.apiTools, @@ -20,15 +28,16 @@ const addressOne = async (address_uuid, account_uuid) => { PATH: { ADDRESS_ONE }, } = config, { - account: { uuid }, authentication: { security }, + user, + user: { portfolio }, } = settings, data = validate(ADDRESS_ONE, { defaults: { - account_uuid: uuid, + account_uuid: user[portfolio].account.uuid, }, optional: { account_uuid }, - required: { address_uuid }, + throw: { address_uuid }, }), json = await get(ADDRESS_ONE, schema, security, data); diff --git a/request/coinbase/address/transactions.mjs b/request/coinbase/address/transactions.mjs index 47bd8dd..924668c 100644 --- a/request/coinbase/address/transactions.mjs +++ b/request/coinbase/address/transactions.mjs @@ -1,35 +1,38 @@ /** - * Handle Coinbase Advanced API endpoint, with list transactions that have been sent. + * Handle Coinbase Advanced API endpoint, listing transactions that have been done by address UUID. * * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-addresses#list-transactions + * @typedef {import('types/request/coinbase/address/transactions.d').T} AddressTransactions * @module request/coinbase/address/transactions */ +import { addressTransactions as schema } from '#res/coinbase/address/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { addressTransactions as schema } from '../../../response/coinbase/address/schema.mjs'; /** * @param {string} address_uuid Address UUID. Also regular cryptocurrency address can be used. + * @param {string} [limit] Pagination limit (default: 25). Not described in documentation. * @param {string} [account_uuid] Account UUID. - * @param {string} [limit] Pagination limit (default is 25). Not described in documentation. - * @returns {Promise<{ data: { id :string } }>} + * @returns {Promise} JSON data from response. */ -const addressTransactions = async (address_uuid, account_uuid, limit) => { +const addressTransactions = async (address_uuid, limit, account_uuid) => { const { config, settings } = global.apiTools, { PATH: { ADDRESS_TRANSACTIONS }, } = config, { - account: { uuid }, authentication: { security }, + user, + user: { portfolio }, } = settings, data = validate(ADDRESS_TRANSACTIONS, { defaults: { - account_uuid: uuid, + account_uuid: user[portfolio].account.uuid, }, optional: { account_uuid }, - required: { address_uuid, limit }, + required: { limit }, + throw: { address_uuid }, }), json = await get(ADDRESS_TRANSACTIONS, schema, security, data); diff --git a/request/coinbase/currency/all.mjs b/request/coinbase/currency/all.mjs index 35f56d3..be9734b 100644 --- a/request/coinbase/currency/all.mjs +++ b/request/coinbase/currency/all.mjs @@ -1,15 +1,23 @@ /** - * Handle Coinbase Advanced API endpoint, with list of all known cryptocurrencies. + * Handle Coinbase Advanced API endpoint, listing all known cryptocurrencies. * * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-currencies#get-cryptocurrencies * @module request/coinbase/currency/all */ +import { currencyAll as schema } from '#res/coinbase/currency/schema.mjs'; import get from '../get.mjs'; -import { currencyAll as schema } from '../../../response/coinbase/currency/schema.mjs'; /** - * @returns {Promise<{ data: [{ asset_id: string }] }>} + * @returns {Promise<{ + * data: [ + * { + * asset_id: string, + * code: string, + * name: string + * } + * ] + * }>} JSON data from response. */ const currencyAll = () => { const { config } = global.apiTools, diff --git a/request/coinbase/currency/one.mjs b/request/coinbase/currency/one.mjs index 4480ce4..39ae887 100644 --- a/request/coinbase/currency/one.mjs +++ b/request/coinbase/currency/one.mjs @@ -1,31 +1,33 @@ /** - * Handle Coinbase Advanced API endpoint, with one cryptocurrency filtered by asset UUID. + * Handle Coinbase Advanced API endpoint, finding one cryptocurrency by asset UUID. * * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-currencies#get-cryptocurrencies * @module request/coinbase/currency/all */ +import { currencyOne as schema } from '#res/coinbase/currency/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { currencyOne as schema } from '../../../response/coinbase/currency/schema.mjs'; /** - * @param {string} asset_uuid Not supported by the API, must be filtered while parsing. - * @returns {Promise<{ data: { asset_id: string } }>} + * @param {string} asset_uuid Not supported by the API, item is found while parsing. + * @returns {Promise<{ + * data: [ + * { + * asset_id: string, + * code: string, + * name: string + * } + * ] + * }>} JSON data from response. */ const currencyOne = (asset_uuid) => { - const { config, settings } = global.apiTools, + const { config } = global.apiTools, { PATH: { CURRENCY_ONE }, } = config, - { - currency: { uuid }, - } = settings, data = validate(CURRENCY_ONE, { - defaults: { - asset_uuid: uuid, - }, - required: { asset_uuid }, + throw: { asset_uuid }, }), json = get(CURRENCY_ONE, schema, null, data); diff --git a/request/coinbase/get.mjs b/request/coinbase/get.mjs index a7513be..8cd3762 100644 --- a/request/coinbase/get.mjs +++ b/request/coinbase/get.mjs @@ -2,21 +2,21 @@ * Request a Coinbase Advanced API endpoint by `GET` method. * * @see https://docs.cdp.coinbase.com/advanced-trade/docs/rest-api-auth/ - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders/ * @see https://docs.cdp.coinbase.com/sign-in-with-coinbase/docs/error-response/ * @see https://docs.cdp.coinbase.com/sign-in-with-coinbase/docs/status-codes/ * @see https://developers.coinbase.com/api#versioning * @module request/coinbase/get */ +import { HTTP } from '#lib/constants.mjs'; +import { endpointGet } from '#lib/fetch.mjs'; +import { dirObject } from '#lib/output.mjs'; +import { obtainName } from '#lib/utility.mjs'; +import parse from '#res/coinbase/parse.mjs'; +import snapshot from '#res/coinbase/snapshot.mjs'; + import { coinbaseKey, coinbaseSign } from './sign.mjs'; import get from '../get.mjs'; -import { HTTP } from '../../lib/constants.mjs'; -import { endpointGet } from '../../lib/fetch.mjs'; -import { dirObject } from '../../lib/output.mjs'; -import { obtainName } from '../../lib/utility.mjs'; -import parse from '../../response/coinbase/parse.mjs'; -import snapshot from '../../response/coinbase/snapshot.mjs'; /** * @param {string} template Path template to be interpolated. @@ -33,6 +33,7 @@ const coinbaseGet = async (template, schema, security, data = {}) => { { HOSTNAME, PATH, PREFIX } = config, { authentication: { delay }, + verbose, } = settings, { path, url } = endpointGet(template, data), { key, timestamp } = coinbaseKey(), @@ -59,7 +60,7 @@ const coinbaseGet = async (template, schema, security, data = {}) => { data, ); - dirObject('JSON', global.apiTools.output); + if (verbose) dirObject('Snapshot', global.apiTools.output); return json; }; diff --git a/request/coinbase/market/all.mjs b/request/coinbase/market/all.mjs index 6df5208..8777929 100644 --- a/request/coinbase/market/all.mjs +++ b/request/coinbase/market/all.mjs @@ -1,44 +1,53 @@ /** - * Coinbase Advanced API endpoint, with all available currency pairs (products) for trading. + * Handle Coinbase Advanced API endpoint, listing all products available for trading. * * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicproducts - * @module request/coinbase/market/information + * @module request/coinbase/market/all */ +import { marketAll as schema } from '#res/coinbase/market/schema.mjs'; import get from '../get.mjs'; -import validate from '../validate.mjs'; -import { marketAll as schema } from '../../../response/coinbase/market/schema.mjs'; +import validate, { pairs } from '../validate.mjs'; /** - * @param {string} product_ids List of trading pairs (e.g. "BTC-USD"). - * @param {string} limit Pagination limit. - * @param {{ contract_expiry_type?, expiring_contract_status?, get_all_products?, offset?, product_type? }} rest - * @returns {Promise<{ products: [{ product_id: string }] }>} + * @param {string} limit Pagination limit (default > 668, maximum unknown). + * @param {{ + * contract_expiry_type?, expiring_contract_status?, get_all_products?, + * offset?, product_ids?, product_type? + * }} rest + * @returns {Promise<{ products: [{ product_id: string }] }>} JSON data from response. */ const marketAll = ( - product_ids, limit, - { contract_expiry_type, expiring_contract_status, get_all_products, offset, product_type } = {}, + { + contract_expiry_type, + expiring_contract_status, + get_all_products, + offset, + product_ids, + product_type, + } = {}, ) => { - const { config, settings } = global.apiTools, + const { config } = global.apiTools, { PATH: { MARKET_ALL }, PRODUCT, } = config, - { - authentication: { security }, - currency: { base, quote }, - } = settings, data = validate(MARKET_ALL, { defaults: { - /** @todo Pass array ?product_ids=BTC-USDT&product_ids=ETH-USDT instead of ?product_ids=ETH-USDT%2CBTC-USDT. */ - product_ids: [base + '-' + quote /* , "BTC-USDT" */], product_type: PRODUCT.SPOT, }, - optional: { product_ids }, - required: { limit }, + optional: { product_type }, + required: { + contract_expiry_type, + expiring_contract_status, + get_all_products, + limit, + offset, + product_ids: pairs(product_ids), + }, }), - json = get(MARKET_ALL, schema, security, data); + json = get(MARKET_ALL, schema, null, data); return json; }; diff --git a/request/coinbase/market/one.mjs b/request/coinbase/market/one.mjs index e636fa7..161b9b7 100644 --- a/request/coinbase/market/one.mjs +++ b/request/coinbase/market/one.mjs @@ -1,35 +1,40 @@ /** - * Coinbase Advanced API endpoint, with one available currency pair (product) for trading. + * Handle Coinbase Advanced API market endpoint, with information about single product by its identifier. * - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicproducts - * @module request/coinbase/market/information + * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicproduct + * @module request/coinbase/market/one */ +import { marketOne as schema } from '#res/coinbase/market/schema.mjs'; import get from '../get.mjs'; -import validate from '../validate.mjs'; -import { marketOne as schema } from '../../../response/coinbase/market/schema.mjs'; +import validate, { pair } from '../validate.mjs'; /** * @param {string} product_id Trading pair (e.g. "BTC-USD"). - * @returns {Promise<{ products: [{ product_id: string }] }>} + * @returns {Promise<{ + * products: [ + * { + * product_id: string, + * product_type: "FUTURE" | "SPOT" | "UNKNOWN_PRODUCT_TYPE" + * } + * ] + * }>} JSON data from response. */ const marketOne = (product_id) => { const { config, settings } = global.apiTools, { PATH: { MARKET_ONE }, - PRODUCT, } = config, { - authentication: { security }, - currency: { base, quote }, + asset: { base, quote }, } = settings, data = validate(MARKET_ONE, { defaults: { - product_id: base + '-' + quote, + product_id: pair(base.code, quote.code), }, optional: { product_id }, }), - json = get(MARKET_ONE, schema, security, data); + json = get(MARKET_ONE, schema, null, data); return json; }; diff --git a/request/coinbase/market/tickers.mjs b/request/coinbase/market/tickers.mjs index 37bbeff..413e1b0 100644 --- a/request/coinbase/market/tickers.mjs +++ b/request/coinbase/market/tickers.mjs @@ -5,15 +5,25 @@ * @module request/coinbase/market/tickers */ +import { marketTickers as schema } from '#res/coinbase/market/schema.mjs'; import get from '../get.mjs'; -import validate from '../validate.mjs'; -import { marketTickers as schema } from '../../../response/coinbase/market/schema.mjs'; +import validate, { pair } from '../validate.mjs'; /** * @param {string} product_id Trading pair (e.g. "BTC-USD"). * @param {string} [limit] Number of trades to be returned. Not required, despite what is stated in documentation. * @param {{ end?, start? }} rest - * @returns {Promise<{ data: { trades: [{ trade_id: string }] } }>} + * @returns {Promise<{ + * data: { + * trades: [ + * { + * product_id: string, + * side: "BUY" | "SELL", + * trade_id: string + * } + * ] + * } + * }>} JSON data from response. */ const marketTickers = async (product_id, limit, { end, start } = {}) => { const { config, settings } = global.apiTools, @@ -21,12 +31,11 @@ const marketTickers = async (product_id, limit, { end, start } = {}) => { PATH: { MARKET_TICKERS }, } = config, { - currency: { base, quote }, + asset: { base, quote }, } = settings, data = validate(MARKET_TICKERS, { defaults: { - /** @todo Formatter. */ - product_id: base + '-' + quote, + product_id: pair(base.code, quote.code), }, optional: { product_id }, required: { end, limit, start }, diff --git a/request/coinbase/order/all.mjs b/request/coinbase/order/all.mjs index 772747e..a9c6bbe 100644 --- a/request/coinbase/order/all.mjs +++ b/request/coinbase/order/all.mjs @@ -5,20 +5,21 @@ * @module request/coinbase/order/all */ +import { orderAll as schema } from '#res/coinbase/order/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { orderAll as schema } from '../../../response/coinbase/order/schema.mjs'; /** * If `has_next` in response data is `true`, more pages are available to fetch. - * The parameters start_date and end_date don’t apply to open orders. + * The parameters `start_date` and `end_date` don't apply to open orders. + * `assetFilters` parameter not applicable for open orders * @param {string} limit Pagination limit (default: no, maximum: 1000). * @param {{ * asset_filters?, contract_expiry_type?, cursor?, end_date?, order_ids?, * order_placement_source?, order_side?, order_status?, order_types?, product_ids?, * product_type?, retail_portfolio_id?, sort_by?, start_date?, time_in_forces? * }} rest - * @returns {Promise<{ orders: [{ order_id: string, product_id: string }] }>} + * @returns {Promise<{ orders: [{ order_id: string, product_id: string }] }>} JSON data from response. */ const orderAll = async ( limit, @@ -65,7 +66,6 @@ const orderAll = async ( order_ids, order_placement_source, order_side, - order_status, order_types, /* product_id, */ product_ids, diff --git a/request/coinbase/order/book.mjs b/request/coinbase/order/book.mjs new file mode 100644 index 0000000..7496818 --- /dev/null +++ b/request/coinbase/order/book.mjs @@ -0,0 +1,42 @@ +/** + * Handle Coinbase Advanced API order book depth endpoint, listing bids/asks by product identifier. + * + * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicproductbook + * @module request/coinbase/order/book + */ + +import { orderBook as schema } from '#res/coinbase/order/schema.mjs'; +import get from '../get.mjs'; +import validate, { pair } from '../validate.mjs'; + +/** + * @param {string} product_id The trading pair (e.g. "BTC-USD"). + * @param {string} [limit] Pagination limit (default: no, maximum: 1000). + * @param {string} [aggregation_price_increment] The minimum price intervals at which buy and sell orders are grouped or combined in the order book. + * @returns {Promise<{ pricebook: [{ product_id: string }] }>} JSON data from response. + */ +const orderBook = async (product_id, limit, aggregation_price_increment) => { + const { config, settings } = global.apiTools, + { + PATH: { ORDER_BOOK }, + } = config, + { + authentication: { security }, + asset: { base, quote }, + } = settings, + data = validate(ORDER_BOOK, { + defaults: { + product_id: pair(base.code, quote.code), + }, + optional: { product_id }, + required: { + aggregation_price_increment, + limit, + }, + }), + json = await get(ORDER_BOOK, schema, security, data); + + return json; +}; + +export default orderBook; diff --git a/request/coinbase/order/cancel.mjs b/request/coinbase/order/cancel.mjs index 2150440..f99f582 100644 --- a/request/coinbase/order/cancel.mjs +++ b/request/coinbase/order/cancel.mjs @@ -1,18 +1,18 @@ /** - * Handle Coinbase Advanced API cancel all orders endpoint. + * Handle Coinbase Advanced API cancel order endpoint by one or more order identifiers. * - * @see https://coinbase-exchange.github.io/docs/v5/order/cancel-order - * @module request/coinbase/order/cancel-all + * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_cancelorders + * @module request/coinbase/order/cancel */ +import { orderCancel as schema } from '#res/coinbase/order/schema.mjs'; import post from '../post.mjs'; import validate from '../validate.mjs'; -import { orderCancel as schema } from '../../../response/coinbase/order/schema.mjs'; /** * The maximum number of order_ids that can be cancelled per request is 100. - * @param {string} order_ids - * @returns {Promise<{ results: { order_id: string, success: boolean } }>} + * @param {string} order_ids The order identifiers that cancel requests should be initiated for. + * @returns {Promise<{ results: { order_id: string, success: boolean } }>} JSON data from response. */ const orderCancel = async (order_ids) => { const { config, settings } = global.apiTools, @@ -23,7 +23,7 @@ const orderCancel = async (order_ids) => { authentication: { security }, } = settings, data = validate(ORDER_CANCEL, { - throw: { order_ids: [order_ids] }, + throw: { order_ids: order_ids.split(',') }, }), json = await post(ORDER_CANCEL, schema, security, data); diff --git a/request/coinbase/order/limit-buy.mjs b/request/coinbase/order/limit-buy.mjs index 71b04f0..94f7a3f 100644 --- a/request/coinbase/order/limit-buy.mjs +++ b/request/coinbase/order/limit-buy.mjs @@ -6,9 +6,9 @@ */ import nodeCrypto from 'node:crypto'; +import { orderLimitBuy as schema } from '#res/coinbase/order/schema.mjs'; import post from '../post.mjs'; -import validate from '../validate.mjs'; -import { orderLimitBuy as schema } from '../../../response/coinbase/order/schema.mjs'; +import validate, { pair } from '../validate.mjs'; /** * The maximum number of open orders allowed per `product_id` is 500. @@ -17,14 +17,47 @@ import { orderLimitBuy as schema } from '../../../response/coinbase/order/schema * @param {string} base_size Size of the first asset in a trading pair. * @param {string} limit_price Price, that an order should be executed at. * @param {string} [product_id] Trading pair (e.g. "BTC-USD"). - * @param {{ client_order_id? }} rest - * @returns {Promise<{ success: boolean, success_response: { order_id: string, product_id: string } }>} + * @param {{ + * client_order_id?, end_time?, leverage?, limit_limit_fok?, limit_limit_gtc?, + * limit_limit_gtd?, market_market_ioc?, margin_type?, post_only?, preview_id?, + * quote_size?, sor_limit_ioc?, stop_direction?, stop_limit_stop_limit_gtc?, + * stop_limit_stop_limit_gtd?, stop_price?, stop_trigger_price?, + * trigger_bracket_gtc?, trigger_bracket_gtd? + * }} rest + * @returns {Promise<{ + * success: boolean, + * success_response: { + * order_id: string, + * product_id: string + * } + * }>} JSON data from response. */ const orderLimitBuy = async ( base_size, limit_price, product_id, - { client_order_id /* , side */ } = {}, + { + client_order_id, + end_time, + leverage, + limit_limit_fok, + limit_limit_gtc, + limit_limit_gtd, + market_market_ioc, + margin_type, + post_only, + preview_id, + quote_size, + /* side, */ + sor_limit_ioc, + stop_direction, + stop_limit_stop_limit_gtc, + stop_limit_stop_limit_gtd, + stop_price, + stop_trigger_price, + trigger_bracket_gtc, + trigger_bracket_gtd, + } = {}, ) => { const { config, settings } = global.apiTools, { @@ -34,12 +67,12 @@ const orderLimitBuy = async ( } = config, { authentication: { security }, - currency: { base, quote }, + asset: { base, quote }, } = settings, data = validate(ORDER_PLACE, { defaults: { client_order_id: nodeCrypto.randomUUID(), - product_id: base + '-' + quote, + product_id: pair(base.code, quote.code), side: SIDE.BUY, }, optional: { client_order_id, product_id }, diff --git a/request/coinbase/order/limit-sell.mjs b/request/coinbase/order/limit-sell.mjs index f3b6121..174b2d8 100644 --- a/request/coinbase/order/limit-sell.mjs +++ b/request/coinbase/order/limit-sell.mjs @@ -6,9 +6,9 @@ */ import nodeCrypto from 'node:crypto'; +import { orderLimitSell as schema } from '#res/coinbase/order/schema.mjs'; import post from '../post.mjs'; -import validate from '../validate.mjs'; -import { orderLimitSell as schema } from '../../../response/coinbase/order/schema.mjs'; +import validate, { pair } from '../validate.mjs'; /** * The maximum number of open orders allowed per `product_id` is 500. @@ -17,14 +17,47 @@ import { orderLimitSell as schema } from '../../../response/coinbase/order/schem * @param {string} base_size Size of the first asset in a trading pair. * @param {string} limit_price Price, that an order should be executed at. * @param {string} [product_id] Trading pair (e.g. "BTC-USD"). - * @param {{ client_order_id? }} rest - * @returns {Promise<{ success: boolean, success_response: { order_id: string, product_id: string } }>} + * @param {{ + * client_order_id?, end_time?, leverage?, limit_limit_fok?, limit_limit_gtc?, + * limit_limit_gtd?, market_market_ioc?, margin_type?, post_only?, preview_id?, + * quote_size?, sor_limit_ioc?, stop_direction?, stop_limit_stop_limit_gtc?, + * stop_limit_stop_limit_gtd?, stop_price?, stop_trigger_price?, + * trigger_bracket_gtc?, trigger_bracket_gtd? + * }} rest + * @returns {Promise<{ + * success: boolean, + * success_response: { + * order_id: string, + * product_id: string + * } + * }>} JSON data from response. */ const orderLimitSell = async ( base_size, limit_price, product_id, - { client_order_id /* , side */ } = {}, + { + client_order_id, + end_time, + leverage, + limit_limit_fok, + limit_limit_gtc, + limit_limit_gtd, + market_market_ioc, + margin_type, + post_only, + preview_id, + quote_size, + /* side, */ + sor_limit_ioc, + stop_direction, + stop_limit_stop_limit_gtc, + stop_limit_stop_limit_gtd, + stop_price, + stop_trigger_price, + trigger_bracket_gtc, + trigger_bracket_gtd, + } = {}, ) => { const { config, settings } = global.apiTools, { @@ -34,12 +67,12 @@ const orderLimitSell = async ( } = config, { authentication: { security }, - currency: { base, quote }, + asset: { base, quote }, } = settings, data = validate(ORDER_PLACE, { defaults: { client_order_id: nodeCrypto.randomUUID(), - product_id: base + '-' + quote, + product_id: pair(base.code, quote.code), side: SIDE.SELL, }, optional: { client_order_id, product_id }, diff --git a/request/coinbase/order/market-buy.mjs b/request/coinbase/order/market-buy.mjs index ce4ef09..bdb36e7 100644 --- a/request/coinbase/order/market-buy.mjs +++ b/request/coinbase/order/market-buy.mjs @@ -6,9 +6,9 @@ */ import nodeCrypto from 'node:crypto'; +import { orderMarketBuy as schema } from '#res/coinbase/order/schema.mjs'; import post from '../post.mjs'; -import validate from '../validate.mjs'; -import { orderMarketBuy as schema } from '../../../response/coinbase/order/schema.mjs'; +import validate, { pair } from '../validate.mjs'; /** * The maximum number of open orders allowed per `product_id` is 500. @@ -16,10 +16,46 @@ import { orderMarketBuy as schema } from '../../../response/coinbase/order/schem * A sell Order will execute at or higher than the market price. * @param {string} quote_size Size of the first asset in a trading pair. * @param {string} [product_id] Trading pair (e.g. "BTC-USD"). - * @param {{ client_order_id? }} rest - * @returns {Promise<{ success: boolean, success_response: { order_id: string, product_id: string } }>} + * @param {{ + * client_order_id?, end_time?, leverage?, limit_limit_fok?, limit_limit_gtc?, + * limit_limit_gtd?, market_market_ioc?, margin_type?, post_only?, preview_id?, + * sor_limit_ioc?, stop_direction?, stop_limit_stop_limit_gtc?, + * stop_limit_stop_limit_gtd?, stop_price?, stop_trigger_price?, + * trigger_bracket_gtc?, trigger_bracket_gtd? + * }} rest + * @returns {Promise<{ + * success: boolean, + * success_response: { + * order_id: string, + * product_id: string + * } + * }>} JSON data from response. */ -const orderMarketBuy = async (quote_size, product_id, { client_order_id /* , side */ } = {}) => { +const orderMarketBuy = async ( + quote_size, + product_id, + { + client_order_id, + end_time, + leverage, + limit_limit_fok, + limit_limit_gtc, + limit_limit_gtd, + market_market_ioc, + margin_type, + post_only, + preview_id, + /* side, */ + sor_limit_ioc, + stop_direction, + stop_limit_stop_limit_gtc, + stop_limit_stop_limit_gtd, + stop_price, + stop_trigger_price, + trigger_bracket_gtc, + trigger_bracket_gtd, + } = {}, +) => { const { config, settings } = global.apiTools, { ORDER, @@ -28,12 +64,12 @@ const orderMarketBuy = async (quote_size, product_id, { client_order_id /* , sid } = config, { authentication: { security }, - currency: { base, quote }, + asset: { base, quote }, } = settings, data = validate(ORDER_PLACE, { defaults: { client_order_id: nodeCrypto.randomUUID(), - product_id: base + '-' + quote, + product_id: pair(base.code, quote.code), side: SIDE.BUY, }, optional: { client_order_id, product_id }, diff --git a/request/coinbase/order/market-sell.mjs b/request/coinbase/order/market-sell.mjs index 94c0b88..de2a4a2 100644 --- a/request/coinbase/order/market-sell.mjs +++ b/request/coinbase/order/market-sell.mjs @@ -6,33 +6,71 @@ */ import nodeCrypto from 'node:crypto'; +import { orderMarketSell as schema } from '#res/coinbase/order/schema.mjs'; import post from '../post.mjs'; -import validate from '../validate.mjs'; -import { orderMarketSell as schema } from '../../../response/coinbase/order/schema.mjs'; +import validate, { pair } from '../validate.mjs'; /** * The maximum number of open orders allowed per `product_id` is 500. * A buy Order will execute at or lower than the market price. * A sell Order will execute at or higher than the market price. - * Trying to use `quote_size` API responses, despite of documentation allowing it: - * OK: { - * data: { - * success: false, - * error_response: { - * error: 'UNSUPPORTED_ORDER_CONFIGURATION', - * error_details: '', - * message: 'rpc error: code = InvalidArgument desc = Market sells must be parameterized in base currency', - * preview_failure_reason: 'PREVIEW_INVALID_ORDER_CONFIG' - * }, - * order_configuration: { market_market_ioc: { quote_size: '1' } } + * Despite of documentation allowing `quote_size`, trying to use it API responses error: + * { + * OK: { + * data: { + * success: false, + * error_response: { + * error: 'UNSUPPORTED_ORDER_CONFIGURATION', + * error_details: '', + * message: 'rpc error: code = InvalidArgument desc = Market sells must be parameterized in base currency', + * preview_failure_reason: 'PREVIEW_INVALID_ORDER_CONFIG' + * }, + * order_configuration: { market_market_ioc: { quote_size: '1' } } + * } * } * } * @param {string} base_size Size of the first asset in a trading pair. * @param {string} [product_id] Trading pair (e.g. "BTC-USD"). - * @param {{ client_order_id? }} rest - * @returns {Promise<{ success: boolean, success_response: { order_id: string, product_id: string } }>} + * @param {{ + * client_order_id?, end_time?, leverage?, limit_limit_fok?, limit_limit_gtc?, + * limit_limit_gtd?, market_market_ioc?, margin_type?, post_only?, preview_id?, + * sor_limit_ioc?, stop_direction?, stop_limit_stop_limit_gtc?, + * stop_limit_stop_limit_gtd?, stop_price?, stop_trigger_price?, + * trigger_bracket_gtc?, trigger_bracket_gtd? + * }} rest + * @returns {Promise<{ + * success: boolean, + * success_response: { + * order_id: string, + * product_id: string + * } + * }>} JSON data from response. */ -const orderMarketSell = async (base_size, product_id, { client_order_id /* , side */ } = {}) => { +const orderMarketSell = async ( + base_size, + product_id, + { + client_order_id, + end_time, + leverage, + limit_limit_fok, + limit_limit_gtc, + limit_limit_gtd, + market_market_ioc, + margin_type, + post_only, + preview_id, + /* side, */ + sor_limit_ioc, + stop_direction, + stop_limit_stop_limit_gtc, + stop_limit_stop_limit_gtd, + stop_price, + stop_trigger_price, + trigger_bracket_gtc, + trigger_bracket_gtd, + } = {}, +) => { const { config, settings } = global.apiTools, { ORDER, @@ -41,12 +79,12 @@ const orderMarketSell = async (base_size, product_id, { client_order_id /* , sid } = config, { authentication: { security }, - currency: { base, quote }, + asset: { base, quote }, } = settings, data = validate(ORDER_PLACE, { defaults: { client_order_id: nodeCrypto.randomUUID(), - product_id: base + '-' + quote, + product_id: pair(base.code, quote.code), side: SIDE.SELL, }, optional: { client_order_id, product_id }, diff --git a/request/coinbase/order/one.mjs b/request/coinbase/order/one.mjs index 0eee09d..b984ead 100644 --- a/request/coinbase/order/one.mjs +++ b/request/coinbase/order/one.mjs @@ -1,17 +1,17 @@ /** - * Handle Coinbase Advanced API one orders endpoint. + * Handle Coinbase Advanced API one order endpoint, by order UUID. * - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders + * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorder * @module request/coinbase/order/one */ +import { orderOne as schema } from '#res/coinbase/order/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { orderOne as schema } from '../../../response/coinbase/order/schema.mjs'; /** * @param {string} order_uuid Order UUID. - * @returns {Promise<{ order: { order_id: string, product_id: string } }>} + * @returns {Promise<{ order: { order_id: string, product_id: string } }>} JSON data from response. */ const orderOne = async (order_uuid) => { const { config, settings } = global.apiTools, diff --git a/request/coinbase/post.mjs b/request/coinbase/post.mjs index e476e2e..29acfbb 100644 --- a/request/coinbase/post.mjs +++ b/request/coinbase/post.mjs @@ -1,32 +1,33 @@ /** * Request a Coinbase Advanced API endpoint by POST method. * Some methods, e.g. `/v2/accounts/${account_uuid}/addresses` suggests to supply additional header: - * '201': { - * ..., - * warnings: [ - * { - * id: 'missing_version', - * message: 'Please supply API version (YYYY-MM-DD) as CB-VERSION header', - * url: 'https://developers.coinbase.com/api#versioning' - * } - * ] + * { + * CREATED: { + * ..., + * warnings: [ + * { + * id: 'missing_version', + * message: 'Please supply API version (YYYY-MM-DD) as CB-VERSION header', + * url: 'https://developers.coinbase.com/api#versioning' + * } + * ] + * } * } - * * @see https://docs.cdp.coinbase.com/advanced-trade/docs/rest-api-auth/ - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders/ * @see https://docs.cdp.coinbase.com/sign-in-with-coinbase/docs/error-response/ * @see https://docs.cdp.coinbase.com/sign-in-with-coinbase/docs/status-codes/ * @module request/coinbase/post */ +import { HTTP } from '#lib/constants.mjs'; +import { endpointPost } from '#lib/fetch.mjs'; +import { dirObject } from '#lib/output.mjs'; +import { obtainName } from '#lib/utility.mjs'; +import parse from '#res/coinbase/parse.mjs'; +import snapshot from '#res/coinbase/snapshot.mjs'; + import { coinbaseKey, coinbaseSign } from './sign.mjs'; import post from '../post.mjs'; -import { HTTP } from '../../lib/constants.mjs'; -import { endpointPost } from '../../lib/fetch.mjs'; -import { dirObject } from '../../lib/output.mjs'; -import { obtainName } from '../../lib/utility.mjs'; -import parse from '../../response/coinbase/parse.mjs'; -import snapshot from '../../response/coinbase/snapshot.mjs'; /** * @param {string} template Path template to be interpolated. @@ -43,6 +44,7 @@ const coinbasePost = async (template, schema, security, data = {}) => { { HOSTNAME, PATH, PREFIX } = config, { authentication: { delay }, + verbose, } = settings, { path, url } = endpointPost(template, data), { key, timestamp } = coinbaseKey(), @@ -69,7 +71,7 @@ const coinbasePost = async (template, schema, security, data = {}) => { data, ); - dirObject('JSON', global.apiTools.output); + if (verbose) dirObject('Snapshot', global.apiTools.output); return json; }; diff --git a/request/coinbase/sign.mjs b/request/coinbase/sign.mjs index d65cb8f..b499ecd 100644 --- a/request/coinbase/sign.mjs +++ b/request/coinbase/sign.mjs @@ -5,8 +5,8 @@ * @module request/coinbase/sign */ -import { blind, signJwt } from '../../lib/authentication.mjs'; -import { AUTH } from '../../lib/constants.mjs'; +import { blind, signJwt } from '#lib/authentication.mjs'; +import { AUTH } from '#lib/constants.mjs'; let timestamp; @@ -18,7 +18,7 @@ export const coinbaseKey = () => { { authentication, user } = settings, { portfolio } = user, { keys } = authentication, - key = keys[user[portfolio]]; + key = keys[user[portfolio].uuid]; /** Timestamp must be fresh for every request from an API flow. */ timestamp = Date.now(); @@ -34,7 +34,7 @@ export const coinbaseSecret = () => { { authentication, user } = settings, { portfolio } = user, { secrets } = authentication, - secret = secrets[user[portfolio]]; + secret = secrets[user[portfolio].uuid]; return secret; }; diff --git a/request/coinbase/transaction/all.mjs b/request/coinbase/transaction/all.mjs index 1ce8bb3..3937abb 100644 --- a/request/coinbase/transaction/all.mjs +++ b/request/coinbase/transaction/all.mjs @@ -1,18 +1,18 @@ /** - * Handle Coinbase Advanced API endpoint, with transactions list of an account. + * Handle Coinbase Advanced API endpoint, listing transactions of an account. * * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-transactions#list-transactions * @module request/coinbase/transaction/all */ +import { transactionAll as schema } from '#res/coinbase/transaction/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { transactionAll as schema } from '../../../response/coinbase/transaction/schema.mjs'; /** * @param {string} account_uuid Account UUID. - * @param {string} [limit] Pagination limit (default is 25). Not described in documentation. - * @returns {Promise<{ data: [{ id: string }] }>} + * @param {string} [limit] Pagination limit (default: 25). Not described in documentation. + * @returns {Promise<{ data: [{ id: string }] }>} JSON data from response. */ const transactionAll = async (account_uuid, limit) => { const { config, settings } = global.apiTools, @@ -20,12 +20,13 @@ const transactionAll = async (account_uuid, limit) => { PATH: { TRANSACTION_ALL }, } = config, { - account: { uuid }, authentication: { security }, + user, + user: { portfolio }, } = settings, data = validate(TRANSACTION_ALL, { defaults: { - account_uuid: uuid, + account_uuid: user[portfolio].account.uuid, }, optional: { account_uuid }, required: { limit }, diff --git a/request/coinbase/transaction/one.mjs b/request/coinbase/transaction/one.mjs index 96c32cb..7666eac 100644 --- a/request/coinbase/transaction/one.mjs +++ b/request/coinbase/transaction/one.mjs @@ -1,19 +1,19 @@ /** - * Handle Coinbase Advanced API endpoint, with one transactions of an account. + * Handle Coinbase Advanced API one account transaction endpoint, by transaction UUID. * * @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-transactions#list-transactions - * @module request/coinbase/transaction/all + * @module request/coinbase/transaction/one */ +import { transactionOne as schema } from '#res/coinbase/transaction/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { transactionOne as schema } from '../../../response/coinbase/transaction/schema.mjs'; /** * @param {string} account_uuid Account UUID. * @param {string} transaction_uuid Transaction UUID. - * @param {string} [limit] Pagination limit (default is 25). Not described in documentation. - * @returns {Promise<{ data: [{ id: string }] }>} + * @param {string} [limit] Pagination limit (default: 25). Not described in documentation. + * @returns {Promise<{ data: [{ id: string }] }>} JSON data from response. */ const transactionOne = async (account_uuid, transaction_uuid, limit) => { const { config, settings } = global.apiTools, @@ -21,12 +21,13 @@ const transactionOne = async (account_uuid, transaction_uuid, limit) => { PATH: { TRANSACTION_ONE }, } = config, { - account: { uuid }, authentication: { security }, + user, + user: { portfolio }, } = settings, data = validate(TRANSACTION_ONE, { defaults: { - account_uuid: uuid, + account_uuid: user[portfolio].account.uuid, }, optional: { account_uuid }, required: { limit }, diff --git a/request/coinbase/user/account-all.mjs b/request/coinbase/user/account-all.mjs index d97fe60..38dcf67 100644 --- a/request/coinbase/user/account-all.mjs +++ b/request/coinbase/user/account-all.mjs @@ -1,15 +1,15 @@ /** * Handle Coinbase Advanced API endpoint, with all authenticated accounts of current user. * + * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccounts * @module request/coinbase/user/account-all */ +import { userAccountAll as schema } from '#res/coinbase/user/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { userAccountAll as schema } from '../../../response/coinbase/user/schema.mjs'; /** - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccounts * @param {string} limit The number of accounts to display per page (49 by default, maximum 250). * @param {string} [cursor] Allows to get response with accounts at specific page. * @param {string} [retail_portfolio_id] Portfolio UUID, only applicable for legacy keys. diff --git a/request/coinbase/user/account-one.mjs b/request/coinbase/user/account-one.mjs index f5eacdb..2c3457c 100644 --- a/request/coinbase/user/account-one.mjs +++ b/request/coinbase/user/account-one.mjs @@ -1,15 +1,15 @@ /** * Handle Coinbase Advanced API endpoint, with an account information of current user by account UUID. * + * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccount * @module request/coinbase/user/account-all */ +import { userAccountOne as schema } from '#res/coinbase/user/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { userAccountOne as schema } from '../../../response/coinbase/user/schema.mjs'; /** - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccount * @param {string} account_uuid Account UUID. * @returns {Promise<{ account }>} JSON data from response. */ @@ -21,10 +21,11 @@ const userAccountOne = (account_uuid) => { { authentication: { security }, user, + user: { portfolio }, } = settings, data = validate(USER_ACCOUNT_ONE, { defaults: { - account_uuid: user.account, + account_uuid: user[portfolio].account.uuid, }, required: { account_uuid }, }), diff --git a/request/coinbase/user/portfolio-all.mjs b/request/coinbase/user/portfolio-all.mjs index 3aec848..8f97414 100644 --- a/request/coinbase/user/portfolio-all.mjs +++ b/request/coinbase/user/portfolio-all.mjs @@ -1,15 +1,15 @@ /** * Handle Coinbase Advanced API endpoint for all portfolios of a user. * + * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfolios * @module request/coinbase/user/portfolio-all */ +import { userPortfolioAll as schema } from '#res/coinbase/user/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { userPortfolioAll as schema } from '../../../response/coinbase/user/schema.mjs'; /** - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfolios * @param {"CONSUMER" | "DEFAULT" | "INTX" | "UNDEFINED"} portfolio_type * @returns {Promise<{ portfolios: [{ uuid: string }] }>} JSON data from response. */ diff --git a/request/coinbase/user/portfolio-one.mjs b/request/coinbase/user/portfolio-one.mjs index 227c8f2..63b2c68 100644 --- a/request/coinbase/user/portfolio-one.mjs +++ b/request/coinbase/user/portfolio-one.mjs @@ -1,18 +1,32 @@ /** - * Handle Coinbase Advanced API endpoint, with one portfolio breakdown of a user by portfolio UUID. + * Handle Coinbase Advanced API endpoint, with portfolio breakdown of a user by portfolio UUID. * + * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfoliobreakdown * @module request/coinbase/user/portfolio-one */ +import { userPortfolioOne as schema } from '#res/coinbase/user/schema.mjs'; import get from '../get.mjs'; import validate from '../validate.mjs'; -import { userPortfolioOne as schema } from '../../../response/coinbase/user/schema.mjs'; /** - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfoliobreakdown + * This endpoint requires the "view" permission (for that portfolio). * @param {string} portfolio_uuid Portfolio UUID. * @param {string} [currency] Calculate values in specified currency. - * @returns {Promise<{ breakdown: object }>} JSON data from response. + * @returns {Promise<{ + * breakdown: { + * portfolio: { + * type: "CONSUMER" | "DEFAULT" | "INTX" | "UNDEFINED", + * uuid: string + * }, + * portfolio_balances: object + * spot_positions: { + * account_uuid: string, + * asset: string, + * asset_uuid: string, + * } + * } + * }>} JSON data from response. */ const userPortfolioOne = async (portfolio_uuid, currency) => { const { config, settings } = global.apiTools, @@ -26,7 +40,7 @@ const userPortfolioOne = async (portfolio_uuid, currency) => { } = settings, data = validate(USER_PORTFOLIO_ONE, { defaults: { - portfolio_uuid: user[portfolio], + portfolio_uuid: user[portfolio].uuid, }, optional: { portfolio_uuid }, required: { currency }, diff --git a/request/coinbase/validate.mjs b/request/coinbase/validate.mjs index 23db9bb..8eb7945 100644 --- a/request/coinbase/validate.mjs +++ b/request/coinbase/validate.mjs @@ -4,45 +4,46 @@ * @module request/coinbase/validate */ -import { hasSome, requestValidate } from '../validate.mjs'; -import { REGEXP } from '../../lib/constants.mjs'; -import { fileNameNewest, fileReadJson } from '../../lib/file_system.mjs'; +import { withinRange } from '#lib/boolean.mjs'; +import { NUMBER, REGEXP } from '#lib/constants.mjs'; +import { fileNameNewest, fileReadJson } from '#lib/file_system.mjs'; + +import { hasSome, isPair, requestValidate } from '../validate.mjs'; /** * @param {string} path * @param {object} options - * @returns + * @returns {object} */ const coinbaseValidate = (path, options) => requestValidate(path, isValid, options); /** - * @param {{ [key: string]: value }} param + * Coinbase Advanced API does not expose available networks. + * It is only possible to collect networks by generating a deposit address and aggregating from `ADDRESS`. + * @param {{ [key: string]: object | string }} param * @returns {boolean} */ const isValid = (param) => { const { UUID } = REGEXP, { config } = global.apiTools, { + CONTRACT, ORDER, + PRODUCT, + SORT, + TRADE: { SIDE }, USER: { PORTFOLIO }, } = config, [key, value] = Object.entries(param)[0], currencyDir = 'collection/coinbase/currency_all', currencyFile = fileNameNewest(currencyDir), - currencyAll = fileReadJson(currencyDir, currencyFile.name); - /* networkDir = 'collection/coinbase/network_all', - networkFile = fileNameNewest(networkDir), - networkAll = fileReadJson(networkDir, networkFile.name) */ + currencyAll = fileReadJson(currencyDir, currencyFile.name).map((item) => item.code); /** - * @todo `contract_expiry_type`. - * @todo `expiring_contract_status`. - * @todo `get_all_products`. - * @todo `offset`. - * @todo `product_id`. - * @todo `product_ids`. - * @todo `product_type`. - * `name` as address label, random string. + * @todo Pass array `?order_types=BTC-USDT&order_types=ETH-USDT` instead of `?order_types=BTC-USDT,ETH-USDT` as API requires. + * @todo Pass array `?product_ids=BTC-USDT&product_ids=ETH-USDT` instead of `?product_ids=BTC-USDT,ETH-USDT` as API requires. + * @todo `cursor`. + * `name` as address label is a random string. */ switch (key) { case 'account_uuid': @@ -52,23 +53,91 @@ const isValid = (param) => { case 'previous_ending_before': case 'retail_portfolio_id': return UUID.test(value); + case 'aggregation_price_increment': case 'limit': return Boolean(Number(value)); - case 'order_ids': - return value instanceof Array; + case 'asset_filters': + return hasSome(currencyAll, value); + case 'contract_expiry_type': + return hasSome(CONTRACT.EXPIRY, value); + case 'end': + return withinDays(1, value, 31); + case 'expiring_contract_status': + return hasSome(CONTRACT.STATUS, value); + case 'get_all_products': + return value === 'true'; case 'order_configuration': + case 'order_ids': const order = value[ORDER.LIMIT] ?? value[ORDER.MARKET]; - if (value[ORDER.MARKET]) { - return typeof order.base_size === 'string' || typeof order.quote_size === 'string'; + /** `ORDER_PLACE` endpoints. */ + if (order) { + if (value[ORDER.MARKET]) { + return Boolean(Number(order.base_size)) || Boolean(Number(order.quote_size)); + } + + return Boolean(Number(order.base_size)) && Boolean(Number(order.limit_price)); } - return typeof order.base_size === 'string' && typeof order.limit_price === 'string'; + return value.every((item) => UUID.test(item)); + case 'order_placement_source': + return hasSome(ORDER.PLACEMENT, value); + case 'order_side': + return hasSome(Object.values(SIDE), value); + case 'order_status': + return hasSome(ORDER.STATUS, value); + case 'order_types': + return hasSome(ORDER.TYPE, value); case 'portfolio_type': - return PORTFOLIO.some((portfolio) => portfolio === value); + return hasSome(PORTFOLIO, value); + case 'product_id': + return isPair(currencyAll, value, pair); + case 'product_ids': + return value.every((item) => isPair(currencyAll, item, pair)); + case 'product_type': + return hasSome(Object.values(PRODUCT), value); + case 'sort_by': + return hasSome(SORT, value); + case 'start': + return withinDays(1, value, 31); + case 'time_in_forces': + return hasSome(ORDER.TIME_IN_FORCES, value); default: return typeof value === 'string'; } }; +/** + * @param {string} base + * @param {string} quote + * @returns {string} + */ +export const pair = (base, quote) => { + const string = [base, quote].join('-'); + + return string; +}; + +/** + * @param {string} pairs + * @returns {string[]} + */ +export const pairs = (pairs) => { + const string = pairs?.split(','); + + return string; +}; + +const withinDays = (min, value, max) => { + const { + DATE: { DAY }, + } = NUMBER, + { timestamp } = global.apiTools, + after = timestamp + DAY * min, + before = timestamp - DAY * max, + isWithin = withinRange(before, value, after); + + return isWithin; +}; + export default coinbaseValidate; diff --git a/request/get.mjs b/request/get.mjs index 0aebdd7..6cdc73a 100644 --- a/request/get.mjs +++ b/request/get.mjs @@ -4,12 +4,11 @@ * @module request/get */ -import { HTTP } from '../lib/constants.mjs'; -import { fetchData } from '../lib/fetch.mjs'; -import analyze from '../response/analyze.mjs'; -import validate from '../response/validate.mjs'; +import { HTTP } from '#lib/constants.mjs'; +import request from '../request.mjs'; /** + * Analyze, validate, parse and snapshot response data. * @param {string} url URL to send request. * @param {string} template Path template to be interpolated. * @param {object} headers Headers to send with request. @@ -17,45 +16,17 @@ import validate from '../response/validate.mjs'; * @param {{ * parse: function, * snapshot: function - * }} utilities Utility functions to process response data. + * }} callback Utility callback functions to process response data. * @param {object} [data] Data to send with request. * @returns {Promise} JSON data from response. */ -const requestGet = async (url, template, headers, schema, { parse, snapshot }, data = {}) => { +const requestGet = async (url, template, headers, schema, callback, data = {}) => { const { - METHOD: { GET }, - } = HTTP; - let response = await fetchData(GET, url, data, headers), - { json, statusText } = response, - { isCodeDescribed, isCodeKnown, isSuccessful } = analyze(response), - isValid = validate(json, schema); + METHOD: { GET }, + } = HTTP, + response = await request(GET, url, template, headers, schema, callback, data); - global.apiTools.output[statusText] = { - headers: response.headers, - data: json, - }; - if (isSuccessful) { - if (isValid) { - const parsed = parse(response, template, data); - - snapshot(global.apiTools.output, template); - json = parsed.json; - statusText = parsed.statusText; - } else { - console.info('Snapshot:', 'response is not valid.'); - console.info('Parse:', 'response is not valid.'); - } - } else { - /** - * @todo Status synchronization with `status.json`. - */ - console.info('isCodeDescribed:', isCodeDescribed); - console.info('isCodeKnown:', isCodeKnown); - console.info('Snapshot:', 'response is not successful.'); - console.info('Parse:', 'response is not successful.'); - } - - return json; + return response; }; export default requestGet; diff --git a/request/post.mjs b/request/post.mjs index 89600ff..9260d07 100644 --- a/request/post.mjs +++ b/request/post.mjs @@ -4,12 +4,11 @@ * @module request/post */ -import { HTTP } from '../lib/constants.mjs'; -import { fetchData } from '../lib/fetch.mjs'; -import analyze from '../response/analyze.mjs'; -import validate from '../response/validate.mjs'; +import { HTTP } from '#lib/constants.mjs'; +import request from '../request.mjs'; /** + * Analyze, validate, parse and snapshot response data. * @param {string} url URL to send request. * @param {string} template Path template to be interpolated. * @param {object} headers Headers to send with request. @@ -17,45 +16,17 @@ import validate from '../response/validate.mjs'; * @param {{ * parse: function, * snapshot: function - * }} utilities Utility functions to process response data. + * }} callback Utility callback functions to process response data. * @param {object} [data] Data to send with request. * @returns {Promise} JSON data from response. */ -const requestPost = async (url, template, headers, schema, { parse, snapshot }, data = {}) => { +const requestPost = async (url, template, headers, schema, callback, data = {}) => { const { - METHOD: { POST }, - } = HTTP; - let response = await fetchData(POST, url, data, headers), - { json, statusText } = response, - { isCodeDescribed, isCodeKnown, isSuccessful } = analyze(response, 0), - isValid = validate(json, schema); + METHOD: { POST }, + } = HTTP, + response = await request(POST, url, template, headers, schema, callback, data); - global.apiTools.output[statusText] = { - headers: response.headers, - data: json, - }; - if (isSuccessful) { - if (isValid) { - const parsed = parse(response, template, data); - - snapshot(global.apiTools.output, template); - json = parsed.json; - statusText = parsed.statusText; - } else { - console.info('Snapshot:', 'response is not valid.'); - console.info('Parse:', 'response is not valid.'); - } - } else { - /** - * @todo Status synchronization with `status.json`. - */ - console.info('isCodeDescribed:', isCodeDescribed); - console.info('isCodeKnown:', isCodeKnown); - console.info('Snapshot:', 'response is not successful.'); - console.info('Parse:', 'response is not successful.'); - } - - return json; + return response; }; export default requestPost; diff --git a/request/validate.mjs b/request/validate.mjs index 3073c42..9d333cf 100644 --- a/request/validate.mjs +++ b/request/validate.mjs @@ -4,18 +4,32 @@ * @module request/validate */ -import { throwRequired, warnOptional, warnRequired } from '../lib/output.mjs'; +import { throwRequired, warnOptional, warnRequired } from '#lib/output.mjs'; /** * @param {array} list * @param {string} value * @param {string} [prop] - * @returns + * @returns {boolean} */ export const hasSome = (list, value, prop) => { - const data = list.some((item) => (prop ? item[prop] === value : item === value)); + const boolean = list.some((item) => (prop ? item[prop] === value : item === value)); - return data; + return boolean; +}; + +/** + * @param {array} list + * @param {string} value + * @param {function} pair + * @returns {boolean} + */ +export const isPair = (list, value, pair) => { + const boolean = list.some((item1) => + list.some((item2) => pair(item1, item2) === value && item1 !== item2), + ); + + return boolean; }; /** diff --git a/response/aggregate.mjs b/response/aggregate.mjs index 91c1176..e215d7a 100644 --- a/response/aggregate.mjs +++ b/response/aggregate.mjs @@ -6,9 +6,15 @@ import nodeFs from 'node:fs'; import nodePath from 'node:path'; -import { obtainName } from '../lib/utility.mjs'; +import { obtainName } from '#lib/utility.mjs'; -const responseAggregate = (target, path, data, key) => { +/** + * @param {string} target + * @param {string} path + * @param {array} data + * @param {{ id, key, name }} properties + */ +const responseAggregate = (target, path, data, { id, key, name }) => { const { config, settings } = global.apiTools, pathName = obtainName(path, config.PATH), isEnabled = settings.enabled.includes('aggregate'); @@ -23,9 +29,13 @@ const responseAggregate = (target, path, data, key) => { let array, fileData2; if (pathName === 'CURRENCY_ALL') { - const currencies = data.map((item) => item[key]); + const currencies = data.map((item) => ({ + [id]: item[id], + [key]: item[key], + [name]: item[name], + })); - array = currencies.sort((a, b) => a.localeCompare(b)); + array = currencies.sort((a, b) => a[key].localeCompare(b[key])); } if (pathName === 'CURRENCY_NETWORK_ALL') { const networks = data.map((row) => diff --git a/response/analyze.mjs b/response/analyze.mjs index 263c702..329bd94 100644 --- a/response/analyze.mjs +++ b/response/analyze.mjs @@ -4,32 +4,50 @@ * @module response/analyze */ -import { HTTP } from '../lib/constants.mjs'; +import { HTTP } from '#lib/constants.mjs'; +import { dirObject } from '#lib/output.mjs'; +/** + * Analyze response and decide whether it is successful for further processing. + * @param {{ code, description, jsonParsed, status, statusText }} response Parsed response data. + * @typedef Result + * @prop {boolean} isKnown Whether response status code is known in `status.json` or not. + * @prop {boolean} isSaved Whether response status description is saved in `status.json` or not. + * @prop {boolean} isSuccessful Whether response status code and description considered successful or not. + * @returns {Result} + */ const responseAnalyze = (response) => { const { STATUS } = HTTP, - { config, status } = global.apiTools, { - RESPONSE: { CODE, DESCRIPTION, OK, SUCCESS }, + config, + status: statusKnown, + settings: { debug }, + } = global.apiTools, + { + RESPONSE: { CODE, DESCRIPTION, OK }, } = config, - { json, statusText } = response; + { jsonParsed, status, statusText } = response, + { code = jsonParsed[CODE], description = jsonParsed[DESCRIPTION] } = response, + known = statusKnown[statusText]?.[code] ?? ''; + + if (debug) { + dirObject('Analyze', { CODE, DESCRIPTION, OK, code, description, known, status }); + } - const code = json[CODE] ?? OK, - message = json[DESCRIPTION] ?? SUCCESS, - description = status[statusText]?.[code] ?? '', - isCodeKnown = - description === message || - (description instanceof Array && description.some((desc) => desc === message)), - isCodeDescribed = Boolean(description), - isSuccessful = - code === OK && (response.status === STATUS.CREATED || response.status === STATUS.OK), - report = { - isCodeDescribed, - isCodeKnown, - isSuccessful, - }; + const isKnown = Boolean(known), + /** + * @todo New status saving in `status.json`. + */ + isSaved = + known === description || + (known instanceof Array && known.some((desc) => desc === description)), + isSuccessful = code === OK && (status === STATUS.CREATED || status === STATUS.OK); - return report; + return { + isKnown, + isSaved, + isSuccessful, + }; }; export default responseAnalyze; diff --git a/response/bybit.js b/response/bybit.js index 0a756b1..8e79390 100644 --- a/response/bybit.js +++ b/response/bybit.js @@ -4,10 +4,11 @@ * @module response/bybit */ -import config from '../configuration/bybit.json' with { type: 'json' }; -import { optional } from '../lib/template.mjs'; -import { parseArguments } from '../lib/utility.mjs'; -import settings from '../settings/bybit.json' with { type: 'json' }; +import config from '#config/bybit.json' with { type: 'json' }; +import { optional } from '#lib/template.mjs'; +import { parseArguments } from '#lib/utility.mjs'; +import settings from '#settings/bybit.json' with { type: 'json' }; + import currencyAll from './bybit/currency/all.mjs'; import currencyNetworkAll from './bybit/currency/network-all.mjs'; diff --git a/response/bybit/aggregate.mjs b/response/bybit/aggregate.mjs index 69099c4..bede4a6 100644 --- a/response/bybit/aggregate.mjs +++ b/response/bybit/aggregate.mjs @@ -4,9 +4,9 @@ * @module response/bybit/aggregate */ +import { fileReadJson } from '#lib/file_system.mjs'; +import { obtainName } from '#lib/utility.mjs'; import aggregate from '../aggregate.mjs'; -import { fileReadJson } from '../../lib/file_system.mjs'; -import { obtainName } from '../../lib/utility.mjs'; const bybitAggregate = (path, fileName) => { const { config } = global.apiTools, diff --git a/response/bybit/currency/all.mjs b/response/bybit/currency/all.mjs index ac7ef45..28da290 100644 --- a/response/bybit/currency/all.mjs +++ b/response/bybit/currency/all.mjs @@ -4,9 +4,9 @@ * @module response/bybit/currency/all */ +import { fileNameNewest } from '#lib/file_system.mjs'; +import { obtainName } from '#lib/utility.mjs'; import aggregate from '../aggregate.mjs'; -import { fileNameNewest } from '../../../lib/file_system.mjs'; -import { obtainName } from '../../../lib/utility.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/asset/coin-info diff --git a/response/bybit/currency/network-all.mjs b/response/bybit/currency/network-all.mjs index f855cb1..ae2417a 100644 --- a/response/bybit/currency/network-all.mjs +++ b/response/bybit/currency/network-all.mjs @@ -4,9 +4,9 @@ * @module response/bybit/network/all */ +import { fileNameNewest } from '#lib/file_system.mjs'; +import { obtainName } from '#lib/utility.mjs'; import aggregate from '../aggregate.mjs'; -import { fileNameNewest } from '../../../lib/file_system.mjs'; -import { obtainName } from '../../../lib/utility.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/asset/coin-info diff --git a/response/bybit/network/all.mjs b/response/bybit/network/all.mjs index 4641aee..4f77572 100644 --- a/response/bybit/network/all.mjs +++ b/response/bybit/network/all.mjs @@ -4,9 +4,9 @@ * @module response/bybit/network/all */ +import { fileNameNewest } from '#lib/file_system.mjs'; +import { obtainName } from '#lib/utility.mjs'; import bybitAggregate from '../aggregate.mjs'; -import { fileNameNewest } from '../../../lib/file_system.mjs'; -import { obtainName } from '../../../lib/utility.mjs'; /** * @see https://bybit-exchange.github.io/docs/v5/asset/coin-info diff --git a/response/bybit/parse.mjs b/response/bybit/parse.mjs index 61181d9..f6fd739 100644 --- a/response/bybit/parse.mjs +++ b/response/bybit/parse.mjs @@ -4,13 +4,27 @@ * @module response/bybit/parse */ +import config from '#config/bybit.json' with { type: 'json' }; +import { obtainName } from '#lib/utility.mjs'; +import settings from '#settings/bybit.json' with { type: 'json' }; + import filter from './parse/filter.mjs'; import find from './parse/find.mjs'; import map from './parse/map.mjs'; -import config from '../../configuration/bybit.json' with { type: 'json' }; -import { obtainName } from '../../lib/utility.mjs'; -import settings from '../../settings/bybit.json' with { type: 'json' }; +/** + * Parse response + * @param {{ json: object, status: string, statusText: string }} response + * @param {string} path + * @typedef Result + * @prop {string} code . + * @prop {string} description . + * @prop {object} jsonParsed . + * @prop {string} output . + * @prop {string} status . + * @prop {string} statusText . + * @returns {Result} + */ const responseParse = (response, path, data) => { const { PATH, @@ -24,17 +38,19 @@ const responseParse = (response, path, data) => { ORDER_ALL, TRADE_HISTORY_ALL, }, + RESPONSE: { CODE, DESCRIPTION }, TRADE, } = config, { currency: { base, quote }, parse, - } = settings; - let { json, statusText } = response; + } = settings, + { json, status, statusText } = response, + code = json[CODE], + description = json[DESCRIPTION], + parsed = []; + let jsonParsed; - /** - * @todo Refactor to `response/parse`. - */ if (parse.includes(obtainName(path, PATH))) { let isFiltered = true, isFound = true, @@ -42,15 +58,15 @@ const responseParse = (response, path, data) => { switch (path) { case BALANCE_ALL: - json = filter(json, { + jsonParsed = filter(json, { criterion: (item) => Number(item.transferBalance) || Number(item.walletBalance), list: 'balance', }); break; case ORDER_ALL: case TRADE_HISTORY_ALL: - json = filter(json, { - criterion: data.side || TRADE.BUY, + jsonParsed = filter(json, { + criterion: data.side || TRADE.SIDE.BUY, key: 'side', list: 'list', }); @@ -67,7 +83,7 @@ const responseParse = (response, path, data) => { case MARKET_HISTORY: case MARKET_INFORMATION: case MARKET_TICKERS: - json = find(json, { + jsonParsed = find(json, { criterion: data.symbol ?? base + quote, key: 'symbol', list: 'list', @@ -78,13 +94,13 @@ const responseParse = (response, path, data) => { } switch (path) { case CURRENCY_ALL: - json = map(json, { + jsonParsed = map(json, { key: 'coin', list: 'rows', }); break; case CURRENCY_NETWORK_ALL: - json = map(json, { + jsonParsed = map(json, { key: ['coin', 'chain'], list: ['rows', 'chains'], }); @@ -92,19 +108,18 @@ const responseParse = (response, path, data) => { default: isMapped = false; } - if (isFiltered || isFound || isMapped) { - const parsed = []; + if (isFiltered) parsed.push('items filtered'); + if (isFound) parsed.push('found one item'); + if (isMapped) parsed.push('items mapped'); - statusText += ' ('; - if (isFiltered) parsed.push('filtered'); - if (isFound) parsed.push('found'); - if (isMapped) parsed.push('mapped'); - statusText += parsed.join(', ') + ')'; - } - console.info(`Parsed endpoint "${obtainName(path, PATH)}" successfully.`); + const output = parsed.length ? ` (${parsed.join(', ')})` : ''; + + console.info(`Parsed endpoint "${obtainName(path, PATH)}" successfully${output}.`); } else console.info(`Parse: endpoint "${obtainName(path, PATH)}" is not enabled is settings.`); - return { json, statusText }; + const output = parsed.length ? parsed.join(', ') + '.' : ''; + + return { code, description, jsonParsed: jsonParsed ?? json, output, status, statusText }; }; export default responseParse; diff --git a/response/coinbase.js b/response/coinbase.js index dc0e2d3..a4cb1cd 100644 --- a/response/coinbase.js +++ b/response/coinbase.js @@ -4,10 +4,11 @@ * @module response/coinbase */ -import config from '../configuration/coinbase.json' with { type: 'json' }; -import { optional } from '../lib/template.mjs'; -import { parseArguments } from '../lib/utility.mjs'; -import settings from '../settings/coinbase.json' with { type: 'json' }; +import config from '#config/coinbase.json' with { type: 'json' }; +import { optional } from '#lib/template.mjs'; +import { parseArguments } from '#lib/utility.mjs'; +import settings from '#settings/coinbase.json' with { type: 'json' }; + import currencyAll from './coinbase/currency/all.mjs'; // import networkAll from './coinbase/network/all.mjs'; diff --git a/response/coinbase/address/all.mjs b/response/coinbase/address/all.mjs index 41d6830..fdb0dfe 100644 --- a/response/coinbase/address/all.mjs +++ b/response/coinbase/address/all.mjs @@ -4,15 +4,16 @@ * @module response/bybit/currency/all */ +import config from '#config/bybit.json' with { type: 'json' }; import bybitAggregate from '../aggregate.mjs'; -import config from '../../../configuration/bybit.json' with { type: 'json' }; + const { - PATH: { ADDRESS_ALL }, + PATH: { TRANSFER_ALL }, } = config; /** * @see https://bybit-exchange.github.io/docs/v5/asset/coin-info */ -const addressAll = () => bybitAggregate(ADDRESS_ALL, '2024-08-17T15:29:51.146Z.json'); +const addressAll = () => bybitAggregate(TRANSFER_ALL, '2024-08-17T15:29:51.146Z.json'); export default addressAll; diff --git a/response/coinbase/address/schema.mjs b/response/coinbase/address/schema.mjs index 6679a33..8928c0e 100644 --- a/response/coinbase/address/schema.mjs +++ b/response/coinbase/address/schema.mjs @@ -5,11 +5,25 @@ * @module response/coinbase/address/schema */ +const address = { + properties: { + address: { type: 'string' }, + id: { type: 'string' }, + network: { type: 'string' }, + }, + required: ['address', 'id', 'network'], + type: 'object', +}; + export const addressAll = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, properties: { - data: { type: 'array' }, + data: { + items: address, + minItems: 1, + type: 'array', + }, pagination: { type: 'object' }, }, required: ['data', 'pagination'], @@ -20,7 +34,7 @@ export const addressNew = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, properties: { - data: { type: 'object' }, + data: address, }, required: ['data'], type: 'object', @@ -30,7 +44,8 @@ export const addressOne = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, properties: { - data: { type: 'object' }, + data: address, + pagination: { type: 'object' }, }, required: ['data'], type: 'object', @@ -40,7 +55,27 @@ export const addressTransactions = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, properties: { - data: { type: 'array' }, + data: { + items: { + properties: { + id: { type: 'string' }, + network: { + properties: { + name: { enum: ['bitcoin', 'ethereum'], type: 'string' }, + status: { enum: ['off_blockchain'], type: 'string' }, + }, + required: ['name', 'status'], + type: 'object', + }, + status: { enum: ['completed'], type: 'string' }, + type: { enum: ['send'], type: 'string' }, + }, + required: ['id', 'network', 'status', 'type'], + type: 'object', + }, + minItems: 0, + type: 'array', + }, pagination: { type: 'object' }, }, required: ['data'], diff --git a/response/coinbase/aggregate.mjs b/response/coinbase/aggregate.mjs index f555f5c..865052f 100644 --- a/response/coinbase/aggregate.mjs +++ b/response/coinbase/aggregate.mjs @@ -6,8 +6,8 @@ import nodeFs from 'node:fs'; import nodePath from 'node:path'; +import { obtainName } from '#lib/utility.mjs'; import responseAggregate from '../aggregate.mjs'; -import { obtainName } from '../../lib/utility.mjs'; const coinbaseAggregate = (path, fileName) => { const { config } = global.apiTools, @@ -17,10 +17,9 @@ const coinbaseAggregate = (path, fileName) => { filePathFull = nodePath.join(filePath, fileName), fileData = nodeFs.readFileSync(filePathFull), json = JSON.parse(String(fileData)), - data = json.data, - key = 'code'; + data = json.data; - responseAggregate('coinbase', path, data, key); + responseAggregate('coinbase', path, data, { id: 'asset_id', key: 'code', name: 'name' }); }; export default coinbaseAggregate; diff --git a/response/coinbase/currency/schema.mjs b/response/coinbase/currency/schema.mjs index fe5e0bb..4c3c461 100644 --- a/response/coinbase/currency/schema.mjs +++ b/response/coinbase/currency/schema.mjs @@ -5,11 +5,21 @@ * @module response/coinbase/currency/schema */ +const currency = { + properties: { + asset_id: { type: 'string' }, + code: { type: 'string' }, + name: { type: 'string' }, + }, + required: ['asset_id', 'code', 'name'], + type: 'object', +}; + export const currencyAll = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, properties: { - data: { type: 'array' }, + data: { items: currency, minItems: 1, type: 'array' }, }, required: ['data'], type: 'object', @@ -19,7 +29,7 @@ export const currencyOne = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, properties: { - data: { type: 'array' }, + data: { items: currency, minItems: 1, type: 'array' }, }, required: ['data'], type: 'object', diff --git a/response/coinbase/market/schema.mjs b/response/coinbase/market/schema.mjs index 366791c..e9dc0d3 100644 --- a/response/coinbase/market/schema.mjs +++ b/response/coinbase/market/schema.mjs @@ -5,6 +5,13 @@ * @module response/coinbase/market/schema */ +import config from '#config/coinbase.json' with { type: 'json' }; + +const { + PRODUCT, + TRADE: { SIDE }, +} = config; + export const marketAll = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, @@ -40,7 +47,7 @@ export const marketOne = { post_only: { type: 'boolean' }, price_increment: { type: 'string' }, product_id: { type: 'string' }, - product_type: { type: 'string' }, + product_type: { enum: Object.values(PRODUCT), type: 'string' }, product_venue: { type: 'string' }, price: { type: 'string' }, price_percentage_change_24h: { type: 'string' }, @@ -104,8 +111,20 @@ export const marketTickers = { properties: { best_ask: { type: 'string' }, best_bid: { type: 'string' }, - trades: { type: 'array' }, + trades: { + items: { + properties: { + product_id: { type: 'string' }, + side: { enum: Object.values(SIDE), type: 'string' }, + trade_id: { type: 'string' }, + }, + required: ['product_id', 'side', 'trade_id'], + type: 'object', + }, + minItems: 1, + type: 'array', + }, }, - required: ['best_ask', 'best_bid'], + required: ['best_ask', 'best_bid', 'trades'], type: 'object', }; diff --git a/response/coinbase/order/schema.mjs b/response/coinbase/order/schema.mjs index f53e22e..e6347b0 100644 --- a/response/coinbase/order/schema.mjs +++ b/response/coinbase/order/schema.mjs @@ -18,6 +18,16 @@ export const orderAll = { type: 'object', }; +export const orderBook = { + // "$schema": "https://json-schema.org/draft/2020-12/schema", + additionalProperties: false, + properties: { + pricebook: { type: 'object' }, + }, + required: ['pricebook'], + type: 'object', +}; + export const orderCancel = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, diff --git a/response/coinbase/parse.mjs b/response/coinbase/parse.mjs index 4801521..5c50787 100644 --- a/response/coinbase/parse.mjs +++ b/response/coinbase/parse.mjs @@ -1,107 +1,87 @@ /** - * Parse a Coinbase Advanced API response, usually for shortening long arrays. + * Parse a Coinbase Advanced API response. + * Used for retrieving response status code/description and shortening long arrays. * * @module response/coinbase/parse */ +import config from '#config/coinbase.json' with { type: 'json' }; +import { obtainName } from '#lib/utility.mjs'; +import settings from '#settings/coinbase.json' with { type: 'json' }; import filter from './parse/filter.mjs'; import find from './parse/find.mjs'; import map from './parse/map.mjs'; -import config from '../../configuration/coinbase.json' with { type: 'json' }; -import { obtainName } from '../../lib/utility.mjs'; -import settings from '../../settings/coinbase.json' with { type: 'json' }; /** - * @param {{ json: object, statusText: string }} response + * Parse response + * @param {{ json: object, status: string, statusText: string }} response * @param {string} path - * @param {object} data - * @returns {{ json: object, statusText: string }} + * @typedef Result + * @prop {string} code . + * @prop {string} description . + * @prop {object} jsonParsed . + * @prop {string} status . + * @prop {string} statusText . + * @returns {Result} */ -const responseParse = (response, path, data) => { +const responseParse = (response, path) => { /** @type {{ PATH: { [key: string]: string } }} */ const { PATH } = config; const { - PATH: { - CURRENCY_ALL, - MARKET_HISTORY, - MARKET_INFORMATION, - MARKET_TICKERS, - NETWORK_ALL, - ORDER_ALL, - TRADE_HISTORY_ALL, - }, - TRADE, + PATH: { CURRENCY_ALL, CURRENCY_ONE }, + RESPONSE: { OK, SUCCESSFUL }, } = config, { - currency: { base, quote }, parse, - } = settings; - let { json, statusText } = response; + user, + user: { portfolio }, + } = settings, + { json, status, statusText } = response, + parsed = []; + let jsonParsed; /** - * @todo Refactor to `response/parse`. + * `errors` array might be in a response of some endpoints: + * `ADDRESS` - if provide `limit` exceeding maximum value. + * `error` and `message` properties might be in a response of some endpoints: + * `MARKET_ONE` - if do not provide `product_id`. */ + const errors = json.errors, + code = json.error ?? errors?.[0]?.id ?? OK, + description = json.message ?? errors?.[0]?.message ?? SUCCESSFUL; + if (parse.includes(obtainName(path, PATH))) { - let isFiltered = true, - isFound = true, - isMapped = true; + let isFiltered = false, + isFound = false, + isMapped = false; - switch (path) { - /* case ACCOUNT_BALANCE_CURRENCIES: json = filter(json, { - criterion: (item) => Number(item.transferBalance) || Number(item.walletBalance), - list: "balance", - }); break; */ - case ORDER_ALL: - case TRADE_HISTORY_ALL: - json = filter(json, { - criterion: data.side || TRADE.BUY, - key: 'side', - list: 'list', - }); - break; - default: - isFiltered = false; - } - /* switch (path) { - case ACCOUNT_BALANCE: - json = find(json, { - criterion: data.asset ?? base, - key: 'asset', - list: 'spot_positions', - }); - break; - default: - isFound = false; - } */ switch (path) { case CURRENCY_ALL: - json = map(json, { - key: 'code', + jsonParsed = map(json, { + key: ['asset_id', 'code', 'name'], list: 'data', }); + isMapped = true; break; - case NETWORK_ALL: - json = map(json, { - key: ['coin', 'chain'], - list: ['rows', 'chains'], + case CURRENCY_ONE: + jsonParsed = find(json, { + criterion: user[portfolio].account.asset, + key: 'asset_id', + list: 'data', }); + isFound = true; break; - default: - isMapped = false; } - if (isFiltered || isFound || isMapped) { - const parsed = []; + if (isFiltered) parsed.push('items filtered'); + if (isFound) parsed.push('found one item'); + if (isMapped) parsed.push('items mapped'); - statusText += ' ('; - if (isFiltered) parsed.push('filtered'); - if (isFound) parsed.push('found'); - if (isMapped) parsed.push('mapped'); - statusText += parsed.join(', ') + ')'; - } - console.info(`Parsed endpoint "${obtainName(path, PATH)}" successfully.`); + const output = parsed.length ? ` (${parsed.join(', ')})` : ''; + + console.info(`Parsed endpoint "${obtainName(path, PATH)}" successfully${output}.`); } else console.info(`Parse: endpoint "${obtainName(path, PATH)}" is not enabled is settings.`); - return { json, statusText }; + return { code, description, jsonParsed: jsonParsed ?? json, status, statusText }; }; export default responseParse; diff --git a/response/coinbase/parse/find.mjs b/response/coinbase/parse/find.mjs index e02042b..2847cf2 100644 --- a/response/coinbase/parse/find.mjs +++ b/response/coinbase/parse/find.mjs @@ -4,20 +4,13 @@ * @module response/coinbase/parse/find */ -const data = 'breakdown'; - const find = (json, { criterion, key, list }) => { if (criterion) { - const items = json[data][list].find((item) => - key ? item[key] === criterion : criterion(item), - ); + const items = json[list].find((item) => (key ? item[key] === criterion : criterion(item))); json = { ...json, - [data]: { - ...json[data], - [list]: [items, `... ${json[data][list].length - 1} more items`], - }, + [list]: [items, `... ${json[list].length - 1} more items`], }; return json; diff --git a/response/coinbase/parse/map.mjs b/response/coinbase/parse/map.mjs index a9b4f29..c37a2b1 100644 --- a/response/coinbase/parse/map.mjs +++ b/response/coinbase/parse/map.mjs @@ -1,7 +1,7 @@ /** * Map items from a Coinbase Advanced API response array by object key. * - * @module response/bybit/parse/map + * @module response/coinbase/parse/map */ const map = (json, { key, list }) => { @@ -15,6 +15,16 @@ const map = (json, { key, list }) => { ...json, [list]: items, }; + } else if (key instanceof Array && typeof list === 'string') { + items = json[list].map((item) => ({ + [key[0]]: item[key[0]], + [key[1]]: item[key[1]], + [key[2]]: item[key[2]], + })); + data = { + ...json, + [list]: items, + }; } else if (typeof key === 'object' && typeof list === 'object') { items = json.result[list[0]].map((item1) => ({ [key[0]]: item1[key[0]], diff --git a/response/coinbase/status.json b/response/coinbase/status.json index bfea4cd..9eb21e0 100644 --- a/response/coinbase/status.json +++ b/response/coinbase/status.json @@ -50,8 +50,12 @@ "INVALID_ARGUMENT": [ "Invalid account uuid", "Invalid product_id", - "start and end argument is invalid - number of candles requested should be less than 350 " + "assetFilters parameter not enabled for OPEN orders", + "cannot pass OPEN, QUEUED or CANCEL_QUEUED status with SortBy param", + "start and end argument is invalid - number of candles requested should be less than 350 ", + "valid product_id is required" ], + "invalid_request": "Invalid `page_size` parameter for pagination (must be under 300)", "unknown": "parsing field \"product_type\": \"[object Object]\" is not a valid value" }, "CREATED": { @@ -66,8 +70,10 @@ "NOT_FOUND": { "NOT_FOUND": [ "Could not find user's account information", - "ProductID \"${product_id}\" could not be found." - ] + "ProductID \"${product_id}\" could not be found.", + "valid product_id is required" + ], + "not_found": "Not found" }, "NOT_IMPLEMENTED": { "unknown": [ @@ -76,7 +82,7 @@ ] }, "OK": { - "OK": "OK" + "0": "Successful." }, "UNAUTHORIZED": {} } diff --git a/response/coinbase/user/schema.mjs b/response/coinbase/user/schema.mjs index e7f9478..8b3ac7c 100644 --- a/response/coinbase/user/schema.mjs +++ b/response/coinbase/user/schema.mjs @@ -5,6 +5,12 @@ * @module response/coinbase/user/schema */ +import config from '#config/coinbase.json' with { type: 'json' }; + +const { + USER: { PORTFOLIO }, +} = config; + export const userAccountAll = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, @@ -41,7 +47,40 @@ export const userPortfolioOne = { // "$schema": "https://json-schema.org/draft/2020-12/schema", additionalProperties: false, properties: { - breakdown: { type: 'object' }, + breakdown: { + additionalProperties: false, + properties: { + futures_positions: { type: 'array' }, + perp_positions: { type: 'array' }, + portfolio: { + properties: { + type: { + enum: PORTFOLIO, + type: 'string', + }, + uuid: { type: 'string' }, + }, + required: ['type', 'uuid'], + type: 'object', + }, + portfolio_balances: { type: 'object' }, + spot_positions: { + items: { + properties: { + account_uuid: { type: 'string' }, + asset: { type: 'string' }, + asset_uuid: { type: 'string' }, + }, + required: ['account_uuid', 'asset', 'asset_uuid'], + type: 'object', + }, + minItems: 1, + type: 'array', + }, + }, + required: ['portfolio', 'portfolio_balances', 'spot_positions'], + type: 'object', + }, }, required: ['breakdown'], type: 'object', diff --git a/response/snapshot.mjs b/response/snapshot.mjs index dce693a..ebd794e 100644 --- a/response/snapshot.mjs +++ b/response/snapshot.mjs @@ -6,7 +6,7 @@ import nodeFs from 'node:fs'; import nodePath from 'node:path'; -import { obtainName } from '../lib/utility.mjs'; +import { obtainName } from '#lib/utility.mjs'; const responseSnapshot = (json, path, target) => { const { config, options, settings } = global.apiTools, diff --git a/response/validate.mjs b/response/validate.mjs index 064fd40..a13671e 100644 --- a/response/validate.mjs +++ b/response/validate.mjs @@ -6,11 +6,8 @@ */ import Ajv2019 from 'ajv/dist/2019.js'; -import { dirObject } from '../lib/output.mjs'; +import { dirObject } from '#lib/output.mjs'; -/** - * @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicmarkettrades - */ const responseValidate = (json, schema) => { const ajv = new Ajv2019({ allErrors: true }), validate = ajv.compile(schema), diff --git a/settings/bybit.json b/settings/bybit.json index 09896ca..94a254f 100644 --- a/settings/bybit.json +++ b/settings/bybit.json @@ -43,10 +43,12 @@ "network": "BBB", "quote": "CCC" }, + "debug": false, "enabled": ["aggregate", "parse", "snapshot"], "parse": [ "ACCOUNT_BALANCE_CURRENCIES", "CURRENCY_ALL", + "CURRENCY_NETWORK_ALL", "MARKET_HISTORY", "MARKET_INFO", "MARKET_TICKERS", @@ -88,5 +90,6 @@ "WITHDRAW_ALL", "WITHDRAW_NEW", "WITHDRAW_ONE" - ] + ], + "verbose": false } diff --git a/settings/coinbase.json b/settings/coinbase.json index 2589854..7ec3941 100644 --- a/settings/coinbase.json +++ b/settings/coinbase.json @@ -1,11 +1,17 @@ { - "account": { - "uuid": "00000000-0000-0000-0000-000000000000" - }, - "address": { - "withdraw": "" - }, "aggregate": ["CURRENCY_ALL"], + "asset": { + "base": { + "code": "AAA", + "network": "aaaaaaaa", + "uuid": "00000000-0000-0000-0000-000000000000" + }, + "quote": { + "code": "BBB", + "network": "bbbbbbbb", + "uuid": "00000000-0000-0000-0000-000000000000" + } + }, "authentication": { "delay": 1e3, "hidden": "full", @@ -17,14 +23,9 @@ }, "security": "JWT" }, - "currency": { - "base": "AAA", - "network": "BBB", - "quote": "CCC", - "uuid": "00000000-0000-0000-0000-000000000000" - }, + "debug": false, "enabled": ["aggregate", "parse", "snapshot", "verbose"], - "parse": ["ACCOUNT_BALANCE"], + "parse": ["CURRENCY_ALL", "CURRENCY_ONE"], "snapshot": [ "ADDRESS", "ADDRESS_ONE", @@ -35,6 +36,7 @@ "MARKET_ONE", "MARKET_TICKERS", "ORDER_ALL", + "ORDER_BOOK", "ORDER_CANCEL", "ORDER_ONE", "ORDER_PLACE", @@ -46,12 +48,15 @@ "USER_PORTFOLIO_ONE" ], "user": { - "00000000-0000-0000-0000-000000000000": { - "main": true, - "permissions": [] + "DEFAULT": { + "account": { + "address": ["00000000-0000-0000-0000-000000000000"], + "asset": "00000000-0000-0000-0000-000000000000", + "uuid": "00000000-0000-0000-0000-000000000000" + }, + "uuid": "00000000-0000-0000-0000-000000000000" }, - "DEFAULT": "00000000-0000-0000-0000-000000000000", - "account": "00000000-0000-0000-0000-000000000000", "portfolio": "DEFAULT" - } + }, + "verbose": false } diff --git a/socket/coinbase.js b/socket/coinbase.js index 983ef9d..4782ad2 100644 --- a/socket/coinbase.js +++ b/socket/coinbase.js @@ -4,6 +4,10 @@ * @module socket/coinbase */ +import { optional } from '#lib/template.mjs'; +import { parseArguments } from '#lib/utility.mjs'; +import settings from '#settings/coinbase.json' with { type: 'json' }; + import candles from './coinbase/channel/candles.mjs'; import futuresBalance from './coinbase/channel/futures_balance.mjs'; import heartbeats from './coinbase/channel/heartbeats.mjs'; @@ -14,9 +18,6 @@ import ticker from './coinbase/channel/ticker.mjs'; import tickerBatch from './coinbase/channel/ticker_batch.mjs'; import user from './coinbase/channel/user.mjs'; import config from '../configuration/coinbase.json' with { type: 'json' }; -import { optional } from '../lib/template.mjs'; -import { parseArguments } from '../lib/utility.mjs'; -import settings from '../settings/coinbase.json' with { type: 'json' }; const requestCoinbase = () => { const { handler, params } = parseArguments(); diff --git a/socket/coinbase.mjs b/socket/coinbase.mjs index 30fd68a..a7cdc3e 100644 --- a/socket/coinbase.mjs +++ b/socket/coinbase.mjs @@ -4,15 +4,16 @@ * @module request/coinbase */ -import config from '../configuration/coinbase.json' with { type: 'json' }; -import { optional } from '../lib/template.mjs'; -import { parseArguments } from '../lib/utility.mjs'; -import settings from '../settings/coinbase.json' with { type: 'json' }; +import config from '#config/coinbase.json' with { type: 'json' }; +import { optional } from '#lib/template.mjs'; +import { parseArguments } from '#lib/utility.mjs'; +import settings from '#settings/coinbase.json' with { type: 'json' }; + import level2 from './coinbase/level2.mjs'; -const { ACCOUNT, TRADE } = config, +const { TRADE } = config, { - currency: { base, network }, + asset: { base }, } = settings, requestCoinbase = () => { const { handler, params } = parseArguments(); diff --git a/socket/coinbase/subscribe.mjs b/socket/coinbase/subscribe.mjs index 76c9883..610a86a 100644 --- a/socket/coinbase/subscribe.mjs +++ b/socket/coinbase/subscribe.mjs @@ -12,11 +12,11 @@ * @module socket/coinbase/subscribe */ -import config from '../../configuration/coinbase.json' with { type: 'json' }; -import { signJwt } from '../../lib/authentication.mjs'; -import { AUTH } from '../../lib/constants.mjs'; -import { socketData } from '../../lib/socket.mjs'; -import settings from '../../settings/coinbase.json' with { type: 'json' }; +import config from '#config/coinbase.json' with { type: 'json' }; +import { signJwt } from '#lib/authentication.mjs'; +import { AUTH } from '#lib/constants.mjs'; +import { socketData } from '#lib/socket.mjs'; +import settings from '#settings/coinbase.json' with { type: 'json' }; /** * @returns {Promise} @@ -46,7 +46,7 @@ const coinbaseSubscribe = async (security, channel, data = {}) => { }; if (security === AUTH.SECURITY.JWT) { - message.jwt = signJwt(ENCODING, payload, secret, key); + message.jwt = signJwt(/** @type {"hex"}*/ (ENCODING), payload, secret, key); } const socket = socketData(URL, message); diff --git a/socket/coinbase/unsubscribe.mjs b/socket/coinbase/unsubscribe.mjs index 7dddffe..1f7bbd3 100644 --- a/socket/coinbase/unsubscribe.mjs +++ b/socket/coinbase/unsubscribe.mjs @@ -10,10 +10,10 @@ * @module socket/coinbase/unsubscribe */ -import config from '../../configuration/coinbase.json' with { type: 'json' }; -import { signJwt } from '../../lib/authentication.mjs'; -import { AUTH } from '../../lib/constants.mjs'; -import settings from '../../settings/coinbase.json' with { type: 'json' }; +import config from '#config/coinbase.json' with { type: 'json' }; +import { signJwt } from '#lib/authentication.mjs'; +import { AUTH } from '#lib/constants.mjs'; +import settings from '#settings/coinbase.json' with { type: 'json' }; /** * @returns {Promise} @@ -43,7 +43,7 @@ const coinbaseUnsubscribe = async (data, socket) => { console.log('coinbaseUnsubscribe', message); if (security === AUTH.SECURITY.JWT) { - message.jwt = signJwt(ENCODING, payload, secret, key); + message.jwt = signJwt(/** @type {"hex"}*/ (ENCODING), payload, secret, key); } socket.send(JSON.stringify(message)); diff --git a/socket/coinbase/validate.mjs b/socket/coinbase/validate.mjs index 42c1d26..599bc89 100644 --- a/socket/coinbase/validate.mjs +++ b/socket/coinbase/validate.mjs @@ -4,8 +4,8 @@ * @module request/coinbase/validate */ +import { fileNameNewest, fileReadJson } from '#lib/file_system.mjs'; import requestValidate from '../validate.mjs'; -import { fileNameNewest, fileReadJson } from '../../lib/file_system.mjs'; const isValid = (param) => { const { config } = global.apiTools, diff --git a/socket/validate.mjs b/socket/validate.mjs index deef200..c208ae4 100644 --- a/socket/validate.mjs +++ b/socket/validate.mjs @@ -4,7 +4,7 @@ * @module socket/validate */ -import { throwRequired, warnOptional, warnRequired } from '../lib/output.mjs'; +import { throwRequired, warnOptional, warnRequired } from '#lib/output.mjs'; const socketValidate = (path, isValidParams, defaults, ...options) => { const data = { ...defaults }, diff --git a/types/request/coinbase/address/transactions.d.js b/types/request/coinbase/address/transactions.d.js new file mode 100644 index 0000000..ad36730 --- /dev/null +++ b/types/request/coinbase/address/transactions.d.js @@ -0,0 +1,18 @@ +/** + * @typedef T + * @type {{ + * data: [ + * { + * "id": string, + * "network": { + * "name": "bitcoin" | "ethereum", + * "status": "off_blockchain", + * }, + * "status": "completed", + * "type": "send", + * } + * ] | [] + * }} + */ + +export default null; From cd8af83634e124988e752bd8b1ef23575bf4d219 Mon Sep 17 00:00:00 2001 From: Definite Prototype <5364018+graycraft@users.noreply.github.com> Date: Thu, 10 Oct 2024 20:03:48 +0500 Subject: [PATCH 2/3] fix: apply patch 9 --- .editorconfig | 17 +- .env | 1 + .gitignore | 1 + .prettierignore | 1 + README.md | 67 +- __tests__/library/utility.test.js | 69 + .../2024-09-18T00:25:03.651Z.json | 555 -- .../2024-10-02T00:03:02.752Z.json | 6068 +++++++++++++++++ .../2024-09-03T21:55:38.458Z.json | 251 - .../2024-10-02T00:29:39.769Z.json | 1247 ++++ configuration/bybit.json | 4 +- configuration/example.json | 52 - jest.config.mjs | 195 + jsconfig.json | 40 +- library/array.mjs | 47 +- library/authentication.mjs | 83 +- library/boolean.mjs | 11 +- library/constants.mjs | 56 +- library/fetch.mjs | 97 +- library/file_system.mjs | 31 +- library/output.mjs | 116 +- library/socket.mjs | 4 +- library/string.mjs | 12 +- library/template.mjs | 2 +- library/utility.mjs | 184 +- library/validation.mjs | 24 +- package-lock.json | 5629 +++++++++++++-- package.json | 24 +- preferences/bybit.json | 57 + preferences/coinbase.json | 28 + request.js | 6 +- request.mjs | 65 - request/README.md | 39 - request/bybit.js | 359 +- request/bybit/account/README.md | 64 - request/bybit/account/information.mjs | 5 +- request/bybit/account/wallets.mjs | 5 +- request/bybit/balance/README.md | 64 - request/bybit/balance/all.mjs | 10 +- request/bybit/balance/information.mjs | 10 +- request/bybit/balance/one.mjs | 17 +- request/bybit/currency/README.md | 26 - request/bybit/currency/all.mjs | 5 +- request/bybit/currency/network-all.mjs | 7 +- request/bybit/currency/network-one.mjs | 13 +- request/bybit/currency/one.mjs | 10 +- request/bybit/deposit/README.md | 66 - request/bybit/deposit/all.mjs | 9 +- request/bybit/deposit/new-master.mjs | 9 +- request/bybit/deposit/new-sub.mjs | 11 +- request/bybit/deposit/one.mjs | 9 +- request/bybit/get.mjs | 33 +- request/bybit/index.mjs | 366 + request/bybit/key/README.md | 17 - request/bybit/key/information.mjs | 5 +- request/bybit/market/README.md | 18 - request/bybit/market/history.mjs | 13 +- request/bybit/market/information.mjs | 19 +- request/bybit/market/tickers.mjs | 17 +- request/bybit/order/all.mjs | 10 +- request/bybit/order/book.mjs | 11 +- request/bybit/order/cancel-all.mjs | 10 +- request/bybit/order/cancel-one.mjs | 10 +- request/bybit/order/history-all.mjs | 11 +- request/bybit/order/history-one.mjs | 11 +- request/bybit/order/limit-buy.mjs | 20 +- request/bybit/order/limit-sell.mjs | 20 +- request/bybit/order/market-buy.mjs | 20 +- request/bybit/order/market-sell.mjs | 20 +- request/bybit/order/one.mjs | 10 +- request/bybit/post.mjs | 35 +- request/bybit/sign.mjs | 27 +- request/bybit/trade/history-all.mjs | 13 +- request/bybit/trade/history-one.mjs | 10 +- request/bybit/trade/rates.mjs | 9 +- request/bybit/transfer/all.mjs | 8 +- request/bybit/transfer/internal.mjs | 12 +- request/bybit/transfer/one.mjs | 10 +- request/bybit/validate.mjs | 39 +- request/bybit/withdraw/all.mjs | 7 +- request/bybit/withdraw/new.mjs | 23 +- request/bybit/withdraw/one.mjs | 7 +- request/coinbase.js | 204 +- request/coinbase/address/README.md | 26 - request/coinbase/address/all.mjs | 13 +- request/coinbase/address/new.mjs | 11 +- request/coinbase/address/one.mjs | 13 +- request/coinbase/address/transactions.mjs | 4 +- request/coinbase/currency/README.md | 26 - request/coinbase/currency/all.mjs | 17 +- request/coinbase/currency/one.mjs | 23 +- request/coinbase/get.mjs | 35 +- request/coinbase/index.mjs | 218 + request/coinbase/market/all.mjs | 11 +- request/coinbase/market/one.mjs | 16 +- request/coinbase/market/tickers.mjs | 17 +- request/coinbase/order/all.mjs | 7 +- request/coinbase/order/book.mjs | 5 +- request/coinbase/order/cancel.mjs | 5 +- request/coinbase/order/limit-buy.mjs | 17 +- request/coinbase/order/limit-sell.mjs | 17 +- request/coinbase/order/market-buy.mjs | 17 +- request/coinbase/order/market-sell.mjs | 17 +- request/coinbase/order/one.mjs | 5 +- request/coinbase/post.mjs | 50 +- request/coinbase/sign.mjs | 22 +- request/coinbase/transaction/README.md | 66 - request/coinbase/transaction/all.mjs | 5 +- request/coinbase/transaction/one.mjs | 5 +- request/coinbase/user/account-all.mjs | 5 +- request/coinbase/user/account-one.mjs | 11 +- request/coinbase/user/portfolio-all.mjs | 12 +- request/coinbase/user/portfolio-one.mjs | 18 +- request/coinbase/validate.mjs | 27 +- request/get.mjs | 25 +- request/index.mjs | 82 + request/post.mjs | 21 +- request/validate.mjs | 33 +- response.js | 6 +- response/README.md | 73 - response/aggregate.mjs | 122 +- response/analyze.mjs | 23 +- response/bybit.js | 39 +- response/bybit/account/schema.mjs | 10 +- response/bybit/aggregate.mjs | 39 +- response/bybit/balance/schema.mjs | 12 +- response/bybit/currency/all.mjs | 16 +- response/bybit/currency/network-all.mjs | 18 +- response/bybit/currency/schema.mjs | 20 +- response/bybit/deposit/schema.mjs | 16 +- response/bybit/index.mjs | 59 + response/bybit/key/schema.mjs | 6 +- response/bybit/market/schema.mjs | 18 +- response/bybit/network/all.mjs | 25 - response/bybit/network/schema.mjs | 34 - response/bybit/order/schema.mjs | 60 +- response/bybit/parse.mjs | 193 +- response/bybit/parse/filter.mjs | 8 +- response/bybit/parse/find.mjs | 13 +- response/bybit/parse/map.mjs | 11 +- response/bybit/snapshot.mjs | 16 +- response/bybit/trade/schema.mjs | 16 +- response/bybit/transfer/schema.mjs | 20 +- response/bybit/withdraw/schema.mjs | 20 +- response/coinbase.js | 38 +- response/coinbase/account/schema.mjs | 30 - response/coinbase/address/all.mjs | 19 - response/coinbase/address/schema.mjs | 8 +- response/coinbase/aggregate.mjs | 40 +- response/coinbase/currency/all.mjs | 18 +- response/coinbase/currency/schema.mjs | 4 +- response/coinbase/index.mjs | 54 + response/coinbase/market/schema.mjs | 6 +- response/coinbase/network/all.mjs | 21 - response/coinbase/order/schema.mjs | 16 +- response/coinbase/parse.mjs | 138 +- response/coinbase/parse/filter.mjs | 17 +- response/coinbase/parse/find.mjs | 15 +- response/coinbase/parse/map.mjs | 9 + response/coinbase/schema/market/history.mjs | 20 - response/coinbase/snapshot.mjs | 18 +- response/coinbase/transaction/schema.mjs | 4 +- response/coinbase/user/schema.mjs | 8 +- response/parse.mjs | 55 + response/snapshot.mjs | 86 +- response/validate.mjs | 12 +- settings/bybit.json | 86 +- settings/coinbase.json | 28 +- socket/coinbase.js | 25 +- socket/coinbase.mjs | 38 - socket/coinbase/channel/candles.mjs | 10 +- socket/coinbase/channel/futures_balance.mjs | 14 +- socket/coinbase/channel/heartbeats.mjs | 6 +- socket/coinbase/channel/level2.mjs | 10 +- socket/coinbase/channel/market_trades.mjs | 10 +- socket/coinbase/channel/status.mjs | 10 +- socket/coinbase/channel/ticker.mjs | 16 +- socket/coinbase/channel/ticker_batch.mjs | 10 +- socket/coinbase/channel/user.mjs | 14 +- socket/coinbase/level2.mjs | 36 - socket/coinbase/subscribe.mjs | 4 +- socket/coinbase/unsubscribe.mjs | 8 +- socket/coinbase/validate.mjs | 8 +- socket/validate.mjs | 8 +- types/api.d.ts | 55 + types/bybit.d.ts | 243 + types/coinbase.d.ts | 44 + types/common.d.ts | 10 + types/global.d.ts | 24 + .../coinbase/address/transactions.d.js | 18 - types/response/bybit.d.js | 9 + types/response/bybit/account/information.d.js | 19 + types/response/bybit/account/wallets.d.js | 16 + types/response/bybit/balance/all.d.js | 20 + types/response/bybit/balance/information.d.js | 44 + types/response/bybit/balance/one.d.js | 20 + types/response/bybit/currency/all.d.js | 13 + .../response/bybit/currency/network-all.d.js | 5 + .../response/bybit/currency/network-one.d.js | 5 + types/response/bybit/currency/one.d.js | 28 + types/response/bybit/deposit/all.d.js | 14 + types/response/bybit/deposit/new-master.d.js | 19 + types/response/bybit/deposit/new-sub.d.js | 19 + types/response/bybit/deposit/one.d.js | 29 + types/response/bybit/key/information.d.js | 47 + types/response/bybit/market/history.d.js | 23 + types/response/bybit/market/information.d.js | 40 + types/response/bybit/market/tickers.d.js | 27 + types/response/bybit/order/all.d.js | 13 + types/response/bybit/order/book.d.js | 24 + types/response/bybit/order/cancel-all.d.js | 14 + types/response/bybit/order/cancel-one.d.js | 13 + types/response/bybit/order/history-all.d.js | 13 + types/response/bybit/order/history-one.d.js | 13 + types/response/bybit/order/limit-buy.d.js | 5 + types/response/bybit/order/limit-sell.d.js | 5 + types/response/bybit/order/market-buy.d.js | 5 + types/response/bybit/order/market-sell.d.js | 5 + types/response/bybit/order/one.d.js | 71 + types/response/bybit/trade/history-all.d.js | 16 + types/response/bybit/trade/history-one.d.js | 47 + types/response/bybit/trade/rates.d.js | 19 + types/response/bybit/transfer/all.d.js | 14 + types/response/bybit/transfer/internal.d.js | 14 + types/response/bybit/transfer/one.d.js | 14 + types/response/bybit/withdraw/all.d.js | 15 + types/response/bybit/withdraw/new.d.js | 12 + types/response/bybit/withdraw/one.d.js | 28 + types/response/coinbase.d.js | 3 + types/response/coinbase/address/all.d.js | 7 + types/response/coinbase/address/new.d.js | 10 + types/response/coinbase/address/one.d.js | 10 + .../coinbase/address/transactions.d.js | 14 + types/response/coinbase/currency/all.d.js | 7 + types/response/coinbase/currency/one.d.js | 10 + types/response/coinbase/market/all.d.js | 7 + types/response/coinbase/market/one.d.js | 10 + types/response/coinbase/market/tickers.d.js | 13 + types/response/coinbase/order/all.d.js | 7 + types/response/coinbase/order/book.d.js | 8 + types/response/coinbase/order/cancel.d.js | 9 + types/response/coinbase/order/limit-buy.d.js | 10 + types/response/coinbase/order/limit-sell.d.js | 10 + types/response/coinbase/order/market-buy.d.js | 10 + .../response/coinbase/order/market-sell.d.js | 10 + types/response/coinbase/order/one.d.js | 9 + types/response/coinbase/transaction/all.d.js | 7 + types/response/coinbase/transaction/one.d.js | 8 + types/response/coinbase/user/account-all.d.js | 4 + types/response/coinbase/user/account-one.d.js | 4 + .../response/coinbase/user/portfolio-all.d.js | 8 + .../response/coinbase/user/portfolio-one.d.js | 18 + types/response/snapshot.d.js | 29 + types/socket/message.d.js | 4 +- 254 files changed, 16572 insertions(+), 4424 deletions(-) create mode 100644 __tests__/library/utility.test.js delete mode 100644 collection/bybit/currency_all/2024-09-18T00:25:03.651Z.json create mode 100644 collection/bybit/currency_all/2024-10-02T00:03:02.752Z.json delete mode 100644 collection/coinbase/currency_all/2024-09-03T21:55:38.458Z.json create mode 100644 collection/coinbase/currency_all/2024-10-02T00:29:39.769Z.json delete mode 100644 configuration/example.json create mode 100644 jest.config.mjs create mode 100644 preferences/bybit.json create mode 100644 preferences/coinbase.json delete mode 100644 request.mjs delete mode 100644 request/README.md delete mode 100644 request/bybit/account/README.md delete mode 100644 request/bybit/balance/README.md delete mode 100644 request/bybit/currency/README.md delete mode 100644 request/bybit/deposit/README.md create mode 100644 request/bybit/index.mjs delete mode 100644 request/bybit/key/README.md delete mode 100644 request/bybit/market/README.md delete mode 100644 request/coinbase/address/README.md delete mode 100644 request/coinbase/currency/README.md create mode 100644 request/coinbase/index.mjs delete mode 100644 request/coinbase/transaction/README.md create mode 100644 request/index.mjs delete mode 100644 response/README.md create mode 100644 response/bybit/index.mjs delete mode 100644 response/bybit/network/all.mjs delete mode 100644 response/bybit/network/schema.mjs delete mode 100644 response/coinbase/account/schema.mjs delete mode 100644 response/coinbase/address/all.mjs create mode 100644 response/coinbase/index.mjs delete mode 100644 response/coinbase/network/all.mjs delete mode 100644 response/coinbase/schema/market/history.mjs create mode 100644 response/parse.mjs delete mode 100644 socket/coinbase.mjs delete mode 100644 socket/coinbase/level2.mjs create mode 100644 types/api.d.ts create mode 100644 types/bybit.d.ts create mode 100644 types/coinbase.d.ts create mode 100644 types/common.d.ts create mode 100644 types/global.d.ts delete mode 100644 types/request/coinbase/address/transactions.d.js create mode 100644 types/response/bybit.d.js create mode 100644 types/response/bybit/account/information.d.js create mode 100644 types/response/bybit/account/wallets.d.js create mode 100644 types/response/bybit/balance/all.d.js create mode 100644 types/response/bybit/balance/information.d.js create mode 100644 types/response/bybit/balance/one.d.js create mode 100644 types/response/bybit/currency/all.d.js create mode 100644 types/response/bybit/currency/network-all.d.js create mode 100644 types/response/bybit/currency/network-one.d.js create mode 100644 types/response/bybit/currency/one.d.js create mode 100644 types/response/bybit/deposit/all.d.js create mode 100644 types/response/bybit/deposit/new-master.d.js create mode 100644 types/response/bybit/deposit/new-sub.d.js create mode 100644 types/response/bybit/deposit/one.d.js create mode 100644 types/response/bybit/key/information.d.js create mode 100644 types/response/bybit/market/history.d.js create mode 100644 types/response/bybit/market/information.d.js create mode 100644 types/response/bybit/market/tickers.d.js create mode 100644 types/response/bybit/order/all.d.js create mode 100644 types/response/bybit/order/book.d.js create mode 100644 types/response/bybit/order/cancel-all.d.js create mode 100644 types/response/bybit/order/cancel-one.d.js create mode 100644 types/response/bybit/order/history-all.d.js create mode 100644 types/response/bybit/order/history-one.d.js create mode 100644 types/response/bybit/order/limit-buy.d.js create mode 100644 types/response/bybit/order/limit-sell.d.js create mode 100644 types/response/bybit/order/market-buy.d.js create mode 100644 types/response/bybit/order/market-sell.d.js create mode 100644 types/response/bybit/order/one.d.js create mode 100644 types/response/bybit/trade/history-all.d.js create mode 100644 types/response/bybit/trade/history-one.d.js create mode 100644 types/response/bybit/trade/rates.d.js create mode 100644 types/response/bybit/transfer/all.d.js create mode 100644 types/response/bybit/transfer/internal.d.js create mode 100644 types/response/bybit/transfer/one.d.js create mode 100644 types/response/bybit/withdraw/all.d.js create mode 100644 types/response/bybit/withdraw/new.d.js create mode 100644 types/response/bybit/withdraw/one.d.js create mode 100644 types/response/coinbase.d.js create mode 100644 types/response/coinbase/address/all.d.js create mode 100644 types/response/coinbase/address/new.d.js create mode 100644 types/response/coinbase/address/one.d.js create mode 100644 types/response/coinbase/address/transactions.d.js create mode 100644 types/response/coinbase/currency/all.d.js create mode 100644 types/response/coinbase/currency/one.d.js create mode 100644 types/response/coinbase/market/all.d.js create mode 100644 types/response/coinbase/market/one.d.js create mode 100644 types/response/coinbase/market/tickers.d.js create mode 100644 types/response/coinbase/order/all.d.js create mode 100644 types/response/coinbase/order/book.d.js create mode 100644 types/response/coinbase/order/cancel.d.js create mode 100644 types/response/coinbase/order/limit-buy.d.js create mode 100644 types/response/coinbase/order/limit-sell.d.js create mode 100644 types/response/coinbase/order/market-buy.d.js create mode 100644 types/response/coinbase/order/market-sell.d.js create mode 100644 types/response/coinbase/order/one.d.js create mode 100644 types/response/coinbase/transaction/all.d.js create mode 100644 types/response/coinbase/transaction/one.d.js create mode 100644 types/response/coinbase/user/account-all.d.js create mode 100644 types/response/coinbase/user/account-one.d.js create mode 100644 types/response/coinbase/user/portfolio-all.d.js create mode 100644 types/response/coinbase/user/portfolio-one.d.js create mode 100644 types/response/snapshot.d.js diff --git a/.editorconfig b/.editorconfig index cefcd2a..9ad1f28 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,16 +1,19 @@ -# @see https://editorconfig.org -# @see https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig +# https://editorconfig.org +# https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig -charset = utf-8 -[*] root = true -[*.{cjs,es,es6,js,jsm,json,json5,json6,jsonc,jsox,jsx,mjs,node,ts,tsx}] + +[**/*] +charset = utf-8 + +[**/*.{cjs,cjsx,cts,ctsx,es,es6,js,jsm,json,json5,json6,jsonc,jsox,jsx,mjs,mjsx,mts,mtsx,node,ts,tsx}] end_of_line = lf indent_size = 2 indent_style = space insert_final_newline = true max_line_length = 120 trim_trailing_whitespace = true -[*.md] -# @see https://github.com/Microsoft/vscode/issues/1679#issuecomment-323608456 + +# https://github.com/Microsoft/vscode/issues/1679#issuecomment-323608456 +[**/*.md] trim_trailing_whitespace = false diff --git a/.env b/.env index 1b4a45b..834b5a5 100644 --- a/.env +++ b/.env @@ -1 +1,2 @@ NODE_NO_WARNINGS=1 +NODE_OPTIONS=--experimental-vm-modules diff --git a/.gitignore b/.gitignore index 1ad1abe..b9adc11 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +coverage node_modules response/**/snapshot diff --git a/.prettierignore b/.prettierignore index 8e30a91..701fbea 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ # Directories with auto-generated files. .vscode collection +coverage response/**/snapshot diff --git a/README.md b/README.md index 78d2540..c844ceb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # API Tools -Tools to work with a REST API (WebSocket and GraphQL support is on the way). +Tools to work with a REST API and WebSocket. This package allows to: @@ -71,7 +71,9 @@ $ npm i ### Environment -Optionally `NODE_NO_WARNINGS` can be exported from `.env` file to silence process warnings regarding experimental features: +Optionally `NODE_NO_WARNINGS` can be exported from `.env` file to silence process warnings regarding experimental features. + +This command also enables `--experimental-vm-modules` option for running [Jest with ESM](https://jestjs.io/docs/ecmascript-modules): ```bash $ export $(cat .env | xargs) @@ -86,13 +88,66 @@ Open settings file of an API and set appropriate fields in `account`, `address` General syntax of commands: ```bash -$ node [ --] -$ node [ ][ ][ ][ --