@coinbase/coinbase-cli 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +33 -33
- package/dist/version.txt +1 -1
- package/package.json +1 -1
- package/skills/coinbase/SKILL.md +32 -0
package/dist/index.js
CHANGED
|
@@ -40,21 +40,21 @@ $cred.Persist = 2
|
|
|
40
40
|
if (-not [Win32.Cred]::CredWrite([ref]$cred, 0)) {
|
|
41
41
|
throw "CredWrite failed: $([Runtime.InteropServices.Marshal]::GetLastWin32Error())"
|
|
42
42
|
}
|
|
43
|
-
[Runtime.InteropServices.Marshal]::FreeHGlobal($blob)`,yt(n))}delete(e,r){try{We(`[void][Win32.Cred]::CredDelete('${de(ze(e,r))}', 1, 0)`)}catch{}}}});function zt(){if(
|
|
44
|
-
`),Qr=!0),
|
|
43
|
+
[Runtime.InteropServices.Marshal]::FreeHGlobal($blob)`,yt(n))}delete(e,r){try{We(`[void][Win32.Cred]::CredDelete('${de(ze(e,r))}', 1, 0)`)}catch{}}}});function zt(){if(ot!==void 0)return ot;try{process.platform==="darwin"?ot=new ce:process.platform==="linux"?ot=new ue:process.platform==="win32"?ot=new ge:ot=null}catch{Qr||(process.stderr.write(`warning: OS keychain not accessible \u2014 secrets stored in keychain will not be available
|
|
44
|
+
`),Qr=!0),ot=null}return ot}function Jr(t){let e=zt();if(!e)return null;try{return e.get(gt,t)}catch{return null}}function Xr(t,e){let r=zt();if(!r)return!1;try{return r.set(gt,t,e),!0}catch{return!1}}function Zr(t){let e=zt();if(e)try{e.delete(gt,t)}catch{}}function tn(){return zt()!==null}function en(){let t=zt();if(!t)return!1;let e="__coinbase_cli_preflight__";try{t.set(gt,e,"ok");let r=t.get(gt,e);return t.delete(gt,e),r==="ok"}catch{try{t.delete(gt,e)}catch{}return!1}}var gt,ot,Qr,Ve=h(()=>{"use strict";l();p();Hr();jr();Yr();gt="coinbase-cli",Qr=!1});var un={};Bt(un,{activeEnvName:()=>Ot,activeEnvironment:()=>$t,authIsViable:()=>Ke,builtinEnvironments:()=>K,clearEnvCredentialCache:()=>Je,clearEnvironmentSecretsFromKeychain:()=>Ye,clearHistory:()=>Ht,configDir:()=>at,configPath:()=>Y,credentialsFor:()=>Vt,envCredential:()=>Wt,getHistory:()=>tr,historyEnabled:()=>pe,hydrateEnvironmentSecrets:()=>cn,isBuiltinURL:()=>vt,loadConfig:()=>H,resolveURL:()=>Z,saveConfig:()=>tt,scrubbedEnv:()=>Xe,setHistory:()=>Ze,setLockOptions:()=>no,withConfigLock:()=>Qe,writeEnvironmentSecretsToKeychain:()=>_n});import{readFileSync as sn,writeFileSync as on,mkdirSync as an,renameSync as Js,unlinkSync as $e,openSync as Xs,closeSync as Zs,statSync as to}from"node:fs";import{homedir as rn}from"node:os";import{join as le}from"node:path";function at(){if(process.env.COINBASE_CONFIG_DIR)return process.env.COINBASE_CONFIG_DIR;if(process.platform==="win32"){let t=process.env.APPDATA??le(rn(),"AppData","Roaming");return le(t,"coinbase")}return le(rn(),".config","coinbase")}function Y(){return le(at(),"config.json")}function Z(t,e){if(t.url)return t.url;if(K[e])return K[e];let r=nn[e];if(r&&K[r])return K[r];let n={...K};for(let[s,a]of Object.entries(nn))K[a]&&(n[s]=K[a]);let i=Object.keys(n).find(s=>e.startsWith(s+"-"));return i?n[i]:""}function vt(t){return Object.values(K).some(e=>t.startsWith(e))}function eo(t,e){return Object.values(kt[e].secrets).map(r=>r(t))}function Ke(t){if(!t)return!1;let e=kt[t.type];return e?Object.keys(e.secrets).every(r=>!!t[r]):!1}function cn(t,e){if(!e.auth)return e;let r=kt[e.auth.type];if(!r)return e;let n=e.auth,i={...n},s=!1,a=!1;for(let[o,c]of Object.entries(r.secrets)){if(n[o]){a=!0;continue}let d=Jr(c(t));d&&(i[o]=d,s=!0)}return Ke(i)?{...e,auth:i,...a&&!s?{_plaintextBacked:!0}:{}}:{...e,auth:void 0}}function _n(t,e){if(!e.auth)return!0;if(!tn())return!1;let r=e.auth.type,n=kt[r];if(!n)return!0;if(!Ke(e.auth)){let s=Object.keys(n.secrets).filter(a=>!e.auth[a]);throw new Error(`writeEnvironmentSecretsToKeychain: ${r} for "${t}" missing ${s.join(", ")}`)}let i=!0;for(let[s,a]of Object.entries(n.secrets))Xr(a(t),e.auth[s])||(i=!1);return i}function Ye(t){for(let e of Object.keys(kt))for(let r of eo(t,e))Zr(r)}function Wt(t){return t.auth}function Vt(t,e){if(e.auth?.type==="cdp_key")return{keyId:e.auth.key_id,keySecret:e.auth.key_secret};throw new Error(`environment "${t}" has no credentials. Run: coinbase env ${t} --key-file path/to/key.json`)}function H(){let t={env:"",environments:{},history:{}};try{let e=sn(Y(),"utf8"),r=JSON.parse(e);t.env=r.env??"";let n=r.environments??{};for(let[i,s]of Object.entries(n))t.environments[i]=cn(i,s);return t.history=r.history??{},r.settings&&(t.settings=r.settings),t}catch(e){if(e.code!=="ENOENT")throw e instanceof SyntaxError?new Error(`invalid config JSON: ${e.message}`):new Error(`reading config: ${e.message}`)}return t}function tt(t,e={}){let r=at();an(r,{recursive:!0,mode:448});let n={},i=[];for(let[c,d]of Object.entries(t.environments)){let _={};if(d.url!==void 0&&(_.url=d.url),!d.auth){n[c]=_;continue}let u=_n(c,d),g=e.allowPlaintext===!0||d._plaintextBacked===!0;if(!u){if(!g){i.push(c);continue}_.auth=d.auth,n[c]=_;continue}let f=kt[d.auth.type];f&&(_.auth=f.metadataOnly(d.auth)),n[c]=_}if(i.length)throw new Error(`OS keychain unavailable; refusing to persist secrets for environment(s): ${i.join(", ")}.
|
|
45
45
|
Re-run the env-setup command with --allow-plaintext-secrets to write secrets to ${Y()} (file is mode 0600), or install/unlock your OS keychain (macOS Keychain, libsecret on Linux, Windows Credential Manager).`);let s={env:t.env,environments:n};Object.keys(t.history).length>0&&(s.history=t.history),t.settings&&(s.settings=t.settings);let a=Y(),o=`${a}.${process.pid}.${Date.now()}.tmp`;try{on(o,JSON.stringify(s,null,2)+`
|
|
46
|
-
`,{mode:384}),Js(o,a)}catch(c){try{$e(o)}catch{}throw c}}function no(t){Et={...Et,...t}}function It(){return Y()+ro}function io(t){let e=Date.now()+t;for(;Date.now()<e;);}function so(){try{let t=Xs(It(),"wx",384);return on(t,String(process.pid)),t}catch(t){if(t.code!=="EEXIST")throw t;return null}}function oo(){try{let t=to(It());if(Date.now()-t.mtimeMs<Et.staleAfterMs)return!1;let e=sn(It(),"utf8").trim(),r=Number(e);if(!Number.isInteger(r)||r<=0)return!0;try{return process.kill(r,0),!1}catch(n){return n.code==="ESRCH"}}catch{return!1}}function Qe(t){an(
|
|
47
|
-
`)),!Z(n,r))throw new Error(`no URL for environment "${r}". Set url in config or use a built-in env name`);if(!n.auth)throw new Error(`no credentials for "${r}". Run: coinbase env ${r} --key-file path/to/key.json`);return{name:r,env:n}}function Xe(){let t={...process.env};for(let e of co)delete t[e];return t}function pe(t){return process.env.COINBASE_NO_HISTORY?!1:t.settings?.history?.enabled!==!1}function Ze(t,e,r,n){t.history[e]||(t.history[e]={}),t.history[e][r]={last_used:new Date().toISOString(),values:n}}function tr(t,e,r){return t.history[e]?.[r]}function Ht(t,e,r){if(e&&r)return t.history[e]?.[r]?(delete t.history[e][r],Object.keys(t.history[e]).length===0&&delete t.history[e],1):0;if(e){let i=Object.keys(t.history[e]??{}).length;return delete t.history[e],i}let n=Object.values(t.history).reduce((i,s)=>i+Object.keys(s).length,0);return t.history={},n}var K,nn,kt,ro,Et,He,je,co,Q=h(()=>{"use strict";l();p();ie();Ve();K=Vr,nn=$r;kt={cdp_key:{secrets:{key_secret:t=>`${t}:cdp:key_secret`},metadataOnly:t=>({type:"cdp_key",key_id:t.key_id})}};ro=".lock",Et={retries:50,baseDelayMs:20,staleAfterMs:5e3};co=["COINBASE_KEY_SECRET","COINBASE_KEY_ID"]});function fo(t,e,r){let n=new Date(Date.UTC(t,e-1,r));return n.getUTCFullYear()===t&&n.getUTCMonth()===e-1&&n.getUTCDate()===r}var J,X,gn,ln,pn,Pt=h(()=>{"use strict";l();p();J=[{name:"convert",actions:[{id:"convert_quote",name:"quote",method:"POST",path:"/convert/quote",summary:"Get Convert Quote",description:"Quotes a currency conversion (e.g. stablecoin pairs), returning rate, fees, and a quote id. Read-only preview \u2014 pass the id to convert_execute to commit; quotes expire, so execute promptly.",pathParams:[],params:[{name:"from",in:"body",type:"string",required:!0,description:"Source currency",example:"USDC"},{name:"to",in:"body",type:"string",required:!0,description:"Target currency",example:"USD"},{name:"amount",in:"body",type:"string",required:!0,description:"Amount to convert",example:"100.00"}],streamable:!1,watchFields:null,template:{from:"USDC",to:"USD",amount:"100.00"},responseFields:{fields:["trade"],nested:{trade:{fields:["id","status","amount","subtotal","total","total_fee","exchange_rate","source_currency","target_currency"]}}}},{id:"convert_execute",name:"execute",method:"POST",path:"/convert/execute/{quote_id}",summary:"Execute Convert Trade",description:"Executes a previously quoted conversion using the quote id from convert_quote. This moves funds at the quoted rate \u2014 always get a fresh quote first, since quotes expire. The from/to currencies must match the original quote.",pathParams:["quote_id"],params:[{name:"quote_id",in:"path",type:"string",required:!0,description:"Quote ID from convert quote response"},{name:"from",in:"body",type:"string",required:!0,description:"Source currency",example:"USDC"},{name:"to",in:"body",type:"string",required:!0,description:"Target currency",example:"USD"}],streamable:!1,watchFields:null,template:{from:"USDC",to:"USD"},responseFields:{fields:["trade"],nested:{trade:{fields:["id","status"]}}}},{id:"convert_get",name:"get",method:"GET",path:"/convert/get/{quote_id}",summary:"Get Convert Status",description:"Check status of a conversion by quote ID.",pathParams:["quote_id"],params:[{name:"quote_id",in:"path",type:"string",required:!0,description:"Quote ID"},{name:"from",in:"query",type:"string",required:!0,description:"Source currency"},{name:"to",in:"query",type:"string",required:!0,description:"Target currency"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["id","status","source_currency","target_currency","exchange_rate"]}}]},{name:"orders",actions:[{id:"orders_list",name:"list",method:"GET",path:"/orders",summary:"List Orders",description:"Lists orders with optional filters by status, product, side, and time range. Read-only. Use status=OPEN to find resting orders that can be edited or cancelled.",pathParams:[],params:[{name:"status",in:"query",type:"string",required:!1,description:"Filter by status"},{name:"product_ids",in:"query",type:"string",required:!1,description:"Filter by product (e.g. BTC-USD). Comma-separated for multiple."},{name:"side",in:"query",type:"string",required:!1,description:"Filter by side",enum:["BUY","SELL"]},{name:"product_type",in:"query",type:"string",required:!1,description:"Filter by product type",enum:["SPOT","FUTURE"]},{name:"start",in:"query",type:"string",required:!1,description:"Start date (RFC 3339 with timezone, e.g. 2024-01-01T00:00:00Z)",format:"date-time"},{name:"end",in:"query",type:"string",required:!1,description:"End date (RFC 3339 with timezone, e.g. 2024-12-31T23:59:59Z)",format:"date-time"},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor"}],streamable:!0,watchFields:{status:{type:"string",enum:["PENDING","OPEN","FILLED","CANCELLED","FAILED","EXPIRED","CANCEL_QUEUED"],description:"Order status"},side:{type:"string",enum:["BUY","SELL"],description:"Order side"},price:{type:"number",description:"Average filled price"},filled_size:{type:"number",description:"Filled quantity"},fees:{type:"number",description:"Total fees"},product_id:{type:"string",description:"Trading pair"},order_id:{type:"string",description:"Order ID"}},template:{},responseFields:{fields:["orders","has_next","cursor"],nested:{orders:{fields:["order_id","product_id","side","status","order_configuration","created_time","completion_percentage","filled_size","average_filled_price","total_fees","total_value_after_fees","number_of_fills"]}}}},{id:"orders_create",name:"create",method:"POST",path:"/orders",summary:"Create Order",description:"Places a live order \u2014 executes immediately and moves funds (market buy spends quote currency; sell disposes of base). Preview with orders_preview first to estimate fees, fill price, and slippage.",pathParams:[],params:[{name:"product_id",in:"body",type:"string",required:!0,description:"Trading pair",example:"BTC-USD"},{name:"side",in:"body",type:"string",required:!0,description:"BUY or SELL",enum:["BUY","SELL"],example:"BUY"},{name:"type",in:"body",type:"string",required:!0,description:"market = fill now; limit = fill at price or better; stop_limit = limit triggered at stop_price",enum:["market","limit","stop_limit"],example:"market"},{name:"quote_size",in:"body",type:"string",required:!1,description:"Quote currency amount (e.g. spend $100 USD). Market buy only. Mutually exclusive with base_size.",oneOf:"base_size|quote_size",example:"100.00"},{name:"base_size",in:"body",type:"string",required:!1,description:"Base currency amount (e.g. buy 0.001 BTC). Any side/type.",oneOf:"base_size|quote_size",example:"0.001"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Limit price (limit/stop_limit orders)",example:"65000.00"},{name:"stop_price",in:"body",type:"string",required:!1,description:"Stop price (stop_limit orders)",example:"60000.00"},{name:"stop_direction",in:"body",type:"string",required:!1,description:"up = trigger when price rises above stop_price. down = trigger when falls below.",enum:["up","down"],example:"down"},{name:"post_only",in:"body",type:"boolean",required:!1,description:"Post-only mode (limit orders). Rejects if would take liquidity."},{name:"time_in_force",in:"body",type:"string",required:!1,description:"GTC=good til cancelled. IOC=immediate or cancel. FOK=fill or kill.",enum:["GTC","IOC","FOK","GTD"],example:"GTC"},{name:"end_time",in:"body",type:"string",required:!1,description:"Expiry time for GTD orders (RFC 3339). Required when time_in_force=GTD.",format:"date-time",example:"2024-12-31T23:59:59Z"},{name:"reduce_only",in:"body",type:"boolean",required:!1,description:"Only reduce existing position. Rejects if would increase exposure."},{name:"portfolio_id",in:"body",type:"string",required:!1,description:"Scopes the order to a specific portfolio (defaults to auth-scoped portfolio)"},{name:"client_order_id",in:"body",type:"string",required:!1,description:"Idempotency key (auto-generated if omitted)"}],streamable:!1,watchFields:null,template:{product_id:"BTC-USD",side:"BUY",type:"market",quote_size:"100.00",base_size:"0.001",limit_price:"65000.00",stop_price:"60000.00",stop_direction:"up",post_only:!1,time_in_force:"GTC",end_time:"2024-12-31T23:59:59Z",reduce_only:!1,portfolio_id:"<string>",client_order_id:"<string>"},responseFields:{fields:["order_id","product_id","side","client_order_id"]}},{id:"orders_preview",name:"preview",method:"POST",path:"/orders/preview",summary:"Preview Order",description:"Estimate fees, fill price, and slippage without executing.",pathParams:[],params:[{name:"product_id",in:"body",type:"string",required:!0,description:"Trading pair (e.g. BTC-USD)",example:"BTC-USD"},{name:"side",in:"body",type:"string",required:!0,description:"BUY or SELL",enum:["BUY","SELL"],example:"BUY"},{name:"type",in:"body",type:"string",required:!0,description:"market = fill now; limit = fill at price or better; stop_limit = limit triggered at stop_price",enum:["market","limit","stop_limit"],example:"market"},{name:"quote_size",in:"body",type:"string",required:!1,description:"Quote currency amount (e.g. spend $100 USD). Mutually exclusive with base_size.",oneOf:"base_size|quote_size",example:"100.00"},{name:"base_size",in:"body",type:"string",required:!1,description:"Base currency amount (e.g. 0.001 BTC). Mutually exclusive with quote_size.",oneOf:"base_size|quote_size",example:"0.001"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Limit price (for limit/stop_limit previews)",example:"65000.00"},{name:"stop_price",in:"body",type:"string",required:!1,description:"Stop price (for stop_limit previews)",example:"60000.00"},{name:"stop_direction",in:"body",type:"string",required:!1,description:"up = trigger when price rises above stop_price. down = trigger when falls below.",enum:["up","down"],example:"down"}],streamable:!1,watchFields:null,template:{product_id:"BTC-USD",side:"BUY",type:"market",quote_size:"100.00",base_size:"0.001",limit_price:"65000.00",stop_price:"60000.00",stop_direction:"up"},responseFields:{fields:["order_total","commission_total","slippage","est_average_filled_price","base_size","quote_size","best_bid","best_ask"]}},{id:"orders_edit",name:"edit",method:"POST",path:"/orders/edit",summary:"Edit Order",description:"Atomically update an open order's price or size without cancelling. Avoids the cancel+replace exposure window.",pathParams:[],params:[{name:"order_id",in:"body",type:"string",required:!0,description:"Order to edit"},{name:"base_size",in:"body",type:"string",required:!1,description:"New base size",example:"0.002"},{name:"limit_price",in:"body",type:"string",required:!1,description:"New limit price",example:"64000.00"}],streamable:!1,watchFields:null,template:{order_id:"<string>",base_size:"0.002",limit_price:"64000.00"},responseFields:{fields:["order_id","status"]}},{id:"orders_get",name:"get",method:"GET",path:"/orders/{order_id}",summary:"Get Order",description:"Retrieves the full status and fill details of a single order by ID. Read-only. Use after creating an order to confirm execution.",pathParams:["order_id"],params:[{name:"order_id",in:"path",type:"string",required:!0,description:"Order ID"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["order_id","product_id","side","status","order_configuration","created_time","completion_percentage","filled_size","average_filled_price","total_fees","total_value_after_fees","number_of_fills"]}},{id:"orders_cancel",name:"cancel",method:"POST",path:"/orders/cancel",summary:"Cancel Orders",description:"Cancels one or more open orders by ID. Removes resting orders from the book so reserved funds are released; already-filled portions are unaffected. Returns per-order success so a partial batch can fail.",pathParams:[],params:[{name:"order_ids",in:"body",type:"array",required:!0,description:"Order IDs to cancel"}],streamable:!1,watchFields:null,template:{order_ids:[]},responseFields:{fields:["results"],nested:{results:{fields:["success","order_id"]}}}},{id:"orders_close_position",name:"close-position",method:"POST",path:"/orders/close-position",summary:"Close Position",description:"Places a market order to flatten an open position for a product, moving funds immediately. Omit size for a full close or set it for a partial close. Preview the equivalent order first if fee or slippage impact matters.",pathParams:[],params:[{name:"client_order_id",in:"body",type:"string",required:!0,description:"Idempotency key"},{name:"product_id",in:"body",type:"string",required:!0,description:"Product to close",example:"BTC-PERP"},{name:"size",in:"body",type:"string",required:!1,description:"Partial close size (omit for full close)",example:"0.001"}],streamable:!1,watchFields:null,template:{client_order_id:"<string>",product_id:"BTC-PERP",size:"0.001"},responseFields:null},{id:"orders_fills",name:"fills",method:"GET",path:"/orders/fills",summary:"List Fills",description:"Lists individual trade executions (fills) with commissions and maker/taker indicator, filterable by product, order, side, and time range. Read-only. Use this to reconcile actual fill prices and fees paid.",pathParams:[],params:[{name:"product_ids",in:"query",type:"string",required:!1,description:"Filter by product (e.g. BTC-USD)"},{name:"order_ids",in:"query",type:"string",required:!1,description:"Filter by order ID"},{name:"start",in:"query",type:"string",required:!1,description:"Start time (RFC 3339 with timezone, e.g. 2024-01-01T00:00:00Z)",format:"date-time"},{name:"end",in:"query",type:"string",required:!1,description:"End time (RFC 3339 with timezone, e.g. 2024-12-31T23:59:59Z)",format:"date-time"},{name:"side",in:"query",type:"string",required:!1,description:"Filter by side",enum:["BUY","SELL"]},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["fills","cursor"],nested:{fills:{fields:["trade_id","order_id","trade_time","price","size","commission","product_id","side","liquidity_indicator"]}}}}]},{name:"portfolios",actions:[{id:"portfolios_list",name:"list",method:"GET",path:"/portfolios",summary:"List Portfolios",description:"Lists all portfolios on the account, including their UUIDs and types. Read-only. Use this to find the portfolio_id needed for orders, transfers, and balance queries.",pathParams:[],params:[{name:"portfolio_type",in:"query",type:"string",required:!1,description:"Filter by type (DEFAULT, CONSUMER, INTX)"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["portfolios"],nested:{portfolios:{fields:["uuid","name","type","deleted"]}}}},{id:"portfolios_create",name:"create",method:"POST",path:"/portfolios",summary:"Create Portfolio",description:"Creates a new named portfolio for segregating funds and positions. Does not move any funds; use transfer afterward to fund it.",pathParams:[],params:[{name:"name",in:"body",type:"string",required:!0,description:"Portfolio name",example:"agent-1"}],streamable:!1,watchFields:null,template:{name:"agent-1"},responseFields:{fields:["uuid","name","type","deleted"]}},{id:"portfolios_get",name:"get",method:"GET",path:"/portfolios/{portfolio_id}",summary:"Get Portfolio Breakdown",description:"Returns portfolio metadata, balances, and positions.",pathParams:["portfolio_id"],params:[{name:"portfolio_id",in:"path",type:"string",required:!0,description:"Portfolio UUID"},{name:"currency",in:"query",type:"string",required:!1,description:"Currency for balance denomination"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["portfolio","portfolio_balances","spot_positions"],nested:{portfolio:{fields:["uuid","name","type","deleted"]},portfolio_balances:{fields:["total_balance","total_crypto_balance","total_cash_equivalent_balance"],nested:{total_balance:{fields:["value","currency"]},total_crypto_balance:{fields:["value","currency"]},total_cash_equivalent_balance:{fields:["value","currency"]}}},spot_positions:{fields:["asset","account_uuid","total_balance_fiat","total_balance_crypto","available_to_trade_fiat","allocation","is_cash"]}}}},{id:"portfolios_edit",name:"edit",method:"PUT",path:"/portfolios/{portfolio_id}",summary:"Edit Portfolio",description:"Renames an existing portfolio. Metadata-only change; does not affect balances or positions.",pathParams:["portfolio_id"],params:[{name:"portfolio_id",in:"path",type:"string",required:!0,description:"Portfolio UUID"},{name:"name",in:"body",type:"string",required:!1,description:"New portfolio name"}],streamable:!1,watchFields:null,template:{name:"<string>"},responseFields:{fields:["uuid","name","type","deleted"]}},{id:"portfolios_delete",name:"delete",method:"DELETE",path:"/portfolios/{portfolio_id}",summary:"Delete Portfolio",description:"Permanently deletes a portfolio. The portfolio must be empty first \u2014 transfer out any remaining funds and close all positions before deleting. The DEFAULT portfolio cannot be deleted.",pathParams:["portfolio_id"],params:[{name:"portfolio_id",in:"path",type:"string",required:!0,description:"Portfolio UUID"}],streamable:!1,watchFields:null,template:{},responseFields:null}]},{name:"products",actions:[{id:"products_list",name:"list",method:"GET",path:"/products",summary:"List Products",description:"Lists tradable products and their current price and 24h stats, optionally filtered by symbol or type. Read-only. Use to discover valid product_id values before placing orders.",pathParams:[],params:[{name:"symbol",in:"query",type:"string",required:!1,description:"Filter products by symbol, matches base or quote side (e.g. USD, BTC). For a specific product use `get` (e.g. BTC-USD). Pagination ignored when set.",pattern:"^[A-Za-z0-9]+$"},{name:"product_type",in:"query",type:"string",required:!1,description:"Product type filter",enum:["SPOT","FUTURE"]},{name:"product_ids",in:"query",type:"string",required:!1,description:"Comma-separated product IDs"},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["products","cursor","has_next","num_products"],nested:{products:{fields:["product_id","price","price_percentage_change_24h","volume_24h","product_type","quote_currency_id","base_currency_id","base_increment","quote_increment","base_min_size","base_max_size","quote_min_size","quote_max_size","status"]}}}},{id:"products_get",name:"get",method:"GET",path:"/products/{product_id}",summary:"Get Product",description:"Returns full details for a single product, including price and trading increments/min sizes. Read-only. Use base_increment and base_min_size to size orders that the exchange will accept.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID (e.g. BTC-USD)"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["product_id","price","price_percentage_change_24h","volume_24h","product_type","quote_currency_id","base_currency_id","base_increment","quote_increment","base_min_size","base_max_size","quote_min_size","quote_max_size","status"]}},{id:"products_ticker",name:"ticker",method:"GET",path:"/products/{product_id}/ticker",summary:"Get Ticker",description:"Returns recent trades plus the current best bid and ask for a product. Read-only. Use for a quick spot price snapshot before previewing or placing an order.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Trading pair (e.g. BTC-USD)"},{name:"limit",in:"query",type:"integer",required:!1,description:"Number of trades. Defaults to 100."}],streamable:!0,watchFields:{price:{type:"number",description:"Last trade price"},bid:{type:"number",description:"Best bid"},ask:{type:"number",description:"Best ask"},bid_size:{type:"number",description:"Size at best bid"},ask_size:{type:"number",description:"Size at best ask"},volume:{type:"number",description:"24h volume"},high:{type:"number",description:"24h high"},low:{type:"number",description:"24h low"},pct_24h:{type:"number",description:"24h price change %"},product_id:{type:"string",description:"Trading pair"}},template:{},responseFields:{fields:["trades","best_bid","best_ask"],nested:{trades:{fields:["trade_id","product_id","price","size","time","side"]}}}},{id:"products_book",name:"book",method:"GET",path:"/products/{product_id}/book",summary:"Get Order Book",description:"Returns the bid/ask order book (price levels and sizes) for a product. Read-only. Use to gauge available liquidity and likely slippage before sizing a market order.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID"},{name:"limit",in:"query",type:"integer",required:!1,description:"Number of levels"}],streamable:!0,watchFields:{spread:{type:"number",description:"Bid-ask spread"},mid:{type:"number",description:"Midpoint price"},product_id:{type:"string",description:"Trading pair"}},template:{},responseFields:{fields:["pricebook"],nested:{pricebook:{fields:["product_id","bids","asks","time"],nested:{bids:{fields:["price","size"]},asks:{fields:["price","size"]}}}}}},{id:"products_candles",name:"candles",method:"GET",path:"/products/{product_id}/candles",summary:"Get Candles",description:"Returns historical OHLCV candles for a product at a chosen granularity and time range. Read-only. Use for price history and technical analysis.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Trading pair (e.g. BTC-USD)"},{name:"start",in:"query",type:"string",required:!1,description:"Start time (RFC 3339, e.g. 2024-01-01T00:00:00Z). Defaults to 60 candles before end.",format:"date-time"},{name:"end",in:"query",type:"string",required:!1,description:"End time (RFC 3339, e.g. 2024-01-01T00:00:00Z). Defaults to now.",format:"date-time"},{name:"granularity",in:"query",type:"string",required:!1,description:"Candle interval: 1m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 1d. Defaults to 1h.",enum:["1m","5m","15m","30m","1h","2h","4h","6h","1d"]},{name:"limit",in:"query",type:"integer",required:!1,description:"Max candles"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["candles"],nested:{candles:{fields:["start","low","high","open","close","volume"]}}}},{id:"products_best_bid_ask",name:"best-bid-ask",method:"GET",path:"/products/best-bid-ask",summary:"Best Bid/Ask for Multiple Products",description:"Returns best bid and ask for one or more products in a single call.",pathParams:[],params:[{name:"product_ids",in:"query",type:"string",required:!1,description:"Comma-separated product IDs (e.g. BTC-USD,ETH-USD)"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["pricebooks"],nested:{pricebooks:{fields:["product_id","bids","asks","time"],nested:{bids:{fields:["price","size"]},asks:{fields:["price","size"]}}}}}}]}],X={balance:{id:"balance",name:"balance",method:"GET",path:"/balance",summary:"View Balances",description:"Lists account balances across currencies, showing available funds and amounts on hold. Read-only. Use before trading or transferring to confirm available funds; available_balance excludes funds held by open orders.",pathParams:[],params:[{name:"portfolio_id",in:"query",type:"string",required:!1,description:"Filter by portfolio"},{name:"show_zero",in:"query",type:"boolean",required:!1,description:"Include zero-balance accounts (default false)"},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["accounts","has_next","cursor","size"],nested:{accounts:{fields:["uuid","name","currency","available_balance","hold","type","active","ready"],nested:{available_balance:{fields:["value","currency"]},hold:{fields:["value","currency"]}}}}}},transfer:{id:"transfer",name:"transfer",method:"POST",path:"/transfer",summary:"Move Funds Between Portfolios",description:"Moves funds of a single currency from one portfolio to another. This executes immediately and moves money \u2014 verify the source has sufficient available balance first. Both portfolio UUIDs come from portfolios_list.",pathParams:[],params:[{name:"amount",in:"body",type:"string",required:!0,description:"Amount to transfer",example:"100.00"},{name:"currency",in:"body",type:"string",required:!0,description:"Currency",example:"USD"},{name:"from",in:"body",type:"string",required:!0,description:"Source portfolio UUID",example:"d17b3486-..."},{name:"to",in:"body",type:"string",required:!0,description:"Target portfolio UUID",example:"a44ef7a8-..."}],streamable:!1,watchFields:null,template:{amount:"100.00",currency:"USD",from:"d17b3486-...",to:"a44ef7a8-..."},responseFields:{fields:["source_portfolio_uuid","target_portfolio_uuid"]}},fees:{id:"fees",name:"fees",method:"GET",path:"/fees",summary:"Fee Tier and Volume",description:"Fee tier, maker/taker rates, and 30-day volume.",pathParams:[],params:[{name:"product_type",in:"query",type:"string",required:!1,description:"Filter by product type",enum:["SPOT","FUTURE"]}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["total_fees","fee_tier","margin_rate","advanced_trade_only_volume","advanced_trade_only_fees","coinbase_pro_volume","coinbase_pro_fees","total_balance","has_cost_plus_commission"],nested:{fee_tier:{fields:["pricing_tier","taker_fee_rate","maker_fee_rate"]}}}}},gn=new Set(["balance","transfer","fees"]),ln={"date-time":/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/};pn={"date-time":t=>{let e=t.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/);if(!e)return!1;let[,r,n,i,s,a,o]=e;return fo(+r,+n,+i)&&+s<24&&+a<60&&+o<61}}});function mn(t){return typeof t=="object"&&"endpoint"in t}function x(t,e){return{endpoint:t,...e}}var lt=h(()=>{"use strict";l();p()});var fn,bn,yn,hn,En,In,vn,kn,On,Rn,Pn,Tn,Sn,wn,xn,Cn,Tt=h(()=>{"use strict";l();p();fn={origin:"RetailBrokerageApi_CancelOrders",method:"POST",path:"/api/v3/brokerage/orders/batch_cancel"},bn={origin:"RetailBrokerageApi_ClosePosition",method:"POST",path:"/api/v3/brokerage/orders/close_position"},yn={origin:"RetailBrokerageApi_CommitConvertTrade",method:"POST",path:"/api/v3/brokerage/convert/trade/{trade_id}"},hn={origin:"RetailBrokerageApi_CreatePortfolio",method:"POST",path:"/api/v3/brokerage/portfolios"},En={origin:"RetailBrokerageApi_DeletePortfolio",method:"DELETE",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},In={origin:"RetailBrokerageApi_EditPortfolio",method:"PUT",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},vn={origin:"RetailBrokerageApi_GetBestBidAsk",method:"GET",path:"/api/v3/brokerage/best_bid_ask"},kn={origin:"RetailBrokerageApi_GetConvertTrade",method:"GET",path:"/api/v3/brokerage/convert/trade/{trade_id}"},On={origin:"RetailBrokerageApi_GetFills",method:"GET",path:"/api/v3/brokerage/orders/historical/fills"},Rn={origin:"RetailBrokerageApi_GetHistoricalOrder",method:"GET",path:"/api/v3/brokerage/orders/historical/{order_id}"},Pn={origin:"RetailBrokerageApi_GetHistoricalOrders",method:"GET",path:"/api/v3/brokerage/orders/historical/batch"},Tn={origin:"RetailBrokerageApi_GetPortfolioBreakdown",method:"GET",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},Sn={origin:"RetailBrokerageApi_GetPortfolios",method:"GET",path:"/api/v3/brokerage/portfolios"},wn={origin:"RetailBrokerageApi_GetProduct",method:"GET",path:"/api/v3/brokerage/products/{product_id}"},xn={origin:"RetailBrokerageApi_GetPublicProductBook",method:"GET",path:"/api/v3/brokerage/market/product_book"},Cn={origin:"RetailBrokerageApi_GetTransactionSummary",method:"GET",path:"/api/v3/brokerage/transaction_summary"}});var An,Nn=h(()=>{"use strict";l();p();lt();Tt();An={portfolios_list:x(Sn),portfolios_get:x(Tn,{requestMap:{portfolio_id:"portfolio_uuid"},responseUnwrap:"breakdown"}),portfolios_create:x(hn,{responseUnwrap:"portfolio"}),portfolios_edit:x(In,{requestMap:{portfolio_id:"portfolio_uuid"},responseUnwrap:"portfolio"}),portfolios_delete:x(En,{requestMap:{portfolio_id:"portfolio_uuid"}})}});var L,pt=h(()=>{"use strict";l();p();L=class t extends Error{status;correlationId;traceId;constructor(e,r,n){super(e),this.status=r,this.correlationId=n?.correlationId,this.traceId=n?.traceId}static stripGrpcPrefix(e){let r=e.match(/^rpc error: code = \w+ desc = (.+)$/s);return r?r[1]:e}static fromResponse(e,r,n){let i=new TextDecoder().decode(e),s,a;try{let c=JSON.parse(i);c.errorType&&c.errorMessage?s=`${c.errorType} \u2014 ${c.errorMessage}`:c.message?s=t.stripGrpcPrefix(c.message):s=i.length>200?i.slice(0,200)+"...":i,a=c.correlationId||c.correlation_id||void 0}catch{s=i.length>200?i.slice(0,200)+"...":i}let o=n?.get("trace-id")??void 0;return new t(s,r,{correlationId:a,traceId:o})}}});function nr(t){if(t?.success===!1){let e=t.error_response,r=t.errors?.[0]?.edit_failure_reason,n=e?.new_order_failure_reason?String(e.new_order_failure_reason).replace(/^NEW_ORDER_FAILURE_REASON_/,"").replace(/_/g," ").toLowerCase():void 0;throw new L(e?.message||e?.error_details||n||r?.toString()||"Operation failed",400)}}var Gn=h(()=>{"use strict";l();p();pt()});var me,ir,mt,Dn=h(()=>{"use strict";l();p();me={MARKET:"market",LIMIT:"limit",STOP_LIMIT:"stop_limit"},ir={UP:"up",DOWN:"down"},mt={GTC:"GTC",IOC:"IOC",FOK:"FOK",GTD:"GTD"}});function bo(t,e){let r={...e},n=t;for(let[i,s]of Object.entries(r)){let a="{"+i+"}";s!=null&&n.includes(a)&&(n=n.replaceAll(a,encodeURIComponent(String(s))),delete r[i])}return{url:n,remaining:r}}async function et(t,e,r,n){let{url:i,remaining:s}=bo(r,n),a=e==="POST"||e==="PUT"||e==="DELETE"||e==="PATCH",o,c=null;if(a)o=t.baseURL+i,Object.keys(s).length>0&&(c=new TextEncoder().encode(JSON.stringify(s)));else{let g=Object.entries(s).filter(([,f])=>f!=null).map(([f,O])=>encodeURIComponent(f)+"="+encodeURIComponent(String(O))).join("&");o=t.baseURL+i+(g?"?"+g:"")}let d=await t.doRequest({method:e,url:o,body:c}),_=new TextDecoder().decode(d.body),u;try{u=JSON.parse(_)}catch{u=_}if(d.status>=400){let g=u,f=g?.error_response?.message??g?.error_response?.error_details??g?.message??g?.error_details??_.slice(0,200);throw new jt(f,d.status,u)}return{status:d.status,data:u}}function Ln(t,e){return et(t,"POST","/api/v3/brokerage/convert/quote",e)}function Mn(t,e){return et(t,"POST","/api/v3/brokerage/orders/edit",e)}function Fn(t,e){return et(t,"GET","/api/v3/brokerage/accounts",e)}function Un(t,e){return et(t,"GET","/api/v3/brokerage/products/{product_id}/candles",e)}function qn(t,e){return et(t,"GET","/api/v3/brokerage/products/{product_id}/ticker",e)}function sr(t,e){return et(t,"GET","/api/v3/brokerage/products",e)}function Bn(t,e){return et(t,"POST","/api/v3/brokerage/portfolios/move_funds",e)}function zn(t,e){return et(t,"POST","/api/v3/brokerage/orders",e)}function Wn(t,e){return et(t,"POST","/api/v3/brokerage/orders/preview",e)}var jt,ft=h(()=>{"use strict";l();p();jt=class extends Error{status;data;constructor(e,r,n){super(e),this.status=r,this.data=n}}});import{randomUUID as yo}from"node:crypto";function Vn(t){let e=t.type;if(e===me.MARKET)return{market_market_ioc:{...t.quote_size&&{quote_size:t.quote_size},...t.base_size&&{base_size:t.base_size}}};if(e===me.LIMIT){let r=t.time_in_force??mt.GTC,n={base_size:t.base_size,limit_price:t.limit_price,...t.post_only&&{post_only:!0}};return r===mt.IOC?{sor_limit_ioc:n}:r===mt.FOK?{limit_limit_fok:n}:r===mt.GTD?{limit_limit_gtd:{...n,...t.end_time&&{end_time:t.end_time}}}:{limit_limit_gtc:n}}else if(e===me.STOP_LIMIT){let r=t.stop_direction===ir.UP?"STOP_DIRECTION_STOP_UP":t.stop_direction===ir.DOWN?"STOP_DIRECTION_STOP_DOWN":(()=>{throw new L("stop_direction is required for stop_limit orders (up or down)",400)})(),n=t.time_in_force??mt.GTC,i={base_size:t.base_size,limit_price:t.limit_price,stop_price:t.stop_price,stop_direction:r};return n===mt.GTD?{stop_limit_stop_limit_gtd:{...i,...t.end_time&&{end_time:t.end_time}}}:{stop_limit_stop_limit_gtc:i}}throw new L(`Unknown order type: ${e}. Use market, limit, or stop_limit.`,400)}function ho(t){let e={client_order_id:t.client_order_id??yo(),product_id:t.product_id,side:t.side,order_configuration:Vn(t)};return t.portfolio_id&&(e.retail_portfolio_id=t.portfolio_id),t.reduce_only&&(e.reduce_only=!0),e}var Eo,Io,vo,$n,Hn=h(()=>{"use strict";l();p();lt();pt();Gn();Dn();Tt();ft();Eo=async(t,e)=>{let r=ho(t),n=await zn(e,r);return nr(n.data),n.data.success_response??n.data},Io=async(t,e)=>{let r=await Wn(e,{product_id:t.product_id,side:t.side,order_configuration:Vn(t)}),n=r.data;if(n.errs?.length>0)throw new L(n.errs[0].replace(/^PREVIEW_/,"").replace(/_/g," ").toLowerCase(),400);return r.data},vo=async(t,e)=>{if(!t.base_size&&!t.limit_price)throw new L("Provide base_size and/or limit_price to edit",400);let r={order_id:t.order_id,size:t.base_size??"",price:t.limit_price??""},n=await Mn(e,r);return nr(n.data),{order_id:t.order_id,status:"EDITED"}},$n={orders_list:x(Pn,{requestMap:{status:"order_status",side:"order_side",start:"start_date",end:"end_date"}}),orders_get:x(Rn,{responseUnwrap:"order"}),orders_create:Eo,orders_preview:Io,orders_edit:vo,orders_cancel:x(fn),orders_close_position:x(bn),orders_fills:x(On,{requestMap:{side:"order_side",start:"start_sequence_timestamp",end:"end_sequence_timestamp"}})}});function jn(t){return String(Math.floor(new Date(t).getTime()/1e3))}var ko,Oo,Ro,Po,To,So,Kn,Yn=h(()=>{"use strict";l();p();lt();Tt();ft();ko={"1m":"ONE_MINUTE","5m":"FIVE_MINUTE","15m":"FIFTEEN_MINUTE","30m":"THIRTY_MINUTE","1h":"ONE_HOUR","2h":"TWO_HOUR","4h":"FOUR_HOUR","6h":"SIX_HOUR","1d":"ONE_DAY"},Oo={"1m":60,"5m":300,"15m":900,"30m":1800,"1h":3600,"2h":7200,"4h":14400,"6h":21600,"1d":86400},Ro=60,Po=async(t,e)=>{let{symbol:r,limit:n,cursor:i,...s}=t;if(r){let o=r.toUpperCase(),_=((await sr(e,s)).data.products??[]).filter(g=>g.base_currency_id===o||g.quote_currency_id===o),u=n!==void 0&&n>0?_.slice(0,n):_;return{products:u,num_products:u.length}}return(await sr(e,{...s,limit:n,cursor:i})).data};To=async(t,e)=>{let r=t.granularity??"1h",n=ko[r],i=Oo[r],s=Math.floor(Date.now()/1e3),a=t.end?jn(t.end):String(s),o=t.start?jn(t.start):String(Number(a)-Ro*i);return(await Un(e,{...t,granularity:n,start:o,end:a})).data},So=async(t,e)=>{let r=t.limit??100;return(await qn(e,{...t,limit:r})).data},Kn={products_list:Po,products_get:x(wn),products_ticker:So,products_book:x(xn),products_candles:To,products_best_bid_ask:x(vn)}});var wo,Qn,Jn=h(()=>{"use strict";l();p();lt();Tt();ft();pt();wo=async(t,e)=>{let{from:r,to:n,...i}=t,s=await Ln(e,{...i,from_account:r,to_account:n});if(!s.data?.trade?.id)throw new L(`Convert quote returned no trade for ${t.from} \u2192 ${t.to}. Verify balance, supported pair, and account eligibility.`,422);return s.data},Qn={convert_quote:wo,convert_execute:x(yn,{requestMap:{quote_id:"trade_id",from:"from_account",to:"to_account"}}),convert_get:x(kn,{requestMap:{quote_id:"trade_id",from:"from_account",to:"to_account"},responseUnwrap:"trade"})}});var xo,Xn,Zn=h(()=>{"use strict";l();p();ft();xo=async(t,e)=>{let r={};t.portfolio_id&&(r.retail_portfolio_id=t.portfolio_id),t.limit&&(r.limit=t.limit),t.cursor&&(r.cursor=t.cursor);let i=(await Fn(e,r)).data,s=i.accounts??[],a=t.show_zero?s:s.filter(o=>parseFloat(o.available_balance?.value??"0")!==0||parseFloat(o.hold?.value??"0")!==0);return{accounts:a,has_next:i.has_next,cursor:i.cursor,size:a.length}},Xn={balance:xo}});var Co,ti,ei=h(()=>{"use strict";l();p();pt();ft();Co=async(t,e)=>{let r={funds:{value:t.amount,currency:t.currency},source_portfolio_uuid:t.from,target_portfolio_uuid:t.to},i=(await Bn(e,r)).data;if(!i?.source_portfolio_uuid)throw new L("Transfer failed \u2014 check amount, currency, and portfolio UUIDs",400);return i},ti={transfer:Co}});var ri,ni=h(()=>{"use strict";l();p();lt();Tt();ri={fees:x(Cn)}});function fe(t){return Ao[t]}var Ao,or=h(()=>{"use strict";l();p();Nn();Hn();Yn();Jn();Zn();ei();ni();Ao={...An,...$n,...Kn,...Qn,...Xn,...ti,...ri}});function ar(t,e){if(!e)return t;let r={};for(let[n,i]of Object.entries(t)){let s=e[n]??n;r[s]=i}return r}function ii(t,e){if(!e||typeof t!="object"||t===null||Array.isArray(t))return t;let r={};for(let[n,i]of Object.entries(t)){let s=e[n]??n;r[s]=i}return r}var si=h(()=>{"use strict";l();p()});function No(t,e){let r={...e},n=t;for(let[i,s]of Object.entries(e)){if(s==null||s==="")continue;let a=`{${i}}`;n.includes(a)&&(n=n.replaceAll(a,encodeURIComponent(String(s))),delete r[i])}return{resolvedPath:n,remainingParams:r}}function Go(t){let e=[];for(let[r,n]of Object.entries(t))if(n!=null)if(Array.isArray(n))for(let i of n)e.push(`${encodeURIComponent(r)}=${encodeURIComponent(String(i))}`);else e.push(`${encodeURIComponent(r)}=${encodeURIComponent(String(n))}`);return e.length>0?"?"+e.join("&"):""}function Do(t,e){let r=e.split("."),n=t;for(let i of r){if(n==null||typeof n!="object")return t;n=n[i]}return n!==void 0?n:t}function Lo(t){return t&&typeof t=="object"&&("body"in t||"query"in t||"path"in t||"rawBody"in t)}function Kt(t,e){if(t==null||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>Kt(n,e));let r={};for(let n of e.fields){if(!(n in t))continue;let i=e.nested?.[n];i&&Array.isArray(t[n])?r[n]=t[n].map(s=>Kt(s,i)):i&&typeof t[n]=="object"&&t[n]!==null?r[n]=Kt(t[n],i):r[n]=t[n]}return r}function Mo(t,e){let r=cr[t];if(!r)return;if(!e)return r;let n=r;for(let i of e.split(".")){let s=n?.nested?.[i];if(!s)return r;n=s}return n}async function St(t,e,r){let n=Lo(e),i=n?e.body??{}:e,s=n?e.query??{}:{},a=n?e.path??{}:{},o=n?e.headers??{}:{},c=n?e.rawBody??null:null,d=fe(t);if(!d)return{status:404,data:{error:"UNKNOWN_OPERATION",code:404,message:`No route for ${t}`}};let _=oi.find(v=>v.id===t);if(_?.params){if(c)try{let v=JSON.parse(new TextDecoder().decode(c));v&&typeof v=="object"&&!Array.isArray(v)&&Object.assign(i,v)}catch{}{let m=_.params.filter(I=>I.in==="body"&&I.required).filter(I=>i[I.name]===void 0||i[I.name]==="");if(m.length>0)return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`Missing required field(s): ${m.map(E=>E.name).join(", ")}`}}}{let v={...a,...i,...s},m={},I={};for(let E of _.params)if(E.oneOf&&(I[E.oneOf]||(I[E.oneOf]=[]),I[E.oneOf].push(E.name),v[E.name]!==void 0&&v[E.name]!=="")){if(m[E.oneOf])return{status:400,data:{error:"CONFLICTING_FIELDS",code:400,message:`${m[E.oneOf]} and ${E.name} are mutually exclusive. Provide one, not both.`}};m[E.oneOf]=E.name}for(let[E,D]of Object.entries(I))if(!m[E])return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`One of ${D.join(", ")} is required.`}}}for(let v of _.params)for(let m of[i,s,a]){if(m[v.name]===void 0)continue;if(v.type==="boolean"&&typeof m[v.name]=="string")m[v.name]=m[v.name]==="true";else if((v.type==="integer"||v.type==="number")&&typeof m[v.name]=="string"){let V=Number(m[v.name]);if(!Number.isFinite(V))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${v.name}: "${m[v.name]}". Expected a number.`}};m[v.name]=V}if(v.enum&&!v.enum.includes(String(m[v.name])))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${v.name}: "${m[v.name]}". Expected one of: ${v.enum.join(", ")}`}};let I=v.pattern?ai.get(v.pattern):void 0,E=v.format?ln[v.format]:void 0,D=I??E;if(D&&typeof m[v.name]=="string"){let V=m[v.name],dt=v.format?pn[v.format]:void 0;if(!(D.test(V)&&(!I||!E||E.test(V))&&(!dt||dt(V)))){let it=(v.description??"").split(/\.\s/)[0].replace(/\.?\s*$/,""),re=it?`. ${it}.`:".";return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${v.name}: "${String(V).slice(0,80)}"${re}`}}}}}}if(!mn(d)){let v={...a,...i,...s};try{let m=await d(v,r),I=cr[t];return I&&(m=Kt(m,I)),{status:200,data:m}}catch(m){if(m instanceof jt)return{status:m.status,data:m.data};let I=m instanceof L?m.status:500,E=L.stripGrpcPrefix(m instanceof Error?m.message:String(m));return{status:I,data:{error:"HANDLER_ERROR",code:I,message:E}}}}let{endpoint:u}=d,g={...a,...i},f=ar(g,d.requestMap),{resolvedPath:O,remainingParams:k}=No(u.path,f);if(O.includes("{"))return{status:400,data:{error:"MISSING_PATH_PARAMS",code:400,message:`Missing required param(s): ${(O.match(/\{([^}]+)\}/g)?.map(m=>m.slice(1,-1))??[]).join(", ")}`}};let S=u.method==="POST"||u.method==="PUT"||u.method==="DELETE"||u.method==="PATCH",T,w=c??null,z={...ar(s,d.requestMap)};S?(T=`${r.baseURL}${O}`,!w&&Object.keys(k).length>0&&(w=new TextEncoder().encode(JSON.stringify(k)))):(Object.assign(z,k),T=`${r.baseURL}${O}`);let P=Go(z);P&&(T+=P);let R=await r.doRequest({method:u.method,url:T,body:w,headers:Object.keys(o).length>0?o:void 0}),N=new TextDecoder().decode(R.body),G;try{G=JSON.parse(N)}catch{G=N}if(R.status>=400)return{status:R.status,data:G,headers:R.headers};d.responseUnwrap&&(G=Do(G,d.responseUnwrap)),d.responseMap&&(G=ii(G,d.responseMap));let ut=Mo(t,d.responseUnwrap);return ut&&(G=Kt(G,ut)),{status:R.status,data:G,headers:R.headers}}var oi,cr,ai,be=h(()=>{"use strict";l();p();lt();or();si();pt();ft();Pt();oi=[...J.flatMap(t=>t.actions),...Object.values(X)],cr={},ai=new Map;for(let t of oi){cr[t.id]=t.responseFields;for(let e of t.params)e.pattern&&ai.set(e.pattern,new RegExp(e.pattern))}});import{readFileSync as Fo,writeFileSync as Uo,mkdirSync as qo}from"node:fs";import{join as _i}from"node:path";function ci(t){let e=t.replace(/^v/,"").split("-")[0],[r,n,i]=e.split(".").map(Number);return{major:r??0,minor:n??0,patch:i??0}}function zo(t,e){let r=ci(t),n=ci(e);return n.major!==r.major?n.major>r.major:n.minor!==r.minor?n.minor>r.minor:n.patch>r.patch}function Vo(t,e){let r=ne===Wo?"":` --registry ${ne}`;return`
|
|
46
|
+
`,{mode:384}),Js(o,a)}catch(c){try{$e(o)}catch{}throw c}}function no(t){Et={...Et,...t}}function It(){return Y()+ro}function io(t){let e=Date.now()+t;for(;Date.now()<e;);}function so(){try{let t=Xs(It(),"wx",384);return on(t,String(process.pid)),t}catch(t){if(t.code!=="EEXIST")throw t;return null}}function oo(){try{let t=to(It());if(Date.now()-t.mtimeMs<Et.staleAfterMs)return!1;let e=sn(It(),"utf8").trim(),r=Number(e);if(!Number.isInteger(r)||r<=0)return!0;try{return process.kill(r,0),!1}catch(n){return n.code==="ESRCH"}}catch{return!1}}function Qe(t){an(at(),{recursive:!0,mode:448});let e=null;for(let r=0;r<Et.retries&&(e=so(),e===null);r++){if(oo()){try{$e(It())}catch{}continue}io(Et.baseDelayMs*(1+Math.random()))}if(e===null)throw new Error(`could not acquire config lock after ${Et.retries} attempts: ${It()}`);try{return t()}finally{try{Zs(e)}catch{}try{$e(It())}catch{}}}function Je(){He=void 0,je=void 0}function ao(){return process.env.COINBASE_KEY_ID&&(He=process.env.COINBASE_KEY_ID,delete process.env.COINBASE_KEY_ID),process.env.COINBASE_KEY_SECRET&&(je=process.env.COINBASE_KEY_SECRET,delete process.env.COINBASE_KEY_SECRET),{keyId:He,keySecret:je}}function Ot(t,e){return e||process.env.COINBASE_ENV||t.env}function $t(t,e){let r=Ot(t,e);if(!r)throw new Error("no environment configured. Run: coinbase env <name>");let n={...t.environments[r]},{keyId:i,keySecret:s}=ao();if(i||s){let o=n.auth?.type==="cdp_key"?n.auth:void 0,c=i??o?.key_id??"",d=s??o?.key_secret??"";c&&d&&(n.auth={type:"cdp_key",key_id:c,key_secret:d})}if(process.env.COINBASE_URL&&(n.url=process.env.COINBASE_URL,vt(n.url)||process.stderr.write(`warning: COINBASE_URL overrides to non-standard endpoint: ${n.url}
|
|
47
|
+
`)),!Z(n,r))throw new Error(`no URL for environment "${r}". Set url in config or use a built-in env name`);if(!n.auth)throw new Error(`no credentials for "${r}". Run: coinbase env ${r} --key-file path/to/key.json`);return{name:r,env:n}}function Xe(){let t={...process.env};for(let e of co)delete t[e];return t}function pe(t){return process.env.COINBASE_NO_HISTORY?!1:t.settings?.history?.enabled!==!1}function Ze(t,e,r,n){t.history[e]||(t.history[e]={}),t.history[e][r]={last_used:new Date().toISOString(),values:n}}function tr(t,e,r){return t.history[e]?.[r]}function Ht(t,e,r){if(e&&r)return t.history[e]?.[r]?(delete t.history[e][r],Object.keys(t.history[e]).length===0&&delete t.history[e],1):0;if(e){let i=Object.keys(t.history[e]??{}).length;return delete t.history[e],i}let n=Object.values(t.history).reduce((i,s)=>i+Object.keys(s).length,0);return t.history={},n}var K,nn,kt,ro,Et,He,je,co,Q=h(()=>{"use strict";l();p();ie();Ve();K=Vr,nn=$r;kt={cdp_key:{secrets:{key_secret:t=>`${t}:cdp:key_secret`},metadataOnly:t=>({type:"cdp_key",key_id:t.key_id})}};ro=".lock",Et={retries:50,baseDelayMs:20,staleAfterMs:5e3};co=["COINBASE_KEY_SECRET","COINBASE_KEY_ID"]});function fo(t,e,r){let n=new Date(Date.UTC(t,e-1,r));return n.getUTCFullYear()===t&&n.getUTCMonth()===e-1&&n.getUTCDate()===r}var J,X,gn,ln,pn,Pt=h(()=>{"use strict";l();p();J=[{name:"convert",actions:[{id:"convert_quote",name:"quote",method:"POST",path:"/convert/quote",summary:"Get Convert Quote",description:"Quotes a currency conversion (e.g. stablecoin pairs), returning rate, fees, and a quote id. Read-only preview \u2014 pass the id to convert_execute to commit; quotes expire, so execute promptly.",pathParams:[],params:[{name:"from",in:"body",type:"string",required:!0,description:"Source currency",example:"USDC"},{name:"to",in:"body",type:"string",required:!0,description:"Target currency",example:"USD"},{name:"amount",in:"body",type:"string",required:!0,description:"Amount to convert",example:"100.00"}],streamable:!1,watchFields:null,template:{from:"USDC",to:"USD",amount:"100.00"},responseFields:{fields:["trade"],nested:{trade:{fields:["id","status","amount","subtotal","total","total_fee","exchange_rate","source_currency","target_currency"]}}}},{id:"convert_execute",name:"execute",method:"POST",path:"/convert/execute/{quote_id}",summary:"Execute Convert Trade",description:"Executes a previously quoted conversion using the quote id from convert_quote. This moves funds at the quoted rate \u2014 always get a fresh quote first, since quotes expire. The from/to currencies must match the original quote.",pathParams:["quote_id"],params:[{name:"quote_id",in:"path",type:"string",required:!0,description:"Quote ID from convert quote response"},{name:"from",in:"body",type:"string",required:!0,description:"Source currency",example:"USDC"},{name:"to",in:"body",type:"string",required:!0,description:"Target currency",example:"USD"}],streamable:!1,watchFields:null,template:{from:"USDC",to:"USD"},responseFields:{fields:["trade"],nested:{trade:{fields:["id","status"]}}}},{id:"convert_get",name:"get",method:"GET",path:"/convert/get/{quote_id}",summary:"Get Convert Status",description:"Check status of a conversion by quote ID.",pathParams:["quote_id"],params:[{name:"quote_id",in:"path",type:"string",required:!0,description:"Quote ID"},{name:"from",in:"query",type:"string",required:!0,description:"Source currency"},{name:"to",in:"query",type:"string",required:!0,description:"Target currency"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["id","status","source_currency","target_currency","exchange_rate"]}}]},{name:"orders",actions:[{id:"orders_list",name:"list",method:"GET",path:"/orders",summary:"List Orders",description:"Lists orders with optional filters by status, product, side, and time range. Read-only. Use status=OPEN to find resting orders that can be edited or cancelled.",pathParams:[],params:[{name:"status",in:"query",type:"string",required:!1,description:"Filter by status"},{name:"product_ids",in:"query",type:"string",required:!1,description:"Filter by product (e.g. BTC-USD). Comma-separated for multiple."},{name:"side",in:"query",type:"string",required:!1,description:"Filter by side",enum:["BUY","SELL"]},{name:"product_type",in:"query",type:"string",required:!1,description:"Filter by product type",enum:["SPOT","FUTURE"]},{name:"start",in:"query",type:"string",required:!1,description:"Start date (RFC 3339 with timezone, e.g. 2024-01-01T00:00:00Z)",format:"date-time"},{name:"end",in:"query",type:"string",required:!1,description:"End date (RFC 3339 with timezone, e.g. 2024-12-31T23:59:59Z)",format:"date-time"},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor"}],streamable:!0,watchFields:{status:{type:"string",enum:["PENDING","OPEN","FILLED","CANCELLED","FAILED","EXPIRED","CANCEL_QUEUED"],description:"Order status"},side:{type:"string",enum:["BUY","SELL"],description:"Order side"},price:{type:"number",description:"Average filled price"},filled_size:{type:"number",description:"Filled quantity"},fees:{type:"number",description:"Total fees"},product_id:{type:"string",description:"Trading pair"},order_id:{type:"string",description:"Order ID"}},template:{},responseFields:{fields:["orders","has_next","cursor"],nested:{orders:{fields:["order_id","product_id","side","status","order_configuration","created_time","completion_percentage","filled_size","average_filled_price","total_fees","total_value_after_fees","number_of_fills"]}}}},{id:"orders_create",name:"create",method:"POST",path:"/orders",summary:"Create Order",description:"Places a live order \u2014 executes immediately and moves funds (market buy spends quote currency; sell disposes of base). Preview with orders_preview first to estimate fees, fill price, and slippage.",pathParams:[],params:[{name:"product_id",in:"body",type:"string",required:!0,description:"Trading pair",example:"BTC-USD"},{name:"side",in:"body",type:"string",required:!0,description:"BUY or SELL",enum:["BUY","SELL"],example:"BUY"},{name:"type",in:"body",type:"string",required:!0,description:"market = fill now; limit = fill at price or better; stop_limit = limit triggered at stop_price",enum:["market","limit","stop_limit"],example:"market"},{name:"quote_size",in:"body",type:"string",required:!1,description:"Quote currency amount (e.g. spend $100 USD). Market buy only. Mutually exclusive with base_size.",oneOf:"base_size|quote_size",example:"100.00"},{name:"base_size",in:"body",type:"string",required:!1,description:"Base currency amount (e.g. buy 0.001 BTC). Any side/type.",oneOf:"base_size|quote_size",example:"0.001"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Limit price (limit/stop_limit orders)",example:"65000.00"},{name:"stop_price",in:"body",type:"string",required:!1,description:"Stop price (stop_limit orders)",example:"60000.00"},{name:"stop_direction",in:"body",type:"string",required:!1,description:"up = trigger when price rises above stop_price. down = trigger when falls below.",enum:["up","down"],example:"down"},{name:"post_only",in:"body",type:"boolean",required:!1,description:"Post-only mode (limit orders). Rejects if would take liquidity."},{name:"time_in_force",in:"body",type:"string",required:!1,description:"GTC=good til cancelled. IOC=immediate or cancel. FOK=fill or kill.",enum:["GTC","IOC","FOK","GTD"],example:"GTC"},{name:"end_time",in:"body",type:"string",required:!1,description:"Expiry time for GTD orders (RFC 3339). Required when time_in_force=GTD.",format:"date-time",example:"2024-12-31T23:59:59Z"},{name:"reduce_only",in:"body",type:"boolean",required:!1,description:"Only reduce existing position. Rejects if would increase exposure."},{name:"portfolio_id",in:"body",type:"string",required:!1,description:"Scopes the order to a specific portfolio (defaults to auth-scoped portfolio)"},{name:"client_order_id",in:"body",type:"string",required:!1,description:"Idempotency key (auto-generated if omitted)"}],streamable:!1,watchFields:null,template:{product_id:"BTC-USD",side:"BUY",type:"market",quote_size:"100.00",base_size:"0.001",limit_price:"65000.00",stop_price:"60000.00",stop_direction:"up",post_only:!1,time_in_force:"GTC",end_time:"2024-12-31T23:59:59Z",reduce_only:!1,portfolio_id:"<string>",client_order_id:"<string>"},responseFields:{fields:["order_id","product_id","side","client_order_id"]}},{id:"orders_preview",name:"preview",method:"POST",path:"/orders/preview",summary:"Preview Order",description:"Estimate fees, fill price, and slippage without executing.",pathParams:[],params:[{name:"product_id",in:"body",type:"string",required:!0,description:"Trading pair (e.g. BTC-USD)",example:"BTC-USD"},{name:"side",in:"body",type:"string",required:!0,description:"BUY or SELL",enum:["BUY","SELL"],example:"BUY"},{name:"type",in:"body",type:"string",required:!0,description:"market = fill now; limit = fill at price or better; stop_limit = limit triggered at stop_price",enum:["market","limit","stop_limit"],example:"market"},{name:"quote_size",in:"body",type:"string",required:!1,description:"Quote currency amount (e.g. spend $100 USD). Mutually exclusive with base_size.",oneOf:"base_size|quote_size",example:"100.00"},{name:"base_size",in:"body",type:"string",required:!1,description:"Base currency amount (e.g. 0.001 BTC). Mutually exclusive with quote_size.",oneOf:"base_size|quote_size",example:"0.001"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Limit price (for limit/stop_limit previews)",example:"65000.00"},{name:"stop_price",in:"body",type:"string",required:!1,description:"Stop price (for stop_limit previews)",example:"60000.00"},{name:"stop_direction",in:"body",type:"string",required:!1,description:"up = trigger when price rises above stop_price. down = trigger when falls below.",enum:["up","down"],example:"down"}],streamable:!1,watchFields:null,template:{product_id:"BTC-USD",side:"BUY",type:"market",quote_size:"100.00",base_size:"0.001",limit_price:"65000.00",stop_price:"60000.00",stop_direction:"up"},responseFields:{fields:["order_total","commission_total","slippage","est_average_filled_price","base_size","quote_size","best_bid","best_ask"]}},{id:"orders_edit",name:"edit",method:"POST",path:"/orders/edit",summary:"Edit Order",description:"Atomically update an open order's price or size without cancelling. Avoids the cancel+replace exposure window.",pathParams:[],params:[{name:"order_id",in:"body",type:"string",required:!0,description:"Order to edit"},{name:"base_size",in:"body",type:"string",required:!1,description:"New base size",example:"0.002"},{name:"limit_price",in:"body",type:"string",required:!1,description:"New limit price",example:"64000.00"}],streamable:!1,watchFields:null,template:{order_id:"<string>",base_size:"0.002",limit_price:"64000.00"},responseFields:{fields:["order_id","status"]}},{id:"orders_get",name:"get",method:"GET",path:"/orders/{order_id}",summary:"Get Order",description:"Retrieves the full status and fill details of a single order by ID. Read-only. Use after creating an order to confirm execution.",pathParams:["order_id"],params:[{name:"order_id",in:"path",type:"string",required:!0,description:"Order ID"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["order_id","product_id","side","status","order_configuration","created_time","completion_percentage","filled_size","average_filled_price","total_fees","total_value_after_fees","number_of_fills"]}},{id:"orders_cancel",name:"cancel",method:"POST",path:"/orders/cancel",summary:"Cancel Orders",description:"Cancels one or more open orders by ID. Removes resting orders from the book so reserved funds are released; already-filled portions are unaffected. Returns per-order success so a partial batch can fail.",pathParams:[],params:[{name:"order_ids",in:"body",type:"array",required:!0,description:"Order IDs to cancel"}],streamable:!1,watchFields:null,template:{order_ids:[]},responseFields:{fields:["results"],nested:{results:{fields:["success","order_id"]}}}},{id:"orders_close_position",name:"close-position",method:"POST",path:"/orders/close-position",summary:"Close Position",description:"Places a market order to flatten an open position for a product, moving funds immediately. Omit size for a full close or set it for a partial close. Preview the equivalent order first if fee or slippage impact matters.",pathParams:[],params:[{name:"client_order_id",in:"body",type:"string",required:!0,description:"Idempotency key"},{name:"product_id",in:"body",type:"string",required:!0,description:"Product to close",example:"BTC-PERP"},{name:"size",in:"body",type:"string",required:!1,description:"Partial close size (omit for full close)",example:"0.001"}],streamable:!1,watchFields:null,template:{client_order_id:"<string>",product_id:"BTC-PERP",size:"0.001"},responseFields:null},{id:"orders_fills",name:"fills",method:"GET",path:"/orders/fills",summary:"List Fills",description:"Lists individual trade executions (fills) with commissions and maker/taker indicator, filterable by product, order, side, and time range. Read-only. Use this to reconcile actual fill prices and fees paid.",pathParams:[],params:[{name:"product_ids",in:"query",type:"string",required:!1,description:"Filter by product (e.g. BTC-USD)"},{name:"order_ids",in:"query",type:"string",required:!1,description:"Filter by order ID"},{name:"start",in:"query",type:"string",required:!1,description:"Start time (RFC 3339 with timezone, e.g. 2024-01-01T00:00:00Z)",format:"date-time"},{name:"end",in:"query",type:"string",required:!1,description:"End time (RFC 3339 with timezone, e.g. 2024-12-31T23:59:59Z)",format:"date-time"},{name:"side",in:"query",type:"string",required:!1,description:"Filter by side",enum:["BUY","SELL"]},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["fills","cursor"],nested:{fills:{fields:["trade_id","order_id","trade_time","price","size","commission","product_id","side","liquidity_indicator"]}}}}]},{name:"portfolios",actions:[{id:"portfolios_list",name:"list",method:"GET",path:"/portfolios",summary:"List Portfolios",description:"Lists all portfolios on the account, including their UUIDs and types. Read-only. Use this to find the portfolio_id needed for orders, transfers, and balance queries.",pathParams:[],params:[{name:"portfolio_type",in:"query",type:"string",required:!1,description:"Filter by type (DEFAULT, CONSUMER, INTX)"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["portfolios"],nested:{portfolios:{fields:["uuid","name","type","deleted"]}}}},{id:"portfolios_create",name:"create",method:"POST",path:"/portfolios",summary:"Create Portfolio",description:"Creates a new named portfolio for segregating funds and positions. Does not move any funds; use transfer afterward to fund it.",pathParams:[],params:[{name:"name",in:"body",type:"string",required:!0,description:"Portfolio name",example:"agent-1"}],streamable:!1,watchFields:null,template:{name:"agent-1"},responseFields:{fields:["uuid","name","type","deleted"]}},{id:"portfolios_get",name:"get",method:"GET",path:"/portfolios/{portfolio_id}",summary:"Get Portfolio Breakdown",description:"Returns portfolio metadata, balances, and positions.",pathParams:["portfolio_id"],params:[{name:"portfolio_id",in:"path",type:"string",required:!0,description:"Portfolio UUID"},{name:"currency",in:"query",type:"string",required:!1,description:"Currency for balance denomination"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["portfolio","portfolio_balances","spot_positions"],nested:{portfolio:{fields:["uuid","name","type","deleted"]},portfolio_balances:{fields:["total_balance","total_crypto_balance","total_cash_equivalent_balance"],nested:{total_balance:{fields:["value","currency"]},total_crypto_balance:{fields:["value","currency"]},total_cash_equivalent_balance:{fields:["value","currency"]}}},spot_positions:{fields:["asset","account_uuid","total_balance_fiat","total_balance_crypto","available_to_trade_fiat","allocation","is_cash"]}}}},{id:"portfolios_edit",name:"edit",method:"PUT",path:"/portfolios/{portfolio_id}",summary:"Edit Portfolio",description:"Renames an existing portfolio. Metadata-only change; does not affect balances or positions.",pathParams:["portfolio_id"],params:[{name:"portfolio_id",in:"path",type:"string",required:!0,description:"Portfolio UUID"},{name:"name",in:"body",type:"string",required:!1,description:"New portfolio name"}],streamable:!1,watchFields:null,template:{name:"<string>"},responseFields:{fields:["uuid","name","type","deleted"]}},{id:"portfolios_delete",name:"delete",method:"DELETE",path:"/portfolios/{portfolio_id}",summary:"Delete Portfolio",description:"Permanently deletes a portfolio. The portfolio must be empty first \u2014 transfer out any remaining funds and close all positions before deleting. The DEFAULT portfolio cannot be deleted.",pathParams:["portfolio_id"],params:[{name:"portfolio_id",in:"path",type:"string",required:!0,description:"Portfolio UUID"}],streamable:!1,watchFields:null,template:{},responseFields:null}]},{name:"products",actions:[{id:"products_list",name:"list",method:"GET",path:"/products",summary:"List Products",description:"Lists tradable products and their current price and 24h stats, optionally filtered by symbol or type. Read-only. Use to discover valid product_id values before placing orders.",pathParams:[],params:[{name:"symbol",in:"query",type:"string",required:!1,description:"Filter products by symbol, matches base or quote side (e.g. USD, BTC). For a specific product use `get` (e.g. BTC-USD). Pagination ignored when set.",pattern:"^[A-Za-z0-9]+$"},{name:"product_type",in:"query",type:"string",required:!1,description:"Product type filter",enum:["SPOT","FUTURE"]},{name:"product_ids",in:"query",type:"string",required:!1,description:"Comma-separated product IDs"},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["products","cursor","has_next","num_products"],nested:{products:{fields:["product_id","price","price_percentage_change_24h","volume_24h","product_type","quote_currency_id","base_currency_id","base_increment","quote_increment","base_min_size","base_max_size","quote_min_size","quote_max_size","status"]}}}},{id:"products_get",name:"get",method:"GET",path:"/products/{product_id}",summary:"Get Product",description:"Returns full details for a single product, including price and trading increments/min sizes. Read-only. Use base_increment and base_min_size to size orders that the exchange will accept.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID (e.g. BTC-USD)"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["product_id","price","price_percentage_change_24h","volume_24h","product_type","quote_currency_id","base_currency_id","base_increment","quote_increment","base_min_size","base_max_size","quote_min_size","quote_max_size","status"]}},{id:"products_ticker",name:"ticker",method:"GET",path:"/products/{product_id}/ticker",summary:"Get Ticker",description:"Returns recent trades plus the current best bid and ask for a product. Read-only. Use for a quick spot price snapshot before previewing or placing an order.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Trading pair (e.g. BTC-USD)"},{name:"limit",in:"query",type:"integer",required:!1,description:"Number of trades. Defaults to 100."}],streamable:!0,watchFields:{price:{type:"number",description:"Last trade price"},bid:{type:"number",description:"Best bid"},ask:{type:"number",description:"Best ask"},bid_size:{type:"number",description:"Size at best bid"},ask_size:{type:"number",description:"Size at best ask"},volume:{type:"number",description:"24h volume"},high:{type:"number",description:"24h high"},low:{type:"number",description:"24h low"},pct_24h:{type:"number",description:"24h price change %"},product_id:{type:"string",description:"Trading pair"}},template:{},responseFields:{fields:["trades","best_bid","best_ask"],nested:{trades:{fields:["trade_id","product_id","price","size","time","side"]}}}},{id:"products_book",name:"book",method:"GET",path:"/products/{product_id}/book",summary:"Get Order Book",description:"Returns the bid/ask order book (price levels and sizes) for a product. Read-only. Use to gauge available liquidity and likely slippage before sizing a market order.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID"},{name:"limit",in:"query",type:"integer",required:!1,description:"Number of levels"}],streamable:!0,watchFields:{spread:{type:"number",description:"Bid-ask spread"},mid:{type:"number",description:"Midpoint price"},product_id:{type:"string",description:"Trading pair"}},template:{},responseFields:{fields:["pricebook"],nested:{pricebook:{fields:["product_id","bids","asks","time"],nested:{bids:{fields:["price","size"]},asks:{fields:["price","size"]}}}}}},{id:"products_candles",name:"candles",method:"GET",path:"/products/{product_id}/candles",summary:"Get Candles",description:"Returns historical OHLCV candles for a product at a chosen granularity and time range. Read-only. Use for price history and technical analysis.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Trading pair (e.g. BTC-USD)"},{name:"start",in:"query",type:"string",required:!1,description:"Start time (RFC 3339, e.g. 2024-01-01T00:00:00Z). Defaults to 60 candles before end.",format:"date-time"},{name:"end",in:"query",type:"string",required:!1,description:"End time (RFC 3339, e.g. 2024-01-01T00:00:00Z). Defaults to now.",format:"date-time"},{name:"granularity",in:"query",type:"string",required:!1,description:"Candle interval: 1m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 1d. Defaults to 1h.",enum:["1m","5m","15m","30m","1h","2h","4h","6h","1d"]},{name:"limit",in:"query",type:"integer",required:!1,description:"Max candles"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["candles"],nested:{candles:{fields:["start","low","high","open","close","volume"]}}}},{id:"products_best_bid_ask",name:"best-bid-ask",method:"GET",path:"/products/best-bid-ask",summary:"Best Bid/Ask for Multiple Products",description:"Returns best bid and ask for one or more products in a single call.",pathParams:[],params:[{name:"product_ids",in:"query",type:"string",required:!1,description:"Comma-separated product IDs (e.g. BTC-USD,ETH-USD)"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["pricebooks"],nested:{pricebooks:{fields:["product_id","bids","asks","time"],nested:{bids:{fields:["price","size"]},asks:{fields:["price","size"]}}}}}}]}],X={balance:{id:"balance",name:"balance",method:"GET",path:"/balance",summary:"View Balances",description:"Lists account balances across currencies, showing available funds and amounts on hold. Read-only. Use before trading or transferring to confirm available funds; available_balance excludes funds held by open orders.",pathParams:[],params:[{name:"portfolio_id",in:"query",type:"string",required:!1,description:"Filter by portfolio"},{name:"show_zero",in:"query",type:"boolean",required:!1,description:"Include zero-balance accounts (default false)"},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor"}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["accounts","has_next","cursor","size"],nested:{accounts:{fields:["uuid","name","currency","available_balance","hold","type","active","ready"],nested:{available_balance:{fields:["value","currency"]},hold:{fields:["value","currency"]}}}}}},transfer:{id:"transfer",name:"transfer",method:"POST",path:"/transfer",summary:"Move Funds Between Portfolios",description:"Moves funds of a single currency from one portfolio to another. This executes immediately and moves money \u2014 verify the source has sufficient available balance first. Both portfolio UUIDs come from portfolios_list.",pathParams:[],params:[{name:"amount",in:"body",type:"string",required:!0,description:"Amount to transfer",example:"100.00"},{name:"currency",in:"body",type:"string",required:!0,description:"Currency",example:"USD"},{name:"from",in:"body",type:"string",required:!0,description:"Source portfolio UUID",example:"d17b3486-..."},{name:"to",in:"body",type:"string",required:!0,description:"Target portfolio UUID",example:"a44ef7a8-..."}],streamable:!1,watchFields:null,template:{amount:"100.00",currency:"USD",from:"d17b3486-...",to:"a44ef7a8-..."},responseFields:{fields:["source_portfolio_uuid","target_portfolio_uuid"]}},fees:{id:"fees",name:"fees",method:"GET",path:"/fees",summary:"Fee Tier and Volume",description:"Fee tier, maker/taker rates, and 30-day volume.",pathParams:[],params:[{name:"product_type",in:"query",type:"string",required:!1,description:"Filter by product type",enum:["SPOT","FUTURE"]}],streamable:!1,watchFields:null,template:{},responseFields:{fields:["total_fees","fee_tier","margin_rate","advanced_trade_only_volume","advanced_trade_only_fees","coinbase_pro_volume","coinbase_pro_fees","total_balance","has_cost_plus_commission"],nested:{fee_tier:{fields:["pricing_tier","taker_fee_rate","maker_fee_rate"]}}}}},gn=new Set(["balance","transfer","fees"]),ln={"date-time":/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/};pn={"date-time":t=>{let e=t.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/);if(!e)return!1;let[,r,n,i,s,a,o]=e;return fo(+r,+n,+i)&&+s<24&&+a<60&&+o<61}}});function mn(t){return typeof t=="object"&&"endpoint"in t}function x(t,e){return{endpoint:t,...e}}var lt=h(()=>{"use strict";l();p()});var fn,bn,yn,hn,En,In,vn,kn,On,Rn,Pn,Tn,Sn,wn,xn,Cn,Tt=h(()=>{"use strict";l();p();fn={origin:"RetailBrokerageApi_CancelOrders",method:"POST",path:"/api/v3/brokerage/orders/batch_cancel"},bn={origin:"RetailBrokerageApi_ClosePosition",method:"POST",path:"/api/v3/brokerage/orders/close_position"},yn={origin:"RetailBrokerageApi_CommitConvertTrade",method:"POST",path:"/api/v3/brokerage/convert/trade/{trade_id}"},hn={origin:"RetailBrokerageApi_CreatePortfolio",method:"POST",path:"/api/v3/brokerage/portfolios"},En={origin:"RetailBrokerageApi_DeletePortfolio",method:"DELETE",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},In={origin:"RetailBrokerageApi_EditPortfolio",method:"PUT",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},vn={origin:"RetailBrokerageApi_GetBestBidAsk",method:"GET",path:"/api/v3/brokerage/best_bid_ask"},kn={origin:"RetailBrokerageApi_GetConvertTrade",method:"GET",path:"/api/v3/brokerage/convert/trade/{trade_id}"},On={origin:"RetailBrokerageApi_GetFills",method:"GET",path:"/api/v3/brokerage/orders/historical/fills"},Rn={origin:"RetailBrokerageApi_GetHistoricalOrder",method:"GET",path:"/api/v3/brokerage/orders/historical/{order_id}"},Pn={origin:"RetailBrokerageApi_GetHistoricalOrders",method:"GET",path:"/api/v3/brokerage/orders/historical/batch"},Tn={origin:"RetailBrokerageApi_GetPortfolioBreakdown",method:"GET",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},Sn={origin:"RetailBrokerageApi_GetPortfolios",method:"GET",path:"/api/v3/brokerage/portfolios"},wn={origin:"RetailBrokerageApi_GetProduct",method:"GET",path:"/api/v3/brokerage/products/{product_id}"},xn={origin:"RetailBrokerageApi_GetPublicProductBook",method:"GET",path:"/api/v3/brokerage/market/product_book"},Cn={origin:"RetailBrokerageApi_GetTransactionSummary",method:"GET",path:"/api/v3/brokerage/transaction_summary"}});var An,Nn=h(()=>{"use strict";l();p();lt();Tt();An={portfolios_list:x(Sn),portfolios_get:x(Tn,{requestMap:{portfolio_id:"portfolio_uuid"},responseUnwrap:"breakdown"}),portfolios_create:x(hn,{responseUnwrap:"portfolio"}),portfolios_edit:x(In,{requestMap:{portfolio_id:"portfolio_uuid"},responseUnwrap:"portfolio"}),portfolios_delete:x(En,{requestMap:{portfolio_id:"portfolio_uuid"}})}});var D,pt=h(()=>{"use strict";l();p();D=class t extends Error{status;correlationId;traceId;constructor(e,r,n){super(e),this.status=r,this.correlationId=n?.correlationId,this.traceId=n?.traceId}static stripGrpcPrefix(e){let r=e.match(/^rpc error: code = \w+ desc = (.+)$/s);return r?r[1]:e}static fromResponse(e,r,n){let i=new TextDecoder().decode(e),s,a;try{let c=JSON.parse(i);c.errorType&&c.errorMessage?s=`${c.errorType} \u2014 ${c.errorMessage}`:c.message?s=t.stripGrpcPrefix(c.message):s=i.length>200?i.slice(0,200)+"...":i,a=c.correlationId||c.correlation_id||void 0}catch{s=i.length>200?i.slice(0,200)+"...":i}let o=n?.get("trace-id")??void 0;return new t(s,r,{correlationId:a,traceId:o})}}});function nr(t){if(t?.success===!1){let e=t.error_response,r=t.errors?.[0]?.edit_failure_reason,n=e?.new_order_failure_reason?String(e.new_order_failure_reason).replace(/^NEW_ORDER_FAILURE_REASON_/,"").replace(/_/g," ").toLowerCase():void 0;throw new D(e?.message||e?.error_details||n||r?.toString()||"Operation failed",400)}}var Gn=h(()=>{"use strict";l();p();pt()});var me,ir,mt,Dn=h(()=>{"use strict";l();p();me={MARKET:"market",LIMIT:"limit",STOP_LIMIT:"stop_limit"},ir={UP:"up",DOWN:"down"},mt={GTC:"GTC",IOC:"IOC",FOK:"FOK",GTD:"GTD"}});function bo(t,e){let r={...e},n=t;for(let[i,s]of Object.entries(r)){let a="{"+i+"}";s!=null&&n.includes(a)&&(n=n.replaceAll(a,encodeURIComponent(String(s))),delete r[i])}return{url:n,remaining:r}}async function et(t,e,r,n){let{url:i,remaining:s}=bo(r,n),a=e==="POST"||e==="PUT"||e==="DELETE"||e==="PATCH",o,c=null;if(a)o=t.baseURL+i,Object.keys(s).length>0&&(c=new TextEncoder().encode(JSON.stringify(s)));else{let g=Object.entries(s).filter(([,f])=>f!=null).map(([f,R])=>encodeURIComponent(f)+"="+encodeURIComponent(String(R))).join("&");o=t.baseURL+i+(g?"?"+g:"")}let d=await t.doRequest({method:e,url:o,body:c}),_=new TextDecoder().decode(d.body),u;try{u=JSON.parse(_)}catch{u=_}if(d.status>=400){let g=u,f=g?.error_response?.message??g?.error_response?.error_details??g?.message??g?.error_details??_.slice(0,200);throw new jt(f,d.status,u)}return{status:d.status,data:u}}function Ln(t,e){return et(t,"POST","/api/v3/brokerage/convert/quote",e)}function Mn(t,e){return et(t,"POST","/api/v3/brokerage/orders/edit",e)}function Fn(t,e){return et(t,"GET","/api/v3/brokerage/accounts",e)}function Un(t,e){return et(t,"GET","/api/v3/brokerage/products/{product_id}/candles",e)}function qn(t,e){return et(t,"GET","/api/v3/brokerage/products/{product_id}/ticker",e)}function sr(t,e){return et(t,"GET","/api/v3/brokerage/products",e)}function Bn(t,e){return et(t,"POST","/api/v3/brokerage/portfolios/move_funds",e)}function zn(t,e){return et(t,"POST","/api/v3/brokerage/orders",e)}function Wn(t,e){return et(t,"POST","/api/v3/brokerage/orders/preview",e)}var jt,ft=h(()=>{"use strict";l();p();jt=class extends Error{status;data;constructor(e,r,n){super(e),this.status=r,this.data=n}}});import{randomUUID as yo}from"node:crypto";function Vn(t){let e=t.type;if(e===me.MARKET)return{market_market_ioc:{...t.quote_size&&{quote_size:t.quote_size},...t.base_size&&{base_size:t.base_size}}};if(e===me.LIMIT){let r=t.time_in_force??mt.GTC,n={base_size:t.base_size,limit_price:t.limit_price,...t.post_only&&{post_only:!0}};return r===mt.IOC?{sor_limit_ioc:n}:r===mt.FOK?{limit_limit_fok:n}:r===mt.GTD?{limit_limit_gtd:{...n,...t.end_time&&{end_time:t.end_time}}}:{limit_limit_gtc:n}}else if(e===me.STOP_LIMIT){let r=t.stop_direction===ir.UP?"STOP_DIRECTION_STOP_UP":t.stop_direction===ir.DOWN?"STOP_DIRECTION_STOP_DOWN":(()=>{throw new D("stop_direction is required for stop_limit orders (up or down)",400)})(),n=t.time_in_force??mt.GTC,i={base_size:t.base_size,limit_price:t.limit_price,stop_price:t.stop_price,stop_direction:r};return n===mt.GTD?{stop_limit_stop_limit_gtd:{...i,...t.end_time&&{end_time:t.end_time}}}:{stop_limit_stop_limit_gtc:i}}throw new D(`Unknown order type: ${e}. Use market, limit, or stop_limit.`,400)}function ho(t){let e={client_order_id:t.client_order_id??yo(),product_id:t.product_id,side:t.side,order_configuration:Vn(t)};return t.portfolio_id&&(e.retail_portfolio_id=t.portfolio_id),t.reduce_only&&(e.reduce_only=!0),e}var Eo,Io,vo,$n,Hn=h(()=>{"use strict";l();p();lt();pt();Gn();Dn();Tt();ft();Eo=async(t,e)=>{let r=ho(t),n=await zn(e,r);return nr(n.data),n.data.success_response??n.data},Io=async(t,e)=>{let r=await Wn(e,{product_id:t.product_id,side:t.side,order_configuration:Vn(t)}),n=r.data;if(n.errs?.length>0)throw new D(n.errs[0].replace(/^PREVIEW_/,"").replace(/_/g," ").toLowerCase(),400);return r.data},vo=async(t,e)=>{if(!t.base_size&&!t.limit_price)throw new D("Provide base_size and/or limit_price to edit",400);let r={order_id:t.order_id,size:t.base_size??"",price:t.limit_price??""},n=await Mn(e,r);return nr(n.data),{order_id:t.order_id,status:"EDITED"}},$n={orders_list:x(Pn,{requestMap:{status:"order_status",side:"order_side",start:"start_date",end:"end_date"}}),orders_get:x(Rn,{responseUnwrap:"order"}),orders_create:Eo,orders_preview:Io,orders_edit:vo,orders_cancel:x(fn),orders_close_position:x(bn),orders_fills:x(On,{requestMap:{side:"order_side",start:"start_sequence_timestamp",end:"end_sequence_timestamp"}})}});function jn(t){return String(Math.floor(new Date(t).getTime()/1e3))}var ko,Oo,Ro,Po,To,So,Kn,Yn=h(()=>{"use strict";l();p();lt();Tt();ft();ko={"1m":"ONE_MINUTE","5m":"FIVE_MINUTE","15m":"FIFTEEN_MINUTE","30m":"THIRTY_MINUTE","1h":"ONE_HOUR","2h":"TWO_HOUR","4h":"FOUR_HOUR","6h":"SIX_HOUR","1d":"ONE_DAY"},Oo={"1m":60,"5m":300,"15m":900,"30m":1800,"1h":3600,"2h":7200,"4h":14400,"6h":21600,"1d":86400},Ro=60,Po=async(t,e)=>{let{symbol:r,limit:n,cursor:i,...s}=t;if(r){let o=r.toUpperCase(),_=((await sr(e,s)).data.products??[]).filter(g=>g.base_currency_id===o||g.quote_currency_id===o),u=n!==void 0&&n>0?_.slice(0,n):_;return{products:u,num_products:u.length}}return(await sr(e,{...s,limit:n,cursor:i})).data};To=async(t,e)=>{let r=t.granularity??"1h",n=ko[r],i=Oo[r],s=Math.floor(Date.now()/1e3),a=t.end?jn(t.end):String(s),o=t.start?jn(t.start):String(Number(a)-Ro*i);return(await Un(e,{...t,granularity:n,start:o,end:a})).data},So=async(t,e)=>{let r=t.limit??100;return(await qn(e,{...t,limit:r})).data},Kn={products_list:Po,products_get:x(wn),products_ticker:So,products_book:x(xn),products_candles:To,products_best_bid_ask:x(vn)}});var wo,Qn,Jn=h(()=>{"use strict";l();p();lt();Tt();ft();pt();wo=async(t,e)=>{let{from:r,to:n,...i}=t,s=await Ln(e,{...i,from_account:r,to_account:n});if(!s.data?.trade?.id)throw new D(`Convert quote returned no trade for ${t.from} \u2192 ${t.to}. Verify balance, supported pair, and account eligibility.`,422);return s.data},Qn={convert_quote:wo,convert_execute:x(yn,{requestMap:{quote_id:"trade_id",from:"from_account",to:"to_account"}}),convert_get:x(kn,{requestMap:{quote_id:"trade_id",from:"from_account",to:"to_account"},responseUnwrap:"trade"})}});var xo,Xn,Zn=h(()=>{"use strict";l();p();ft();xo=async(t,e)=>{let r={};t.portfolio_id&&(r.retail_portfolio_id=t.portfolio_id),t.limit&&(r.limit=t.limit),t.cursor&&(r.cursor=t.cursor);let i=(await Fn(e,r)).data,s=i.accounts??[],a=t.show_zero?s:s.filter(o=>parseFloat(o.available_balance?.value??"0")!==0||parseFloat(o.hold?.value??"0")!==0);return{accounts:a,has_next:i.has_next,cursor:i.cursor,size:a.length}},Xn={balance:xo}});var Co,ti,ei=h(()=>{"use strict";l();p();pt();ft();Co=async(t,e)=>{let r={funds:{value:t.amount,currency:t.currency},source_portfolio_uuid:t.from,target_portfolio_uuid:t.to},i=(await Bn(e,r)).data;if(!i?.source_portfolio_uuid)throw new D("Transfer failed \u2014 check amount, currency, and portfolio UUIDs",400);return i},ti={transfer:Co}});var ri,ni=h(()=>{"use strict";l();p();lt();Tt();ri={fees:x(Cn)}});function fe(t){return Ao[t]}var Ao,or=h(()=>{"use strict";l();p();Nn();Hn();Yn();Jn();Zn();ei();ni();Ao={...An,...$n,...Kn,...Qn,...Xn,...ti,...ri}});function ar(t,e){if(!e)return t;let r={};for(let[n,i]of Object.entries(t)){let s=e[n]??n;r[s]=i}return r}function ii(t,e){if(!e||typeof t!="object"||t===null||Array.isArray(t))return t;let r={};for(let[n,i]of Object.entries(t)){let s=e[n]??n;r[s]=i}return r}var si=h(()=>{"use strict";l();p()});function No(t,e){let r={...e},n=t;for(let[i,s]of Object.entries(e)){if(s==null||s==="")continue;let a=`{${i}}`;n.includes(a)&&(n=n.replaceAll(a,encodeURIComponent(String(s))),delete r[i])}return{resolvedPath:n,remainingParams:r}}function Go(t){let e=[];for(let[r,n]of Object.entries(t))if(n!=null)if(Array.isArray(n))for(let i of n)e.push(`${encodeURIComponent(r)}=${encodeURIComponent(String(i))}`);else e.push(`${encodeURIComponent(r)}=${encodeURIComponent(String(n))}`);return e.length>0?"?"+e.join("&"):""}function Do(t,e){let r=e.split("."),n=t;for(let i of r){if(n==null||typeof n!="object")return t;n=n[i]}return n!==void 0?n:t}function Lo(t){return t&&typeof t=="object"&&("body"in t||"query"in t||"path"in t||"rawBody"in t)}function Kt(t,e){if(t==null||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>Kt(n,e));let r={};for(let n of e.fields){if(!(n in t))continue;let i=e.nested?.[n];i&&Array.isArray(t[n])?r[n]=t[n].map(s=>Kt(s,i)):i&&typeof t[n]=="object"&&t[n]!==null?r[n]=Kt(t[n],i):r[n]=t[n]}return r}function Mo(t,e){let r=cr[t];if(!r)return;if(!e)return r;let n=r;for(let i of e.split(".")){let s=n?.nested?.[i];if(!s)return r;n=s}return n}async function St(t,e,r){let n=Lo(e),i=n?e.body??{}:e,s=n?e.query??{}:{},a=n?e.path??{}:{},o=n?e.headers??{}:{},c=n?e.rawBody??null:null,d=fe(t);if(!d)return{status:404,data:{error:"UNKNOWN_OPERATION",code:404,message:`No route for ${t}`}};let _=oi.find(I=>I.id===t);if(_?.params){if(c)try{let I=JSON.parse(new TextDecoder().decode(c));I&&typeof I=="object"&&!Array.isArray(I)&&Object.assign(i,I)}catch{}{let m=_.params.filter(v=>v.in==="body"&&v.required).filter(v=>i[v.name]===void 0||i[v.name]==="");if(m.length>0)return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`Missing required field(s): ${m.map(E=>E.name).join(", ")}`}}}{let I={...a,...i,...s},m={},v={};for(let E of _.params)if(E.oneOf&&(v[E.oneOf]||(v[E.oneOf]=[]),v[E.oneOf].push(E.name),I[E.name]!==void 0&&I[E.name]!=="")){if(m[E.oneOf])return{status:400,data:{error:"CONFLICTING_FIELDS",code:400,message:`${m[E.oneOf]} and ${E.name} are mutually exclusive. Provide one, not both.`}};m[E.oneOf]=E.name}for(let[E,G]of Object.entries(v))if(!m[E])return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`One of ${G.join(", ")} is required.`}}}for(let I of _.params)for(let m of[i,s,a]){if(m[I.name]===void 0)continue;if(I.type==="boolean"&&typeof m[I.name]=="string")m[I.name]=m[I.name]==="true";else if((I.type==="integer"||I.type==="number")&&typeof m[I.name]=="string"){let V=Number(m[I.name]);if(!Number.isFinite(V))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${m[I.name]}". Expected a number.`}};m[I.name]=V}if(I.enum&&!I.enum.includes(String(m[I.name])))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${m[I.name]}". Expected one of: ${I.enum.join(", ")}`}};let v=I.pattern?ai.get(I.pattern):void 0,E=I.format?ln[I.format]:void 0,G=v??E;if(G&&typeof m[I.name]=="string"){let V=m[I.name],dt=I.format?pn[I.format]:void 0;if(!(G.test(V)&&(!v||!E||E.test(V))&&(!dt||dt(V)))){let st=(I.description??"").split(/\.\s/)[0].replace(/\.?\s*$/,""),re=st?`. ${st}.`:".";return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${String(V).slice(0,80)}"${re}`}}}}}}if(!mn(d)){let I={...a,...i,...s};try{let m=await d(I,r),v=cr[t];return v&&(m=Kt(m,v)),{status:200,data:m}}catch(m){if(m instanceof jt)return{status:m.status,data:m.data};let v=m instanceof D?m.status:500,E=D.stripGrpcPrefix(m instanceof Error?m.message:String(m));return{status:v,data:{error:"HANDLER_ERROR",code:v,message:E}}}}let{endpoint:u}=d,g={...a,...i},f=ar(g,d.requestMap),{resolvedPath:R,remainingParams:k}=No(u.path,f);if(R.includes("{"))return{status:400,data:{error:"MISSING_PATH_PARAMS",code:400,message:`Missing required param(s): ${(R.match(/\{([^}]+)\}/g)?.map(m=>m.slice(1,-1))??[]).join(", ")}`}};let T=u.method==="POST"||u.method==="PUT"||u.method==="DELETE"||u.method==="PATCH",S,A=c??null,j={...ar(s,d.requestMap)};T?(S=`${r.baseURL}${R}`,!A&&Object.keys(k).length>0&&(A=new TextEncoder().encode(JSON.stringify(k)))):(Object.assign(j,k),S=`${r.baseURL}${R}`);let P=Go(j);P&&(S+=P);let O=await r.doRequest({method:u.method,url:S,body:A,headers:Object.keys(o).length>0?o:void 0}),q=new TextDecoder().decode(O.body),w;try{w=JSON.parse(q)}catch{w=q}if(O.status>=400)return{status:O.status,data:w,headers:O.headers};d.responseUnwrap&&(w=Do(w,d.responseUnwrap)),d.responseMap&&(w=ii(w,d.responseMap));let it=Mo(t,d.responseUnwrap);return it&&(w=Kt(w,it)),{status:O.status,data:w,headers:O.headers}}var oi,cr,ai,be=h(()=>{"use strict";l();p();lt();or();si();pt();ft();Pt();oi=[...J.flatMap(t=>t.actions),...Object.values(X)],cr={},ai=new Map;for(let t of oi){cr[t.id]=t.responseFields;for(let e of t.params)e.pattern&&ai.set(e.pattern,new RegExp(e.pattern))}});import{readFileSync as Fo,writeFileSync as Uo,mkdirSync as qo}from"node:fs";import{join as _i}from"node:path";function ci(t){let e=t.replace(/^v/,"").split("-")[0],[r,n,i]=e.split(".").map(Number);return{major:r??0,minor:n??0,patch:i??0}}function zo(t,e){let r=ci(t),n=ci(e);return n.major!==r.major?n.major>r.major:n.minor!==r.minor?n.minor>r.minor:n.patch>r.patch}function Vo(t,e){let r=ne===Wo?"":` --registry ${ne}`;return`
|
|
48
48
|
Update available: ${t} \u2192 ${e}
|
|
49
49
|
Run: npm i -g ${ye}${r}
|
|
50
|
-
`}function gi(){return
|
|
51
|
-
`)}var fr,br,xa,hr=h(()=>{"use strict";l();p();fr={k:1e3,m:1e6,b:1e9};br=class{tokens;pos=0;constructor(e){this.tokens=e}parse(){let e=this.parseOr();if(this.current().type!==11)throw new Error(`Unexpected token '${this.current().value}' at position ${this.current().pos}`);return e}parseOr(){let e=this.parseAnd();for(;this.current().type===10;)this.advance(),e={type:"or",left:e,right:this.parseAnd()};return e}parseAnd(){let e=this.parseAtom();for(;this.current().type===9;)this.advance(),e={type:"and",left:e,right:this.parseAtom()};return e}parseAtom(){if(this.current().type===12){this.advance();let e=this.parseOr();if(this.current().type!==13)throw new Error(`Expected ')' at position ${this.current().pos}`);return this.advance(),e}return this.parseComparison()}parseComparison(){let r=this.expect(0,"field name").value,n;this.current().type===0&&this.pos+1<this.tokens.length&&Sa(this.tokens[this.pos+1].type)&&(n=this.advance().value);let i=this.parseOp(),s;if(this.current().type===1)s=this.advance().value;else if(this.current().type===2)s=this.advance().value;else throw new Error(`Expected number or string at position ${this.current().pos}, got '${this.current().value}'`);return{type:"comparison",field:r,product:n,op:i,value:s}}parseOp(){let e=this.current();switch(e.type){case 3:return this.advance(),"==";case 4:return this.advance(),"!=";case 5:return this.advance(),">";case 6:return this.advance(),"<";case 7:return this.advance(),">=";case 8:return this.advance(),"<=";default:throw new Error(`Expected operator at position ${e.pos}, got '${e.value}'`)}}current(){return this.tokens[this.pos]}advance(){return this.tokens[this.pos++]}expect(e,r){let n=this.current();if(n.type!==e)throw new Error(`Expected ${r} at position ${n.pos}, got '${n.value}'`);return this.advance()}};xa=/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/});function Re(t){return Ga[t]??null}var Er,Na,Ga,Ir=h(()=>{"use strict";l();p();Er="wss://advanced-trade-ws.coinbase.com",Na="wss://advanced-trade-ws-user.coinbase.com",Ga={products_ticker:{name:"ticker",endpoint:Er,requiresAuth:!1,coalesce:!0},products_book:{name:"level2",wireName:"l2_data",endpoint:Er,requiresAuth:!1,coalesce:!0},orders_list:{name:"user",endpoint:Na,requiresAuth:!0,coalesce:!1},products_trades:{name:"market_trades",endpoint:Er,requiresAuth:!1,coalesce:!0}}});var M,Da,La,Pe,Te=h(()=>{"use strict";l();p();M={CONNECTING:"CONNECTING",CONNECTED:"CONNECTED",SUBSCRIBED:"SUBSCRIBED",RECONNECTING:"RECONNECTING",FAILED:"FAILED"},Da=3e4,La=1e3,Pe=class{url;opts;ws=null;_state=M.CONNECTING;heartbeatTimer=null;reconnectTimer=null;retryCount=0;closed=!1;WSClass;heartbeatTimeoutMs;maxRetries;now;lastActivityTime=0;wasReconnecting=!1;constructor(e,r){this.url=e,this.opts=r,this.WSClass=r.WebSocketClass??globalThis.WebSocket,this.heartbeatTimeoutMs=r.heartbeatTimeoutMs??5e3,this.maxRetries=r.maxRetries??1/0,this.now=r.now??Date.now}get state(){return this._state}connect(){if(!this.closed){this.clearReconnectTimer(),this.teardownSocket(),this.setState(M.CONNECTING);try{this.ws=new this.WSClass(this.url)}catch{this.scheduleReconnect();return}this.resetHeartbeat(),this.ws.onopen=()=>{this.lastActivityTime=this.now(),this.setState(M.CONNECTED),this.resetHeartbeat()},this.ws.onmessage=e=>{let r=this.now();if(this.lastActivityTime>0&&r-this.lastActivityTime>this.heartbeatTimeoutMs*2){this.forceClose();return}this.lastActivityTime=r,this.resetHeartbeat();let n;try{n=typeof e.data=="string"?JSON.parse(e.data):e.data}catch{return}this.opts.onMessage(n)},this.ws.onclose=()=>{this.clearHeartbeat(),this.closed||this.scheduleReconnect()},this.ws.onerror=()=>{}}}send(e){this.ws&&this.ws.readyState===1&&this.ws.send(e)}markSubscribed(){this.setState(M.SUBSCRIBED),this.retryCount=0}close(){this.closed=!0,this.clearHeartbeat(),this.clearReconnectTimer(),this.teardownSocket()}teardownSocket(){this.ws&&(this.ws.onopen=null,this.ws.onclose=null,this.ws.onmessage=null,this.ws.onerror=null,this.ws.readyState<2&&this.ws.close(1e3,"teardown"),this.ws=null)}forceClose(){this.ws&&(this.clearHeartbeat(),this.teardownSocket(),this.scheduleReconnect())}setState(e){this._state=e,e===M.RECONNECTING&&!this.wasReconnecting&&(this.wasReconnecting=!0,this.opts.onDisconnect?.()),e===M.CONNECTED&&this.wasReconnecting&&(this.wasReconnecting=!1,this.opts.onReconnect?.()),this.opts.onStateChange?.(e)}resetHeartbeat(){this.clearHeartbeat(),this.heartbeatTimer=setTimeout(()=>{this.forceClose()},this.heartbeatTimeoutMs)}clearHeartbeat(){this.heartbeatTimer&&(clearTimeout(this.heartbeatTimer),this.heartbeatTimer=null)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}scheduleReconnect(){if(this.closed)return;if(this.clearReconnectTimer(),this.retryCount>=this.maxRetries){this.setState(M.FAILED);return}this.setState(M.RECONNECTING);let e=Math.min(La*Math.pow(2,this.retryCount),Da),r=500+Math.random()*(e-500);this.retryCount++,this.reconnectTimer=setTimeout(()=>{this.connect()},r)}}});var Se,Vi=h(()=>{"use strict";l();p();Te();Se=class{conn;channel;productIds=[];jwt;lastSeq;hasSubscribed=!1;wasReconnecting=!1;eventHandler;gapHandler;heartbeatHandler;errorHandler;reconnectedHandler;refreshJWTFn;constructor(e){this.channel=e.channel,this.eventHandler=e.onEvent,this.gapHandler=e.onSequenceGap,this.heartbeatHandler=e.onHeartbeat,this.errorHandler=e.onError,this.reconnectedHandler=e.onReconnected,this.refreshJWTFn=e.refreshJWT;let r={onMessage:n=>this.handleMessage(n),onStateChange:n=>{n===M.CONNECTED&&this.hasSubscribed&&(this.refreshJWTFn&&this.wasReconnecting&&(this.jwt=this.refreshJWTFn()),this.lastSeq=void 0,this.sendSubscribe()),e.onStateChange?.(n)},onDisconnect:()=>{this.wasReconnecting=!0,e.onDisconnect?.()},onReconnect:()=>{e.onReconnect?.()},heartbeatTimeoutMs:e.heartbeatTimeoutMs,maxRetries:e.maxRetries,WebSocketClass:e.WebSocketClass,now:e.now};this.conn=new Pe(e.channel.endpoint,r)}connect(){this.conn.connect()}subscribe(e,r){this.productIds=e,this.jwt=r,this.hasSubscribed=!0,this.lastSeq=void 0,(this.conn.state===M.CONNECTED||this.conn.state===M.SUBSCRIBED)&&this.sendSubscribe()}unsubscribe(e){let r={type:"unsubscribe",channel:this.channel.name};e.length>0&&(r.product_ids=e),this.jwt&&(r.jwt=this.jwt),this.conn.send(JSON.stringify(r));let n={type:"unsubscribe",channel:"heartbeats"};e.length>0&&(n.product_ids=e),this.jwt&&(n.jwt=this.jwt),this.conn.send(JSON.stringify(n)),this.productIds=this.productIds.filter(i=>!e.includes(i))}updateJWT(e){this.jwt=e}close(){this.conn.close()}get state(){return this.conn.state}get subscribedProducts(){return[...this.productIds]}sendSubscribe(){let e={type:"subscribe",channel:this.channel.name};this.productIds.length>0&&(e.product_ids=this.productIds),this.jwt&&(e.jwt=this.jwt),this.conn.send(JSON.stringify(e));let r={type:"subscribe",channel:"heartbeats"};this.productIds.length>0&&(r.product_ids=this.productIds),this.jwt&&(r.jwt=this.jwt),this.conn.send(JSON.stringify(r))}handleMessage(e){if(typeof e!="object"||e===null)return;let r=e;if(r.type==="error"){this.errorHandler?.(String(r.message??r.reason??"unknown error"));return}if(r.type==="subscriptions"||r.channel==="subscriptions"){typeof r.sequence_num=="number"&&(this.lastSeq===void 0||r.sequence_num>this.lastSeq)&&(this.lastSeq=r.sequence_num),this.conn.markSubscribed(),this.wasReconnecting&&(this.wasReconnecting=!1,this.reconnectedHandler?.());return}if(typeof r.sequence_num=="number"){let i=r.sequence_num;if(this.lastSeq!==void 0&&i<=this.lastSeq)return;this.lastSeq!==void 0&&i>this.lastSeq+1&&this.gapHandler?.(this.lastSeq+1,i),(this.lastSeq===void 0||i>this.lastSeq)&&(this.lastSeq=i)}if(r.channel==="heartbeats"){this.heartbeatHandler?.();return}let n=this.channel.wireName??this.channel.name;r.channel===n&&this.eventHandler(e)}}});function we(t,e){return ur(t,e,"","","")}var vr=h(()=>{"use strict";l();p();ve()});var xe,$i=h(()=>{"use strict";l();p();xe=class{snapshots=new Map;timestamps=new Map;now;constructor(e){this.now=e??Date.now}update(e,r){this.snapshots.set(e,r),this.timestamps.set(e,this.now())}get(e){return this.snapshots.get(e)}all(){return this.snapshots}isStale(e,r){let n=this.timestamps.get(e);return n===void 0?!1:this.now()-n>r}staleProducts(e,r){let n=new Set;for(let i of e)this.isStale(i,r)&&n.add(i);return n}hasSeen(e){return this.timestamps.has(e)}age(e){let r=this.timestamps.get(e);if(r!==void 0)return this.now()-r}}});function kr(t,e,r){if(!r||t===0)return"";let n=t>0?Ct:At;return e?`${xt}${n}`:n}function Ji(t,e,r){if(!r)return"";let n=t==="bid"||t==="BUY"?Ct:At;return e?`${xt}${n}`:n}var B,xt,Ct,At,Hi,F,ji,Ki,Yi,Qi,Nt=h(()=>{"use strict";l();p();B="\x1B[2m",xt="\x1B[1m",Ct="\x1B[32m",At="\x1B[31m",Hi="\x1B[33m",F="\x1B[0m",ji="\x1B[?25l",Ki="\x1B[?25h",Yi="\x1B[?1049h",Qi="\x1B[?1049l"});var Gt,Xi=h(()=>{"use strict";l();p();Nt();Gt=class{out;inAltScreen=!1;cursorHidden=!1;scrollRegionSet=!1;cleanedUp=!1;resizeHandlers=[];sigwinchHandler=null;sigintHandler=null;sigtermHandler=null;stdinHandler=null;constructor(e){this.out=e??process.stdout}enterAltScreen(){this.out.write(Yi),this.inAltScreen=!0}exitAltScreen(){this.out.write(Qi),this.inAltScreen=!1}hideCursor(){this.out.write(ji),this.cursorHidden=!0}showCursor(){this.out.write(Ki),this.cursorHidden=!1}setScrollRegion(e,r){this.out.write(`\x1B[${e};${r}r`),this.scrollRegionSet=!0}resetScrollRegion(){this.out.write("\x1B[r"),this.scrollRegionSet=!1}moveTo(e,r){this.out.write(`\x1B[${e};${r}H`)}clearLine(){this.out.write("\x1B[K")}insertLine(){this.out.write("\x1B[L")}write(e){this.out.write(e)}get cols(){return this.out.columns??80}get rows(){return this.out.rows??24}onResize(e){this.resizeHandlers.push(e),this.sigwinchHandler||(this.sigwinchHandler=()=>{let r=this.cols,n=this.rows;for(let i of this.resizeHandlers)i(r,n)},process.on("SIGWINCH",this.sigwinchHandler))}installSignalHandlers(e){let r=e??(()=>process.exit(0));process.stdin.isTTY&&typeof process.stdin.setRawMode=="function"&&(process.stdin.setRawMode(!0),process.stdin.resume(),this.stdinHandler=n=>{n[0]===3&&(this.cleanup(),r())},process.stdin.on("data",this.stdinHandler)),this.sigintHandler=()=>{this.cleanup(),r()},this.sigtermHandler=()=>{this.cleanup(),r()},process.on("SIGINT",this.sigintHandler),process.on("SIGTERM",this.sigtermHandler)}cleanup(){this.cleanedUp||(this.cleanedUp=!0,process.stdin.isTTY&&typeof process.stdin.setRawMode=="function"&&process.stdin.setRawMode(!1),this.scrollRegionSet&&this.resetScrollRegion(),this.cursorHidden&&this.showCursor(),this.inAltScreen&&this.exitAltScreen(),this.out.write(F),this.removeListeners())}removeListeners(){this.stdinHandler&&(process.stdin.removeListener("data",this.stdinHandler),this.stdinHandler=null,process.stdin.isTTY&&process.stdin.pause()),this.sigwinchHandler&&(process.removeListener("SIGWINCH",this.sigwinchHandler),this.sigwinchHandler=null),this.sigintHandler&&(process.removeListener("SIGINT",this.sigintHandler),this.sigintHandler=null),this.sigtermHandler&&(process.removeListener("SIGTERM",this.sigtermHandler),this.sigtermHandler=null)}}});var Xt,Zi=h(()=>{"use strict";l();p();Xt=class{flashes=new Map;offsets=new Map;now;constructor(e){this.now=e??Date.now}flash(e,r=600){this.flashes.set(e,this.now()+r)}isFlashing(e){let r=this.flashes.get(e);return r===void 0?!1:this.now()<r}expired(){let e=this.now(),r=[];for(let[n,i]of this.flashes)e>=i&&(r.push(n),this.flashes.delete(n),this.offsets.delete(n));return r}flashWithOffset(e,r,n=1500){let i=this.now()+n;this.flashes.set(e,i),this.offsets.set(e,{indexAtCreation:r,durationMs:n,expiry:i})}getRow(e,r,n){let i=this.offsets.get(e);if(!i)return null;if(this.now()>=i.expiry)return this.offsets.delete(e),null;let s=r-i.indexAtCreation-1;return n+s}clear(){this.flashes.clear(),this.offsets.clear()}}});function q(t,e){let r=at(t);return r>=e?t.slice(0,t.length-(r-e)):t+" ".repeat(e-r)}function C(t,e){let r=at(t);return r>=e?t.slice(0,t.length-(r-e)):" ".repeat(e-r)+t}function ct(t,e){let r="\u2500".repeat(t);return e?`${B}${r}${F}`:r}function Dt(t,e,r){let n=at(t),i=at(e);if(n+1+i>r){let o=r-i-1;return o>0?`${t.slice(0,o)} ${e}`:e.slice(0,r)}let a=r-n-i;return a<0?q(`${t} ${e}`,r):`${t}${" ".repeat(a)}${e}`}function Lt(t,e){return e?t?`${xt}\xB7${F}`:`${B}\xB7${F}`:""}function $(){let t=new Date,e=String(t.getHours()).padStart(2,"0"),r=String(t.getMinutes()).padStart(2,"0"),n=String(t.getSeconds()).padStart(2,"0");return`${e}:${r}:${n}`}var Zt=h(()=>{"use strict";l();p();ke();Nt()});function W(t){let e=Math.abs(t);return e>=1e3?t.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2}):e>=1?t.toFixed(2):t.toFixed(4)}function Mt(t){let e=Math.abs(t);return e>=100?t.toFixed(1):e>=10?t.toFixed(2):e>=1?t.toFixed(3):e>=.01?t.toFixed(4):e>=1e-4?t.toFixed(6):t===0?"0":t.toFixed(8)}function ts(t){return t>=1e9?`${(t/1e9).toFixed(1)}B`:t>=1e6?`${(t/1e6).toFixed(0)}M`:t>=1e3?`${(t/1e3).toFixed(0)}K`:t.toFixed(0)}function es(t){return`${t>=0?"+":""}${t.toFixed(2)}%`}function rs(t){let e=new Date(t);if(isNaN(e.getTime()))return t;let r=String(e.getHours()).padStart(2,"0"),n=String(e.getMinutes()).padStart(2,"0"),i=String(e.getSeconds()).padStart(2,"0"),s=String(e.getMilliseconds()).padStart(3,"0");return`${r}:${n}:${i}.${s}`}var Ce=h(()=>{"use strict";l();p()});function is(t){let e=[],r=0;for(let n of Ma){if(r+n.width+1>t){let i=t-r-1;i>=4&&n.key==="id"&&e.push({...n,width:i});break}e.push(n),r+=n.width+1}return e}function ss(){return{events:[],positions:new Map,openOrders:new Set,totalFees:0,lastClock:$(),netCash:0,fillCount:0,accounted:new Map,prependCount:0,heartbeat:!1,updateCount:0}}function Fa(t){let e=t.order_configuration;if(e)for(let r of Object.values(e)){if(r&&typeof r=="object"&&"base_size"in r)return String(r.base_size);if(r&&typeof r=="object"&&"quote_size"in r)return`$${String(r.quote_size)}`}}function Ua(t,e){let r=e.creation_time?Date.parse(e.creation_time):NaN;if(Number.isNaN(r))return 0;for(let n=0;n<t.length;n++){let i=t[n].creation_time?Date.parse(t[n].creation_time):NaN;if(!Number.isNaN(i)&&i<r)return n}return t.length}function Or(t,e,r="live"){let n=t.events;if(!n)return{inserts:[],updates:[]};let i=[],s=[];for(let a of n){let o=a.orders;if(o)for(let c of o){let d={order_id:String(c.order_id??""),status:String(c.status??""),product_id:String(c.product_id??""),order_side:String(c.order_side??c.side??""),order_type:c.order_type?String(c.order_type):void 0,average_filled_price:String(c.average_filled_price??c.avg_price??"0"),total_fees:String(c.total_fees??"0"),filled_size:String(c.filled_size??c.cumulative_quantity??"0"),base_size:Fa(c),creation_time:c.creation_time?String(c.creation_time):c.created_time?String(c.created_time):void 0},_=e.events.findIndex(u=>u.order_id===d.order_id);if(_>=0){let u=e.events[_],g=u.status!==d.status||u.filled_size!==d.filled_size||u.total_fees!==d.total_fees||u.average_filled_price!==d.average_filled_price;u.status=d.status,u.average_filled_price=d.average_filled_price,u.filled_size=d.filled_size,u.total_fees=d.total_fees,g&&(ns(e,d),s.push(u));continue}r==="backfill"?e.events.splice(Ua(e.events,d),0,d):e.events.unshift(d),e.prependCount++,ns(e,d),i.push(d),e.events.length>1e4&&e.events.pop()}}return{inserts:i,updates:s}}function ns(t,e){t.updateCount++,t.lastClock=$();let r=e.status.toUpperCase();r==="OPEN"||r==="PENDING"?t.openOrders.add(e.order_id):t.openOrders.delete(e.order_id);let n=parseFloat(e.total_fees??"0")||0,i=parseFloat(e.filled_size??"0")||0,s=parseFloat(e.average_filled_price??"0")||0,a=i*s,o=t.accounted.get(e.order_id)??{fees:0,size:0,value:0},c=n-o.fees,d=i-o.size,_=a-o.value;(d!==0||c!==0)&&(o.size===0&&i>0&&t.fillCount++,t.totalFees+=c,e.order_side==="BUY"?(t.netCash-=_,t.positions.set(e.product_id,(t.positions.get(e.product_id)??0)+d)):(t.netCash+=_,t.positions.set(e.product_id,(t.positions.get(e.product_id)??0)-d)),t.accounted.set(e.order_id,{fees:n,size:i,value:a}))}function qa(t,e,r,n,i){let s=e.order_side==="BUY"?"BUY":"SELL",a=Ji(s,n,i),o=e.status.toUpperCase(),c=i?F:"",d=parseFloat(e.average_filled_price??"0"),_=parseFloat(e.filled_size??"0");switch(t){case"time":return q(rs(e.creation_time??new Date().toISOString()),r);case"status":return`${(o==="OPEN"||o==="PENDING")&&i?Hi:""}${q(o,r)}${c}`;case"product":return q(e.product_id,r);case"side":return`${a}${q(s,r)}${c}`;case"size":{let u=_>0?Mt(_):e.base_size??"-";return`${a}${C(u,r)}${c}`}case"price":return`${a}${C(d>0?W(d):"-",r)}${c}`;case"fee":{let u=parseFloat(e.total_fees??"0");return C(u>0?W(u):"-",r)}case"id":return`${i?B:""}${q(e.order_id.slice(0,r),r)}${c}`;default:return q("",r)}}function te(t,e,r,n=80){return is(n).map(i=>qa(i.key,t,i.width,e,r)).join(" ")}function Ba(t,e=80){let r=new Set(["size","price","fee"]),i=is(e).map(s=>r.has(s.key)?C(s.header,s.width):q(s.header,s.width)).join(" ");return t?`${B}${i}${F}`:i}function za(t,e,r){let n=t.netCash>=0?r?Ct:"":r?At:"",i=r?F:"",s=`Fills:${t.fillCount}`,a=`Open:${t.openOrders.size}`,o=`Fees:${W(t.totalFees)}`,c=`Net:${t.netCash>=0?"+":""}${W(t.netCash)}`,d=`${n}${c}${i}`,u=`${Lt(t.heartbeat,r)} ${t.lastClock}`,g=`\xB7 ${t.lastClock}`,f=`${s} ${a} ${o} ${c}`,O=`${s} ${a} ${o} ${d}`,k=[],S=[];for(let[z,P]of t.positions){if(Math.abs(P)<1e-6)continue;let N=`${z.replace(/-USD[C]?$/,"")}:${Mt(P)}`;k.push(N),S.push(N)}let T=e-f.length-g.length-6,w="";if(k.length>0&&T>8){let z="",P=0,R=0;for(let N=0;N<k.length;N++){let G=R>0?" ":"";if(P+G.length+S[N].length>T){let ut=k.length-R;ut>0&&(z+=` +${ut}`);break}z+=G+k[N],P+=G.length+S[N].length,R++}w=z}let H=w?`${O} ${w}`:O;return Dt(H,u,e)}function os(t,e,r,n,i){let s=i??e.events,a=t.cols,o=t.rows,c=o,d=o-1,_=o-2;n.inserts.forEach((u,g)=>{r.flashWithOffset(u.order_id,e.prependCount-1-g,1500),t.moveTo(Ae,1),t.insertLine(),t.write(te(u,!0,!0,t.cols)+"\x1B[K")});for(let u of n.updates){let g=s.indexOf(u);if(g>=0){let f=Ae+g;f<=_&&(r.flash(u.order_id,1500),t.moveTo(f,1),t.write(te(u,!0,!0,t.cols)+"\x1B[K"))}}for(let u of r.expired()){let g=s.findIndex(f=>f.order_id===u);if(g>=0){let f=Ae+g;f<=_&&(t.moveTo(f,1),t.write(te(s[g],!1,!0,t.cols)+"\x1B[K"))}}t.moveTo(d,1),t.write(ct(a,!0)),t.moveTo(c,1),t.write(za(e,a-1,!0)+"\x1B[K")}function Rr(t){t.enterAltScreen(),t.hideCursor();let e=t.rows;t.setScrollRegion(Ae,e-2),t.moveTo(1,1),t.write(Ba(!0,t.cols)+"\x1B[K"),t.moveTo(2,1),t.write(ct(t.cols,!0))}function Ne(t,e,r){return{_ch:"user",_seq:e,_ts:r,order_id:t.order_id,status:t.status,product_id:t.product_id,side:t.order_side,filled_size:t.filled_size??null,price:t.average_filled_price??null,fees:t.total_fees??null}}function as(t,e,r){return JSON.stringify(Ne(t,e,r))}var Ae,Ma,cs=h(()=>{"use strict";l();p();Zt();Nt();Ce();Ae=3,Ma=[{header:"TIME",width:13,key:"time"},{header:"STATUS",width:10,key:"status"},{header:"PRODUCT",width:10,key:"product"},{header:"SIDE",width:5,key:"side"},{header:"SIZE",width:12,key:"size"},{header:"PRICE",width:12,key:"price"},{header:"FEE",width:8,key:"fee"},{header:"ORDER ID",width:12,key:"id"}]});function _s(t,e,r,n=8){let i=r-e;if(i<=0)return"\u2500".repeat(n);let s=Math.max(0,Math.min(1,(t-e)/i)),a=Math.round(s*(n-1)),o="";for(let c=0;c<n;c++)o+=c===a?"\u25CF":"\u2500";return o}function us(t,e,r){if(e<=0||t<=0)return"";let n=Math.max(0,Math.round(t/e*r));return"\u2588".repeat(n)}var Pr=h(()=>{"use strict";l();p()});function ls(t){let e=[],r=0;for(let n of $a){if(r+n.width+1>t)break;e.push(n),r+=n.width+1}return e}function ps(){return{products:new Map,prevPrices:new Map,productOrder:[],heartbeat:!1,updateCount:0,lastClock:$()}}function ms(t,e){let r=t.events;if(!r)return[];let n=[];for(let i of r){let s=i.tickers;if(s)for(let a of s){let o={product_id:String(a.product_id??""),price:String(a.price??"0"),volume_24_h:String(a.volume_24_h??"0"),price_percent_chg_24_h:String(a.price_percent_chg_24_h??"0"),best_bid:String(a.best_bid??"0"),best_bid_quantity:String(a.best_bid_quantity??"0"),best_ask:String(a.best_ask??"0"),best_ask_quantity:String(a.best_ask_quantity??"0"),high_24_h:String(a.high_24_h??"0"),low_24_h:String(a.low_24_h??"0")},c=e.prevPrices.get(o.product_id),d=parseFloat(o.price),_=0;c!==void 0&&(d>c?_=1:d<c&&(_=-1)),e.prevPrices.set(o.product_id,d),e.products.set(o.product_id,o),e.productOrder.includes(o.product_id)||e.productOrder.push(o.product_id),e.updateCount++,e.lastClock=$(),n.push({ticker:o,direction:_})}}return n}function Ha(t,e,r,n,i,s){let a=parseFloat(e.price),o=s?F:"";switch(t){case"symbol":return q(e.product_id,r);case"price":return`${kr(n,i,s)}${C(W(a),r)}${o}`;case"pct":{let c=parseFloat(e.price_percent_chg_24_h),d=c>0?1:c<0?-1:0;return`${kr(d,!1,s)}${C(es(c),r)}${o}`}case"bid":return C(W(parseFloat(e.best_bid)),r);case"ask":return C(W(parseFloat(e.best_ask)),r);case"bidSz":return`${s?B:""}${C(Mt(parseFloat(e.best_bid_quantity)),r)}${o}`;case"askSz":return`${s?B:""}${C(Mt(parseFloat(e.best_ask_quantity)),r)}${o}`;case"low":return`${s?B:""}${C(W(parseFloat(e.low_24_h)),r)}${o}`;case"high":return`${s?B:""}${C(W(parseFloat(e.high_24_h)),r)}${o}`;case"range":return q(_s(a,parseFloat(e.low_24_h),parseFloat(e.high_24_h),r),r);case"vol":return`${s?B:""}${C(ts(parseFloat(e.volume_24_h)),r)}${o}`;default:return q("",r)}}function gs(t,e,r,n,i=80){return ls(i).map(a=>Ha(a.key,t,a.width,e,r,n)).join(" ")}function ja(t,e=80){let n=ls(e).map(i=>i.key==="symbol"||i.key==="range"?q(i.header,i.width):C(i.header,i.width)).join(" ");return t?`${B}${n}${F}`:n}function Ka(t,e,r){let n=`${t.products.size} product${t.products.size!==1?"s":""}`,s=`${Lt(t.heartbeat,r)} ${t.lastClock}`;return Dt(n,s,e)}function Tr(t){t.enterAltScreen(),t.hideCursor(),t.moveTo(Wa,1),t.write(ja(!0,t.cols)+"\x1B[K"),t.moveTo(Va,1),t.write(ct(t.cols,!0))}function fs(t,e,r,n,i){let s=t.cols,a=t.rows,o=a,c=a-1;for(let{ticker:d,direction:_}of n){let u=e.productOrder.indexOf(d.product_id);if(u<0)continue;let g=ds+u;if(g>=c)continue;let f=i?.has(d.product_id)??!1,O=!f&&r.isFlashing(d.product_id);t.moveTo(g,1);let k=gs(d,f?0:_,O,!0,s);t.write((f?B+k+F:k)+"\x1B[K")}for(let d of r.expired()){let _=e.productOrder.indexOf(d);if(_<0)continue;let u=ds+_;if(u>=c)continue;let g=e.products.get(d);g&&(t.moveTo(u,1),t.write(gs(g,0,!1,!0,s)+"\x1B[K"))}t.moveTo(c,1),t.write(ct(s,!0)),t.moveTo(o,1),t.write(Ka(e,s-1,!0)+"\x1B[K")}function Sr(t,e,r){return{_ch:"ticker",_seq:e,_ts:r,product_id:t.product_id,price:t.price,pct_24h:t.price_percent_chg_24_h,bid:t.best_bid,bid_size:t.best_bid_quantity,ask:t.best_ask,ask_size:t.best_ask_quantity,volume:t.volume_24_h,high:t.high_24_h,low:t.low_24_h}}function bs(t,e,r){return JSON.stringify(Sr(t,e,r))}var Wa,Va,ds,$a,ys=h(()=>{"use strict";l();p();Zt();Nt();Ce();Pr();Wa=1,Va=2,ds=3,$a=[{header:"SYMBOL",width:10,key:"symbol"},{header:"PRICE",width:12,key:"price"},{header:"%24h",width:8,key:"pct"},{header:"BID",width:11,key:"bid"},{header:"ASK",width:11,key:"ask"},{header:"LOW",width:11,key:"low"},{header:"RANGE",width:10,key:"range"},{header:"HIGH",width:11,key:"high"},{header:"BIDSZ",width:7,key:"bidSz"},{header:"ASKSZ",width:7,key:"askSz"},{header:"VOL",width:6,key:"vol"}]});function Es(t,e=0){return{productId:t,bids:new Map,asks:new Map,heartbeat:!1,updateCount:0,msgCount:0,lastMsgTime:Date.now(),msgRate:0,depth:e,lastClock:$()}}function Is(t,e){let r=t.events;if(!r)return;e.msgCount++;let n=Date.now(),i=(n-e.lastMsgTime)/1e3;i>=1&&(e.msgRate=Math.round(e.msgCount/i),e.msgCount=0,e.lastMsgTime=n);for(let s of r){let a=s.type,o=s.updates;if(a==="snapshot"&&(e.bids.clear(),e.asks.clear()),!!o){for(let c of o){let d=String(c.side??"").toLowerCase(),_=parseFloat(String(c.price_level??"0")),u=parseFloat(String(c.new_quantity??"0"));if(_<=0)continue;let g=d==="bid"?e.bids:e.asks;u<=0?g.delete(_):g.set(_,u)}e.updateCount++,e.lastClock=$()}}}function Ge(t){let e=[];for(let[r,n]of t.bids)e.push({price:r,size:n});return e.sort((r,n)=>n.price-r.price),e}function De(t){let e=[];for(let[r,n]of t.asks)e.push({price:r,size:n});return e.sort((r,n)=>r.price-n.price),e}function hs(t,e,r,n,i,s,a){let o=a?i==="bid"?Ct:At:"",c=a?F:"",d=us(r,n,s),_=`${o}${d}${c}`;return[`${o}${C(W(t),_t[0])}${c}`,C(e.toFixed(4),_t[1]),C(r.toFixed(4),_t[2]),_].join(" ")}function Ja(t,e,r){let n=De(t),i=Ge(t),s=n.length>0?n[0].price:0,a=i.length>0?i[0].price:0,o=s-a,c=(s+a)/2,d=c>0?o/c*100:0,_=c>0?` Spread: ${W(o).padStart(10)} (${d.toFixed(3).padStart(6)}%) Mid: ${W(c).padStart(12)}`:" Waiting for data...",u=r?B:"",g=r?F:"";return`${u}${q(_,e)}${g}`}function Xa(t,e,r){let n=Qa.map((c,d)=>d===3?q(c,_t[d]):C(c,_t[d])).join(" "),i=r?B:"",s=r?xt:"",a=r?F:"",o=`${s}${t.productId}${a}`;return`${q(o,e)}
|
|
52
|
-
${i}${n}${a}`}function Za(t,e,r){let n=Ge(t).reduce((_,u)=>_+u.size,0),i=De(t).reduce((_,u)=>_+u.size,0),s=i>0?(n/i).toFixed(2):"-",o=`${t.depth?`Depth:${t.depth} `:""}B/A:${s} Rate:${t.msgRate}/s`,d=`${Lt(t.heartbeat,r)} ${t.lastClock}`;return Dt(o,d,e)}function wr(t,e){t.enterAltScreen(),t.hideCursor(),xr(t,e)}function xr(t,e){let r=t.cols,n=t.rows;if(n<4)return;let i=
|
|
50
|
+
`}function gi(){return at()}function Ho(){try{return JSON.parse(Fo(_i(gi(),di),"utf8"))}catch{return null}}function jo(t){try{let e=gi();qo(e,{recursive:!0}),Uo(_i(e,di),JSON.stringify(t))}catch{}}async function Ko(){try{let t=new AbortController,e=setTimeout(()=>t.abort(),3e3),r=await fetch(Bo,{signal:t.signal,headers:{Accept:"application/json"}});return clearTimeout(e),r.ok?(await r.json())?.["dist-tags"]?.latest??null:null}catch{return null}}async function li(){if(process.env.CI||process.env.COINBASE_NO_UPDATE_CHECK)return"";let t=Ho();if(t&&Date.now()-t.checkedAt<$o)return"";let e=await Ko();return e?(jo({checkedAt:Date.now(),latestVersion:e}),zo(rt,e)?Vo(rt,e):""):""}var ui,rt,ye,Bo,di,Wo,$o,he=h(()=>{"use strict";l();p();ie();Q();ui="0.0.4";rt=ui,ye=Wr,Bo=`${ne}/${encodeURIComponent(ye)}`,di="version-check.json";Wo="https://registry.npmjs.org";$o=1440*60*1e3});import{createSign as Yo,createPrivateKey as Qo,sign as Jo,randomBytes as Xo}from"node:crypto";function _r(t){return Buffer.from(t).toString("base64url")}function Ee(t){return _r(Buffer.from(JSON.stringify(t)))}function Zo(){return Xo(16).toString("hex")}function mi(t){return t.includes("-----BEGIN EC PRIVATE KEY-----")}function fi(t){let e=Buffer.from(t,"base64");return e.length===32||e.length===64}function ur(t,e,r,n,i){let s=Math.floor(Date.now()/1e3),a=Zo(),o={sub:t,iss:"cdp",nbf:s,iat:s,exp:s+120},c=`${r} ${n}${i}`;if(r&&n&&i&&(o.uris=[c]),mi(e))return ea(t,e,o,a);if(fi(e))return ra(t,e,o,a);throw new Error("invalid key format - must be either PEM EC key or base64 Ed25519 key")}function ta(t,e,r){let n=`${Ee(t)}.${Ee(e)}`,i=Yo("SHA256");i.update(n);let s=i.sign(r);return`${n}.${_r(na(s))}`}function ea(t,e,r,n){return ta({alg:"ES256",typ:"JWT",kid:t,nonce:n},r,e)}function ra(t,e,r,n){let s=`${Ee({alg:"EdDSA",typ:"JWT",kid:t,nonce:n})}.${Ee(r)}`,a=Buffer.from(e,"base64"),o=Qo({key:Buffer.concat([Buffer.from("302e020100300506032b657004220420","hex"),a.subarray(0,32)]),format:"der",type:"pkcs8"}),c=Jo(null,Buffer.from(s),o);return`${s}.${_r(c)}`}function na(t){let e=2;if(t[e]!==2)throw new Error("invalid DER signature");e++;let r=t[e];e++;let n=t.subarray(e,e+r);if(e+=r,t[e]!==2)throw new Error("invalid DER signature");e++;let i=t[e];e++;let s=t.subarray(e,e+i);return n=pi(n,32),s=pi(s,32),Buffer.concat([n,s])}function pi(t,e){if(t.length===e)return Buffer.from(t);if(t.length>e)return Buffer.from(t.subarray(t.length-e));let r=Buffer.alloc(e);return r.set(t,e-t.length),r}function ia(t){return mi(t)?"ecdsa":fi(t)?"ed25519":"unknown"}async function Ie(t){let e;if(t.keyId&&t.keySecret){let a=new URL(t.url);e=`Bearer ${ur(t.keyId,t.keySecret,t.method,a.host,a.pathname)}`}else throw new Error("doAuthenticatedRequest: must supply keyId+keySecret");let r={Authorization:e,"Content-Type":"application/json","Correlation-Context":`sdk_version=${encodeURIComponent(rt)},sdk_language=typescript,source=${encodeURIComponent(ye)}`,...t.headers},n=await fetch(t.url,{method:t.method,headers:r,body:t.body?Buffer.from(t.body):void 0}),s={body:new Uint8Array(await n.arrayBuffer()),status:n.status,headers:n.headers};return n.status===401&&t.keySecret&&ia(t.keySecret)==="ed25519"&&(s.hint="CDP key is Ed25519 but Coinbase Advanced Trade requires ECDSA. Create an ECDSA key at https://portal.cdp.coinbase.com/projects/api-keys (set Signature algorithm to ECDSA at key creation), then `coinbase env <name> --key-file ...`."),s}var ve=h(()=>{"use strict";l();p();he()});function Ra(t,e){return t.FORCE_HYPERLINK==="0"?!1:t.FORCE_HYPERLINK?!0:!e||t.CI?!1:!!(/ghostty|iterm|wezterm|hyper/i.test(t.TERM_PROGRAM||"")||t.WT_SESSION||parseInt(t.VTE_VERSION||"",10)>=5e3)}function ct(t){return t.replace(/\x1b\]8;;[^\x07]*\x07/g,"").replace(/\x1b\[[0-9;]*m/g,"").length}var Ui,ke=h(()=>{"use strict";l();p();Ui=Ra(process.env,!!process.stdout.isTTY)});function Ta(t){let e=[],r=0;for(;r<t.length;){if(t[r]===" "||t[r]===" "){r++;continue}let n=r;if(t[r]==="("){e.push({type:12,value:"(",pos:n}),r++;continue}if(t[r]===")"){e.push({type:13,value:")",pos:n}),r++;continue}if(r+1<t.length){let i=t[r]+t[r+1];if(i==="=="){e.push({type:3,value:"==",pos:n}),r+=2;continue}if(i==="!="){e.push({type:4,value:"!=",pos:n}),r+=2;continue}if(i===">="){e.push({type:7,value:">=",pos:n}),r+=2;continue}if(i==="<="){e.push({type:8,value:"<=",pos:n}),r+=2;continue}if(i==="&&"){e.push({type:9,value:"&&",pos:n}),r+=2;continue}if(i==="||"){e.push({type:10,value:"||",pos:n}),r+=2;continue}}if(t[r]===">"){e.push({type:5,value:">",pos:n}),r++;continue}if(t[r]==="<"){e.push({type:6,value:"<",pos:n}),r++;continue}if(t[r]==='"'){r++;let i="";for(;r<t.length&&t[r]!=='"';)t[r]==="\\"&&r+1<t.length&&r++,i+=t[r],r++;if(r>=t.length)throw new Error(`Unterminated string at position ${n}`);r++,e.push({type:2,value:i,pos:n});continue}if(t[r]==="-"||t[r]>="0"&&t[r]<="9"){let i="";if(t[r]==="-")if(r+1<t.length&&t[r+1]>="0"&&t[r+1]<="9")i+=t[r],r++;else throw new Error(`Unexpected character '-' at position ${n}`);for(;r<t.length&&t[r]>="0"&&t[r]<="9";)i+=t[r],r++;if(r<t.length&&t[r]===".")for(i+=".",r++;r<t.length&&t[r]>="0"&&t[r]<="9";)i+=t[r],r++;let s=r<t.length?t[r]:"",a=s.toLowerCase()in fr&&(r+1>=t.length||t[r+1]===" "||t[r+1]===" "||t[r+1]===")"||t[r+1]==="&"||t[r+1]==="|");if(s&&!a&&(s>="a"&&s<="z"||s>="A"&&s<="Z"||s==="-"))r=n;else{let o=parseFloat(i);r<t.length&&t[r].toLowerCase()in fr&&(o*=fr[t[r].toLowerCase()],r++),e.push({type:1,value:o,pos:n});continue}}if(t[r]>="a"&&t[r]<="z"||t[r]>="A"&&t[r]<="Z"||t[r]==="_"||t[r]>="0"&&t[r]<="9"){let i="";for(;r<t.length&&(t[r]>="a"&&t[r]<="z"||t[r]>="A"&&t[r]<="Z"||t[r]>="0"&&t[r]<="9"||t[r]==="_"||t[r]==="-");)i+=t[r],r++;e.push({type:0,value:i,pos:n});continue}throw new Error(`Unexpected character '${t[r]}' at position ${n}`)}return e.push({type:11,value:"",pos:r}),e}function Sa(t){return t>=3&&t<=8}function yr(t){let e=t.trim();if(e.length===0)throw new Error("Empty predicate");return new br(Ta(e)).parse()}function Jt(t){switch(t.type){case"comparison":return t.product?[t.product]:[];case"and":case"or":return[...Jt(t.left),...Jt(t.right)]}}function zi(t,e){let r=[];function n(i){switch(i.type){case"comparison":{let s=e[i.field];if(!s){r.push({field:i.field,message:`Unknown field '${i.field}'`});return}s.type==="string"&&typeof i.value=="number"&&r.push({field:i.field,message:`'${i.field}' is a string field \u2014 use "${i.value}" not ${i.value}`}),s.type==="number"&&typeof i.value=="string"&&r.push({field:i.field,message:`'${i.field}' is a numeric field \u2014 use ${i.value} not "${i.value}"`}),s.type==="string"&&(i.op===">"||i.op==="<"||i.op===">="||i.op==="<=")&&r.push({field:i.field,message:`'${i.field}' is a string field \u2014 only == and != are supported`}),s.enum&&typeof i.value=="string"&&!s.enum.includes(i.value)&&r.push({field:i.field,message:`'${i.value}' is not valid for '${i.field}' \u2014 expected: ${s.enum.join(", ")}`});break}case"and":case"or":n(i.left),n(i.right);break}}return n(t),r}function wa(t,e){let r=e.split("."),n=t;for(let i of r){if(n==null||typeof n!="object")return;n=n[i]}return n}function Ca(t,e){if(typeof e=="number"){if(typeof t=="number")return[t,e];if(typeof t=="string"&&xa.test(t))return[parseFloat(t),e]}return null}function Aa(t,e,r){let n=t.product&&r?r.get(t.product)??e:e;if(t.product&&n.product_id!==t.product)return!1;let i=wa(n,t.field);if(i==null)return!1;let s=Ca(i,t.value);switch(t.op){case"==":return s?s[0]===s[1]:i===t.value;case"!=":return s?s[0]!==s[1]:i!==t.value;case">":return s?s[0]>s[1]:!1;case"<":return s?s[0]<s[1]:!1;case">=":return s?s[0]>=s[1]:!1;case"<=":return s?s[0]<=s[1]:!1}}function wt(t,e,r){switch(t.type){case"comparison":return Aa(t,e,r);case"and":return wt(t.left,e,r)&&wt(t.right,e,r);case"or":return wt(t.left,e,r)||wt(t.right,e,r)}}function Wi(t){let e=[];e.push(" --until <predicate> Exit when predicate matches"),e.push(""),e.push(" Predicate: field [product] op value [&& | || ...]"),e.push(" Operators: == != > < >= <="),e.push(" Grouping: ( )"),e.push(" Suffixes: k (1,000) m (1,000,000) b (1,000,000,000)"),e.push(""),e.push(" Fields:");let r=Math.max(...Object.keys(t).map(s=>s.length));for(let[s,a]of Object.entries(t)){let o=a.enum?a.enum.join("|"):a.type;e.push(` ${s.padEnd(r)} ${o.padEnd(12)} ${a.description}`)}let n=Object.entries(t).filter(([,s])=>s.type==="number").map(([s])=>s),i=Object.entries(t).filter(([,s])=>s.enum).map(([s,a])=>({k:s,vals:a.enum}));if(e.push(""),e.push(" Examples:"),n.length>0&&e.push(` --until "${n[0]} > 70k"`),n.length>1&&e.push(` --until "${n[0]} >= 70k && ${n[0]} <= 75k"`),i.length>0){let s=i[0];e.push(` --until "${s.k} == \\"${s.vals[0]}\\""`)}return n.length>0&&e.push(` --until "(${n[0]} > 72k || ${n[0]} < 68k)"`),e.join(`
|
|
51
|
+
`)}var fr,br,xa,hr=h(()=>{"use strict";l();p();fr={k:1e3,m:1e6,b:1e9};br=class{tokens;pos=0;constructor(e){this.tokens=e}parse(){let e=this.parseOr();if(this.current().type!==11)throw new Error(`Unexpected token '${this.current().value}' at position ${this.current().pos}`);return e}parseOr(){let e=this.parseAnd();for(;this.current().type===10;)this.advance(),e={type:"or",left:e,right:this.parseAnd()};return e}parseAnd(){let e=this.parseAtom();for(;this.current().type===9;)this.advance(),e={type:"and",left:e,right:this.parseAtom()};return e}parseAtom(){if(this.current().type===12){this.advance();let e=this.parseOr();if(this.current().type!==13)throw new Error(`Expected ')' at position ${this.current().pos}`);return this.advance(),e}return this.parseComparison()}parseComparison(){let r=this.expect(0,"field name").value,n;this.current().type===0&&this.pos+1<this.tokens.length&&Sa(this.tokens[this.pos+1].type)&&(n=this.advance().value);let i=this.parseOp(),s;if(this.current().type===1)s=this.advance().value;else if(this.current().type===2)s=this.advance().value;else throw new Error(`Expected number or string at position ${this.current().pos}, got '${this.current().value}'`);return{type:"comparison",field:r,product:n,op:i,value:s}}parseOp(){let e=this.current();switch(e.type){case 3:return this.advance(),"==";case 4:return this.advance(),"!=";case 5:return this.advance(),">";case 6:return this.advance(),"<";case 7:return this.advance(),">=";case 8:return this.advance(),"<=";default:throw new Error(`Expected operator at position ${e.pos}, got '${e.value}'`)}}current(){return this.tokens[this.pos]}advance(){return this.tokens[this.pos++]}expect(e,r){let n=this.current();if(n.type!==e)throw new Error(`Expected ${r} at position ${n.pos}, got '${n.value}'`);return this.advance()}};xa=/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/});function Re(t){return Ga[t]??null}var Er,Na,Ga,Ir=h(()=>{"use strict";l();p();Er="wss://advanced-trade-ws.coinbase.com",Na="wss://advanced-trade-ws-user.coinbase.com",Ga={products_ticker:{name:"ticker",endpoint:Er,requiresAuth:!1,coalesce:!0},products_book:{name:"level2",wireName:"l2_data",endpoint:Er,requiresAuth:!1,coalesce:!0},orders_list:{name:"user",endpoint:Na,requiresAuth:!0,coalesce:!1},products_trades:{name:"market_trades",endpoint:Er,requiresAuth:!1,coalesce:!0}}});var L,Da,La,Pe,Te=h(()=>{"use strict";l();p();L={CONNECTING:"CONNECTING",CONNECTED:"CONNECTED",SUBSCRIBED:"SUBSCRIBED",RECONNECTING:"RECONNECTING",FAILED:"FAILED"},Da=3e4,La=1e3,Pe=class{url;opts;ws=null;_state=L.CONNECTING;heartbeatTimer=null;reconnectTimer=null;retryCount=0;closed=!1;WSClass;heartbeatTimeoutMs;maxRetries;now;lastActivityTime=0;wasReconnecting=!1;constructor(e,r){this.url=e,this.opts=r,this.WSClass=r.WebSocketClass??globalThis.WebSocket,this.heartbeatTimeoutMs=r.heartbeatTimeoutMs??5e3,this.maxRetries=r.maxRetries??1/0,this.now=r.now??Date.now}get state(){return this._state}connect(){if(!this.closed){this.clearReconnectTimer(),this.teardownSocket(),this.setState(L.CONNECTING);try{this.ws=new this.WSClass(this.url)}catch{this.scheduleReconnect();return}this.resetHeartbeat(),this.ws.onopen=()=>{this.lastActivityTime=this.now(),this.setState(L.CONNECTED),this.resetHeartbeat()},this.ws.onmessage=e=>{let r=this.now();if(this.lastActivityTime>0&&r-this.lastActivityTime>this.heartbeatTimeoutMs*2){this.forceClose();return}this.lastActivityTime=r,this.resetHeartbeat();let n;try{n=typeof e.data=="string"?JSON.parse(e.data):e.data}catch{return}this.opts.onMessage(n)},this.ws.onclose=()=>{this.clearHeartbeat(),this.closed||this.scheduleReconnect()},this.ws.onerror=()=>{}}}send(e){this.ws&&this.ws.readyState===1&&this.ws.send(e)}markSubscribed(){this.setState(L.SUBSCRIBED),this.retryCount=0}close(){this.closed=!0,this.clearHeartbeat(),this.clearReconnectTimer(),this.teardownSocket()}teardownSocket(){this.ws&&(this.ws.onopen=null,this.ws.onclose=null,this.ws.onmessage=null,this.ws.onerror=null,this.ws.readyState<2&&this.ws.close(1e3,"teardown"),this.ws=null)}forceClose(){this.ws&&(this.clearHeartbeat(),this.teardownSocket(),this.scheduleReconnect())}setState(e){this._state=e,e===L.RECONNECTING&&!this.wasReconnecting&&(this.wasReconnecting=!0,this.opts.onDisconnect?.()),e===L.CONNECTED&&this.wasReconnecting&&(this.wasReconnecting=!1,this.opts.onReconnect?.()),this.opts.onStateChange?.(e)}resetHeartbeat(){this.clearHeartbeat(),this.heartbeatTimer=setTimeout(()=>{this.forceClose()},this.heartbeatTimeoutMs)}clearHeartbeat(){this.heartbeatTimer&&(clearTimeout(this.heartbeatTimer),this.heartbeatTimer=null)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}scheduleReconnect(){if(this.closed)return;if(this.clearReconnectTimer(),this.retryCount>=this.maxRetries){this.setState(L.FAILED);return}this.setState(L.RECONNECTING);let e=Math.min(La*Math.pow(2,this.retryCount),Da),r=500+Math.random()*(e-500);this.retryCount++,this.reconnectTimer=setTimeout(()=>{this.connect()},r)}}});var Se,Vi=h(()=>{"use strict";l();p();Te();Se=class{conn;channel;productIds=[];jwt;lastSeq;hasSubscribed=!1;wasReconnecting=!1;eventHandler;gapHandler;heartbeatHandler;errorHandler;reconnectedHandler;refreshJWTFn;constructor(e){this.channel=e.channel,this.eventHandler=e.onEvent,this.gapHandler=e.onSequenceGap,this.heartbeatHandler=e.onHeartbeat,this.errorHandler=e.onError,this.reconnectedHandler=e.onReconnected,this.refreshJWTFn=e.refreshJWT;let r={onMessage:n=>this.handleMessage(n),onStateChange:n=>{n===L.CONNECTED&&this.hasSubscribed&&(this.refreshJWTFn&&this.wasReconnecting&&(this.jwt=this.refreshJWTFn()),this.lastSeq=void 0,this.sendSubscribe()),e.onStateChange?.(n)},onDisconnect:()=>{this.wasReconnecting=!0,e.onDisconnect?.()},onReconnect:()=>{e.onReconnect?.()},heartbeatTimeoutMs:e.heartbeatTimeoutMs,maxRetries:e.maxRetries,WebSocketClass:e.WebSocketClass,now:e.now};this.conn=new Pe(e.channel.endpoint,r)}connect(){this.conn.connect()}subscribe(e,r){this.productIds=e,this.jwt=r,this.hasSubscribed=!0,this.lastSeq=void 0,(this.conn.state===L.CONNECTED||this.conn.state===L.SUBSCRIBED)&&this.sendSubscribe()}unsubscribe(e){let r={type:"unsubscribe",channel:this.channel.name};e.length>0&&(r.product_ids=e),this.jwt&&(r.jwt=this.jwt),this.conn.send(JSON.stringify(r));let n={type:"unsubscribe",channel:"heartbeats"};e.length>0&&(n.product_ids=e),this.jwt&&(n.jwt=this.jwt),this.conn.send(JSON.stringify(n)),this.productIds=this.productIds.filter(i=>!e.includes(i))}updateJWT(e){this.jwt=e}close(){this.conn.close()}get state(){return this.conn.state}get subscribedProducts(){return[...this.productIds]}sendSubscribe(){let e={type:"subscribe",channel:this.channel.name};this.productIds.length>0&&(e.product_ids=this.productIds),this.jwt&&(e.jwt=this.jwt),this.conn.send(JSON.stringify(e));let r={type:"subscribe",channel:"heartbeats"};this.productIds.length>0&&(r.product_ids=this.productIds),this.jwt&&(r.jwt=this.jwt),this.conn.send(JSON.stringify(r))}handleMessage(e){if(typeof e!="object"||e===null)return;let r=e;if(r.type==="error"){this.errorHandler?.(String(r.message??r.reason??"unknown error"));return}if(r.type==="subscriptions"||r.channel==="subscriptions"){typeof r.sequence_num=="number"&&(this.lastSeq===void 0||r.sequence_num>this.lastSeq)&&(this.lastSeq=r.sequence_num),this.conn.markSubscribed(),this.wasReconnecting&&(this.wasReconnecting=!1,this.reconnectedHandler?.());return}if(typeof r.sequence_num=="number"){let i=r.sequence_num;if(this.lastSeq!==void 0&&i<=this.lastSeq)return;this.lastSeq!==void 0&&i>this.lastSeq+1&&this.gapHandler?.(this.lastSeq+1,i),(this.lastSeq===void 0||i>this.lastSeq)&&(this.lastSeq=i)}if(r.channel==="heartbeats"){this.heartbeatHandler?.();return}let n=this.channel.wireName??this.channel.name;r.channel===n&&this.eventHandler(e)}}});function we(t,e){return ur(t,e,"","","")}var vr=h(()=>{"use strict";l();p();ve()});var xe,$i=h(()=>{"use strict";l();p();xe=class{snapshots=new Map;timestamps=new Map;now;constructor(e){this.now=e??Date.now}update(e,r){this.snapshots.set(e,r),this.timestamps.set(e,this.now())}get(e){return this.snapshots.get(e)}all(){return this.snapshots}isStale(e,r){let n=this.timestamps.get(e);return n===void 0?!1:this.now()-n>r}staleProducts(e,r){let n=new Set;for(let i of e)this.isStale(i,r)&&n.add(i);return n}hasSeen(e){return this.timestamps.has(e)}age(e){let r=this.timestamps.get(e);if(r!==void 0)return this.now()-r}}});function kr(t,e,r){if(!r||t===0)return"";let n=t>0?Ct:At;return e?`${xt}${n}`:n}function Ji(t,e,r){if(!r)return"";let n=t==="bid"||t==="BUY"?Ct:At;return e?`${xt}${n}`:n}var B,xt,Ct,At,Hi,M,ji,Ki,Yi,Qi,Nt=h(()=>{"use strict";l();p();B="\x1B[2m",xt="\x1B[1m",Ct="\x1B[32m",At="\x1B[31m",Hi="\x1B[33m",M="\x1B[0m",ji="\x1B[?25l",Ki="\x1B[?25h",Yi="\x1B[?1049h",Qi="\x1B[?1049l"});var Gt,Xi=h(()=>{"use strict";l();p();Nt();Gt=class{out;inAltScreen=!1;cursorHidden=!1;scrollRegionSet=!1;cleanedUp=!1;resizeHandlers=[];sigwinchHandler=null;sigintHandler=null;sigtermHandler=null;stdinHandler=null;constructor(e){this.out=e??process.stdout}enterAltScreen(){this.out.write(Yi),this.inAltScreen=!0}exitAltScreen(){this.out.write(Qi),this.inAltScreen=!1}hideCursor(){this.out.write(ji),this.cursorHidden=!0}showCursor(){this.out.write(Ki),this.cursorHidden=!1}setScrollRegion(e,r){this.out.write(`\x1B[${e};${r}r`),this.scrollRegionSet=!0}resetScrollRegion(){this.out.write("\x1B[r"),this.scrollRegionSet=!1}moveTo(e,r){this.out.write(`\x1B[${e};${r}H`)}clearLine(){this.out.write("\x1B[K")}insertLine(){this.out.write("\x1B[L")}write(e){this.out.write(e)}get cols(){return this.out.columns??80}get rows(){return this.out.rows??24}onResize(e){this.resizeHandlers.push(e),this.sigwinchHandler||(this.sigwinchHandler=()=>{let r=this.cols,n=this.rows;for(let i of this.resizeHandlers)i(r,n)},process.on("SIGWINCH",this.sigwinchHandler))}installSignalHandlers(e){let r=e??(()=>process.exit(0));process.stdin.isTTY&&typeof process.stdin.setRawMode=="function"&&(process.stdin.setRawMode(!0),process.stdin.resume(),this.stdinHandler=n=>{n[0]===3&&(this.cleanup(),r())},process.stdin.on("data",this.stdinHandler)),this.sigintHandler=()=>{this.cleanup(),r()},this.sigtermHandler=()=>{this.cleanup(),r()},process.on("SIGINT",this.sigintHandler),process.on("SIGTERM",this.sigtermHandler)}cleanup(){this.cleanedUp||(this.cleanedUp=!0,process.stdin.isTTY&&typeof process.stdin.setRawMode=="function"&&process.stdin.setRawMode(!1),this.scrollRegionSet&&this.resetScrollRegion(),this.cursorHidden&&this.showCursor(),this.inAltScreen&&this.exitAltScreen(),this.out.write(M),this.removeListeners())}removeListeners(){this.stdinHandler&&(process.stdin.removeListener("data",this.stdinHandler),this.stdinHandler=null,process.stdin.isTTY&&process.stdin.pause()),this.sigwinchHandler&&(process.removeListener("SIGWINCH",this.sigwinchHandler),this.sigwinchHandler=null),this.sigintHandler&&(process.removeListener("SIGINT",this.sigintHandler),this.sigintHandler=null),this.sigtermHandler&&(process.removeListener("SIGTERM",this.sigtermHandler),this.sigtermHandler=null)}}});var Xt,Zi=h(()=>{"use strict";l();p();Xt=class{flashes=new Map;offsets=new Map;now;constructor(e){this.now=e??Date.now}flash(e,r=600){this.flashes.set(e,this.now()+r)}isFlashing(e){let r=this.flashes.get(e);return r===void 0?!1:this.now()<r}expired(){let e=this.now(),r=[];for(let[n,i]of this.flashes)e>=i&&(r.push(n),this.flashes.delete(n),this.offsets.delete(n));return r}flashWithOffset(e,r,n=1500){let i=this.now()+n;this.flashes.set(e,i),this.offsets.set(e,{indexAtCreation:r,durationMs:n,expiry:i})}getRow(e,r,n){let i=this.offsets.get(e);if(!i)return null;if(this.now()>=i.expiry)return this.offsets.delete(e),null;let s=r-i.indexAtCreation-1;return n+s}clear(){this.flashes.clear(),this.offsets.clear()}}});function U(t,e){let r=ct(t);return r>=e?t.slice(0,t.length-(r-e)):t+" ".repeat(e-r)}function C(t,e){let r=ct(t);return r>=e?t.slice(0,t.length-(r-e)):" ".repeat(e-r)+t}function _t(t,e){let r="\u2500".repeat(t);return e?`${B}${r}${M}`:r}function Dt(t,e,r){let n=ct(t),i=ct(e);if(n+1+i>r){let o=r-i-1;return o>0?`${t.slice(0,o)} ${e}`:e.slice(0,r)}let a=r-n-i;return a<0?U(`${t} ${e}`,r):`${t}${" ".repeat(a)}${e}`}function Lt(t,e){return e?t?`${xt}\xB7${M}`:`${B}\xB7${M}`:""}function $(){let t=new Date,e=String(t.getHours()).padStart(2,"0"),r=String(t.getMinutes()).padStart(2,"0"),n=String(t.getSeconds()).padStart(2,"0");return`${e}:${r}:${n}`}var Zt=h(()=>{"use strict";l();p();ke();Nt()});function z(t){let e=Math.abs(t);return e>=1e3?t.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2}):e>=1?t.toFixed(2):t.toFixed(4)}function Mt(t){let e=Math.abs(t);return e>=100?t.toFixed(1):e>=10?t.toFixed(2):e>=1?t.toFixed(3):e>=.01?t.toFixed(4):e>=1e-4?t.toFixed(6):t===0?"0":t.toFixed(8)}function ts(t){return t>=1e9?`${(t/1e9).toFixed(1)}B`:t>=1e6?`${(t/1e6).toFixed(0)}M`:t>=1e3?`${(t/1e3).toFixed(0)}K`:t.toFixed(0)}function es(t){return`${t>=0?"+":""}${t.toFixed(2)}%`}function rs(t){let e=new Date(t);if(isNaN(e.getTime()))return t;let r=String(e.getHours()).padStart(2,"0"),n=String(e.getMinutes()).padStart(2,"0"),i=String(e.getSeconds()).padStart(2,"0"),s=String(e.getMilliseconds()).padStart(3,"0");return`${r}:${n}:${i}.${s}`}var Ce=h(()=>{"use strict";l();p()});function is(t){let e=[],r=0;for(let n of Ma){if(r+n.width+1>t){let i=t-r-1;i>=4&&n.key==="id"&&e.push({...n,width:i});break}e.push(n),r+=n.width+1}return e}function ss(){return{events:[],positions:new Map,openOrders:new Set,totalFees:0,lastClock:$(),netCash:0,fillCount:0,accounted:new Map,prependCount:0,heartbeat:!1,updateCount:0}}function Fa(t){let e=t.order_configuration;if(e)for(let r of Object.values(e)){if(r&&typeof r=="object"&&"base_size"in r)return String(r.base_size);if(r&&typeof r=="object"&&"quote_size"in r)return`$${String(r.quote_size)}`}}function Ua(t,e){let r=e.creation_time?Date.parse(e.creation_time):NaN;if(Number.isNaN(r))return 0;for(let n=0;n<t.length;n++){let i=t[n].creation_time?Date.parse(t[n].creation_time):NaN;if(!Number.isNaN(i)&&i<r)return n}return t.length}function Or(t,e,r="live"){let n=t.events;if(!n)return{inserts:[],updates:[]};let i=[],s=[];for(let a of n){let o=a.orders;if(o)for(let c of o){let d={order_id:String(c.order_id??""),status:String(c.status??""),product_id:String(c.product_id??""),order_side:String(c.order_side??c.side??""),order_type:c.order_type?String(c.order_type):void 0,average_filled_price:String(c.average_filled_price??c.avg_price??"0"),total_fees:String(c.total_fees??"0"),filled_size:String(c.filled_size??c.cumulative_quantity??"0"),base_size:Fa(c),creation_time:c.creation_time?String(c.creation_time):c.created_time?String(c.created_time):void 0},_=e.events.findIndex(u=>u.order_id===d.order_id);if(_>=0){let u=e.events[_],g=u.status!==d.status||u.filled_size!==d.filled_size||u.total_fees!==d.total_fees||u.average_filled_price!==d.average_filled_price;u.status=d.status,u.average_filled_price=d.average_filled_price,u.filled_size=d.filled_size,u.total_fees=d.total_fees,g&&(ns(e,d),s.push(u));continue}r==="backfill"?e.events.splice(Ua(e.events,d),0,d):e.events.unshift(d),e.prependCount++,ns(e,d),i.push(d),e.events.length>1e4&&e.events.pop()}}return{inserts:i,updates:s}}function ns(t,e){t.updateCount++,t.lastClock=$();let r=e.status.toUpperCase();r==="OPEN"||r==="PENDING"?t.openOrders.add(e.order_id):t.openOrders.delete(e.order_id);let n=parseFloat(e.total_fees??"0")||0,i=parseFloat(e.filled_size??"0")||0,s=parseFloat(e.average_filled_price??"0")||0,a=i*s,o=t.accounted.get(e.order_id)??{fees:0,size:0,value:0},c=n-o.fees,d=i-o.size,_=a-o.value;(d!==0||c!==0)&&(o.size===0&&i>0&&t.fillCount++,t.totalFees+=c,e.order_side==="BUY"?(t.netCash-=_,t.positions.set(e.product_id,(t.positions.get(e.product_id)??0)+d)):(t.netCash+=_,t.positions.set(e.product_id,(t.positions.get(e.product_id)??0)-d)),t.accounted.set(e.order_id,{fees:n,size:i,value:a}))}function qa(t,e,r,n,i){let s=e.order_side==="BUY"?"BUY":"SELL",a=Ji(s,n,i),o=e.status.toUpperCase(),c=i?M:"",d=parseFloat(e.average_filled_price??"0"),_=parseFloat(e.filled_size??"0");switch(t){case"time":return U(rs(e.creation_time??new Date().toISOString()),r);case"status":return`${(o==="OPEN"||o==="PENDING")&&i?Hi:""}${U(o,r)}${c}`;case"product":return U(e.product_id,r);case"side":return`${a}${U(s,r)}${c}`;case"size":{let u=_>0?Mt(_):e.base_size??"-";return`${a}${C(u,r)}${c}`}case"price":return`${a}${C(d>0?z(d):"-",r)}${c}`;case"fee":{let u=parseFloat(e.total_fees??"0");return C(u>0?z(u):"-",r)}case"id":return`${i?B:""}${U(e.order_id.slice(0,r),r)}${c}`;default:return U("",r)}}function te(t,e,r,n=80){return is(n).map(i=>qa(i.key,t,i.width,e,r)).join(" ")}function Ba(t,e=80){let r=new Set(["size","price","fee"]),i=is(e).map(s=>r.has(s.key)?C(s.header,s.width):U(s.header,s.width)).join(" ");return t?`${B}${i}${M}`:i}function za(t,e,r){let n=t.netCash>=0?r?Ct:"":r?At:"",i=r?M:"",s=`Fills:${t.fillCount}`,a=`Open:${t.openOrders.size}`,o=`Fees:${z(t.totalFees)}`,c=`Net:${t.netCash>=0?"+":""}${z(t.netCash)}`,d=`${n}${c}${i}`,u=`${Lt(t.heartbeat,r)} ${t.lastClock}`,g=`\xB7 ${t.lastClock}`,f=`${s} ${a} ${o} ${c}`,R=`${s} ${a} ${o} ${d}`,k=new Map;for(let[P,O]of t.positions){if(Math.abs(O)<1e-9)continue;let w=(P.match(/-/g)??[]).length===1?P.slice(0,P.indexOf("-")):P;k.set(w,(k.get(w)??0)+O)}let T=[],S=[];for(let[P,O]of k){if(Math.abs(O)<1e-9)continue;let q=`${P}:${Mt(O)}`;T.push(q),S.push(q)}let A=e-f.length-g.length-6,W="";if(T.length>0&&A>8){let P="",O=0,q=0;for(let w=0;w<T.length;w++){let it=q>0?" ":"";if(O+it.length+S[w].length>A){let I=T.length-q;I>0&&(P+=` +${I}`);break}P+=it+T[w],O+=it.length+S[w].length,q++}W=P}let j=W?`${R} ${W}`:R;return Dt(j,u,e)}function os(t,e,r,n,i){let s=i??e.events,a=t.cols,o=t.rows,c=o,d=o-1,_=o-2;n.inserts.forEach((u,g)=>{r.flashWithOffset(u.order_id,e.prependCount-1-g,1500),t.moveTo(Ae,1),t.insertLine(),t.write(te(u,!0,!0,t.cols)+"\x1B[K")});for(let u of n.updates){let g=s.indexOf(u);if(g>=0){let f=Ae+g;f<=_&&(r.flash(u.order_id,1500),t.moveTo(f,1),t.write(te(u,!0,!0,t.cols)+"\x1B[K"))}}for(let u of r.expired()){let g=s.findIndex(f=>f.order_id===u);if(g>=0){let f=Ae+g;f<=_&&(t.moveTo(f,1),t.write(te(s[g],!1,!0,t.cols)+"\x1B[K"))}}t.moveTo(d,1),t.write(_t(a,!0)),t.moveTo(c,1),t.write(za(e,a-1,!0)+"\x1B[K")}function Rr(t){t.enterAltScreen(),t.hideCursor();let e=t.rows;t.setScrollRegion(Ae,e-2),t.moveTo(1,1),t.write(Ba(!0,t.cols)+"\x1B[K"),t.moveTo(2,1),t.write(_t(t.cols,!0))}function Ne(t,e,r){return{_ch:"user",_seq:e,_ts:r,order_id:t.order_id,status:t.status,product_id:t.product_id,side:t.order_side,filled_size:t.filled_size??null,price:t.average_filled_price??null,fees:t.total_fees??null}}function as(t,e,r){return JSON.stringify(Ne(t,e,r))}var Ae,Ma,cs=h(()=>{"use strict";l();p();Zt();Nt();Ce();Ae=3,Ma=[{header:"TIME",width:13,key:"time"},{header:"STATUS",width:10,key:"status"},{header:"PRODUCT",width:10,key:"product"},{header:"SIDE",width:5,key:"side"},{header:"SIZE",width:12,key:"size"},{header:"PRICE",width:12,key:"price"},{header:"FEE",width:8,key:"fee"},{header:"ORDER ID",width:12,key:"id"}]});function _s(t,e,r,n=8){let i=r-e;if(i<=0)return"\u2500".repeat(n);let s=Math.max(0,Math.min(1,(t-e)/i)),a=Math.round(s*(n-1)),o="";for(let c=0;c<n;c++)o+=c===a?"\u25CF":"\u2500";return o}function us(t,e,r){if(e<=0||t<=0)return"";let n=Math.max(0,Math.round(t/e*r));return"\u2588".repeat(n)}var Pr=h(()=>{"use strict";l();p()});function ls(t){let e=[],r=0;for(let n of $a){if(r+n.width+1>t)break;e.push(n),r+=n.width+1}return e}function ps(){return{products:new Map,prevPrices:new Map,productOrder:[],heartbeat:!1,updateCount:0,lastClock:$()}}function ms(t,e){let r=t.events;if(!r)return[];let n=[];for(let i of r){let s=i.tickers;if(s)for(let a of s){let o={product_id:String(a.product_id??""),price:String(a.price??"0"),volume_24_h:String(a.volume_24_h??"0"),price_percent_chg_24_h:String(a.price_percent_chg_24_h??"0"),best_bid:String(a.best_bid??"0"),best_bid_quantity:String(a.best_bid_quantity??"0"),best_ask:String(a.best_ask??"0"),best_ask_quantity:String(a.best_ask_quantity??"0"),high_24_h:String(a.high_24_h??"0"),low_24_h:String(a.low_24_h??"0")},c=e.prevPrices.get(o.product_id),d=parseFloat(o.price),_=0;c!==void 0&&(d>c?_=1:d<c&&(_=-1)),e.prevPrices.set(o.product_id,d),e.products.set(o.product_id,o),e.productOrder.includes(o.product_id)||e.productOrder.push(o.product_id),e.updateCount++,e.lastClock=$(),n.push({ticker:o,direction:_})}}return n}function Ha(t,e,r,n,i,s){let a=parseFloat(e.price),o=s?M:"";switch(t){case"symbol":return U(e.product_id,r);case"price":return`${kr(n,i,s)}${C(z(a),r)}${o}`;case"pct":{let c=parseFloat(e.price_percent_chg_24_h),d=c>0?1:c<0?-1:0;return`${kr(d,!1,s)}${C(es(c),r)}${o}`}case"bid":return C(z(parseFloat(e.best_bid)),r);case"ask":return C(z(parseFloat(e.best_ask)),r);case"bidSz":return`${s?B:""}${C(Mt(parseFloat(e.best_bid_quantity)),r)}${o}`;case"askSz":return`${s?B:""}${C(Mt(parseFloat(e.best_ask_quantity)),r)}${o}`;case"low":return`${s?B:""}${C(z(parseFloat(e.low_24_h)),r)}${o}`;case"high":return`${s?B:""}${C(z(parseFloat(e.high_24_h)),r)}${o}`;case"range":return U(_s(a,parseFloat(e.low_24_h),parseFloat(e.high_24_h),r),r);case"vol":return`${s?B:""}${C(ts(parseFloat(e.volume_24_h)),r)}${o}`;default:return U("",r)}}function gs(t,e,r,n,i=80){return ls(i).map(a=>Ha(a.key,t,a.width,e,r,n)).join(" ")}function ja(t,e=80){let n=ls(e).map(i=>i.key==="symbol"||i.key==="range"?U(i.header,i.width):C(i.header,i.width)).join(" ");return t?`${B}${n}${M}`:n}function Ka(t,e,r){let n=`${t.products.size} product${t.products.size!==1?"s":""}`,s=`${Lt(t.heartbeat,r)} ${t.lastClock}`;return Dt(n,s,e)}function Tr(t){t.enterAltScreen(),t.hideCursor(),t.moveTo(Wa,1),t.write(ja(!0,t.cols)+"\x1B[K"),t.moveTo(Va,1),t.write(_t(t.cols,!0))}function fs(t,e,r,n,i){let s=t.cols,a=t.rows,o=a,c=a-1;for(let{ticker:d,direction:_}of n){let u=e.productOrder.indexOf(d.product_id);if(u<0)continue;let g=ds+u;if(g>=c)continue;let f=i?.has(d.product_id)??!1,R=!f&&r.isFlashing(d.product_id);t.moveTo(g,1);let k=gs(d,f?0:_,R,!0,s);t.write((f?B+k+M:k)+"\x1B[K")}for(let d of r.expired()){let _=e.productOrder.indexOf(d);if(_<0)continue;let u=ds+_;if(u>=c)continue;let g=e.products.get(d);g&&(t.moveTo(u,1),t.write(gs(g,0,!1,!0,s)+"\x1B[K"))}t.moveTo(c,1),t.write(_t(s,!0)),t.moveTo(o,1),t.write(Ka(e,s-1,!0)+"\x1B[K")}function Sr(t,e,r){return{_ch:"ticker",_seq:e,_ts:r,product_id:t.product_id,price:t.price,pct_24h:t.price_percent_chg_24_h,bid:t.best_bid,bid_size:t.best_bid_quantity,ask:t.best_ask,ask_size:t.best_ask_quantity,volume:t.volume_24_h,high:t.high_24_h,low:t.low_24_h}}function bs(t,e,r){return JSON.stringify(Sr(t,e,r))}var Wa,Va,ds,$a,ys=h(()=>{"use strict";l();p();Zt();Nt();Ce();Pr();Wa=1,Va=2,ds=3,$a=[{header:"SYMBOL",width:10,key:"symbol"},{header:"PRICE",width:12,key:"price"},{header:"%24h",width:8,key:"pct"},{header:"BID",width:11,key:"bid"},{header:"ASK",width:11,key:"ask"},{header:"LOW",width:11,key:"low"},{header:"RANGE",width:10,key:"range"},{header:"HIGH",width:11,key:"high"},{header:"BIDSZ",width:7,key:"bidSz"},{header:"ASKSZ",width:7,key:"askSz"},{header:"VOL",width:6,key:"vol"}]});function Es(t,e=0){return{productId:t,bids:new Map,asks:new Map,heartbeat:!1,updateCount:0,msgCount:0,lastMsgTime:Date.now(),msgRate:0,depth:e,lastClock:$()}}function Is(t,e){let r=t.events;if(!r)return;e.msgCount++;let n=Date.now(),i=(n-e.lastMsgTime)/1e3;i>=1&&(e.msgRate=Math.round(e.msgCount/i),e.msgCount=0,e.lastMsgTime=n);for(let s of r){let a=s.type,o=s.updates;if(a==="snapshot"&&(e.bids.clear(),e.asks.clear()),!!o){for(let c of o){let d=String(c.side??"").toLowerCase(),_=parseFloat(String(c.price_level??"0")),u=parseFloat(String(c.new_quantity??"0"));if(_<=0)continue;let g=d==="bid"?e.bids:e.asks;u<=0?g.delete(_):g.set(_,u)}e.updateCount++,e.lastClock=$()}}}function Ge(t){let e=[];for(let[r,n]of t.bids)e.push({price:r,size:n});return e.sort((r,n)=>n.price-r.price),e}function De(t){let e=[];for(let[r,n]of t.asks)e.push({price:r,size:n});return e.sort((r,n)=>r.price-n.price),e}function hs(t,e,r,n,i,s,a){let o=a?i==="bid"?Ct:At:"",c=a?M:"",d=us(r,n,s),_=`${o}${d}${c}`;return[`${o}${C(z(t),ut[0])}${c}`,C(e.toFixed(4),ut[1]),C(r.toFixed(4),ut[2]),_].join(" ")}function Ja(t,e,r){let n=De(t),i=Ge(t),s=n.length>0?n[0].price:0,a=i.length>0?i[0].price:0,o=s-a,c=(s+a)/2,d=c>0?o/c*100:0,_=c>0?` Spread: ${z(o).padStart(10)} (${d.toFixed(3).padStart(6)}%) Mid: ${z(c).padStart(12)}`:" Waiting for data...",u=r?B:"",g=r?M:"";return`${u}${U(_,e)}${g}`}function Xa(t,e,r){let n=Qa.map((c,d)=>d===3?U(c,ut[d]):C(c,ut[d])).join(" "),i=r?B:"",s=r?xt:"",a=r?M:"",o=`${s}${t.productId}${a}`;return`${U(o,e)}
|
|
52
|
+
${i}${n}${a}`}function Za(t,e,r){let n=Ge(t).reduce((_,u)=>_+u.size,0),i=De(t).reduce((_,u)=>_+u.size,0),s=i>0?(n/i).toFixed(2):"-",o=`${t.depth?`Depth:${t.depth} `:""}B/A:${s} Rate:${t.msgRate}/s`,d=`${Lt(t.heartbeat,r)} ${t.lastClock}`;return Dt(o,d,e)}function wr(t,e){t.enterAltScreen(),t.hideCursor(),xr(t,e)}function xr(t,e){let r=t.cols,n=t.rows;if(n<4)return;let i=ut[0]+ut[1]+ut[2]+3,s=Math.max(4,r-i),a=De(e),o=Ge(e),c=n-1,d=n,_=Math.max(0,n-4),u=Math.floor(_/2),g=_>u*2||u>0,f=e.depth?Math.min(u,e.depth):u,R=a.slice(0,f),k=o.slice(0,f),T=0,S=[];for(let O of R)T+=O.size,S.push(T);let A=0,W=[];for(let O of k)A+=O.size,W.push(A);let j=Math.max(T,A),P=1;t.moveTo(P,1),t.write(Xa(e,r,!0)+"\x1B[K"),P=Ya;for(let O=0;O<f&&P<c;O++,P++)if(t.moveTo(P,1),O<R.length){let q=R.length-1-O;t.write(hs(R[q].price,R[q].size,S[q],j,"ask",s,!0)+"\x1B[K")}else t.clearLine();g&&P<c&&(t.moveTo(P,1),t.write(Ja(e,r,!0)+"\x1B[K"),P++);for(let O=0;O<f&&P<c;O++,P++)t.moveTo(P,1),O<k.length?t.write(hs(k[O].price,k[O].size,W[O],j,"bid",s,!0)+"\x1B[K"):t.clearLine();for(;P<c;)t.moveTo(P,1),t.clearLine(),P++;t.moveTo(c,1),t.write(_t(r,!0)),t.moveTo(d,1),t.write(Za(e,r-1,!0)+"\x1B[K")}function Cr(t,e,r){let n=Ge(t).map(o=>({price:o.price,size:o.size})),i=De(t).map(o=>({price:o.price,size:o.size})),s=i.length>0?i[0].price:0,a=n.length>0?n[0].price:0;return{_ch:"level2",_seq:e,_ts:r,product_id:t.productId,spread:s-a,mid:(s+a)/2,bids:n,asks:i}}function vs(t,e,r){return JSON.stringify(Cr(t,e,r))}var Ya,ut,Qa,ks=h(()=>{"use strict";l();p();Zt();Nt();Ce();Pr();Ya=3,ut=[14,12,12,16],Qa=["PRICE","SIZE","TOTAL","DEPTH"]});function Os(t,e,r,n,i){return new Ar(t,e,r,n,i)}function Rs(t,e,r){return new Nr(t,e,r)}function Ps(t,e,r,n){return new Gr(t,e,r,n)}var Ar,Nr,Gr,Ts=h(()=>{"use strict";l();p();Te();vr();Xi();Zi();Zt();cs();ys();ks();be();Ar=class{productIds=[];screen;refreshJWT;state=ss();flash=new Xt;queryFilter;context;jwt;until;liveness=!1;connected=!1;constructor(e,r,n,i,s){this.context=r,this.jwt=n,this.until=s,this.queryFilter=e.flags.query,e.isTTY&&!e.untilActive&&(this.screen=new Gt(e.out),Rr(this.screen),this.screen.onResize(()=>{Rr(this.screen),this.repaintFrame()})),i.requiresAuth&&(this.refreshJWT=()=>this.freshJWT())}freshJWT(){let e=this.context.env;return e?.auth?.key_id&&e?.auth?.key_secret?we(e.auth.key_id,e.auth.key_secret):this.jwt}matchesFilter(e){let r=this.queryFilter;return r?!(r.status&&e.status.toUpperCase()!==String(r.status).toUpperCase()||r.product_ids&&!String(r.product_ids).split(",").includes(e.product_id)||r.side&&e.order_side.toUpperCase()!==String(r.side).toUpperCase()):!0}visibleEvents(){return this.queryFilter?this.state.events.filter(e=>this.matchesFilter(e)):void 0}syncHeartbeat(){this.state.heartbeat=this.connected&&this.liveness}render(e){this.screen&&(this.syncHeartbeat(),os(this.screen,this.state,this.flash,e,this.visibleEvents()))}repaintFrame(){if(!this.screen)return;let e=this.queryFilter?this.state.events.filter(i=>this.matchesFilter(i)):this.state.events,r=this.screen.rows-4,n=Math.min(e.length,r);for(let i=n-1;i>=0;i--)this.screen.moveTo(3+i,1),this.screen.write(te(e[i],!1,!0,this.screen.cols)+"\x1B[K");for(let i=n;i<r;i++)this.screen.moveTo(3+i,1),this.screen.write("\x1B[K");this.render({inserts:[],updates:[]})}onData(e,r,n){let i=this.queryFilter?this.visibleEvents().map(c=>c.order_id):void 0,s=Or(e,this.state);this.liveness=!this.liveness;let a={inserts:s.inserts.filter(c=>this.matchesFilter(c)),updates:s.updates.filter(c=>this.matchesFilter(c))};if(i){let c=this.visibleEvents().map(_=>_.order_id);c.length!==i.length||c.some((_,u)=>_!==i[u])?this.repaintFrame():this.render(a)}else this.render(a);return[...a.inserts,...a.updates].map(c=>({obj:Ne(c,r,n),line:as(c,r,n)}))}onHeartbeat(){this.liveness=!this.liveness,this.state.lastClock=$(),this.render({inserts:[],updates:[]})}onConnState(e){this.connected=e===L.SUBSCRIBED,this.repaintFrame()}onGap(){this.backfill().catch(()=>{})}onReconnected(){this.backfill().catch(()=>{})}setup(){return this.backfill()}cleanup(){this.screen?.cleanup()}async backfill(){try{let e=await St("orders_list",{query:{limit:100,...this.queryFilter}},this.context);if(e.status<400&&e.data?.orders){let r=e.data.orders;for(let n of r.reverse()){let s=Or({events:[{orders:[n]}]},this.state,"backfill");if(this.until.active)for(let a of[...s.inserts,...s.updates]){let o=String(n.created_time??new Date().toISOString());if(this.until.check(Ne(a,0,o)))return}}}}catch{}this.repaintFrame()}};Nr=class{productIds;screen;state=ps();flash=new Xt;until;liveness=!1;connected=!1;constructor(e,r,n){this.until=n,this.productIds=r,e.isTTY&&!e.untilActive&&(this.screen=new Gt(e.out),Tr(this.screen),this.screen.onResize(()=>{Tr(this.screen),this.repaintFrame()}))}syncHeartbeat(){this.state.heartbeat=this.connected&&this.liveness}render(e){this.screen&&(this.syncHeartbeat(),fs(this.screen,this.state,this.flash,e,this.until.active?this.until.stale:void 0))}repaintFrame(){if(!this.screen)return;let e=this.state.productOrder.map(r=>this.state.products.get(r)).filter(r=>!!r).map(r=>({ticker:r,direction:0}));this.render(e)}onData(e,r,n){let i=ms(e,this.state);this.liveness=!this.liveness;for(let{ticker:s}of i)this.flash.flash(s.product_id,600);return this.render(i),i.map(({ticker:s})=>({obj:Sr(s,r,n),line:bs(s,r,n)}))}onHeartbeat(){this.liveness=!this.liveness,this.state.lastClock=$(),this.render([])}onConnState(e){this.connected=e===L.SUBSCRIBED,this.render([])}onGap(){}onReconnected(){}async setup(){}cleanup(){this.screen?.cleanup()}};Gr=class{productIds;screen;state;productId;liveness=!1;connected=!1;constructor(e,r,n,i){this.productId=r,this.productIds=[r],this.state=Es(r,e.flags.depth??0),e.isTTY&&!e.untilActive&&(this.screen=new Gt(e.out),wr(this.screen,this.state),this.screen.onResize(()=>{wr(this.screen,this.state),this.render()}))}syncHeartbeat(){this.state.heartbeat=this.connected&&this.liveness}render(){this.screen&&(this.syncHeartbeat(),xr(this.screen,this.state))}onData(e,r,n){return Is(e,this.state),this.liveness=!this.liveness,this.render(),[{obj:Cr(this.state,r,n),line:vs(this.state,r,n)}]}onHeartbeat(){this.liveness=!this.liveness,this.state.lastClock=$(),this.render()}onConnState(e){this.connected=e===L.SUBSCRIBED,this.render()}onGap(){return this.state.bids.clear(),this.state.asks.clear(),this.render(),{resubscribe:[this.productId]}}onReconnected(){}async setup(){}cleanup(){this.screen?.cleanup()}}});var Ss={};Bt(Ss,{applyJQ:()=>Dr});import{execFileSync as tc}from"node:child_process";function Dr(t,e){try{return tc("jq",["-r",e],{input:t,encoding:"utf8",maxBuffer:10*1024*1024,env:Xe()}).trimEnd()}catch(r){if(r.code==="ENOENT")throw new Error("jq is not installed. Install it: https://jqlang.github.io/jq/download/");let n=(r.stderr??r.message??"").toString().trim();throw new Error(`jq: ${n}`)}}var Lr=h(()=>{"use strict";l();p();Q()});var Ds={};Bt(Ds,{UntilController:()=>Ft,__test:()=>oc,startWatch:()=>sc,surfaceForChannel:()=>Me});function rc(t){return ec.find(e=>e.id===t)}function Me(t){switch(t.name){case"user":return"blotter";case"ticker":return"watchlist";case"level2":return"ladder";default:return null}}async function ic(t,e){if(!e.requiresAuth)return;let n=t.env?.auth;if(!n)throw new Error("WebSocket channel requires authentication. Run: coinbase env <name> --key-file key.json");if(n.type==="oauth")throw new Error(`The --watch blotter requires CDP API key auth (WebSocket does not support OAuth).
|
|
53
53
|
Set up a CDP key: coinbase env <name> --key-file key.json`);if(n.type==="cdp_key"&&n.key_id&&n.key_secret)return we(n.key_id,n.key_secret);throw new Error("Unsupported auth type for WebSocket")}async function sc(t,e,r,n){let i=Re(t);if(!i)throw new Error(`--watch is not supported for "${t.replace(/_/g," ")}"`);let s=Me(i);if(!s)throw new Error(`--watch is not yet implemented for channel "${i.name}"`);if(n.until){let c;try{c=yr(n.until)}catch(u){throw new Error(`Invalid --until predicate: ${u.message}`)}let d=rc(t);if(d?.watchFields){let u=zi(c,d.watchFields);if(u.length>0){let g=Object.keys(d.watchFields).join(", ");throw new Error(u.map(f=>f.message).join(`
|
|
54
54
|
`)+`
|
|
55
55
|
Available fields: ${g}`)}}let _=Jt(c);if(_.length>0&&e.length>0){let u=_.filter(g=>!e.includes(g));if(u.length>0)throw new Error(`Predicate references product${u.length>1?"s":""} not in watch: ${u.join(", ")}
|
|
56
|
-
Watching: ${e.join(", ")}`)}}let a=await ic(r,i),o=!!process.stdout.isTTY;await cc(n),s==="blotter"?await xs(i,a,r,n,o):s==="watchlist"?await Cs(i,e,a,n,o):s==="ladder"&&await As(i,e,a,n,o)}async function Fe(t,e,r,n,i,s){let a=n.start();await i.setup();let o=0,c;c=new Se({channel:t,WebSocketClass:s,onEvent:_=>{let u=_;o=u.sequence_num??o;let g=String(u.timestamp??new Date().toISOString()),f=i.onData(u,o,g);if(f.length!==0){if(!i.screen&&!n.active)for(let
|
|
57
|
-
`),onStateChange:_=>{_===
|
|
56
|
+
Watching: ${e.join(", ")}`)}}let a=await ic(r,i),o=!!process.stdout.isTTY;await cc(n),s==="blotter"?await xs(i,a,r,n,o):s==="watchlist"?await Cs(i,e,a,n,o):s==="ladder"&&await As(i,e,a,n,o)}async function Fe(t,e,r,n,i,s){let a=n.start();await i.setup();let o=0,c;c=new Se({channel:t,WebSocketClass:s,onEvent:_=>{let u=_;o=u.sequence_num??o;let g=String(u.timestamp??new Date().toISOString()),f=i.onData(u,o,g);if(f.length!==0){if(!i.screen&&!n.active)for(let R of f)Gs(R.line,r);if(n.active){for(let R of f)if(n.check(R.obj))return}}},onHeartbeat:()=>i.onHeartbeat(),onSequenceGap:()=>{let _=i.onGap();_&&(c.unsubscribe(_.resubscribe),c.subscribe(_.resubscribe,i.refreshJWT?i.refreshJWT():e))},onError:i.screen?void 0:_=>process.stderr.write(`ws error: ${_}
|
|
57
|
+
`),onStateChange:_=>{_===L.FAILED&&n.onFailed(),i.onConnState(_)},onDisconnect:()=>n.onDisconnect(),onReconnect:()=>n.onReconnect(),onReconnected:()=>i.onReconnected(),refreshJWT:i.refreshJWT}),c.connect(),c.subscribe(i.productIds,e);let d=await ac(a,i.screen);c.close(),Ns(d,i,r,n),d===null&&process.exit(process.exitCode??0)}async function xs(t,e,r,n,i,s,a){let o=new Ft(n),c=Os({isTTY:i,untilActive:o.active,flags:n,out:s?.out},r,e,t,o);await Fe(t,e,n,o,c,a)}async function Cs(t,e,r,n,i,s,a){if(e.length===0)throw new Error("--watch requires at least one product_id (e.g. BTC-USD)");let o=new Ft(n),c=Rs({isTTY:i,untilActive:o.active,flags:n,out:s?.out},e,o);await Fe(t,r,n,o,c,a)}async function As(t,e,r,n,i,s,a){if(e.length===0)throw new Error("--watch requires a product_id (e.g. BTC-USD)");if(e.length>1)throw new Error("--watch book supports a single product_id; got: "+e.join(", "));let o=e[0],c=new Ft(n),d=Ps({isTTY:i,untilActive:c.active,flags:n,out:s?.out},o,r,c);await Fe(t,r,n,c,d,a)}function ac(t,e){return new Promise(r=>{let n=()=>{},i=s=>{n(),r(s)};if(e)e.installSignalHandlers(()=>i(null));else{let s=()=>i(null),a=()=>i(null);n=()=>{process.off("SIGINT",s),process.off("SIGTERM",a)},process.on("SIGINT",s),process.on("SIGTERM",a)}t.then(i)})}function Ns(t,e,r,n){if(e.cleanup(),n?.cleanup(),!!t)switch(t.type){case"matched":Gs(JSON.stringify(t.event),r??{}),process.exitCode=0;break;case"timeout":process.stderr.write(`error: --until timed out
|
|
58
58
|
`),process.exitCode=124;break;case"failed":process.stderr.write(`error: WebSocket connection failed permanently
|
|
59
59
|
`),process.exitCode=2;break;case"disconnect_budget_exceeded":process.stderr.write(`error: cumulative disconnection exceeded ${Math.round(t.totalMs/1e3)}s
|
|
60
60
|
`),process.exitCode=2;break}}function Gs(t,e){if(e.jq)try{let{applyJQ:r}=Le,n=r(new TextEncoder().encode(t),e.jq);process.stdout.write(n+`
|
|
@@ -67,9 +67,9 @@ Watching: ${e.join(", ")}`)}}let a=await ic(r,i),o=!!process.stdout.isTTY;await
|
|
|
67
67
|
`),process.stderr.write(`jq error: ${i.message}
|
|
68
68
|
`)}else n&&process.stdout.isTTY||(process.stdout.isTTY?process.stdout.write(JSON.stringify(t.data,null,2)+`
|
|
69
69
|
`):process.stdout.write(r+`
|
|
70
|
-
`));if(n){let i=t.data?.message||t.data?.errorMessage||r.slice(0,200),s=t.data?.correlationId,a=t.headers?.get("trace-id"),o=[a?`trace ${a}`:"",s?`correlation ${s}`:""].filter(Boolean).join(", ");throw new Error(`${i} (HTTP ${t.status})${o?` [${o}]`:""}`)}}var Bs=h(()=>{"use strict";l();p();Lr()});l();p();l();p();Q();Ve();import{createInterface as rr}from"node:readline/promises";import{readFileSync as _o}from"node:fs";function Rt(t,e={}){Qe(()=>{let r=
|
|
71
|
-
Re-run with --allow-plaintext-secrets to write secrets to ${Y()} (file is mode 0600), or install/unlock your OS keychain (macOS Keychain, libsecret on Linux, Windows Credential Manager).`)}async function dn(t,e){uo(e);let r=
|
|
72
|
-
`);return}let u=Math.max(14,..._.map(g=>g.length));for(let g of _){let f=r.environments[g]??{},
|
|
70
|
+
`));if(n){let i=t.data?.message||t.data?.errorMessage||r.slice(0,200),s=t.data?.correlationId,a=t.headers?.get("trace-id"),o=[a?`trace ${a}`:"",s?`correlation ${s}`:""].filter(Boolean).join(", ");throw new Error(`${i} (HTTP ${t.status})${o?` [${o}]`:""}`)}}var Bs=h(()=>{"use strict";l();p();Lr()});l();p();l();p();Q();Ve();import{createInterface as rr}from"node:readline/promises";import{readFileSync as _o}from"node:fs";function Rt(t,e={}){Qe(()=>{let r=H();t(r),tt(r,{allowPlaintext:e.allowPlaintext})})}function uo(t){let e=[];if(t.keyFile&&e.push("key-file"),(t.keyId||t.keySecret)&&e.push("key-id/--key-secret"),t.status&&e.push("status"),t.remove&&e.push("remove"),e.length>1)throw new Error(`--${e.join(", --")} are mutually exclusive on \`coinbase env\`. Pick one.`)}function er(t,e){if(!e&&!en())throw new Error(`OS keychain unavailable; refusing to persist secrets for "${t}".
|
|
71
|
+
Re-run with --allow-plaintext-secrets to write secrets to ${Y()} (file is mode 0600), or install/unlock your OS keychain (macOS Keychain, libsecret on Linux, Windows Credential Manager).`)}async function dn(t,e){uo(e);let r=H();if(t.length===0){let _=[...new Set([...Object.keys(r.environments),...Object.keys(K)])].sort();if(_.length===0){process.stderr.write(`No environments configured. Run: coinbase env <name>
|
|
72
|
+
`);return}let u=Math.max(14,..._.map(g=>g.length));for(let g of _){let f=r.environments[g]??{},R=Z(f,g),k=Wt(f),T=!!r.environments[g],S=k?.type==="cdp_key"?k.key_id:"(no key)",A=S.length>60?S.slice(0,57)+"...":S;process.stdout.write(`${g===r.env?"* ":" "}${g.padEnd(u)} ${(R.length>45?R.slice(0,42)+"...":R).padEnd(45)} ${A}
|
|
73
73
|
`)}return}let n=t[0];if(e.remove){Rt(_=>{delete _.environments[n],_.env===n&&(_.env="")}),Ye(n),process.stderr.write(`Removed ${n}.
|
|
74
74
|
`);return}let i=r.environments[n]??{};if(e.status){po(n,i);return}let s=(_,u)=>{i.auth={type:"cdp_key",key_id:_,key_secret:u}};if(e.keyFile){er(n,!!e.allowPlaintextSecrets);let _=mo(e.keyFile);s(_.keyId,_.keySecret),e.url&&(i.url=e.url,vt(e.url)||process.stderr.write(`warning: custom URL does not match a known endpoint
|
|
75
75
|
`)),Rt(u=>{u.environments[n]=i,u.env=n},{allowPlaintext:e.allowPlaintextSecrets}),process.stderr.write(`Loaded key from ${e.keyFile}. Switched to ${n}.
|
|
@@ -86,23 +86,23 @@ Re-run with --allow-plaintext-secrets to write secrets to ${Y()} (file is mode 0
|
|
|
86
86
|
`),process.exit(1)),process.stdout.write(`env: ${t}
|
|
87
87
|
`),process.stdout.write(`auth: cdp_key
|
|
88
88
|
`),process.stdout.write(`key_id: ${lo(e.auth.key_id)}
|
|
89
|
-
`)}function mo(t){let e;try{e=_o(t,"utf-8")}catch{throw new Error(`cannot read key file: ${t}`)}let r;try{r=JSON.parse(e)}catch{throw new Error(`key file is not valid JSON: ${t}`)}let n=r.name??r.id,i=r.privateKey??r.secret;if(!n||!i)throw new Error(`key file must contain name/privateKey (or id/secret): ${t}`);return{keyId:n,keySecret:i}}l();p();Pt();be();or();Q();ve();he();import{createInterface as aa}from"node:readline";l();p();Q();pt();function
|
|
90
|
-
Run: coinbase env <name> --key-id=... --key-secret=... to configure.`),
|
|
91
|
-
`))}function Ei(t,e){if(!e)return
|
|
92
|
-
`))}function vi(t,e,r,n){if(n&&Object.hasOwn(n,e)&&(!t||t===e))return{act:n[e],toolName:`coinbase_${e}`};if(t){let a=r.find(o=>o.name===t);if(a){let o=a.actions.find(c=>c.name===e);return o?{act:o,toolName:bi(a.name,o.name)}:
|
|
89
|
+
`)}function mo(t){let e;try{e=_o(t,"utf-8")}catch{throw new Error(`cannot read key file: ${t}`)}let r;try{r=JSON.parse(e)}catch{throw new Error(`key file is not valid JSON: ${t}`)}let n=r.name??r.id,i=r.privateKey??r.secret;if(!n||!i)throw new Error(`key file must contain name/privateKey (or id/secret): ${t}`);return{keyId:n,keySecret:i}}l();p();Pt();be();or();Q();ve();he();import{createInterface as aa}from"node:readline";l();p();Q();pt();function N(t,e=!1){return{content:[{type:"text",text:t}],isError:e}}function bi(t,e){return t===e?`coinbase_${t.replace(/-/g,"_")}`:`coinbase_${t.replace(/-/g,"_")}_${e.replace(/[-\s]/g,"_")}`}function yi(t){let e=[{name:"coinbase_env",description:"Show the active environment and configured environments.",inputSchema:{type:"object",properties:{}}},{name:"coinbase_set_env",description:"Switch the active environment.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Environment name"}},required:["name"]}},{name:"coinbase_template",description:"Get a full request body example for a command, ready to copy and modify.",inputSchema:{type:"object",properties:{resource:{type:"string",description:'Resource name (e.g. "orders"). Omit for top-level actions like balance, transfer, fees.'},action:{type:"string",description:'Action name (e.g. "create", "balance")'}},required:["action"]}},{name:"coinbase_help",description:"Get detailed help for a command: field descriptions, query parameters, and usage.",inputSchema:{type:"object",properties:{resource:{type:"string",description:'Resource name (e.g. "orders"). Omit for top-level actions like balance, transfer, fees.'},action:{type:"string",description:'Action name (e.g. "create", "balance")'}},required:["action"]}}];for(let r of t)for(let n of r.actions){let i={},s=[];for(let g of n.params){let f={type:g.type,description:g.description};g.enum&&(f.enum=g.enum),g.pattern&&(f.pattern=g.pattern),g.format&&(f.format=g.format),g.example!==void 0&&(f.example=g.example),g.default!==void 0&&(f.default=g.default),i[g.name]=f,g.required&&s.push(g.name)}let a=n.params.filter(g=>g.in==="body").length,o=n.params.filter(g=>g.in==="body"&&g.required).length,c=a>0?o>0?` (${a} fields, ${o} required)`:` (${a} fields)`:"",_=[...new Set(n.params.map(g=>g.oneOf).filter(g=>!!g))].map(g=>` (one of: ${g.split("|").join(", ")})`).join(""),u=n.description||n.summary;e.push({name:bi(r.name,n.name),description:`${n.method} ${n.path}${u?" \u2014 "+u:""}${c}${_}`,inputSchema:{type:"object",properties:i,required:s.length>0?s:void 0}})}return e}function hi(t){if(t.status>=400){let e=t.data?.message??JSON.stringify(t.data).slice(0,200),r=t.data?.correlationId,n=t.headers?.get("trace-id"),i=[n?`trace ${n}`:"",r?`correlation ${r}`:""].filter(Boolean).join(", ");return N(`HTTP ${t.status}: ${e}${i?` [${i}]`:""}`,!0)}if(t.data&&typeof t.data=="object"&&"error"in t.data&&typeof t.data.error=="string"){let e=t.data.message?D.stripGrpcPrefix(t.data.message):t.data.error;return N(`Error: ${e}`,!0)}return N(JSON.stringify(t.data,null,2))}function dr(t){let e=Ot(t,""),r=Object.keys(t.environments??{}),n=[`Active: ${e||"(none)"}`,`Configured: ${r.length>0?r.join(", "):"(none)"}`];return e||n.push(`
|
|
90
|
+
Run: coinbase env <name> --key-id=... --key-secret=... to configure.`),N(n.join(`
|
|
91
|
+
`))}function Ei(t,e){if(!e)return N("Environment name is required.",!0);let r=Object.keys(t.environments??{});return r.length===0?N("No environments configured. Run: coinbase env <name> --key-id=... --key-secret=... to configure.",!0):t.environments[e]?{cfg:{...t,env:e}}:N(`Unknown environment: "${e}". Available environments: ${r.join(", ")}`,!0)}function Ii(t){return dr(t)}function sa(t,e){let r=t.params??[],n=[];n.push(`${t.summary||t.name}`),n.push(`${t.method} ${t.path}`);let i=t.pathParams.map(o=>`${o}="..."`).join(", ");n.push("",`Usage: ${e}(${i})`);let s=r.filter(o=>o.in==="body");if(s.length>0){n.push("","Fields:");for(let o of s){let c=o.required?" (required)":"",d=o.description?` \u2014 ${o.description}`:"";n.push(` ${o.name} (${o.type})${c}${d}`)}}let a=r.filter(o=>o.in==="query");if(a.length>0){n.push("","Query parameters:");for(let o of a){let c=o.description?` \u2014 ${o.description}`:"";n.push(` ${o.name} (${o.type})${c}`)}}return N(n.join(`
|
|
92
|
+
`))}function vi(t,e,r,n){if(n&&Object.hasOwn(n,e)&&(!t||t===e))return{act:n[e],toolName:`coinbase_${e}`};if(t){let a=r.find(o=>o.name===t);if(a){let o=a.actions.find(c=>c.name===e);return o?{act:o,toolName:bi(a.name,o.name)}:N(`Unknown action: ${e}. Available for ${t}: ${a.actions.map(c=>c.name).join(", ")}`,!0)}}let i=r.map(a=>a.name),s=n?Object.keys(n):[];return N(`Not found. Resources: ${i.join(", ")}. Top-level actions: ${s.join(", ")}`,!0)}function ki(t,e,r,n){if(!e)return N("action is required",!0);let i=vi(t,e,r,n);return"isError"in i?i:sa(i.act,i.toolName)}function oa(t){let e=(t.params??[]).filter(i=>i.in==="body");if(e.length===0)return N("This action has no request body.");let r=t.template??{},n=[];for(let i of e){let s=i.required?" (required)":"",a=i.description?` \u2014 ${i.description}`:"";n.push(`${i.name} (${i.type})${s}${a}`)}return N(`Template:
|
|
93
93
|
${JSON.stringify(r,null,2)}
|
|
94
94
|
|
|
95
95
|
Fields:
|
|
96
96
|
${n.join(`
|
|
97
|
-
`)}`)}function Oi(t,e,r,n){if(!e)return
|
|
98
|
-
`)}function Yt(t,e){Pi({id:t,result:e})}function Qt(t,e,r){Pi({id:t,error:{code:e,message:r}})}function ca(){return J}async function _a(t,e){let r=ca();if(t==="coinbase_env")return dr(
|
|
97
|
+
`)}`)}function Oi(t,e,r,n){if(!e)return N("action is required",!0);let i=vi(t,e,r,n);return"isError"in i?i:oa(i.act)}function Pi(t){process.stdout.write(JSON.stringify({jsonrpc:"2.0",...t})+`
|
|
98
|
+
`)}function Yt(t,e){Pi({id:t,result:e})}function Qt(t,e,r){Pi({id:t,error:{code:e,message:r}})}function ca(){return J}async function _a(t,e){let r=ca();if(t==="coinbase_env")return dr(H());if(t==="coinbase_set_env"){let n=H(),i=Ei(n,e.name);return"isError"in i?i:(tt(i.cfg),Je(),Ii(i.cfg))}return t==="coinbase_help"?ki(String(e.resource??""),String(e.action??""),r,X):t==="coinbase_template"?Oi(String(e.resource??""),String(e.action??""),r,X):ua(t,e)}async function ua(t,e){let r=t.replace(/^coinbase_/,"");if(!fe(r))return N(`Unknown tool: ${t}`,!0);let n=H(),i;try{i=$t(n,"")}catch(o){return N(`Environment error: ${o.message}
|
|
99
99
|
|
|
100
|
-
Run: coinbase env <name> --key-id=... --key-secret=...`,!0)}let{name:s,env:a}=i;try{let o=await Vt(s,a),c={envName:s,env:a,baseURL:Z(a,s),doRequest:_=>Ie({..._,...o})},d=await St(r,e,c);return hi(d)}catch(o){return
|
|
100
|
+
Run: coinbase env <name> --key-id=... --key-secret=...`,!0)}let{name:s,env:a}=i;try{let o=await Vt(s,a),c={envName:s,env:a,baseURL:Z(a,s),doRequest:_=>Ie({..._,...o})},d=await St(r,e,c);return hi(d)}catch(o){return N(`Request failed: ${o.message}`,!0)}}var da={name:"coinbase",version:rt},ga={tools:{}},gr=null;function Ri(){if(!gr){let t=[...J];for(let[e,r]of Object.entries(X))t.push({name:e,actions:[r]});gr=yi(t)}return gr}async function la(t){let{id:e,method:r,params:n}=t;switch(r){case"initialize":Yt(e,{protocolVersion:"2024-11-05",serverInfo:da,capabilities:ga});break;case"notifications/initialized":break;case"tools/list":Yt(e,{tools:Ri()});break;case"tools/call":{let{name:i,arguments:s}=n??{};if(!i){Qt(e,-32602,"Missing tool name");return}if(!Ri().find(o=>o.name===i)){Qt(e,-32602,`Unknown tool: ${i}`);return}try{let o=await _a(i,s??{});Yt(e,o)}catch(o){Yt(e,N(`Internal error: ${o.message}`,!0))}break}case"ping":Yt(e,{});break;default:e!=null&&Qt(e,-32601,`Method not found: ${r}`);break}}function Ti(){let t=aa({input:process.stdin,terminal:!1}),e=new Set;t.on("line",r=>{if(r.trim())try{let n=JSON.parse(r),i=la(n).catch(s=>{process.stderr.write(`MCP error: ${s.message}
|
|
101
101
|
`),n.id!=null&&Qt(n.id,-32603,s.message)}).finally(()=>e.delete(i));e.add(i)}catch{Qt(null,-32700,"Parse error")}}),t.on("close",async()=>{await Promise.all(e),process.exit(0)}),process.stderr.write(`coinbase MCP server v${rt} ready
|
|
102
|
-
`)}l();p();Q();function Si(t){let e=
|
|
102
|
+
`)}l();p();Q();function Si(t){let e=H();if(t.length===0)return pa(e);if(t[0]==="clear"){let r=t[1],n;if(r&&r.includes(".")){let i=r.indexOf(".");n=Ht(e,r.slice(0,i),r.slice(i+1))}else r?n=Ht(e,r):n=Ht(e);tt(e),process.stderr.write(`Cleared ${n} history ${n===1?"entry":"entries"}.
|
|
103
103
|
`);return}throw new Error("usage: coinbase history [clear [env.action]]")}function pa(t){let e=[];for(let[i,s]of Object.entries(t.history))for(let[a,o]of Object.entries(s))e.push({env:i,action:a,lastUsed:o.last_used,fields:Object.keys(o.values)});if(e.length===0){process.stderr.write(`No saved history.
|
|
104
104
|
`);return}e.sort((i,s)=>s.lastUsed.localeCompare(i.lastUsed));let r=Math.max(...e.map(i=>i.env.length))+2,n=Math.max(...e.map(i=>i.action.length))+2;for(let i of e){let s=i.lastUsed.slice(0,10);process.stdout.write(`${i.env.padEnd(r)}${i.action.padEnd(n)}${s} ${i.fields.join(", ")}
|
|
105
|
-
`)}}l();p();Q();import{readFileSync as Ni,writeFileSync as ma,mkdirSync as Gi,readdirSync as Di,existsSync as bt,cpSync as fa,rmSync as ba}from"node:fs";import wi,{join as nt,resolve as xi}from"node:path";import{fileURLToPath as ya}from"node:url";import{homedir as Ci}from"node:os";import{createInterface as Ai}from"node:readline";function pr(){try{return JSON.parse(Ni(Y(),"utf8"))}catch{return{}}}function lr(t){let e=
|
|
105
|
+
`)}}l();p();Q();import{readFileSync as Ni,writeFileSync as ma,mkdirSync as Gi,readdirSync as Di,existsSync as bt,cpSync as fa,rmSync as ba}from"node:fs";import wi,{join as nt,resolve as xi}from"node:path";import{fileURLToPath as ya}from"node:url";import{homedir as Ci}from"node:os";import{createInterface as Ai}from"node:readline";function pr(){try{return JSON.parse(Ni(Y(),"utf8"))}catch{return{}}}function lr(t){let e=at();Gi(e,{recursive:!0,mode:448}),ma(Y(),JSON.stringify(t,null,2)+`
|
|
106
106
|
`,{mode:384})}function Li(){let t=wi.dirname(ya(import.meta.url));return wi.join(t,"..","skills")}function ha(t){let e=t.match(/^---\n([\s\S]*?)\n---/);if(!e)return{name:"",description:""};let r=e[1],n=r.match(/^name:\s*(.+)$/m),i=r.match(/^description:\s*(.+)$/m);return{name:(n?.[1]??"").trim(),description:(i?.[1]??"").trim()}}function Mi(t){let e=t??Li();if(!bt(e))return[];let r=[];for(let n of Di(e,{withFileTypes:!0})){if(!n.isDirectory())continue;let i=nt(e,n.name,"SKILL.md");if(!bt(i))continue;let s=Ni(i,"utf8"),a=ha(s);r.push({name:a.name||n.name,description:a.description,dir:nt(e,n.name)})}return r.sort((n,i)=>n.name.localeCompare(i.name))}function Ea(t,e){if(!bt(t))return 0;Gi(e,{recursive:!0});let r=0;for(let n of Di(t,{withFileTypes:!0})){if(!n.isDirectory())continue;let i=nt(t,n.name,"SKILL.md");if(!bt(i))continue;let s=nt(e,n.name);fa(nt(t,n.name),s,{recursive:!0,force:!0}),r++}return r}async function Ia(){let t=process.platform==="win32"?nt(process.env.USERPROFILE??Ci(),".claude","skills"):nt(Ci(),".claude","skills");process.stderr.write(`Where should skills be installed?
|
|
107
107
|
`),process.stderr.write(`Tip: Not sure where your agent looks for skills? Ask your agent.
|
|
108
108
|
|
|
@@ -139,7 +139,7 @@ Run: coinbase skills --help
|
|
|
139
139
|
`).trim().split(`
|
|
140
140
|
`).flatMap(n=>{n=mr(n).replace(/^\s*\*\s+/," - ").replace(/^\s*(\d+)\.\s+/," $1. ");let i=[];for(;n.length>r;){let s=n.lastIndexOf(" ",r);s<=0&&(s=r),i.push(n.slice(0,s)),n=n.slice(s+1)}return i.push(n),i}).join(`
|
|
141
141
|
`)+`
|
|
142
|
-
`}l();p();ke();function Oe(t,e,r,n){let i=n??e.length,s=Math.max(20,(process.stdout.columns||80)-i),a=r.split(" "),o="",c=!0;for(let d of a){let _=
|
|
142
|
+
`}l();p();ke();function Oe(t,e,r,n){let i=n??e.length,s=Math.max(20,(process.stdout.columns||80)-i),a=r.split(" "),o="",c=!0;for(let d of a){let _=ct(d),u=ct(o),g=d.includes("\x1B]8;;");(u+_+1>s||g&&u>0&&u+_+1>s*.6)&&o.length>0&&(t.write((c?e:" ".repeat(i))+o.trimEnd()+`
|
|
143
143
|
`),o="",c=!1),o+=(o?" ":"")+d}o&&t.write((c?e:" ".repeat(i))+o.trimEnd()+`
|
|
144
144
|
`)}hr();Ir();Mr();function Fr(){return J}function Ls(t){return gn.has(t)}function Ms(t,e,r){for(let n of e.fields){let i=e.nested?.[n];t.write(`${r}${n}
|
|
145
145
|
`),i&&Ms(t,i,r+" ")}}function Ur(t,e){let r=process.stderr;r.write(`${e.summary||e.name}
|
|
@@ -151,9 +151,9 @@ Usage:
|
|
|
151
151
|
Arguments:
|
|
152
152
|
`);let u=Math.max(...s.map(g=>g.name.length));for(let g of s){let f=` <${g.name}>${" ".repeat(Math.max(1,u-g.name.length+2))}${g.type}${g.required?" required":""} `;Oe(r,f,g.description)}}let a=i.filter(u=>u.in==="body");if(a.length>0){r.write(`
|
|
153
153
|
Fields:
|
|
154
|
-
`);let u=Math.max(...a.map(g=>g.name.length));for(let g of a){let f=g.required?"required":"",
|
|
154
|
+
`);let u=Math.max(...a.map(g=>g.name.length));for(let g of a){let f=g.required?"required":"",R=" ".repeat(Math.max(1,u-g.name.length+2)),k=" ".repeat(Math.max(1,8-g.type.length)),T=f?" ":" ",S=g.type==="array"||g.type==="object"?" (use :=json)":"",A=qi(mr(g.description)),W=` ${g.name}${R}${g.type}${k}${f}${T}`;Oe(r,W,A+S)}}let o=i.filter(u=>u.in==="query");if(o.length>0){r.write(`
|
|
155
155
|
Query params (use == syntax):
|
|
156
|
-
`);let u=Math.max(...o.map(g=>g.name.length));for(let g of o){let f=g.description;g.enum?.length&&(f+=(f?" ":"")+`[${g.enum.join(", ")}]`);let
|
|
156
|
+
`);let u=Math.max(...o.map(g=>g.name.length));for(let g of o){let f=g.description;g.enum?.length&&(f+=(f?" ":"")+`[${g.enum.join(", ")}]`);let R=` ${g.name}${" ".repeat(Math.max(1,u-g.name.length+2))}${g.type} `;Oe(r,R,f)}}e.responseFields&&(r.write(`
|
|
157
157
|
Response:
|
|
158
158
|
`),Ms(r,e.responseFields," "));let c=a.length>0;r.write(`
|
|
159
159
|
Flags:
|
|
@@ -182,23 +182,23 @@ Flags:
|
|
|
182
182
|
--edit Open request body in $EDITOR
|
|
183
183
|
--jq <expr> jq filter expression for response
|
|
184
184
|
`)}l();p();be();l();p();var Us=t=>t?.has_next===!1?null:t?.cursor||null;Q();ve();async function Br(t,e,r,n){if(r.flags.template){let m=e.template??{};process.stdout.write(JSON.stringify(m,null,2)+`
|
|
185
|
-
`);return}let i=[],s=[],{isFieldArg:a}=await Promise.resolve().then(()=>(qe(),Ue));for(let m of r.args)i.length<e.pathParams.length&&!a(m)?i.push(m):s.push(m);if(i.length<e.pathParams.length){let m=e.pathParams.slice(i.length);throw new Error(`Missing argument(s): ${m.map(
|
|
185
|
+
`);return}let i=[],s=[],{isFieldArg:a}=await Promise.resolve().then(()=>(qe(),Ue));for(let m of r.args)i.length<e.pathParams.length&&!a(m)?i.push(m):s.push(m);if(i.length<e.pathParams.length){let m=e.pathParams.slice(i.length);throw new Error(`Missing argument(s): ${m.map(v=>`<${v}>`).join(" ")}
|
|
186
186
|
|
|
187
|
-
Usage: coinbase ${t.replace(/_/g," ")} ${e.pathParams.map(
|
|
188
|
-
`),{..._}):{...c.body},
|
|
189
|
-
`),r.flags.edit=!0;else{let m=
|
|
187
|
+
Usage: coinbase ${t.replace(/_/g," ")} ${e.pathParams.map(v=>`<${v}>`).join(" ")} [fields...]`)}let{parseFields:o}=await Promise.resolve().then(()=>(qe(),Ue)),c=o(s),d=!1,_={},u=H(),g=Ot(u,n);if(g&&pe(u)){let m=tr(u,g,t);if(m){let{setNested:v}=await Promise.resolve().then(()=>(qe(),Ue));for(let[E,G]of Object.entries(m.values))try{v(_,E,JSON.parse(G))}catch{v(_,E,G)}d=!0}}let f=e.params??[];for(let m of Object.keys(c.body)){let v=f.find(E=>E.name===m);if(v?.oneOf)for(let E of f)E.oneOf===v.oneOf&&E.name!==m&&delete _[E.name]}let k=Object.keys(c.body).length>0?{..._,...c.body}:d?(process.stderr.write(`Using saved values from last ${t.replace(/_/g," ")} call. Pass fields to override.
|
|
188
|
+
`),{..._}):{...c.body},T={};for(let[m,v]of c.query.entries())T[m]=v;let S={};for(let m=0;m<i.length;m++)S[e.pathParams[m]]=i[m];let A=f.filter(m=>m.in==="body"&&m.required&&m.type!=="object"&&m.type!=="array"),W=A.map(m=>m.name);if(W.length>0&&Object.keys(k).length===0&&!r.flags.edit&&!c.rawBody)if(process.stdin.isTTY)if(A.length<=3){let{createInterface:m}=await import("node:readline"),v=m({input:process.stdin,output:process.stderr});for(let E of A){let G=E.enum?` [${E.enum.join(", ")}]`:"",V=E.example?` (e.g. ${E.example})`:"",dt=await new Promise(qt=>{v.question(`${E.name}${G}${V}: `,qt)});dt&&(k[E.name]=dt)}v.close()}else process.stderr.write(`This action requires ${W.length} fields. Opening editor.
|
|
189
|
+
`),r.flags.edit=!0;else{let m=W.join(", ");throw new Error(`Missing required field(s): ${m}
|
|
190
190
|
|
|
191
191
|
Provide fields inline:
|
|
192
|
-
coinbase ${t.replace(/_/g," ")} ${
|
|
192
|
+
coinbase ${t.replace(/_/g," ")} ${W.map(v=>`${v}=<value>`).join(" ")}
|
|
193
193
|
|
|
194
194
|
Or use --template to see the full body:
|
|
195
195
|
coinbase ${t.replace(/_/g," ")} --template
|
|
196
|
-
`)}if(r.flags.edit){let
|
|
197
|
-
`);let m={...
|
|
198
|
-
`);return}let{name:
|
|
196
|
+
`)}if(r.flags.edit){let v={...e.template??{},...k},E=await kc(JSON.stringify(v,null,2));for(let G of Object.keys(k))delete k[G];Object.assign(k,E)}if(r.flags["dry-run"]){process.stderr.write(`would execute ${t}
|
|
197
|
+
`);let m={...S,...k,...Object.keys(T).length>0?{_query:T}:{}};process.stdout.write(JSON.stringify(m,null,2)+`
|
|
198
|
+
`);return}let{name:j,env:P}=$t(u,n),O=await Vt(j,P),q={envName:j,env:P,baseURL:Z(P,j),doRequest:m=>Ie({...m,...O})};if(r.flags.watch||r.flags.until){let{startWatch:m}=await Promise.resolve().then(()=>(Mr(),Ds)),v=i.length>0?i.flatMap(V=>V.split(",")).filter(Boolean):[],E=r.flags.depth?Number(r.flags.depth):void 0,G=r.flags["until-timeout"]?Number(r.flags["until-timeout"]):void 0;if(E!==void 0&&(!Number.isFinite(E)||E<1))throw new Error(`Invalid --depth value: ${r.flags.depth}`);if(G!==void 0&&(!Number.isFinite(G)||G<1))throw new Error(`Invalid --until-timeout value: ${r.flags["until-timeout"]}`);await m(t,v,q,{jq:r.flags.jq,depth:E,until:r.flags.until,untilTimeout:G,query:Object.keys(T).length>0?T:void 0});return}let w={body:k,query:{...T},path:S,headers:c.headers,rawBody:c.rawBody??void 0},{outputResult:it}=await Promise.resolve().then(()=>(Bs(),qs)),I=0;do{let m=await St(t,w,q);if(it(m,r.flags.jq),m.status<400&&Object.keys(k).length>0)try{if(g&&pe(u)){let E={};(function G(V,dt){for(let[qt,st]of Object.entries(dt)){let re=V?`${V}.${qt}`:qt;typeof st=="object"&&st&&!Array.isArray(st)?G(re,st):E[re]=JSON.stringify(st)}})("",k),Ze(u,g,t,E),tt(u)}}catch{}if(!r.flags.paginate)break;let v=Us(m.data);if(!v||v===w.query.cursor)break;if(w.query.cursor=v,++I>=100){process.stderr.write(`Pagination limit reached (100 pages)
|
|
199
199
|
`);break}}while(!0)}function Ic(){if(process.platform!=="win32")return"vi";try{let{execSync:t}=Hs("node:child_process");return t("where code",{stdio:"pipe"}),"code --wait"}catch{}return"notepad"}function vc(t){return t.split(`
|
|
200
200
|
`).filter(e=>!e.trimStart().startsWith("//")).join(`
|
|
201
|
-
`)}async function kc(t){let{writeFileSync:e,readFileSync:r,unlinkSync:n,mkdtempSync:i}=await import("node:fs"),{tmpdir:s}=await import("node:os"),{join:a}=await import("node:path"),{execFileSync:o}=await import("node:child_process"),{scrubbedEnv:c}=await Promise.resolve().then(()=>(Q(),un));if(!process.stdin.isTTY)throw new Error("--edit requires an interactive terminal. Use --template to get the request body, then pass fields as arguments.");let d=process.env.VISUAL??process.env.EDITOR??Ic();(d.trim()==="code"||d.trim().endsWith("/code"))&&(d+=" --wait");let _=a(i(a(s(),"coinbase-")),"request.json");e(_,t);try{let[u,...g]=d.split(/\s+/);o(u,[...g,_],{stdio:"inherit",env:c()});let f=vc(r(_,"utf8"));return JSON.parse(f)}catch(u){throw new Error(u.message?.includes("Unexpected")?`Edited file is not valid JSON: ${u.message}`:`Editor: ${u.message}`)}finally{try{n(_)}catch{}}}Pt();l();p();var ee=class extends Error{constructor(e){super(e),this.name="HelpExit"}};function zs(t){let e={children:new Map};for(let r of t){let n=e;for(let i of r.name.split(" "))n.children.has(i)||n.children.set(i,{children:new Map}),n=n.children.get(i);n.action=r}return e}function Ws(t,e,r){let n=t,i,s=0,a=[],o=[];for(let u=0;u<e.length;u++){let g=e[u],f=n.children.get(g);if(f){o.push(g),a=[...n.children.keys()],n=f,n.action&&(i=n.action,s=o.length);continue}if(g.includes("=")){let
|
|
201
|
+
`)}async function kc(t){let{writeFileSync:e,readFileSync:r,unlinkSync:n,mkdtempSync:i}=await import("node:fs"),{tmpdir:s}=await import("node:os"),{join:a}=await import("node:path"),{execFileSync:o}=await import("node:child_process"),{scrubbedEnv:c}=await Promise.resolve().then(()=>(Q(),un));if(!process.stdin.isTTY)throw new Error("--edit requires an interactive terminal. Use --template to get the request body, then pass fields as arguments.");let d=process.env.VISUAL??process.env.EDITOR??Ic();(d.trim()==="code"||d.trim().endsWith("/code"))&&(d+=" --wait");let _=a(i(a(s(),"coinbase-")),"request.json");e(_,t);try{let[u,...g]=d.split(/\s+/);o(u,[...g,_],{stdio:"inherit",env:c()});let f=vc(r(_,"utf8"));return JSON.parse(f)}catch(u){throw new Error(u.message?.includes("Unexpected")?`Edited file is not valid JSON: ${u.message}`:`Editor: ${u.message}`)}finally{try{n(_)}catch{}}}Pt();l();p();var ee=class extends Error{constructor(e){super(e),this.name="HelpExit"}};function zs(t){let e={children:new Map};for(let r of t){let n=e;for(let i of r.name.split(" "))n.children.has(i)||n.children.set(i,{children:new Map}),n=n.children.get(i);n.action=r}return e}function Ws(t,e,r){let n=t,i,s=0,a=[],o=[];for(let u=0;u<e.length;u++){let g=e[u],f=n.children.get(g);if(f){o.push(g),a=[...n.children.keys()],n=f,n.action&&(i=n.action,s=o.length);continue}if(g.includes("=")){let R=g.split("=")[0],k=n.children.get(R);if(k?.action){let T=k.action.pathParams.map(A=>` <${A}>`).join(""),S=o.length>0?`coinbase ${r} ${o.join(" ")}`:`coinbase ${r}`;throw new Error(`Did you mean: ${S} ${k.action.name.split(" ").pop()}${T}`)}}break}if(i)return{action:i,remaining:e.slice(s),siblingNames:a};let c=e[o.length],d=o.length>0?`coinbase ${r} ${o.join(" ")}`:`coinbase ${r}`,_=Oc(n,r);throw c&&c!=="--help"&&c!=="-h"?new Error(`unknown subcommand "${c}" for ${d}
|
|
202
202
|
|
|
203
203
|
Available actions:
|
|
204
204
|
${_}`):new ee(`${d}
|
package/dist/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.4
|
package/package.json
CHANGED
package/skills/coinbase/SKILL.md
CHANGED
|
@@ -24,6 +24,22 @@ Authenticated commands need a CDP API key configured per environment.
|
|
|
24
24
|
|
|
25
25
|
Each CDP key is scoped to one portfolio. To operate across portfolios, register one env per portfolio (`live-primary`, `live-trading`) and switch with `coinbase env live-trading` or per-command `-e live-primary`. See `coinbase-portfolios`.
|
|
26
26
|
|
|
27
|
+
## Permissions
|
|
28
|
+
|
|
29
|
+
By default agents prompt before each `coinbase` command. To reduce or remove those prompts, allow-list commands in your agent's permission settings. Offer the user two tiers:
|
|
30
|
+
|
|
31
|
+
- **Read-only** — never prompted for safe reads (prices, balances, history); still prompted before any order or transfer. Good default.
|
|
32
|
+
- **Everything** — never prompted at all, including orders and transfers. Confirm explicitly before enabling.
|
|
33
|
+
|
|
34
|
+
Allow-list rules for each tier:
|
|
35
|
+
|
|
36
|
+
| Tier | Rules |
|
|
37
|
+
| :--- | :--- |
|
|
38
|
+
| Read-only | `coinbase balance`, `coinbase products *`, `coinbase orders list`, `coinbase orders get *`, `coinbase orders fills`, `coinbase fees`, `coinbase env`, `coinbase portfolios list`, `coinbase portfolios get *` |
|
|
39
|
+
| Everything | `coinbase *` |
|
|
40
|
+
|
|
41
|
+
How to apply depends on the agent. For Claude Code, add the rules to `permissions.allow` in settings.json (e.g. `Bash(coinbase products *)`) — `~/.claude/settings.json` for all projects or `.claude/settings.json` to share with a team. Other agents have their own allow-list mechanism.
|
|
42
|
+
|
|
27
43
|
## MCP vs CLI — which lane
|
|
28
44
|
|
|
29
45
|
Both surfaces wrap the same API. Pick by the shape of the task:
|
|
@@ -35,6 +51,22 @@ Rule of thumb: one structured action → MCP; a pipeline, a stream, or a conditi
|
|
|
35
51
|
|
|
36
52
|
Add MCP with: `claude mcp add --scope user --transport stdio coinbase -- coinbase mcp`
|
|
37
53
|
|
|
54
|
+
## Install agent skills
|
|
55
|
+
|
|
56
|
+
Skills give your agent step-by-step guidance for common Coinbase workflows (trading, market data, watch, convert, portfolios).
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
coinbase skills add
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If non-interactive, pass the directory explicitly:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
coinbase skills add --dir ~/.claude/skills
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Skills auto-update on future `npm i -g @coinbase/coinbase-cli` upgrades.
|
|
69
|
+
|
|
38
70
|
## Discovery
|
|
39
71
|
|
|
40
72
|
```sh
|