@coinbase/coinbase-cli 0.0.9 → 0.0.11
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 +117 -109
- package/dist/version.txt +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
2
|
+
var __=Object.defineProperty;var a_=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var C=(t,e)=>()=>(t&&(e=t(t=0)),e);var Mt=(t,e)=>{for(var r in e)__(t,r,{get:e[r],enumerable:!0})};var A,E=C(()=>{A={live:{brokerageApi:"https://api.coinbase.com",agentApi:"https://agents.coinbase.com/api"}}});var N,l=C(()=>{N={production:"live"}});var d_,yn,Ae,Dn,bn,Ne=C(()=>{"use strict";E();l();d_="https://agents.coinbase.com/api",yn="@coinbase/coinbase-cli",Ae="https://registry.npmjs.org",Dn=typeof A<"u"?A:{live:{brokerageApi:"https://api.coinbase.com",agentApi:d_}},bn=typeof N<"u"?N:{production:"live"}});function kt(t){return Er+Buffer.from(t,"utf8").toString("base64")}function Ft(t){return t.startsWith(Er)?Buffer.from(t.slice(Er.length),"base64").toString("utf8"):t}var Er,Se=C(()=>{"use strict";E();l();Er="b64:"});import{execFileSync as Ce}from"node:child_process";var Pe,fe,Ln=C(()=>{"use strict";E();l();Se();Pe="/usr/bin/security",fe=class{constructor(){try{Ce(Pe,["list-keychains"],{stdio:["pipe","pipe","pipe"]})}catch{throw new Error("Keychain not accessible")}}get(e,r){try{let n=Ce(Pe,["find-generic-password","-s",e,"-a",r,"-w"],{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trimEnd();return Ft(n)}catch{return null}}set(e,r,n){Ce(Pe,["add-generic-password","-U","-s",e,"-a",r,"-w",kt(n)],{stdio:["pipe","pipe","pipe"]})}delete(e,r){try{Ce(Pe,["delete-generic-password","-s",e,"-a",r],{stdio:["pipe","pipe","pipe"]})}catch{}}}});import{execFileSync as ye}from"node:child_process";var De,hn=C(()=>{"use strict";E();l();Se();De=class{constructor(){try{ye("which",["secret-tool"],{stdio:["pipe","pipe","pipe"]})}catch{throw new Error("secret-tool not found")}}get(e,r){try{let n=ye("secret-tool",["lookup","service",e,"account",r],{encoding:"utf8",stdio:["pipe","pipe","pipe"]});return Ft(n.trimEnd())}catch{return null}}set(e,r,n){ye("secret-tool",["store","--label",`${e}:${r}`,"service",e,"account",r],{input:kt(n),stdio:["pipe","pipe","pipe"]})}delete(e,r){try{ye("secret-tool",["clear","service",e,"account",r],{stdio:["pipe","pipe","pipe"]})}catch{}}}});import{execFileSync as E_}from"node:child_process";function lr(t,e){return`${t}:${e}`}function be(t){return t.replace(/'/g,"''")}function gr(t,e){let r=l_+t,n=Buffer.from(r,"utf16le").toString("base64"),i=e===void 0?process.env:{...process.env,[Un]:e};return E_("powershell.exe",["-NoProfile","-NonInteractive","-EncodedCommand",n],{encoding:"utf8",stdio:["pipe","pipe","pipe"],env:i}).trimEnd()}var l_,Un,Le,vn=C(()=>{"use strict";E();l();Se();l_=`
|
|
3
3
|
if (-not ([System.Management.Automation.PSTypeName]'Win32.Cred').Type) {
|
|
4
4
|
Add-Type -Namespace Win32 -Name Cred -MemberDefinition '
|
|
5
5
|
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
@@ -17,7 +17,7 @@ if (-not ([System.Management.Automation.PSTypeName]'Win32.Cred').Type) {
|
|
|
17
17
|
public string TargetAlias; public string UserName;
|
|
18
18
|
}'
|
|
19
19
|
}
|
|
20
|
-
`,
|
|
20
|
+
`,Un="COINBASE_KEYRING_SECRET";Le=class{get(e,r){try{let n=be(lr(e,r)),i=gr(`
|
|
21
21
|
$ptr = [IntPtr]::Zero
|
|
22
22
|
if ([Win32.Cred]::CredRead('${n}', 1, 0, [ref]$ptr)) {
|
|
23
23
|
$cred = [Runtime.InteropServices.Marshal]::PtrToStructure($ptr, [Type][Win32.Cred+CREDENTIAL])
|
|
@@ -25,8 +25,8 @@ if ([Win32.Cred]::CredRead('${n}', 1, 0, [ref]$ptr)) {
|
|
|
25
25
|
[Runtime.InteropServices.Marshal]::Copy($cred.CredentialBlob, $bytes, 0, $cred.CredentialBlobSize)
|
|
26
26
|
[Win32.Cred]::CredFree($ptr)
|
|
27
27
|
[Text.Encoding]::UTF8.GetString($bytes)
|
|
28
|
-
}`);return i?
|
|
29
|
-
$sec = $env:${
|
|
28
|
+
}`);return i?Ft(i):null}catch{return null}}set(e,r,n){let i=be(lr(e,r)),s=be(r);gr(`
|
|
29
|
+
$sec = $env:${Un}
|
|
30
30
|
$bytes = [Text.Encoding]::UTF8.GetBytes($sec)
|
|
31
31
|
$blob = [Runtime.InteropServices.Marshal]::AllocHGlobal($bytes.Length)
|
|
32
32
|
[Runtime.InteropServices.Marshal]::Copy($bytes, 0, $blob, $bytes.Length)
|
|
@@ -40,95 +40,98 @@ $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)`,
|
|
44
|
-
`),
|
|
45
|
-
Re-run the env-setup command with --allow-plaintext-secrets to write secrets to ${
|
|
46
|
-
`,{mode:384}),
|
|
47
|
-
`)}let _=nt(n,r),o=Rt(n,r);if(!_&&!o)throw new Error(`no REST endpoint for environment "${r}". Set a brokerage URL, an Agent API URL, or use a built-in environment 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 lr(){let t={...process.env};for(let e of X_)delete t[e];return t}function ye(t){return process.env.COINBASE_NO_HISTORY?!1:t.settings?.history?.enabled!==!1}function Ir(t,e,r,n){t.history[e]||(t.history[e]={}),t.history[e][r]={last_used:new Date().toISOString(),values:n}}function pr(t,e,r){return t.history[e]?.[r]}function ie(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 rt,Cn,Ft,Y_,vt,ar,cr,X_,it=S(()=>{"use strict";u();d();Te();_r();rt=un,Cn=dn;Ft={cdp_key:{secrets:{key_secret:t=>`${t}:cdp:key_secret`},metadataOnly:t=>({type:"cdp_key",key_id:t.key_id})}};Y_=".lock",vt={retries:50,baseDelayMs:20,staleAfterMs:5e3};X_=["COINBASE_KEY_SECRET","COINBASE_KEY_ID"]});function Mn(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 X,Z,vn,kn,Fn,ft=S(()=>{"use strict";u();d();X=[{name:"api-key",actions:[{id:"api_key_permissions",name:"permissions",method:"GET",path:"/api-key/permissions",summary:"Get Current API Key Permissions",description:"Returns the authoritative permissions and portfolio association for the API key used to authenticate this request. It accepts no key or customer identifier and always inspects the current credential.",pathParams:[],params:[],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["can_view","can_trade","can_transfer","portfolio_uuid","portfolio_type"]},annotations:{readOnlyHint:!0},agentApi:"eligible",noInput:!0,history:"disabled"}]},{name:"convert",actions:[{id:"convert_quote",name:"quote",method:"POST",path:"/convert/quote",summary:"Get Convert Quote",description:"Quotes stablecoin\u2194fiat and stablecoin\u2194stablecoin conversions, returning rate, fees, and a quote ID. It does not support BTC, ETH, or other non-stablecoin assets; use an order to trade those assets. Pass the ID to convert_execute promptly because quotes expire.",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,watch: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"]}}},annotations:{readOnlyHint:!1,destructiveHint:!1},agentApi:"eligible"},{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 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,watch:null,template:{from:"USDC",to:"USD"},responseFields:{fields:["trade"],nested:{trade:{fields:["id","status"]}}},annotations:{destructiveHint:!0},agentApi:"eligible"},{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,watch:null,template:{},responseFields:{fields:["id","status","source_currency","target_currency","exchange_rate"]},annotations:{readOnlyHint:!0},agentApi:"eligible"}]},{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. Use status=OPEN to find resting orders that can be edited or cancelled. For EQUITY orders, product_id is TICKER-QUOTE (e.g. AAPL-USD), the same form orders_create expects.",pathParams:[],params:[{name:"portfolio_id",in:"query",type:"string",required:!1,description:"Scope to a specific portfolio (defaults to all portfolios the caller can access)"},{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"],example:"BUY"},{name:"product_type",in:"query",type:"string",required:!1,description:"Filter by product type",enum:["SPOT","FUTURE","EQUITY"],example:"SPOT"},{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:"string",format:"decimal",description:"Average filled price"},filled_size:{type:"string",format:"decimal",description:"Filled quantity"},fees:{type:"string",format:"decimal",description:"Total fees"},product_id:{type:"string",description:"Trading pair"},order_id:{type:"string",description:"Order ID"}},watch:{channel:"user",endpoint:"user",requiresAuth:!0,coalesce:!1},template:{},responseFields:{fields:["orders","has_next","cursor"],nested:{orders:{fields:["order_id","product_id","side","status","order_configuration","attached_order_id","attached_order_configuration","created_time","last_fill_time","completion_percentage","filled_size","average_filled_price","total_fees","total_value_after_fees","number_of_fills"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{id:"orders_create",name:"create",method:"POST",path:"/orders",summary:"Create Order",description:"Place a market, limit, stop_limit, bracket, twap, or scaled order, subject to venue eligibility. Equities: use market or limit. Spot brackets require SELL; for entry, use market/limit BUY with attached exits. Futures brackets support BUY/SELL. Bracket stops become aggressive limit exits; fills and loss limits are not guaranteed. TWAP requires base_size, start_time, end_time, and a positive limit_price; slice count is automatic. Use orders_preview for optional fee, fill, and execution-plan estimates. Set exactly one size: limit and market SELL convert quote_size to base_size; market BUY spends quote_size; stop_limit/bracket/twap/scaled require base_size. Attached exits require market/limit parents and activate as the parent fills, including partial fills. If a FUTURE order is rejected for account eligibility, direct the user to https://help.coinbase.com/en/coinbase/trading-and-funding/derivatives/futures-intro to apply.",pathParams:[],params:[{name:"product_id",in:"body",type:"string",required:!0,description:`Trading pair (BASE-QUOTE, e.g. BTC-USD or BTC-USDC) for spot crypto, a dated-futures contract code for CFM. For equities, use TICKER-QUOTE (e.g. AAPL-USD or AAPL-USDC). If the user names a quote currency (e.g. "use my USDC"), use that pair \u2014 never default to USD instead. If they don't say, check the balance for this request's portfolio_id (or the default portfolio if omitted) and use whichever of USD/USDC they hold there; if both, prefer the USDC pair. If the resulting pair doesn't exist, tell the user rather than silently substituting a different one.`,example:"BTC-USDC"},{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: current price. limit: specified price or better. stop_limit: stop triggers a limit order. bracket: take-profit limit and stop-triggered aggressive limit exit; fills and loss limits are not guaranteed; spot SELL or eligible futures BUY/SELL. twap: split base_size over start_time/end_time with a positive limit_price and automatic slice count; requires GTD. scaled: 2 to 20 limit child orders between positive min_price/max_price. Equities: use market/limit. Other types depend on venue eligibility.",enum:["market","limit","stop_limit","bracket","twap","scaled"],example:"market"},{name:"quote_size",in:"body",type:"string",required:!1,description:"Quote-currency amount (e.g. $100 USD). Mutually exclusive with base_size. Market BUYs spend this amount; limit and market SELL convert it to base_size. Not supported for stop_limit, bracket, twap, or scaled \u2014 use base_size for those. Max 15,000 USD notional.",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. Required for stop_limit, bracket, twap, and scaled. Max 15,000 USD notional.",oneOf:"base_size|quote_size",example:"0.001"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Required limit price for limit/stop_limit/bracket/twap. Bracket take-profit and TWAP execution price ceiling/floor must be strictly positive decimals.",example:"65000.00"},{name:"stop_price",in:"body",type:"string",required:!1,description:"Stop trigger for stop_limit. For bracket, required positive decimal: above limit_price for futures BUY, below for SELL. Bracket stops become aggressive limit exits; no guaranteed fill or loss cap.",example:"60000.00"},{name:"stop_direction",in:"body",type:"string",required:!1,description:"stop_limit only. Bracket direction is implied by side.",enum:["up","down"],example:"down"},{name:"post_only",in:"body",type:"boolean",required:!1,description:"Post-only limit order: rejects if it would take liquidity. true is rejected for non-limit types."},{name:"time_in_force",in:"body",type:"string",required:!1,description:"GTC=good til cancelled. IOC=immediate or cancel. FOK=fill or kill. GTD=good til date; requires end_time. stop_limit, bracket, and scaled support GTC/GTD. twap requires GTD. Extended-hours equity orders require GTD.",enum:["GTC","IOC","FOK","GTD"],example:"GTC"},{name:"end_time",in:"body",type:"string",required:!1,description:"Expiry or execution end time (RFC 3339). Required for GTD and twap. The TWAP schedule may be adjusted.",format:"date-time",example:"2024-12-31T23:59:59Z"},{name:"reduce_only",in:"body",type:"boolean",required:!1,description:"Restrict the order to reducing existing exposure. Supported for INTX perpetuals; US dated futures, spot, and equities may reject it. Not supported for scaled."},{name:"attached_take_profit_price",in:"body",type:"string",required:!1,description:"Positive decimal take-profit limit exit, activated as a market/limit parent fills (including partial fills). May combine with attached_stop_loss_price. Spot: BUY parent only. Futures: BUY/SELL subject to venue eligibility. Not equities. No guaranteed fill.",example:"70000.00"},{name:"attached_stop_loss_price",in:"body",type:"string",required:!1,description:"Positive decimal stop trigger, activated as a market/limit parent fills (including partial fills). Becomes an aggressive limit exit, not a guaranteed fill or loss cap. May combine with attached_take_profit_price. Spot: BUY parent only. Futures: BUY/SELL subject to venue eligibility. Not equities.",example:"58000.00"},{name:"start_time",in:"body",type:"string",required:!1,description:"Requested execution start (RFC 3339). Required for twap. Slice count is automatic.",format:"date-time",example:"2024-12-31T14:00:00Z"},{name:"num_orders",in:"body",type:"integer",required:!1,description:"Number of limit child orders, from 2 to 20. Required for scaled.",example:5},{name:"min_price",in:"body",type:"string",required:!1,description:"Lowest child limit price. Required for scaled. Must be positive and below max_price.",example:"58000.00"},{name:"max_price",in:"body",type:"string",required:!1,description:"Highest child limit price. Required for scaled. Must be positive and above min_price.",example:"62000.00"},{name:"price_distribution",in:"body",type:"string",required:!1,description:"Scaled price spacing. Defaults to FLAT (evenly spaced prices).",enum:["FLAT","LINEAR_INCREASING","LINEAR_DECREASING"],example:"FLAT"},{name:"size_distribution",in:"body",type:"string",required:!1,description:"Scaled size distribution. Defaults to an even split across child orders.",enum:["INCREASING","DECREASING","EVENLY_SPLIT"],example:"EVENLY_SPLIT"},{name:"portfolio_id",in:"body",type:"string",required:!1,description:"The optional UUID of a portfolio containing accounts with which to trade. Defaults to the default portfolio when no portfolio_id is provided."},{name:"client_order_id",in:"body",type:"string",required:!1,description:"Idempotency key (auto-generated if omitted)"},{name:"equity_trading_session",in:"body",type:"string",required:!1,description:"Equity trading session. Ignored for crypto and futures.",enum:["NORMAL","PRE_MARKET","AFTER_HOURS","OVERNIGHT","MULTI_SESSION"]},{name:"equity_order_date",in:"body",type:"string",required:!1,description:"Equity trade date (YYYY-MM-DD). Ignored for crypto and futures.",format:"date"}],streamable:!1,watchFields:null,watch:null,template:{product_id:"BTC-USDC",side:"BUY",type:"market",quote_size:"100.00",base_size:"0.001",limit_price:"65000.00",stop_price:"60000.00",stop_direction:"down",post_only:!1,time_in_force:"GTC",end_time:"2024-12-31T23:59:59Z",reduce_only:!1,attached_take_profit_price:"70000.00",attached_stop_loss_price:"58000.00",start_time:"2024-12-31T14:00:00Z",num_orders:5,min_price:"58000.00",max_price:"62000.00",price_distribution:"FLAT",size_distribution:"EVENLY_SPLIT",portfolio_id:"<string>",client_order_id:"<string>",equity_trading_session:"NORMAL",equity_order_date:"<string>"},responseFields:{fields:["order_id","product_id","side","client_order_id"]},annotations:{destructiveHint:!0},agentApi:"eligible"},{id:"orders_preview",name:"preview",method:"POST",path:"/orders/preview",summary:"Preview Order",description:"Estimate fees, fill price, slippage, and execution plans without placing an order. Optional before orders_create; the same order-type and asset-class restrictions apply. Futures previews also estimate margin, leverage, and liquidation impact: compare current and projected margin ratios and liquidation buffers. If a FUTURE preview is rejected for account eligibility, direct the user to https://help.coinbase.com/en/coinbase/trading-and-funding/derivatives/futures-intro to apply.",pathParams:[],params:[{name:"product_id",in:"body",type:"string",required:!0,description:`Trading pair (BASE-QUOTE, e.g. BTC-USD or BTC-USDC) for spot crypto, a dated-futures contract code for CFM. For equities, use TICKER-QUOTE (e.g. AAPL-USD or AAPL-USDC). If the user names a quote currency (e.g. "use my USDC"), use that pair \u2014 never default to USD instead. If they don't say, check the balance for this request's portfolio_id (or the default portfolio if omitted) and use whichever of USD/USDC they hold there; if both, prefer the USDC pair. If the resulting pair doesn't exist, tell the user rather than silently substituting a different one.`,example:"BTC-USDC"},{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: current price. limit: specified price or better. stop_limit: stop triggers a limit order. bracket: take-profit limit and stop-triggered aggressive limit exit; fills and loss limits are not guaranteed; spot SELL or eligible futures BUY/SELL. twap: split base_size over start_time/end_time with a positive limit_price and automatic slice count; requires GTD. scaled: 2 to 20 limit child orders between positive min_price/max_price. Equities: use market/limit. Other types depend on venue eligibility.",enum:["market","limit","stop_limit","bracket","twap","scaled"],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. Not supported for stop_limit, bracket, twap, or scaled \u2014 use base_size for those.",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. Required for stop_limit, bracket, twap, and scaled.",oneOf:"base_size|quote_size",example:"0.001"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Required limit price for limit/stop_limit/bracket/twap. Bracket take-profit and TWAP execution price ceiling/floor must be strictly positive decimals.",example:"65000.00"},{name:"stop_price",in:"body",type:"string",required:!1,description:"Stop trigger for stop_limit. For bracket, required positive decimal: above limit_price for futures BUY, below for SELL. Bracket stops become aggressive limit exits; no guaranteed fill or loss cap.",example:"60000.00"},{name:"stop_direction",in:"body",type:"string",required:!1,description:"stop_limit only. Bracket direction is implied by side.",enum:["up","down"],example:"down"},{name:"post_only",in:"body",type:"boolean",required:!1,description:"Post-only limit order: rejects if it would take liquidity. true is rejected for non-limit types."},{name:"time_in_force",in:"body",type:"string",required:!1,description:"GTC=good til cancelled. IOC=immediate or cancel. FOK=fill or kill. GTD=good til date; requires end_time. stop_limit, bracket, and scaled support GTC/GTD. twap requires GTD. Extended-hours equity orders require GTD.",enum:["GTC","IOC","FOK","GTD"],example:"GTC"},{name:"end_time",in:"body",type:"string",required:!1,description:"Expiry or execution end time (RFC 3339). Required for GTD and twap. The TWAP schedule may be adjusted.",format:"date-time",example:"2024-12-31T23:59:59Z"},{name:"reduce_only",in:"body",type:"boolean",required:!1,description:"Restrict the order to reducing existing exposure. Supported for INTX perpetuals; US dated futures, spot, and equities may reject it. Not supported for scaled."},{name:"attached_take_profit_price",in:"body",type:"string",required:!1,description:"Positive decimal take-profit limit exit, activated as a market/limit parent fills (including partial fills). May combine with attached_stop_loss_price. Spot: BUY parent only. Futures: BUY/SELL subject to venue eligibility. Not equities. No guaranteed fill.",example:"70000.00"},{name:"attached_stop_loss_price",in:"body",type:"string",required:!1,description:"Positive decimal stop trigger, activated as a market/limit parent fills (including partial fills). Becomes an aggressive limit exit, not a guaranteed fill or loss cap. May combine with attached_take_profit_price. Spot: BUY parent only. Futures: BUY/SELL subject to venue eligibility. Not equities.",example:"58000.00"},{name:"start_time",in:"body",type:"string",required:!1,description:"Requested execution start (RFC 3339). Required for twap. Slice count is automatic.",format:"date-time",example:"2024-12-31T14:00:00Z"},{name:"num_orders",in:"body",type:"integer",required:!1,description:"Number of limit child orders, from 2 to 20. Required for scaled.",example:5},{name:"min_price",in:"body",type:"string",required:!1,description:"Lowest child limit price. Required for scaled. Must be positive and below max_price.",example:"58000.00"},{name:"max_price",in:"body",type:"string",required:!1,description:"Highest child limit price. Required for scaled. Must be positive and above min_price.",example:"62000.00"},{name:"price_distribution",in:"body",type:"string",required:!1,description:"Scaled price spacing. Defaults to FLAT (evenly spaced prices).",enum:["FLAT","LINEAR_INCREASING","LINEAR_DECREASING"],example:"FLAT"},{name:"size_distribution",in:"body",type:"string",required:!1,description:"Scaled size distribution. Defaults to an even split across child orders.",enum:["INCREASING","DECREASING","EVENLY_SPLIT"],example:"EVENLY_SPLIT"},{name:"portfolio_id",in:"body",type:"string",required:!1,description:"The optional UUID of a portfolio containing accounts with which to trade. Defaults to the default portfolio when no portfolio_id is provided."},{name:"equity_trading_session",in:"body",type:"string",required:!1,description:"Equity trading session. Ignored for crypto and futures.",enum:["NORMAL","PRE_MARKET","AFTER_HOURS","OVERNIGHT","MULTI_SESSION"]},{name:"equity_order_date",in:"body",type:"string",required:!1,description:"Equity trade date (YYYY-MM-DD). Ignored for crypto and futures.",format:"date"}],streamable:!1,watchFields:null,watch:null,template:{product_id:"BTC-USDC",side:"BUY",type:"market",quote_size:"100.00",base_size:"0.001",limit_price:"65000.00",stop_price:"60000.00",stop_direction:"down",post_only:!1,time_in_force:"GTC",end_time:"2024-12-31T23:59:59Z",reduce_only:!1,attached_take_profit_price:"70000.00",attached_stop_loss_price:"58000.00",start_time:"2024-12-31T14:00:00Z",num_orders:5,min_price:"58000.00",max_price:"62000.00",price_distribution:"FLAT",size_distribution:"EVENLY_SPLIT",portfolio_id:"<string>",equity_trading_session:"NORMAL",equity_order_date:"<string>"},responseFields:{fields:["order_total","commission_total","slippage","est_average_filled_price","warning","twap_bucket_metadata","scaled_metadata","base_size","quote_size","best_bid","best_ask","leverage","long_leverage","short_leverage","max_leverage","position_notional_limit","available_buying_power","order_margin_total","current_liquidation_buffer","projected_liquidation_buffer","predicted_liquidation_price","margin_ratio_data"],nested:{twap_bucket_metadata:{fields:["bucket_duration","bucket_size","number_buckets","start_time","end_time"]},scaled_metadata:{fields:["scaled_order_distribution"],nested:{scaled_order_distribution:{fields:["size","price","errs","warning"]}}},margin_ratio_data:{fields:["current_margin_ratio","projected_margin_ratio"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{id:"orders_edit",name:"edit",method:"POST",path:"/orders/{order_id}/edit",summary:"Edit Order",description:"Atomically update an open order's price or size without cancelling. Omit attached fields to keep existing exits. Attach or change exits only on eligible unfilled limit orders: spot BUY or futures BUY/SELL, not equities. Exits activate as the parent fills, including partial fills. Stops become aggressive limit exits; fills and loss limits are not guaranteed. Attached updates replace both legs: send attached_take_profit_price and attached_stop_loss_price to keep both, even when changing one. Read orders_get first: attached_order_configuration.trigger_bracket_gtc.limit_price maps to attached_take_profit_price; stop_trigger_price maps to attached_stop_loss_price. cancel_attached_order removes both legs, but may be rejected after an exit activates.",pathParams:["order_id"],params:[{name:"order_id",in:"path",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"},{name:"attached_take_profit_price",in:"body",type:"string",required:!1,description:"Positive take-profit limit price for an eligible unfilled limit order. Send both attached prices to keep both legs. Spot BUY or eligible futures BUY/SELL; not equities.",example:"70000.00"},{name:"attached_stop_loss_price",in:"body",type:"string",required:!1,description:"Positive stop trigger for an eligible unfilled limit order. Send both attached prices to keep both legs. Triggers an aggressive limit exit; fills and loss limits are not guaranteed. Spot BUY or eligible futures BUY/SELL; not equities.",example:"58000.00"},{name:"cancel_attached_order",in:"body",type:"boolean",required:!1,description:"Remove both attached exit legs while keeping the parent order. Cannot be combined with attached_take_profit_price or attached_stop_loss_price. May be rejected after an exit activates."}],streamable:!1,watchFields:null,watch:null,template:{base_size:"0.002",limit_price:"64000.00",attached_take_profit_price:"70000.00",attached_stop_loss_price:"58000.00",cancel_attached_order:!1},responseFields:{fields:["order_id","status"]},annotations:{destructiveHint:!0},agentApi:"eligible"},{id:"orders_edit_preview",name:"edit-preview",method:"POST",path:"/orders/edit-preview",summary:"Preview Order Edit",description:"Estimate the result, fees, fill price, and slippage of changing an open order's size or limit price without editing it. Hosted OAuth requires mcp:orders:create. CDP API-key callers may use rat#view where supported. Unsupported replacements return errors.",pathParams:[],params:[{name:"order_id",in:"body",type:"string",required:!0,description:"Open order UUID to preview editing"},{name:"base_size",in:"body",type:"string",required:!1,description:"Positive decimal replacement base size",example:"0.002"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Positive decimal replacement limit price",example:"64000.00"}],streamable:!1,watchFields:null,watch:null,template:{order_id:"<string>",base_size:"0.002",limit_price:"64000.00"},responseFields:{fields:["slippage","order_total","commission_total","quote_size","base_size","best_bid","best_ask","average_filled_price","order_margin_total","commission_detail_total","pnl_configuration"],nested:{commission_detail_total:{fields:["total_commission","gst_commission","withholding_commission","client_commission","venue_commission","regulatory_commission","clearing_commission"]},pnl_configuration:{fields:["trigger_bracket_pnl"],nested:{trigger_bracket_pnl:{fields:["take_profit_pnl","stop_loss_pnl"]}}}}},anyOf:[["base_size"],["limit_price"]],annotations:{readOnlyHint:!0,destructiveHint:!1},agentApi:"eligible"},{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. Use after creating an order to confirm execution, and before orders_edit to see the current attached take-profit/stop-loss (attached_order_id / attached_order_configuration). For EQUITY orders, product_id is TICKER-QUOTE (e.g. AAPL-USD), the same form orders_create expects.",pathParams:["order_id"],params:[{name:"order_id",in:"path",type:"string",required:!0,description:"Order ID"}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["order_id","product_id","side","status","order_configuration","attached_order_id","attached_order_configuration","created_time","last_fill_time","completion_percentage","filled_size","average_filled_price","total_fees","total_value_after_fees","number_of_fills"]},annotations:{readOnlyHint:!0},agentApi:"eligible"},{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,watch:null,template:{order_ids:[]},responseFields:{fields:["results"],nested:{results:{fields:["success","order_id"]}}},annotations:{destructiveHint:!0},agentApi:"eligible"},{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,watch:null,template:{client_order_id:"<string>",product_id:"BTC-PERP",size:"0.001"},responseFields:{fields:["success","order_id","product_id"]},annotations:{destructiveHint:!0},agentApi:"eligible"},{id:"orders_fills",name:"fills",method:"GET",path:"/orders/fills",summary:"List Fills",description:"Lists individual trade executions with commissions and maker/taker indicator, filterable by product, order, side, and time range. Use this to reconcile actual fill prices and fees paid. For EQUITY fills, product_id is TICKER-QUOTE (e.g. AAPL-USD), the same form orders_create expects.",pathParams:[],params:[{name:"portfolio_id",in:"query",type:"string",required:!1,description:"Scope to a specific portfolio (defaults to all portfolios the caller can access)"},{name:"product_ids",in:"query",type:"string",required:!1,description:"Filter by product (e.g. BTC-USD)"},{name:"order_ids",in:"query",type:"array",required:!1,description:"Filter by order ID"},{name:"side",in:"query",type:"string",required:!1,description:"Filter by side",enum:["BUY","SELL"],example:"BUY"},{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:"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,watch:null,template:{},responseFields:{fields:["fills","cursor"],nested:{fills:{fields:["trade_id","order_id","trade_time","price","size","commission","product_id","side","liquidity_indicator"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"}]},{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. 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)",enum:["DEFAULT","CONSUMER"]}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["portfolios"],nested:{portfolios:{fields:["uuid","name","type","deleted"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{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,watch:null,template:{name:"agent-1"},responseFields:{fields:["uuid","name","type","deleted"]},annotations:{destructiveHint:!1},agentApi:"eligible"},{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,watch:null,template:{},responseFields:{fields:["portfolio","portfolio_balances","spot_positions","futures_positions","equity_positions"],nested:{portfolio:{fields:["uuid","name","type","deleted"]},portfolio_balances:{fields:["total_balance","total_crypto_balance","total_cash_equivalent_balance","total_equities_balance"],nested:{total_balance:{fields:["value","currency"]},total_crypto_balance:{fields:["value","currency"]},total_cash_equivalent_balance:{fields:["value","currency"]},total_equities_balance:{fields:["value","currency"]}}},spot_positions:{fields:["asset","account_uuid","total_balance_fiat","total_balance_crypto","available_to_trade_fiat","allocation","is_cash"]},futures_positions:{fields:["product_id","contract_size","side","amount","avg_entry_price","current_price","unrealized_pnl","expiry","underlying_asset","product_name","venue","notional_value"]},equity_positions:{fields:["asset","account_uuid","total_balance_fiat","total_balance_equity","available_to_trade_equity","available_to_trade_fiat","account_type","allocation","cost_basis","average_entry_price","unrealized_pnl"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{id:"portfolios_edit",name:"edit",method:"PUT",path:"/portfolios/{portfolio_id}",summary:"Edit Portfolio",description:"Renames an existing portfolio. 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,watch:null,template:{name:"<string>"},responseFields:{fields:["uuid","name","type","deleted"]},annotations:{destructiveHint:!1},agentApi:"eligible"},{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,watch:null,template:{},responseFields:null,annotations:{destructiveHint:!0},agentApi:"eligible"}]},{name:"products",actions:[{id:"products_list",name:"list",method:"GET",path:"/products",summary:"List Products",description:"Viewing products, including FUTURE ones, doesn't require any special account approval. Trading them is a separate matter \u2014 see the product_type field description.",pathParams:[],params:[{name:"product_type",in:"query",type:"string",required:!1,description:"Product type filter",enum:["SPOT","FUTURE","EQUITY"],example:"SPOT"},{name:"product_ids",in:"query",type:"string",required:!1,description:"Comma-separated product IDs"},{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 products_get (e.g. BTC-USD). Pagination ignored when set.",pattern:"^[A-Za-z0-9]+$"},{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,watch: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","future_product_details","fcm_trading_session_details"],nested:{future_product_details:{fields:["contract_expiry_type","contract_size","contract_expiry","time_to_expiry_ms","open_interest","funding_rate","funding_interval","funding_time","intraday_margin_rate","overnight_margin_rate"],nested:{intraday_margin_rate:{fields:["long_margin_rate","short_margin_rate"]},overnight_margin_rate:{fields:["long_margin_rate","short_margin_rate"]}}},fcm_trading_session_details:{fields:["is_session_open","open_time","close_time","session_state"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{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. Omit product_ids to return pricebooks for all products. Not currently available for equities.",pathParams:[],params:[{name:"product_ids",in:"query",type:"array",required:!1,description:"Product IDs (e.g. BTC-USD and ETH-USD). Omit to return all products."}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["pricebooks"],nested:{pricebooks:{fields:["product_id","bids","asks","time"],nested:{bids:{fields:["price","size"]},asks:{fields:["price","size"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{id:"products_get",name:"get",method:"GET",path:"/products/{product_id}",summary:"Get Product",description:"Viewing a product, including a FUTURE one, doesn't require any special account approval. Trading it is a separate matter \u2014 see the product_type field description.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID (e.g. BTC-USD)"}],streamable:!1,watchFields:null,watch: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","future_product_details","fcm_trading_session_details"],nested:{future_product_details:{fields:["contract_expiry_type","contract_size","contract_expiry","time_to_expiry_ms","open_interest","funding_rate","funding_interval","funding_time","intraday_margin_rate","overnight_margin_rate"],nested:{intraday_margin_rate:{fields:["long_margin_rate","short_margin_rate"]},overnight_margin_rate:{fields:["long_margin_rate","short_margin_rate"]}}},fcm_trading_session_details:{fields:["is_session_open","open_time","close_time","session_state"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{id:"products_ticker",name:"ticker",method:"GET",path:"/products/{product_id}/ticker",summary:"Get Ticker",description:"Returns recent trade prints plus the current best bid/ask for a product. Use for a quick spot-price snapshot before previewing or placing an order. Not currently available for equities.",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:"string",format:"decimal",description:"Last trade price"},bid:{type:"string",format:"decimal",description:"Best bid"},ask:{type:"string",format:"decimal",description:"Best ask"},bid_size:{type:"string",format:"decimal",description:"Size at best bid"},ask_size:{type:"string",format:"decimal",description:"Size at best ask"},volume:{type:"string",format:"decimal",description:"24h volume"},high:{type:"string",format:"decimal",description:"24h high"},low:{type:"string",format:"decimal",description:"24h low"},pct_24h:{type:"string",format:"decimal",description:"24h price change %"},product_id:{type:"string",description:"Trading pair"}},watch:{channel:"ticker",endpoint:"public",requiresAuth:!1,coalesce:!0},template:{},responseFields:{fields:["trades","best_bid","best_ask"],nested:{trades:{fields:["trade_id","product_id","price","size","time","side"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{id:"products_book",name:"book",method:"GET",path:"/products/{product_id}/book",summary:"Get Order Book",description:"Returns the current bid/ask order book for a product. Use to gauge available liquidity and likely slippage before sizing a market order. Not currently available for equities.",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:"string",format:"decimal",description:"Bid-ask spread"},mid:{type:"string",format:"decimal",description:"Midpoint price"},product_id:{type:"string",description:"Trading pair"}},watch:{channel:"level2",wireName:"l2_data",endpoint:"public",requiresAuth:!1,coalesce:!0},template:{},responseFields:{fields:["pricebook"],nested:{pricebook:{fields:["product_id","bids","asks","time"],nested:{bids:{fields:["price","size"]},asks:{fields:["price","size"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{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. Use for price history and technical analysis. Not currently available for equities.",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"],default:"1h"},{name:"limit",in:"query",type:"integer",required:!1,description:"Max candles"}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["candles","truncated"],nested:{candles:{fields:["start","low","high","open","close","volume"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"}]},{name:"x402",actions:[{id:"x402_resources",name:"resources",method:"GET",path:"/x402/resources",summary:"Discover x402 Resources",description:`Discover curated x402 resources: paid on-chain and market metrics, wallet and entity intelligence, and derivatives data. Discovery spends nothing. An optional keyword q filters the catalog; omit it to list all. Each result carries the resource URL, its advisory price, and its input and output schemas. All currently supported x402 purchases through this connector use Base USDC. accepts[].amount and coinbase_x402_fetch's max_amount use USDC's 6-decimal atomic units; for example, "50000" means "0.05 USDC". A result's inputSchema is coinbase_x402_fetch's input verbatim: pass those properties flat; do not build an HTTP envelope. The live 402 challenge sets the exact amount.`,pathParams:[],params:[{name:"q",in:"query",type:"string",required:!1,description:"Optional keyword filter. Matched against each resource's description, provider name, and tags using case-insensitive token search. Omit to return the full catalog."}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["resources"],nested:{resources:{fields:["resource","description","accepts","inputSchema","outputSchema"],nested:{accepts:{fields:["amount"]}}}}},annotations:{readOnlyHint:!0},agentApi:"only"},{id:"x402_pay",name:"pay",method:"POST",path:"/x402/pay",summary:"Pay an x402 Payment Requirement",description:`Turns an x402 PaymentRequirements challenge into a ready-to-send payment header by placing a pre-authorized hold on the caller's Base USDC balance (EIP-3009 exact scheme, v0). All currently supported x402 purchases through this connector use Base USDC, and amount and max_amount use its 6-decimal atomic units; for example, "50000" means "0.05 USDC". Attach the returned header as X-PAYMENT for v1 or PAYMENT-SIGNATURE for v2. This authorizes moving funds up to max_amount \u2014 pass the smallest amount that satisfies the requirement. Funds-touching and gated internal-only behind a default-off feature flag.`,pathParams:[],params:[{name:"scheme",in:"body",type:"string",required:!0,description:'x402 payment scheme. Only "exact" is supported in v0.'},{name:"network",in:"body",type:"string",required:!0,description:'x402 network as a CAIP-2 chain id. Only "eip155:8453" (Base mainnet) is supported in v0.'},{name:"asset",in:"body",type:"string",required:!0,description:"USDC asset contract address on the network (the x402 asset field)."},{name:"pay_to",in:"body",type:"string",required:!0,description:"Recipient address the payment authorizes (the x402 payTo field)."},{name:"amount",in:"body",type:"string",required:!0,description:`The amount the resource requires, in Base USDC's 6-decimal atomic units; for example, "50000" means "0.05 USDC". Decimal string; never truncated.`},{name:"max_amount",in:"body",type:"string",required:!0,description:`Caller-set spend cap in Base USDC's 6-decimal atomic units; for example, "50000" means "0.05 USDC". The hold is rejected if amount exceeds this. Decimal string.`},{name:"max_timeout_seconds",in:"body",type:"integer",required:!0,description:"Validity window for the signed authorization, in seconds (the x402 maxTimeoutSeconds field). Must be between 1 and 300; the server caps how long the authorization stays valid. Pass a value no greater than the resource's advertised maxTimeoutSeconds (a shorter window is valid, and settlement is near-instant); requests above 300 are rejected."},{name:"x402_version",in:"body",type:"integer",required:!1,description:"x402 protocol version from the resource's 402 challenge. Pass the value the resource advertised. Optional; defaults to 1."},{name:"extra",in:"body",type:"object",required:!1,description:"Full extra object from the resource's 402 PaymentRequirements. Required when x402_version is 2; name and version must match the Base USDC EIP-712 domain."},{name:"portfolio_id",in:"body",type:"string",required:!1,description:'Optional UUID of the consumer portfolio to pay from. Omit only when exactly one accessible non-deleted consumer portfolio is available and the caller has portfolio listing permission. If discovery is not authorized, provide portfolio_id explicitly. For OAuth, ask the user to reconnect and select "View your trading portfolios" in Coinbase consent. For an API key, ask the user to edit it, open Advanced Settings, and enable "View (read-only)" for every portfolio the agent needs. If multiple consumer portfolios are available, call coinbase_portfolios_list, select the funding portfolio with the use'},{name:"account_id",in:"body",type:"string",required:!1,description:"Optional UUID of the USDC account to debit, within the chosen portfolio. Omit to use that portfolio's single USDC account; the tool returns an error (it does NOT guess) when the portfolio has zero or multiple USDC accounts."},{name:"idempotency_key",in:"body",type:"string",required:!1,description:"Optional caller-supplied idempotency key; must be a UUID. Omit it on a first attempt \u2014 one is generated and returned to you. Reuse the SAME key when retrying an outcome-unknown payment so a duplicate hold is not placed. If the tool reports a terminal rejection, do not reuse that key; start a new payment attempt with a new key."}],streamable:!1,watchFields:null,watch:null,template:{scheme:"<string>",network:"<string>",asset:"<string>",pay_to:"<string>",amount:"<string>",max_amount:"<string>",max_timeout_seconds:0,x402_version:0,extra:{name:"<string>",version:"<string>"},portfolio_id:"<string>",account_id:"<string>",idempotency_key:"<string>"},responseFields:{fields:["payment_header","payment_id","idempotency_key","expires_at"]},annotations:{destructiveHint:!0},agentApi:"only"},{id:"x402_fetch",name:"fetch",method:"POST",path:"/x402/fetch",summary:"Pay For and Fetch x402 Resource",description:`Fetches a resource returned by x402_resources. On a 402 challenge, pays from the caller's custodial Base USDC via a pre-authorized hold, then retries with PAYMENT-SIGNATURE \u2014 no manual challenge handling. All currently supported x402 purchases through this connector use Base USDC, and max_amount uses its 6-decimal atomic units; for example, "50000" means "0.05 USDC". This tool accepts only resource URLs returned by x402_resources. max_amount is the spend control; when the user has requested the data or stated a budget, proceed in a single call rather than re-confirming. Protocol v2 only; v1 challenges are rejected.`,pathParams:[],params:[{name:"resource",in:"body",type:"string",required:!0,description:"Resource URL returned by coinbase_x402_resources, with any path parameters substituted. Any URL that does not match a catalog resource is rejected."},{name:"input",in:"body",type:"object",required:!1,description:"Request parameters, exactly as described by the resource's inputSchema from coinbase_x402_resources \u2014 pass those properties flat, at the top level. The tool routes them to the query string or the request body per the resource's HTTP method; you do not construct the HTTP envelope. Validated strictly as a closed allowlist; unknown keys are rejected."},{name:"max_amount",in:"body",type:"string",required:!1,description:`Optional caller-set spend cap in Base USDC's 6-decimal atomic units; for example, "50000" means "0.05 USDC". Defaults to the catalog advisory ceiling for the resource; when supplied the effective cap is min(max_amount, advisory ceiling). Never derived from the live 402 challenge.`},{name:"portfolio_id",in:"body",type:"string",required:!1,description:'Optional UUID of the consumer portfolio to pay from. Omit only when exactly one accessible non-deleted consumer portfolio is available and the caller has portfolio listing permission. If discovery is not authorized, provide portfolio_id explicitly. For OAuth, ask the user to reconnect and select "View your trading portfolios" in Coinbase consent. For an API key, ask the user to edit it, open Advanced Settings, and enable "View (read-only)" for every portfolio the agent needs. If multiple consumer portfolios are available, call coinbase_portfolios_list, select the funding portfolio with the use'},{name:"account_id",in:"body",type:"string",required:!1,description:"Optional UUID of the USDC account to debit, within the chosen portfolio. Omit to use that portfolio's single USDC account; an error (not a guess) is returned when the portfolio has zero or multiple USDC accounts."},{name:"idempotency_key",in:"body",type:"string",required:!1,description:"Optional caller-supplied idempotency key for the payment; must be a UUID. Omit it on a first attempt \u2014 one is generated and returned to you. Reuse the SAME key when retrying an outcome-unknown fetch so a duplicate hold is not placed. If the tool reports a terminal rejection, do not reuse that key; start a new payment attempt with a new key."}],streamable:!1,watchFields:null,watch:null,template:{resource:"<string>",input:{},max_amount:"<string>",portfolio_id:"<string>",account_id:"<string>",idempotency_key:"<string>"},responseFields:{fields:["data","paid","payment_id","idempotency_key","expires_at"]},annotations:{destructiveHint:!0},agentApi:"only"}]}],Z={balance:{id:"balance",name:"balance",method:"GET",path:"/balance",summary:"View Balances",description:"Returns account balances for exactly one portfolio. If portfolio_id is omitted, only the default portfolio is returned. Results are not aggregated across portfolios; use coinbase_portfolios_list and query each portfolio for a complete multi-portfolio view. The response portfolio_id identifies the effective portfolio queried. Balances show available funds and amounts on hold; available_balance excludes funds held by open orders. Use before trading or transferring to confirm available funds.",pathParams:[],params:[{name:"portfolio_id",in:"query",type:"string",required:!1,description:"UUID of the single portfolio to query. Omit to query only the default 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,watch:null,template:{},responseFields:{fields:["portfolio_id","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"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},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","EQUITY"],example:"SPOT"}],streamable:!1,watchFields:null,watch: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"]},margin_rate:{fields:["value"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},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-8f2c-4a1e-9b30-5c7e1f2a4d61"},{name:"to",in:"body",type:"string",required:!0,description:"Target portfolio UUID",example:"a44ef7a8-3c95-4d18-bf62-90ad7e5c1b04"}],streamable:!1,watchFields:null,watch:null,template:{amount:"100.00",currency:"USD",from:"d17b3486-8f2c-4a1e-9b30-5c7e1f2a4d61",to:"a44ef7a8-3c95-4d18-bf62-90ad7e5c1b04"},responseFields:{fields:["source_portfolio_uuid","target_portfolio_uuid"]},annotations:{destructiveHint:!0},agentApi:"eligible"}},vn=new Set(["balance","fees","transfer"]),kn={date:/^\d{4}-\d{2}-\d{2}$/,"date-time":/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/};Fn={date:t=>{let e=t.match(/^(\d{4})-(\d{2})-(\d{2})$/);return!!e&&Mn(+e[1],+e[2],+e[3])},"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,_,o]=e;return Mn(+r,+n,+i)&&+s<24&&+_<60&&+o<61}}});function be(t){return typeof t=="object"&&"endpoint"in t}function F(t,e){return{endpoint:t,...e}}var Dt=S(()=>{"use strict";u();d()});var Vn,Gn,wn,Wn,xn,Bn,Hn,Kn,Yn,qn,zn,$n,jn,Qn,Xn,wt=S(()=>{"use strict";u();d();Vn={origin:"RetailBrokerageApi_CancelOrders",method:"POST",path:"/api/v3/brokerage/orders/batch_cancel"},Gn={origin:"RetailBrokerageApi_ClosePosition",method:"POST",path:"/api/v3/brokerage/orders/close_position"},wn={origin:"RetailBrokerageApi_CommitConvertTrade",method:"POST",path:"/api/v3/brokerage/convert/trade/{trade_id}"},Wn={origin:"RetailBrokerageApi_CreatePortfolio",method:"POST",path:"/api/v3/brokerage/portfolios"},xn={origin:"RetailBrokerageApi_DeletePortfolio",method:"DELETE",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},Bn={origin:"RetailBrokerageApi_EditPortfolio",method:"PUT",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},Hn={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}"},Yn={origin:"RetailBrokerageApi_GetFills",method:"GET",path:"/api/v3/brokerage/orders/historical/fills"},qn={origin:"RetailBrokerageApi_GetHistoricalOrder",method:"GET",path:"/api/v3/brokerage/orders/historical/{order_id}"},zn={origin:"RetailBrokerageApi_GetHistoricalOrders",method:"GET",path:"/api/v3/brokerage/orders/historical/batch"},$n={origin:"RetailBrokerageApi_GetPortfolios",method:"GET",path:"/api/v3/brokerage/portfolios"},jn={origin:"RetailBrokerageApi_GetProduct",method:"GET",path:"/api/v3/brokerage/products/{product_id}"},Qn={origin:"RetailBrokerageApi_GetPublicProductBook",method:"GET",path:"/api/v3/brokerage/market/product_book"},Xn={origin:"RetailBrokerageApi_GetTransactionSummary",method:"GET",path:"/api/v3/brokerage/transaction_summary"}});function io(t,e){let r={...e},n=t;for(let[i,s]of Object.entries(r)){let _="{"+i+"}";s!=null&&n.includes(_)&&(n=n.replaceAll(_,encodeURIComponent(String(s))),delete r[i])}return{url:n,remaining:r}}async function et(t,e,r,n){let{url:i,remaining:s}=io(r,n),_=e==="POST"||e==="PUT"||e==="DELETE"||e==="PATCH",o,a=null;if(_)o=t.baseURL+i,Object.keys(s).length>0&&(a=new TextEncoder().encode(JSON.stringify(s)));else{let l=Object.entries(s).filter(([,p])=>p!=null).flatMap(([p,A])=>(Array.isArray(A)?A:[A]).map(T=>encodeURIComponent(p)+"="+encodeURIComponent(String(T)))).join("&");o=t.baseURL+i+(l?"?"+l:"")}let E=await t.doRequest({method:e,url:o,body:a}),g=new TextDecoder().decode(E.body),c;try{c=JSON.parse(g)}catch{c=g}if(E.status>=400){let l=c,p=l?.error_response?.message??l?.error_response?.error_details??l?.message??l?.error_details??g.slice(0,200);throw new _t(p,E.status,c)}return{status:E.status,data:c}}function Zn(t,e){return et(t,"POST","/api/v3/brokerage/convert/quote",e)}function Jn(t,e){return et(t,"POST","/api/v3/brokerage/orders/edit",e)}function ti(t,e){return et(t,"GET","/api/v3/brokerage/accounts",e)}function ei(t,e){return et(t,"GET","/api/v3/brokerage/key_permissions",e)}function ri(t,e){return et(t,"GET","/api/v3/brokerage/products/{product_id}/candles",e)}function ni(t,e){return et(t,"GET","/api/v3/brokerage/products/{product_id}/ticker",e)}function ii(t,e){return et(t,"GET","/api/v3/brokerage/portfolios/{portfolio_uuid}",e)}function Or(t,e){return et(t,"GET","/api/v3/brokerage/products",e)}function si(t,e){return et(t,"POST","/api/v3/brokerage/portfolios/move_funds",e)}function _i(t,e){return et(t,"POST","/api/v3/brokerage/orders",e)}function oi(t,e){return et(t,"POST","/api/v3/brokerage/orders/edit_preview",e)}function ai(t,e){return et(t,"POST","/api/v3/brokerage/orders/preview",e)}var _t,dt=S(()=>{"use strict";u();d();_t=class extends Error{status;data;constructor(e,r,n){super(e),this.status=r,this.data=n}}});function oo(t,e,r){if(!(!t||t===r))return e[t]??t}function co(t){if(typeof t=="number")return t;if(t&&typeof t=="object"&&"value"in t){let e=Number(t.value);return Number.isFinite(e)?e:void 0}}var so,_o,ao,Eo,ci,Ei=S(()=>{"use strict";u();d();Dt();wt();dt();so={FUTURES_POSITION_SIDE_LONG:"LONG",FUTURES_POSITION_SIDE_SHORT:"SHORT"},_o="FUTURES_POSITION_SIDE_UNSPECIFIED";ao=["total_balance_fiat","total_balance_equity","available_to_trade_equity","available_to_trade_fiat","cost_basis","average_entry_price","unrealized_pnl"];Eo=async(t,e)=>{let n=(await ii(e,{portfolio_uuid:t.portfolio_id,currency:t.currency})).data.breakdown??{},i=(n.futures_positions??[]).map(_=>({..._,side:oo(_.side,so,_o)})),s=(n.equity_positions??[]).map(_=>{let o={..._};for(let a of ao)a in o&&(o[a]=co(o[a]));return o});return{...n,futures_positions:i,equity_positions:s}},ci={portfolios_list:F($n),portfolios_get:Eo,portfolios_create:F(Wn,{responseUnwrap:"portfolio"}),portfolios_edit:F(Bn,{requestMap:{portfolio_id:"portfolio_uuid"},responseUnwrap:"portfolio"}),portfolios_delete:F(xn,{requestMap:{portfolio_id:"portfolio_uuid"}})}});var P,Ot=S(()=>{"use strict";u();d();P=class t extends Error{status;correlationId;traceId;code;constructor(e,r,n){super(e),this.status=r,this.correlationId=n?.correlationId,this.traceId=n?.traceId,this.code=n?.code}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,_;try{let a=JSON.parse(i);a.errorType&&a.errorMessage?s=`${a.errorType} \u2014 ${a.errorMessage}`:a.message?s=t.stripGrpcPrefix(a.message):s=i.length>200?i.slice(0,200)+"...":i,_=a.correlationId||a.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:_,traceId:o})}}});function ui(t){return String(t).replace(/^(NEW_ORDER_FAILURE_REASON_|PREVIEW_|EDIT_ORDER_FAILURE_REASON_)/,"").replace(/_/g," ").toLowerCase()}function mr(t){if(t?.success===!1){let e=t.error_response,r=t.errors?.[0]?.edit_failure_reason,n=e?.new_order_failure_reason??e?.preview_failure_reason??e?.error,i=n?ui(n):void 0;throw new P(e?.message||e?.error_details||i||(r?ui(r):void 0)||"Operation failed",400)}}var di=S(()=>{"use strict";u();d();Ot()});var yt,Ar,bt,Wt,gi=S(()=>{"use strict";u();d();yt={MARKET:"market",LIMIT:"limit",STOP_LIMIT:"stop_limit",BRACKET:"bracket",TWAP:"twap",SCALED:"scaled"},Ar={UP:"up",DOWN:"down"},bt={GTC:"GTC",IOC:"IOC",FOK:"FOK",GTD:"GTD"},Wt={NORMAL:"NORMAL",PRE_MARKET:"PRE_MARKET",AFTER_HOURS:"AFTER_HOURS",OVERNIGHT:"OVERNIGHT",MULTI_SESSION:"MULTI_SESSION"}});import{randomUUID as uo}from"node:crypto";function li(t){let e=t.type;if(e===yt.BRACKET||e===yt.TWAP||e===yt.SCALED)throw new P(`Order type "${e}" requires the Agent API.`,400,{code:"AGENT_API_REQUIRED"});if(e===yt.MARKET)return{market_market_ioc:{...t.quote_size&&{quote_size:t.quote_size},...t.base_size&&{base_size:t.base_size}}};if(e===yt.LIMIT){let r=t.time_in_force??bt.GTC,n={...t.quote_size&&{quote_size:t.quote_size},...t.base_size&&{base_size:t.base_size},limit_price:t.limit_price,...t.post_only&&{post_only:!0}};return r===bt.IOC?{sor_limit_ioc:n}:r===bt.FOK?{limit_limit_fok:n}:r===bt.GTD?{limit_limit_gtd:{...n,...t.end_time&&{end_time:t.end_time}}}:{limit_limit_gtc:n}}else if(e===yt.STOP_LIMIT){let r=t.stop_direction===Ar.UP?"STOP_DIRECTION_STOP_UP":t.stop_direction===Ar.DOWN?"STOP_DIRECTION_STOP_DOWN":(()=>{throw new P("stop_direction is required for stop_limit orders (up or down)",400)})(),n=t.time_in_force??bt.GTC,i={base_size:t.base_size,limit_price:t.limit_price,stop_price:t.stop_price,stop_direction:r};return n===bt.GTD?{stop_limit_stop_limit_gtd:{...i,...t.end_time&&{end_time:t.end_time}}}:{stop_limit_stop_limit_gtc:i}}throw new P(`Unknown order type: ${e}. Use market, limit, or stop_limit.`,400)}function Ii(t){if(!t.equity_trading_session&&!t.equity_order_date)return;let e={};if(t.equity_trading_session){let r=go[t.equity_trading_session];if(!r)throw new P(`Unknown equity_trading_session: ${t.equity_trading_session}`,400);e.equity_trading_session=r}if(t.equity_order_date){let r=t.equity_order_date.match(lo);if(!r)throw new P("equity_order_date must be YYYY-MM-DD",400);e.equity_order_date={year:Number(r[1]),month:Number(r[2]),day:Number(r[3])}}return e}function Io(t){let e={client_order_id:t.client_order_id??uo(),product_id:t.product_id,side:t.side,order_configuration:li(t)};t.portfolio_id&&(e.retail_portfolio_id=t.portfolio_id),t.reduce_only&&(e.reduce_only=!0);let r=Ii(t);return r&&(e.equity_order_metadata=r),e}function Nr(t,e){let r=e.filter(n=>Object.hasOwn(t,n));if(r.length>0)throw new P(`Field(s) ${r.join(", ")} require the Agent API.`,400,{code:"AGENT_API_REQUIRED"})}function mo(t){let e=new Set,r=new Set,n=0,i=!0;for(let s=0;s<t.length;s++){let _=t[s];if(_==='"'){let o=s;for(s++;s<t.length;s++)if(t[s]==="\\")s++;else if(t[s]==='"')break;if(n===1&&i){let a=JSON.parse(t.slice(o,s+1));e.has(a)&&r.add(a),e.add(a),i=!1}}else _==="{"||_==="["?n++:_==="}"||_==="]"?n--:_===","&&n===1&&(i=!0)}return[...r]}function Ti(t){if(!t||typeof t!="object"||Array.isArray(t))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});let e=t;if(e.errors!==void 0&&!Array.isArray(e.errors))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});let r=e.errors;if(r?.some(_=>!_||typeof _!="object"||Array.isArray(_)))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});if(r?.length){let _=r[0],o=_?.edit_failure_reason??_?.preview_failure_reason,a=typeof o=="string"&&/^[A-Z0-9_]+$/.test(o)&&!o.startsWith("UNKNOWN_")?o.slice(o.indexOf("FAILURE_REASON_")>=0?o.indexOf("FAILURE_REASON_")+15:0).replaceAll("_"," ").toLowerCase():"operation failed";throw new P(`Order edit preview rejected: ${a}`,400,{code:"UPSTREAM_REJECTION"})}for(let _ of["slippage","order_total","commission_total","quote_size","base_size","best_bid","best_ask","average_filled_price","order_margin_total"])if(e[_]!==void 0&&typeof e[_]!="string")throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});for(let _ of["commission_detail_total","pnl_configuration"])if(e[_]!==void 0&&(!e[_]||typeof e[_]!="object"||Array.isArray(e[_])))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});let n=e.commission_detail_total;for(let _ of["total_commission","gst_commission","withholding_commission","client_commission","venue_commission","regulatory_commission","clearing_commission"])if(n?.[_]!==void 0&&typeof n[_]!="string")throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});let s=e.pnl_configuration?.trigger_bracket_pnl;if(s!==void 0&&(!s||typeof s!="object"||Array.isArray(s)))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});for(let _ of["take_profit_pnl","stop_loss_pnl"])if(s&&s[_]!==void 0&&typeof s[_]!="string")throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"})}function Ri(t){if(!t||typeof t!="object"||Array.isArray(t))return{error:"ORDER_EDIT_PREVIEW_FAILED",message:"Order edit preview failed"};let e=t,r=s=>String(s).replace(/Bearer\s+\S+/gi,"Bearer [REDACTED]").replace(/-----BEGIN [^-]+-----[\s\S]*?-----END [^-]+-----/g,"[REDACTED PRIVATE KEY]").slice(0,500),n=s=>typeof s=="string"&&/^[A-Z][A-Z0-9_]*$/.test(s)?s:"ORDER_EDIT_PREVIEW_FAILED";if(typeof e.errorType=="string"&&typeof e.errorMessage=="string")return{errorType:n(e.errorType),errorMessage:r(e.errorMessage),...typeof e.correlationId=="string"?{correlationId:e.correlationId}:{}};let i=e.message??e.errorMessage??e.error_response?.message??e.error_response?.error_details??e.error_details??"Order edit preview failed";return{error:n(e.error??e.errorType),...typeof e.code=="number"?{code:e.code}:{},message:r(i),...typeof e.correlationId=="string"?{correlationId:e.correlationId}:{},...typeof e.correlation_id=="string"?{correlation_id:e.correlation_id}:{}}}var go,lo,pi,po,To,Ro,Oo,Ao,No,So,Oi,mi=S(()=>{"use strict";u();d();Dt();Ot();di();gi();wt();dt();go={[Wt.NORMAL]:"EQUITY_TRADING_SESSION_NORMAL",[Wt.PRE_MARKET]:"EQUITY_TRADING_SESSION_PRE_MARKET",[Wt.AFTER_HOURS]:"EQUITY_TRADING_SESSION_AFTER_HOURS",[Wt.OVERNIGHT]:"EQUITY_TRADING_SESSION_OVERNIGHT",[Wt.MULTI_SESSION]:"EQUITY_TRADING_SESSION_MULTI_SESSION"},lo=new RegExp("^(\\d{4})-(\\d{2})-(\\d{2})$");pi=["attached_take_profit_price","attached_stop_loss_price","start_time","num_orders","min_price","max_price","price_distribution","size_distribution"],po=["attached_take_profit_price","attached_stop_loss_price","cancel_attached_order"];To=async(t,e)=>{Nr(t,pi);let r=Io(t),n=await _i(e,r);return mr(n.data),n.data.success_response??n.data},Ro=async(t,e)=>{Nr(t,[...pi,"reduce_only"]);let r=Ii(t),n=await ai(e,{product_id:t.product_id,side:t.side,order_configuration:li(t),...t.portfolio_id&&{retail_portfolio_id:t.portfolio_id},...r&&{equity_order_metadata:r}}),i=n.data;if(i.errs?.length>0)throw new P(i.errs[0].replace(/^PREVIEW_/,"").replace(/_/g," ").toLowerCase(),400);return n.data},Oo=async(t,e)=>{if(Nr(t,po),!t.base_size&&!t.limit_price)throw new P("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 Jn(e,r);return mr(n.data),{order_id:t.order_id,status:"EDITED"}};Ao=({body:t,query:e,path:r,headers:n,rawBody:i,originalParams:s,structured:_})=>{let o=(T,N)=>{throw new P(N,400,{code:T})},a=["order_id","base_size","limit_price"];if(_){for(let T of["body","query","path","headers"]){let N=s[T];N!==void 0&&(!N||typeof N!="object"||Array.isArray(N))&&o(T==="body"?"INVALID_BODY":"INVALID_PARAMETERS",`${T} must be an object.`)}i!==null&&!(i instanceof Uint8Array)&&o("INVALID_BODY","Raw request body must be bytes containing a JSON object.")}let E={};if(i){let T=new TextDecoder().decode(i),N;try{N=JSON.parse(T)}catch{o("INVALID_BODY","Request body must be valid JSON.")}(!N||typeof N!="object"||Array.isArray(N))&&o("INVALID_BODY","Request body must be a JSON object."),E=N;let f=[...new Set([...mo(T),...Object.keys(E).filter(M=>Object.hasOwn(t,M))])];f.length>0&&o("AMBIGUOUS_FIELDS",`Field(s) supplied more than once: ${f.join(", ")}`)}if(_){let T=["body","query","path","headers","rawBody"],N=Object.keys(s).filter(v=>!T.includes(v)),f=N.filter(v=>!a.includes(v));f.length>0&&o("UNKNOWN_FIELDS",`Unknown field(s): ${f.join(", ")}`);let M=N.filter(v=>Object.hasOwn(t,v)||Object.hasOwn(E,v));M.length>0&&o("AMBIGUOUS_FIELDS",`Field(s) supplied more than once: ${M.join(", ")}`),N.length>0&&o("INVALID_PARAMETER_LOCATION",`Body field(s) cannot be supplied outside the body in structured input: ${N.join(", ")}`)}let g=Object.keys(n),c=g.filter(T=>!a.includes(T));c.length>0&&o("UNKNOWN_FIELDS",`Unknown header field(s): ${c.join(", ")}`),g.length>0&&o("INVALID_PARAMETER_LOCATION",`Body field(s) cannot be supplied as headers: ${g.join(", ")}`);let l={...r,...t,...E,...e};(l.order_id===void 0||l.order_id==="")&&o("MISSING_FIELDS","Missing required field(s): order_id");let p=Object.keys(_?l:s).filter(T=>!a.includes(T));p.length>0&&o("UNKNOWN_FIELDS",`Unknown field(s): ${p.join(", ")}`);let A=a.filter(T=>Object.hasOwn(e,T)||Object.hasOwn(r,T));A.length>0&&o("INVALID_PARAMETER_LOCATION",`Body field(s) cannot be supplied as query or path parameters: ${A.join(", ")}`),[l.base_size,l.limit_price].every(T=>T===void 0||T==="")&&o("MISSING_FIELDS","One of base_size, or limit_price is required.");for(let T of a){let N=l[T];if(N===void 0)continue;if(typeof N!="string"&&o("INVALID_VALUE",`Invalid value for ${T}. Expected a string.`),!(T==="order_id"?/^(?!00000000-0000-0000-0000-000000000000$)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/:/^(?=.*[1-9])[0-9]+(?:\.[0-9]+)?$/).test(N)){let M=T==="order_id"?"Open order canonical non-nil UUID to preview editing":`Positive decimal replacement ${T==="base_size"?"base size":"limit price"}; at least one replacement is required`;o("INVALID_VALUE",`Invalid value for ${T}: "${String(N).slice(0,80)}". ${M}.`)}}};No=async(t,e)=>{let r={order_id:t.order_id,size:t.base_size??"",price:t.limit_price??""};try{let n=await oi(e,r);return Ti(n.data),n.data}catch(n){if(n instanceof _t){let i=Ri(n.data),s=i.message??i.errorMessage??i.error??"Order edit preview failed";throw new P(String(s),n.status,{code:"UPSTREAM_REQUEST_FAILED"})}throw n}},So={status:"order_status",side:"order_side",start:"start_date",end:"end_date",portfolio_id:"retail_portfolio_id"},Oi={orders_list:F(zn,{requestMap:So}),orders_get:F(qn,{responseUnwrap:"order"}),orders_create:To,orders_preview:Ro,orders_edit_preview:Object.assign(No,{validateInput:Ao,validateResponse:Ti,sanitizeError:Ri}),orders_edit:Oo,orders_cancel:F(Vn),orders_close_position:F(Gn),orders_fills:F(Yn,{requestMap:{side:"order_side",start:"start_sequence_timestamp",end:"end_sequence_timestamp",portfolio_id:"retail_portfolio_id"}})}});function Ai(t){return String(Math.floor(new Date(t).getTime()/1e3))}var Co,Po,fo,Do,yo,bo,Ni,Si=S(()=>{"use strict";u();d();Dt();Ot();wt();dt();Co={"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"},Po={"1m":60,"5m":300,"15m":900,"30m":1800,"1h":3600,"2h":7200,"4h":14400,"6h":21600,"1d":86400},fo=60,Do=async(t,e)=>{let{symbol:r,limit:n,cursor:i,...s}=t;if(r){let o=r.toUpperCase(),g=((await Or(e,s)).data.products??[]).filter(l=>l.base_currency_id===o||l.quote_currency_id===o),c=n!==void 0&&n>0?g.slice(0,n):g;return{products:c,num_products:c.length}}return(await Or(e,{...s,limit:n,cursor:i})).data};yo=async(t,e)=>{if(!t.granularity)throw new P("granularity is required (expected execute() to apply its default)",500);let r=t.granularity,n=Co[r],i=Po[r],s=Math.floor(Date.now()/1e3),_=t.end?Ai(t.end):String(s),o=t.start?Ai(t.start):String(Number(_)-fo*i);return(await ri(e,{...t,granularity:n,start:o,end:_})).data},bo=async(t,e)=>{let r=t.limit??100;return(await ni(e,{...t,limit:r})).data},Ni={products_list:Do,products_get:F(jn),products_ticker:bo,products_book:F(Qn),products_candles:yo,products_best_bid_ask:F(Hn)}});var Lo,Ci,Pi=S(()=>{"use strict";u();d();Dt();wt();dt();Ot();Lo=async(t,e)=>{let{from:r,to:n,...i}=t,s=await Zn(e,{...i,from_account:r,to_account:n});if(!s.data?.trade?.id)throw new P(`Convert quote returned no trade for ${t.from} \u2192 ${t.to}. Verify balance, supported pair, and account eligibility.`,422);return s.data},Ci={convert_quote:Lo,convert_execute:F(wn,{requestMap:{quote_id:"trade_id",from:"from_account",to:"to_account"}}),convert_get:F(Kn,{requestMap:{quote_id:"trade_id",from:"from_account",to:"to_account"},responseUnwrap:"trade"})}});var ho,fi,Di=S(()=>{"use strict";u();d();dt();ho=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 ti(e,r)).data,s=i.accounts??[],_=t.show_zero?s:s.filter(o=>parseFloat(o.available_balance?.value??"0")!==0||parseFloat(o.hold?.value??"0")!==0);return{accounts:_,has_next:i.has_next,cursor:i.cursor,size:_.length}},fi={balance:ho}});var Uo,yi,bi=S(()=>{"use strict";u();d();Ot();dt();Uo=async(t,e)=>{let r={funds:{value:t.amount,currency:t.currency},source_portfolio_uuid:t.from,target_portfolio_uuid:t.to},i=(await si(e,r)).data;if(!i?.source_portfolio_uuid)throw new P("Transfer failed \u2014 check amount, currency, and portfolio UUIDs",400);return i},yi={transfer:Uo}});var Li,hi=S(()=>{"use strict";u();d();Dt();wt();Li={fees:F(Xn)}});var Ui,Mi=S(()=>{"use strict";u();d();Ui={x402_resources:{endpoint:{origin:"AgentAPI_X402Resources",method:"GET",path:"/x402/resources"}},x402_pay:{endpoint:{origin:"AgentAPI_X402Pay",method:"POST",path:"/x402/pay"}},x402_fetch:{endpoint:{origin:"AgentAPI_X402Fetch",method:"POST",path:"/x402/fetch"}}}});function vi(t){let e=t&&typeof t=="object"?t:{},r={};return typeof e.can_view=="boolean"&&(r.can_view=e.can_view),typeof e.can_trade=="boolean"&&(r.can_trade=e.can_trade),typeof e.can_transfer=="boolean"&&(r.can_transfer=e.can_transfer),typeof e.portfolio_uuid=="string"&&(r.portfolio_uuid=e.portfolio_uuid),(e.portfolio_type==="UNDEFINED"||e.portfolio_type==="DEFAULT"||e.portfolio_type==="CONSUMER"||e.portfolio_type==="INTX")&&(r.portfolio_type=e.portfolio_type),r}function ki(t){let e=t===401?"AUTHENTICATION_FAILED":t===403?"PERMISSION_INTROSPECTION_FORBIDDEN":"BROKERAGE_REQUEST_FAILED",r=t===401?"Authentication failed for the current API key. Coinbase Advanced Trade requires an ECDSA key; if this environment uses Ed25519, create an ECDSA key and update the environment credentials.":t===403?"The current API key is not authorized to inspect its permissions.":`Brokerage API permission introspection failed with HTTP ${t}.`;return new _t(r,t,{error:e,code:t,message:r})}var Sr,Fi,Vi=S(()=>{"use strict";u();d();dt();Sr=async(t,e)=>{try{let{data:r}=await ei(e,{});return vi(r)}catch(r){throw r instanceof _t?ki(r.status):r}};Sr.normalizeResponse=vi;Sr.errorResponse=t=>ki(t).data;Fi={api_key_permissions:Sr}});function Le(t){return Mo[t]}var Mo,Cr=S(()=>{"use strict";u();d();Ei();mi();Si();Pi();Di();bi();hi();Mi();Vi();Mo={...ci,...Oi,...Ni,...Ci,...fi,...yi,...Li,...Ui,...Fi}});function Pr(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 Gi(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 wi=S(()=>{"use strict";u();d()});function vo(t,e){let r={...e},n=t;for(let[i,s]of Object.entries(e)){if(s==null||s==="")continue;let _=`{${i}}`;n.includes(_)&&(n=n.replaceAll(_,encodeURIComponent(String(s))),delete r[i])}return{resolvedPath:n,remainingParams:r}}function ko(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 Vo(t,e){for(let[r,n]of Object.entries(e))for(let i of t){let s=i[r];if(s!=null){if(n==="join-comma"&&Array.isArray(s))i[r]=s.join(",");else if(n==="split-comma"){let _=Array.isArray(s)?s:[s];i[r]=_.flatMap(o=>String(o).split(",").map(a=>a.trim()).filter(Boolean))}}}}function Wi(t,e){return`${t.replace(/\/+$/,"")}${e}`}function Go(t){return t===408||t===429||t>=500}function wo(t){return t instanceof TypeError||t instanceof Error&&(t.name==="AbortError"||t.name==="TimeoutError")}function Wo(t,e){if(t&&typeof t=="object"&&!Array.isArray(t)){let r=typeof t.hint=="string"&&t.hint?`${t.hint} `:"";return{...t,hint:`${r}${fr}`}}return{error:"AGENT_API_REQUEST_FAILED",code:e,message:typeof t=="string"&&t?t:`Agent API request failed with HTTP ${e}.`,hint:fr}}function xi(t,e){return{status:400,data:{error:"REST_ENDPOINT_UNAVAILABLE",code:400,message:`${e} endpoint is not configured for environment "${t.envName}". Configure the endpoint for this environment before retrying.`}}}function xo(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 Bo(t){return t&&typeof t=="object"&&("body"in t||"query"in t||"path"in t||"rawBody"in t)}function se(t,e){if(t==null||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>se(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=>se(s,i)):i&&typeof t[n]=="object"&&t[n]!==null?r[n]=se(t[n],i):r[n]=t[n]}return r}function Ho(t,e){let r=Dr[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 xt(t,e,r){let n=Bo(e),i=n?e.body??{}:{},s=n?e.query??{}:{},_=n?e.path??{}:{},o=n?e.headers??{}:{},a=n?e.rawBody??null:null,E=!1,g=Le(t);if(!g)return{status:404,data:{error:"UNKNOWN_OPERATION",code:404,message:`No route for ${t}`}};let c=Bi.find(I=>I.id===t),l=be(g)?void 0:g;if(!n)for(let[I,R]of Object.entries(e)){let L=c?.params.find(H=>H.name===I),b=L?.in==="query"?s:L?.in==="path"?_:i;b[I]=R}if(c?.noInput&&([...Object.keys(i),...Object.keys(s),...Object.keys(_),...Object.keys(o)].length>0||(a?.length??0)>0))return{status:400,data:{error:"UNEXPECTED_FIELDS",code:400,message:`${t} does not accept input fields; it always inspects the current credential.`}};if(r.transport==="agent"&&!c?.agentApi)return{status:400,data:{error:"AGENT_API_ROUTE_UNAVAILABLE",code:400,message:`${t} is not available through the Agent API. Set COINBASE_TRANSPORT=brokerage to use direct brokerage.`}};let p=c?.agentApi?Rt(r.env,r.envName):"",A=c?.agentApi==="only"||r.transport==="agent"||c?.agentApi==="eligible"&&r.transport!=="brokerage"&&!!p;if(l?.validateInput)try{l.validateInput({body:i,query:s,path:_,headers:o,rawBody:a,originalParams:e,structured:n})}catch(I){if(!(I instanceof P))throw I;return{status:I.status,data:{error:I.code??"INVALID_VALUE",code:I.status,message:I.message}}}if(c?.params){if(a)try{let I=JSON.parse(new TextDecoder().decode(a));if(I&&typeof I=="object"&&!Array.isArray(I)){if(c.closedInput){let R=Object.keys(I).filter(L=>Object.hasOwn(i,L));if(R.length>0)return{status:400,data:{error:"AMBIGUOUS_FIELDS",code:400,message:`Field(s) supplied more than once: ${R.join(", ")}`}}}E=!0,Object.assign(i,I)}else if(c.closedInput)return{status:400,data:{error:"INVALID_BODY",code:400,message:"Request body must be a JSON object."}}}catch{if(c.closedInput)return{status:400,data:{error:"INVALID_BODY",code:400,message:"Request body must be valid JSON."}}}for(let I of c.params){if(I.default===void 0||I.required||_[I.name]!==void 0||i[I.name]!==void 0||s[I.name]!==void 0)continue;let R=I.in==="query"?s:I.in==="path"?_:i;R[I.name]=I.default}{let I=c.params.filter(b=>(b.in==="body"||!be(g)&&b.in==="path")&&b.required),R={..._,...i,...s},L=I.filter(b=>R[b.name]===void 0||R[b.name]==="");if(L.length>0)return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`Missing required field(s): ${L.map(H=>H.name).join(", ")}`}}}{let I={..._,...i,...s},R={},L={};for(let b of c.params)if(b.oneOf&&(L[b.oneOf]||(L[b.oneOf]=[]),L[b.oneOf].push(b.name),I[b.name]!==void 0&&I[b.name]!=="")){if(R[b.oneOf])return{status:400,data:{error:"CONFLICTING_FIELDS",code:400,message:`${R[b.oneOf]} and ${b.name} are mutually exclusive. Provide one, not both.`}};R[b.oneOf]=b.name}for(let[b,H]of Object.entries(L))if(!R[b])return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`One of ${H.join(", ")} is required.`}}}{let I={..._,...i,...s};if(c.closedInput){let R=new Set(c.params.map(H=>H.name)),L=Object.keys(I).filter(H=>!R.has(H));if(L.length>0)return{status:400,data:{error:"UNKNOWN_FIELDS",code:400,message:`Unknown field(s): ${L.join(", ")}`}};let b=c.params.filter(H=>H.in==="body"&&(Object.hasOwn(s,H.name)||Object.hasOwn(_,H.name))).map(H=>H.name);if(b.length>0)return{status:400,data:{error:"INVALID_PARAMETER_LOCATION",code:400,message:`Body field(s) cannot be supplied as query or path parameters: ${b.join(", ")}`}}}if(c.anyOf&&!c.anyOf.some(R=>R.every(L=>I[L]!==void 0&&I[L]!=="")))return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`One of ${c.anyOf.map(L=>L.join(" and ")).join(", or ")} is required.`}}}for(let I of c.params)for(let R of[i,s,_]){if(R[I.name]===void 0)continue;if(c.closedInput&&I.type==="string"&&typeof R[I.name]!="string")return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}. Expected a string.`}};if(I.type==="array"&&typeof R[I.name]=="string"?R[I.name]=R[I.name].split(",").map(Et=>Et.trim()).filter(Boolean):I.type==="string"&&Array.isArray(R[I.name])&&(R[I.name]=R[I.name].join(",")),I.type==="boolean"){if(typeof R[I.name]!="boolean"&&(typeof R[I.name]!="string"||R[I.name]!=="true"&&R[I.name]!=="false"))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${R[I.name]}". Expected "true" or "false".`}};typeof R[I.name]=="string"&&(R[I.name]=R[I.name]==="true")}else if((I.type==="integer"||I.type==="number")&&typeof R[I.name]=="string"){let Et=Number(R[I.name]);if(!Number.isFinite(Et))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${R[I.name]}". Expected a number.`}};R[I.name]=Et}if(I.enum&&!I.enum.includes(String(R[I.name])))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${R[I.name]}". Expected one of: ${I.enum.join(", ")}`}};let L=I.pattern?Hi.get(I.pattern):void 0,b=I.format?kn[I.format]:void 0,H=L??b;if(H&&typeof R[I.name]=="string"){let Et=R[I.name],an=I.format?Fn[I.format]:void 0;if(!(H.test(Et)&&(!L||!b||b.test(Et))&&(!an||an(Et)))){let cn=(I.description??"").split(/\.\s/)[0].replace(/\.?\s*$/,""),h_=cn?`. ${cn}.`:".";return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${String(Et).slice(0,80)}"${h_}`}}}}}}if(!A&&!r.baseURL)return xi(r,"Brokerage API");let T=Fo[t];if(!A&&T&&Vo([i,s,_],T),!A&&!be(g)){let I={...i,...s,..._};try{let R=await g(I,r),L=Dr[t];return L&&(R=se(R,L)),{status:200,data:R}}catch(R){if(R instanceof _t)return{status:R.status,data:R.data};let L=R instanceof P?R.status:500,b=P.stripGrpcPrefix(R instanceof Error?R.message:String(R));return{status:L,data:{error:R instanceof P&&R.code?R.code:"HANDLER_ERROR",code:L,message:b}}}}let N=g,f=A?{origin:"AgentAPI",method:c.method,path:c.path}:N.endpoint,M=A?void 0:N.requestMap,v=A?void 0:N.responseMap,Q=A?void 0:N.responseUnwrap,y={...i,..._},h=Pr(y,M),{resolvedPath:x,remainingParams:$}=vo(f.path,h);if(x.includes("{"))return{status:400,data:{error:"MISSING_PATH_PARAMS",code:400,message:`Missing required param(s): ${(x.match(/\{([^}]+)\}/g)?.map(R=>R.slice(1,-1))??[]).join(", ")}`}};let at=f.method==="POST"||f.method==="PUT"||f.method==="DELETE"||f.method==="PATCH",ct,ht=a??null,U={...A?s:Pr(s,M)},D=A?p:f.baseURL??r.baseURL;if(!D)return xi(r,A?"Agent API":"Brokerage API");at?(ct=Wi(D,x),a&&E&&(Object.keys(_).length>0||c?.closedInput||l?.validateInput)?ht=new TextEncoder().encode(JSON.stringify($)):!ht&&Object.keys($).length>0&&(ht=new TextEncoder().encode(JSON.stringify($)))):(Object.assign(U,$),ct=Wi(D,x));let V=ko(U);V&&(ct+=V);let B;try{B=await r.doRequest({method:f.method,url:ct,body:ht,headers:Object.keys(o).length>0?o:void 0})}catch(I){if(!A||c?.agentApi!=="eligible"||!wo(I))throw I;let R=I instanceof Error?I.message:String(I);throw new Error(`${R}
|
|
48
|
-
|
|
43
|
+
[Runtime.InteropServices.Marshal]::FreeHGlobal($blob)`,kt(n))}delete(e,r){try{gr(`[void][Win32.Cred]::CredDelete('${be(lr(e,r))}', 1, 0)`)}catch{}}}});function ne(){if(It!==void 0)return It;try{process.platform==="darwin"?It=new fe:process.platform==="linux"?It=new De:process.platform==="win32"?It=new Le:It=null}catch{Mn||(process.stderr.write(`warning: OS keychain not accessible \u2014 secrets stored in keychain will not be available
|
|
44
|
+
`),Mn=!0),It=null}return It}function kn(t){let e=ne();if(!e)return null;try{return e.get(bt,t)}catch{return null}}function Fn(t,e){let r=ne();if(!r)return!1;try{return r.set(bt,t,e),!0}catch{return!1}}function Vn(t){let e=ne();if(e)try{e.delete(bt,t)}catch{}}function Gn(){return ne()!==null}function wn(){let t=ne();if(!t)return!1;let e="__coinbase_cli_preflight__";try{t.set(bt,e,"ok");let r=t.get(bt,e);return t.delete(bt,e),r==="ok"}catch{try{t.delete(bt,e)}catch{}return!1}}var bt,It,Mn,pr=C(()=>{"use strict";E();l();Ln();hn();vn();bt="coinbase-cli",Mn=!1});var $n={};Mt($n,{activeEnvName:()=>xt,activeEnvironment:()=>oe,authIsViable:()=>mr,builtinEnvironments:()=>st,clearEnvCredentialCache:()=>Nr,clearEnvironmentSecretsFromKeychain:()=>Or,clearHistory:()=>_e,configDir:()=>Rt,configPath:()=>at,credentialsFor:()=>se,envCredential:()=>ie,getHistory:()=>Pr,historyEnabled:()=>ve,hydrateEnvironmentSecrets:()=>Yn,isBuiltinURL:()=>Ue,loadConfig:()=>rt,resolveAgentAPIURLForEnvironment:()=>Tt,resolveBrokerageURL:()=>ot,resolveURL:()=>T_,saveConfig:()=>Et,scrubbedEnv:()=>Sr,setHistory:()=>Cr,setLockOptions:()=>A_,withConfigLock:()=>Ar,writeEnvironmentSecretsToKeychain:()=>zn});import{readFileSync as Bn,writeFileSync as Hn,mkdirSync as Kn,renameSync as g_,unlinkSync as Ir,openSync as p_,closeSync as I_,statSync as R_}from"node:fs";import{homedir as xn}from"node:os";import{join as he}from"node:path";function Rt(){if(process.env.COINBASE_CONFIG_DIR)return process.env.COINBASE_CONFIG_DIR;if(process.platform==="win32"){let t=process.env.APPDATA??he(xn(),"AppData","Roaming");return he(t,"coinbase")}return he(xn(),".config","coinbase")}function at(){return he(Rt(),"config.json")}function qn(t){if(st[t])return st[t];let e=Wn[t];if(e&&st[e])return st[e];let r={...st};for(let[i,s]of Object.entries(Wn))st[s]&&(r[i]=st[s]);let n=Object.keys(r).find(i=>t.startsWith(i+"-"));return n?r[n]:void 0}function ot(t,e){return t.endpoints?.brokerageApi??t.url??qn(e)?.brokerageApi??""}function T_(t,e){return ot(t,e)}function Tt(t,e){return t.endpoints?.agentApi??qn(e)?.agentApi??""}function Ue(t){return Object.values(st).some(e=>e.brokerageApi&&t.startsWith(e.brokerageApi))}function m_(t,e){return Object.values(wt[e].secrets).map(r=>r(t))}function mr(t){if(!t)return!1;let e=wt[t.type];return e?Object.keys(e.secrets).every(r=>!!t[r]):!1}function Yn(t,e){if(!e.auth)return e;let r=wt[e.auth.type];if(!r)return e;let n=e.auth,i={...n},s=!1,o=!1;for(let[_,a]of Object.entries(r.secrets)){if(n[_]){o=!0;continue}let u=kn(a(t));u&&(i[_]=u,s=!0)}return mr(i)?{...e,auth:i,...o&&!s?{_plaintextBacked:!0}:{}}:{...e,auth:void 0}}function zn(t,e){if(!e.auth)return!0;if(!Gn())return!1;let r=e.auth.type,n=wt[r];if(!n)return!0;if(!mr(e.auth)){let s=Object.keys(n.secrets).filter(o=>!e.auth[o]);throw new Error(`writeEnvironmentSecretsToKeychain: ${r} for "${t}" missing ${s.join(", ")}`)}let i=!0;for(let[s,o]of Object.entries(n.secrets))Fn(o(t),e.auth[s])||(i=!1);return i}function Or(t){for(let e of Object.keys(wt))for(let r of m_(t,e))Vn(r)}function ie(t){return t.auth}function se(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 rt(){let t={env:"",environments:{},history:{}};try{let e=Bn(at(),"utf8"),r=JSON.parse(e);t.env=r.env??"";let n=r.environments??{};for(let[i,s]of Object.entries(n))t.environments[i]=Yn(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 Et(t,e={}){let r=Rt();Kn(r,{recursive:!0,mode:448});let n={},i=[];for(let[a,u]of Object.entries(t.environments)){let d={};if(u.url!==void 0&&(d.url=u.url),u.endpoints!==void 0&&(d.endpoints={...u.endpoints}),!u.auth){n[a]=d;continue}let c=zn(a,u),g=e.allowPlaintext===!0||u._plaintextBacked===!0;if(!c){if(!g){i.push(a);continue}d.auth=u.auth,n[a]=d;continue}let p=wt[u.auth.type];p&&(d.auth=p.metadataOnly(u.auth)),n[a]=d}if(i.length)throw new Error(`OS keychain unavailable; refusing to persist secrets for environment(s): ${i.join(", ")}.
|
|
45
|
+
Re-run the env-setup command with --allow-plaintext-secrets to write secrets to ${at()} (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 o=at(),_=`${o}.${process.pid}.${Date.now()}.tmp`;try{Hn(_,JSON.stringify(s,null,2)+`
|
|
46
|
+
`,{mode:384}),g_(_,o)}catch(a){try{Ir(_)}catch{}throw a}}function A_(t){Vt={...Vt,...t}}function Gt(){return at()+O_}function N_(t){let e=Date.now()+t;for(;Date.now()<e;);}function S_(){try{let t=p_(Gt(),"wx",384);return Hn(t,String(process.pid)),t}catch(t){if(t.code!=="EEXIST")throw t;return null}}function C_(){try{let t=R_(Gt());if(Date.now()-t.mtimeMs<Vt.staleAfterMs)return!1;let e=Bn(Gt(),"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 Ar(t){Kn(Rt(),{recursive:!0,mode:448});let e=null;for(let r=0;r<Vt.retries&&(e=S_(),e===null);r++){if(C_()){try{Ir(Gt())}catch{}continue}N_(Vt.baseDelayMs*(1+Math.random()))}if(e===null)throw new Error(`could not acquire config lock after ${Vt.retries} attempts: ${Gt()}`);try{return t()}finally{try{I_(e)}catch{}try{Ir(Gt())}catch{}}}function Nr(){Rr=void 0,Tr=void 0}function P_(){return process.env.COINBASE_KEY_ID&&(Rr=process.env.COINBASE_KEY_ID,delete process.env.COINBASE_KEY_ID),process.env.COINBASE_KEY_SECRET&&(Tr=process.env.COINBASE_KEY_SECRET,delete process.env.COINBASE_KEY_SECRET),{keyId:Rr,keySecret:Tr}}function xt(t,e){return e||process.env.COINBASE_ENV||t.env}function oe(t,e){let r=xt(t,e);if(!r)throw new Error("no environment configured. Run: coinbase env <name>");let n={...t.environments[r]},{keyId:i,keySecret:s}=P_();if(i||s){let a=n.auth?.type==="cdp_key"?n.auth:void 0,u=i??a?.key_id??"",d=s??a?.key_secret??"";u&&d&&(n.auth={type:"cdp_key",key_id:u,key_secret:d})}if(process.env.COINBASE_URL){let a=process.env.COINBASE_URL;n.endpoints={...n.endpoints,brokerageApi:a},n.url=a,Ue(a)||process.stderr.write(`warning: COINBASE_URL overrides to non-standard endpoint: ${a}
|
|
47
|
+
`)}let o=ot(n,r),_=Tt(n,r);if(!o&&!_)throw new Error(`no REST endpoint for environment "${r}". Set a brokerage URL, an Agent API URL, or use a built-in environment 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 Sr(){let t={...process.env};for(let e of f_)delete t[e];return t}function ve(t){return process.env.COINBASE_NO_HISTORY?!1:t.settings?.history?.enabled!==!1}function Cr(t,e,r,n){t.history[e]||(t.history[e]={}),t.history[e][r]={last_used:new Date().toISOString(),values:n}}function Pr(t,e,r){return t.history[e]?.[r]}function _e(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 st,Wn,wt,O_,Vt,Rr,Tr,f_,_t=C(()=>{"use strict";E();l();Ne();pr();st=Dn,Wn=bn;wt={cdp_key:{secrets:{key_secret:t=>`${t}:cdp:key_secret`},metadataOnly:t=>({type:"cdp_key",key_id:t.key_id})}};O_=".lock",Vt={retries:50,baseDelayMs:20,staleAfterMs:5e3};f_=["COINBASE_KEY_SECRET","COINBASE_KEY_ID"]});function Qn(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,Q,Xn,Zn,Jn,mt=C(()=>{"use strict";E();l();j=[{name:"api-key",actions:[{id:"api_key_permissions",name:"permissions",method:"GET",path:"/api-key/permissions",summary:"Get Current API Key Permissions",description:"Returns the authoritative permissions and portfolio association for the API key used to authenticate this request. It accepts no key or customer identifier and always inspects the current credential.",pathParams:[],params:[],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["can_view","can_trade","can_transfer","portfolio_uuid","portfolio_type"]},annotations:{readOnlyHint:!0},agentApi:"eligible",noInput:!0,history:"disabled"}]},{name:"convert",actions:[{id:"convert_quote",name:"quote",method:"POST",path:"/convert/quote",summary:"Get Convert Quote",description:"Quotes USD\u2194USDC conversions only, returning rate, fees, and a quote ID. For other currency pairs, use an order instead. Pass the ID to convert_execute promptly because quotes expire.",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,watch: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"]}}},annotations:{readOnlyHint:!1,destructiveHint:!1},agentApi:"eligible"},{id:"convert_execute",name:"execute",method:"POST",path:"/convert/execute/{quote_id}",summary:"Execute Convert Trade",description:"Executes a previously quoted USD\u2194USDC conversion using the quote_id from convert_quote. This moves funds at the quoted rate \u2014 get a fresh quote first since quotes expire. The from/to currencies must match the original quote; use orders for other pairs.",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,watch:null,template:{from:"USDC",to:"USD"},responseFields:{fields:["trade"],nested:{trade:{fields:["id","status"]}}},annotations:{destructiveHint:!0},agentApi:"eligible"},{id:"convert_get",name:"get",method:"GET",path:"/convert/get/{quote_id}",summary:"Get Convert Status",description:"Check status of a USD\u2194USDC conversion by quote ID. For other pairs, use orders instead.",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,watch:null,template:{},responseFields:{fields:["id","status","source_currency","target_currency","exchange_rate"]},annotations:{readOnlyHint:!0},agentApi:"eligible"}]},{name:"derivatives",actions:[{id:"derivatives_updates",name:"updates",method:"GET",path:"/derivatives/updates",summary:"Subscribe to Global Derivatives snapshots",description:"Stream live GLOBAL_PERP prices or order books as Server-Sent Events. Ticker and book require product_id and product-read access. Reconnect with a fresh token after expiry.",pathParams:[],params:[{name:"product_type",in:"query",type:"string",required:!0,description:"",enum:["GLOBAL_PERP"]},{name:"channel",in:"query",type:"string",required:!0,description:"",enum:["ticker","book"]},{name:"product_id",in:"query",type:"string",required:!1,description:""},{name:"portfolio_id",in:"query",type:"string",required:!1,description:"",format:"uuid"}],streamable:!1,eventStream:!0,watchFields:null,watch:null,template:{},responseFields:null,annotations:{readOnlyHint:!0,destructiveHint:!1},agentApi:"only"}]},{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. Use status=OPEN to find resting orders that can be edited or cancelled. For EQUITY orders, product_id is TICKER-QUOTE (e.g. AAPL-USD), the same form orders_create expects. Does not list recurring-buys scheduled; an empty result does not mean there are no active recurring buys. GLOBAL_PERP pages traverse active, recent and archived sources which may repeat an order; reconcile by order_id. Deduplication is limited to individual pages and adjacent continuation boundaries within a source. Follow each cursor until absent, including after empty pages. Do not assume global chronological ordering across products.",pathParams:[],params:[{name:"portfolio_id",in:"query",type:"string",required:!1,description:"Scope to a specific portfolio (defaults to all portfolios the caller can access for other asset classes). For GLOBAL_PERP, use your authorized Global Derivatives portfolio UUID or omit to select it automatically. Requires portfolio-read permission."},{name:"status",in:"query",type:"string",required:!1,description:"Filter by a single status, case-insensitive. One of PENDING, OPEN, FILLED, CANCELLED, EXPIRED, FAILED, QUEUED, CANCEL_QUEUED, EDIT_QUEUED. Omit to list every 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"],example:"BUY"},{name:"product_type",in:"query",type:"string",required:!1,description:"Filter by product type. Required as GLOBAL_PERP for international perpetual orders; optional for other asset classes. For GLOBAL_PERP, OPEN and PENDING list active orders, FILLED/CANCELLED/FAILED/TRIGGERED list history, and omitted status lists active orders followed by history. TRIGGERED means a trigger activated, not that its resulting order filled. Results page by currency, then by source and continuation. GLOBAL_PERP limit is 1 to 100.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{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:"string",format:"decimal",description:"Average filled price"},filled_size:{type:"string",format:"decimal",description:"Filled quantity"},fees:{type:"string",format:"decimal",description:"Total fees"},product_id:{type:"string",description:"Trading pair"},order_id:{type:"string",description:"Order ID"}},watch:{channel:"user",endpoint:"user",requiresAuth:!0,coalesce:!1},template:{},responseFields:{fields:["orders","has_next","cursor"],nested:{orders:{fields:["order_id","product_id","side","status","order_configuration","reduce_only","trigger_reference","triggered_order_id","attached_order_id","attached_order_configuration","created_time","last_fill_time","completion_percentage","filled_size","average_filled_price","total_fees","total_value_after_fees","number_of_fills"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"orders_create",name:"create",method:"POST",path:"/orders",summary:"Create Order",description:`Place a market, limit, stop_limit, bracket, twap, or scaled order, subject to venue eligibility. For spot crypto, only top assets listed on the Coinbase Exchange order book are tradable here; assets available only via Coinbase's DEX (onchain-routed) are not supported, even if quotes or public product metadata appear to work. If an order is rejected as "not supported for trading on this domain", tell the user the asset can't be traded through this MCP; do not retry with USD/USDC or other aliases. Equities: use market or limit. Before an equity order, check current US Eastern time and the trading calendar, and choose equity_trading_session explicitly; do not default to NORMAL when regular trading is closed. Ask before changing the user's requested order type, size, or trading session. Spot brackets require SELL; for entry, use market/limit BUY with attached exits. Futures brackets support BUY/SELL. Bracket stops become aggressive limit exits; fills and loss limits are not guaranteed. TWAP requires base_size, start_time, end_time, and a positive limit_price; slice count is automatic. Use orders_preview for optional fee, fill, and execution-plan estimates. Set exactly one size: limit and market SELL convert quote_size to base_size; market BUY spends quote_size; stop_limit/bracket/twap/scaled require base_size. Attached exits require market/limit parents and activate as the parent fills, including partial fills. If a FUTURE order is rejected for account eligibility, direct the\u2026`,pathParams:[],params:[{name:"product_id",in:"body",type:"string",required:!0,description:`Trading pair (BASE-QUOTE, e.g. BTC-USD or BTC-USDC) for spot crypto, a dated-futures contract code for CFM. For equities, use TICKER-USD (e.g. AAPL-USD); USDC is not supported for equities. For spot crypto, if the user names a quote currency (e.g. "use my USDC"), use that pair \u2014 never default to USD instead. If they don't say, check the balance for this request's portfolio_id (or the default portfolio if omitted) and use whichever of USD/USDC they hold there; if both, prefer the USDC pair. If the resulting pair doesn't exist, tell the user rather than silently substituting a different one.`,example:"BTC-USDC"},{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: current price. limit: specified price or better. stop_limit: stop triggers a limit order. bracket: take-profit limit and stop-triggered aggressive limit exit; fills and loss limits are not guaranteed; spot SELL or eligible futures BUY/SELL. twap: split base_size over start_time/end_time with a positive limit_price and automatic slice count; requires GTD. scaled: 2 to 20 limit child orders between positive min_price/max_price. Equities: use market/limit. GLOBAL_PERP: market, limit and stop_limit only; always use positive plain-decimal base_size in contracts (at most 128 characters), nev",enum:["market","limit","stop_limit","bracket","twap","scaled"],example:"market"},{name:"quote_size",in:"body",type:"string",required:!1,description:"Quote-currency amount (e.g. $100 USD). Mutually exclusive with base_size. Market BUYs spend this amount; limit and market SELL convert it to base_size. For CFM futures limit and market SELL, this is dollar notional: contracts = quote_size / (underlying price \xD7 contract_size), rounded down to base_increment. Not supported for stop_limit, bracket, twap, or scaled \u2014 use base_size for those. Max 15,000 USD notional.",oneOf:"base_size|quote_size",example:"100.00"},{name:"base_size",in:"body",type:"string",required:!1,description:"Base amount for spot, number of contracts for derivatives (CFM and GLOBAL_PERP). Mutually exclusive with quote_size. Required for stop_limit, bracket, twap, scaled and every GLOBAL_PERP order. Max 15,000 USD notional applies to spot, US futures and equities.",oneOf:"base_size|quote_size",example:"0.001"},{name:"product_type",in:"body",type:"string",required:!1,description:"Required as GLOBAL_PERP for international perpetuals. Use the product_id returned by discovery unchanged. Supported types are market, limit and stop_limit; linked exits, bracket, twap, scaled, GTD, scheduling and equity fields are rejected. Sizes/prices must be positive plain decimals of at most 128 characters. Trading validates current instruments, state, minimums and increments; discovery is not a trading guarantee. stop_limit requires trigger_reference and stop_direction=up for BUY or down for SELL; opposite-direction take-profit triggers are unsupported. post_only=true requires limit and G",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"trigger_reference",in:"body",type:"string",required:!1,description:"GLOBAL_PERP stop_limit trigger price source. Required for stop_limit, rejected for other order types and asset classes.",enum:["INDEX","MARK","LAST"]},{name:"limit_price",in:"body",type:"string",required:!1,description:"Required limit price for limit/stop_limit/bracket/twap. Bracket take-profit and TWAP execution price ceiling/floor must be strictly positive decimals.",example:"65000.00"},{name:"stop_price",in:"body",type:"string",required:!1,description:"Stop trigger for stop_limit. For bracket, required positive decimal: above limit_price for futures BUY, below for SELL. Bracket stops become aggressive limit exits; no guaranteed fill or loss cap.",example:"60000.00"},{name:"stop_direction",in:"body",type:"string",required:!1,description:"stop_limit only. Bracket direction is implied by side.",enum:["up","down"],example:"down"},{name:"post_only",in:"body",type:"boolean",required:!1,description:"Post-only limit order: rejects if it would take liquidity. true is rejected for non-limit types."},{name:"time_in_force",in:"body",type:"string",required:!1,description:"GTC=good til cancelled for crypto. IOC=immediate or cancel. FOK=fill or kill. GTD=good til date; requires end_time. Crypto stop_limit, bracket, and scaled support GTC/GTD. twap requires GTD. Equities only support market (IOC or omitted time_in_force) and limit (GTC or omitted time_in_force) orders, with no end_time. Equity limits are good for day. Extended-hours equities require whole-share base-sized limit orders; the selected session determines expiry.",enum:["GTC","IOC","FOK","GTD"],example:"GTC"},{name:"end_time",in:"body",type:"string",required:!1,description:"Expiry or execution end time (RFC 3339). Required for GTD and twap. The TWAP schedule may be adjusted.",format:"date-time",example:"2024-12-31T23:59:59Z"},{name:"reduce_only",in:"body",type:"boolean",required:!1,description:"Restrict the order to reducing existing exposure. Supported for INTX perpetuals; US dated futures, spot, and equities may reject it. Not supported for scaled."},{name:"attached_take_profit_price",in:"body",type:"string",required:!1,description:"Positive decimal take-profit limit exit, activated as a market/limit parent fills (including partial fills). May combine with attached_stop_loss_price. Spot: BUY parent only. Futures: BUY/SELL subject to venue eligibility. Not equities. No guaranteed fill.",example:"70000.00"},{name:"attached_stop_loss_price",in:"body",type:"string",required:!1,description:"Positive decimal stop trigger, activated as a market/limit parent fills (including partial fills). Becomes an aggressive limit exit, not a guaranteed fill or loss cap. May combine with attached_take_profit_price. Spot: BUY parent only. Futures: BUY/SELL subject to venue eligibility. Not equities.",example:"58000.00"},{name:"start_time",in:"body",type:"string",required:!1,description:"Requested execution start (RFC 3339). Required for twap. Slice count is automatic.",format:"date-time",example:"2024-12-31T14:00:00Z"},{name:"num_orders",in:"body",type:"integer",required:!1,description:"Number of limit child orders, from 2 to 20. Required for scaled.",example:5},{name:"min_price",in:"body",type:"string",required:!1,description:"Lowest child limit price. Required for scaled. Must be positive and below max_price.",example:"58000.00"},{name:"max_price",in:"body",type:"string",required:!1,description:"Highest child limit price. Required for scaled. Must be positive and above min_price.",example:"62000.00"},{name:"price_distribution",in:"body",type:"string",required:!1,description:"Scaled price spacing. Defaults to FLAT (evenly spaced prices).",enum:["FLAT","LINEAR_INCREASING","LINEAR_DECREASING"],example:"FLAT"},{name:"size_distribution",in:"body",type:"string",required:!1,description:"Scaled size distribution. Defaults to an even split across child orders.",enum:["INCREASING","DECREASING","EVENLY_SPLIT"],example:"EVENLY_SPLIT"},{name:"portfolio_id",in:"body",type:"string",required:!1,description:"Portfolio UUID for this asset class; omit to use its default portfolio. GLOBAL_PERP requires portfolio-read permission and authorization for your Global Derivatives portfolio."},{name:"client_order_id",in:"body",type:"string",required:!1,description:"Idempotency key for spot, US futures and equities (auto-generated if omitted). Unsupported for global perpetuals; do not supply it. Never automatically retry an unknown global-perpetual write outcome; check order state and fills first."},{name:"equity_trading_session",in:"body",type:"string",required:!1,description:"Equity trading session; ignored for crypto and futures. Defaults to NORMAL (regular trading), not the active session. MULTI_SESSION spans pre-market, regular, and after-hours, excluding overnight. All non-NORMAL sessions require whole-share limit orders.",enum:["NORMAL","PRE_MARKET","AFTER_HOURS","OVERNIGHT","MULTI_SESSION"]},{name:"equity_order_date",in:"body",type:"string",required:!1,description:"Optional equity trade date (YYYY-MM-DD); brokerage populates it when omitted. Ignored for crypto and futures.",format:"date"}],streamable:!1,watchFields:null,watch:null,template:{product_id:"BTC-USDC",side:"BUY",type:"market",quote_size:"100.00",base_size:"0.001",product_type:"SPOT",trigger_reference:"INDEX",limit_price:"65000.00",stop_price:"60000.00",stop_direction:"down",post_only:!1,time_in_force:"GTC",end_time:"2024-12-31T23:59:59Z",reduce_only:!1,attached_take_profit_price:"70000.00",attached_stop_loss_price:"58000.00",start_time:"2024-12-31T14:00:00Z",num_orders:5,min_price:"58000.00",max_price:"62000.00",price_distribution:"FLAT",size_distribution:"EVENLY_SPLIT",portfolio_id:"<string>",client_order_id:"<string>",equity_trading_session:"NORMAL",equity_order_date:"<string>"},responseFields:{fields:["order_id","product_id","side","client_order_id","status","created_time","filled_size","average_filled_price","total_fees","number_of_fills","reduce_only","trigger_reference"]},annotations:{destructiveHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"orders_preview",name:"preview",method:"POST",path:"/orders/preview",summary:"Preview Order",description:"Estimate fees, fill price, slippage, and execution plans without placing an order. Optional before orders_create; DEX-only (onchain-routed) assets are not supported, and equity and GLOBAL_PERP previews are not available. Stop-limit previews validate the stop relative to the current last trade and estimate execution using the current order book and limit price, not a hypothetical market after the stop triggers. A sell preview may show the current bid even when the stop is below the current market. These estimates do not guarantee a fill or fill price after the stop triggers. US domestic (CFM) futures previews also estimate margin, leverage, and liquidation impact: compare current and projected margin ratios and liquidation buffers. For CFM futures, the returned quote_size is contract count \xD7 underlying price, not dollar notional; multiply by the product's contract_size for notional. Response values are returned unchanged. If a FUTURE preview is rejected for account eligibility, direct the user to https://help.coinbase.com/en/coinbase/trading-and-funding/derivatives/futures-intro to apply.",pathParams:[],params:[{name:"product_id",in:"body",type:"string",required:!0,description:`Trading pair (BASE-QUOTE, e.g. BTC-USD or BTC-USDC) for spot crypto, a dated-futures contract code for CFM. For equities, use TICKER-USD (e.g. AAPL-USD); USDC is not supported for equities. For spot crypto, if the user names a quote currency (e.g. "use my USDC"), use that pair \u2014 never default to USD instead. If they don't say, check the balance for this request's portfolio_id (or the default portfolio if omitted) and use whichever of USD/USDC they hold there; if both, prefer the USDC pair. If the resulting pair doesn't exist, tell the user rather than silently substituting a different one.`,example:"BTC-USDC"},{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: current price. limit: specified price or better. stop_limit: stop triggers a limit order. bracket: take-profit limit and stop-triggered aggressive limit exit; fills and loss limits are not guaranteed; spot SELL or eligible futures BUY/SELL. twap: split base_size over start_time/end_time with a positive limit_price and automatic slice count; requires GTD. scaled: 2 to 20 limit child orders between positive min_price/max_price. Equities: use market/limit. GLOBAL_PERP: market, limit and stop_limit only; always use positive plain-decimal base_size in contracts (at most 128 characters), nev",enum:["market","limit","stop_limit","bracket","twap","scaled"],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. For CFM futures limit and market SELL, this is dollar notional: contracts = quote_size / (underlying price \xD7 contract_size), rounded down to base_increment. Not supported for stop_limit, bracket, twap, or scaled \u2014 use base_size for those.",oneOf:"base_size|quote_size",example:"100.00"},{name:"base_size",in:"body",type:"string",required:!1,description:"Base amount for spot, number of contracts for US domestic (CFM) futures. Mutually exclusive with quote_size. Required for stop_limit, bracket, twap and scaled. GLOBAL_PERP previews are not available.",oneOf:"base_size|quote_size",example:"0.001"},{name:"product_type",in:"body",type:"string",required:!1,description:"Global perpetual and equity previews are unavailable.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Required limit price for limit/stop_limit/bracket/twap. Bracket take-profit and TWAP execution price ceiling/floor must be strictly positive decimals.",example:"65000.00"},{name:"stop_price",in:"body",type:"string",required:!1,description:"Stop trigger for stop_limit. For bracket, required positive decimal: above limit_price for futures BUY, below for SELL. Bracket stops become aggressive limit exits; no guaranteed fill or loss cap.",example:"60000.00"},{name:"stop_direction",in:"body",type:"string",required:!1,description:"stop_limit only. Bracket direction is implied by side.",enum:["up","down"],example:"down"},{name:"post_only",in:"body",type:"boolean",required:!1,description:"Post-only limit order: rejects if it would take liquidity. true is rejected for non-limit types."},{name:"time_in_force",in:"body",type:"string",required:!1,description:"GTC=good til cancelled for crypto. IOC=immediate or cancel. FOK=fill or kill. GTD=good til date; requires end_time. Crypto stop_limit, bracket, and scaled support GTC/GTD. twap requires GTD. Equities only support market (IOC or omitted time_in_force) and limit (GTC or omitted time_in_force) orders, with no end_time. Equity limits are good for day. Extended-hours equities require whole-share base-sized limit orders; the selected session determines expiry.",enum:["GTC","IOC","FOK","GTD"],example:"GTC"},{name:"end_time",in:"body",type:"string",required:!1,description:"Expiry or execution end time (RFC 3339). Required for GTD and twap. The TWAP schedule may be adjusted.",format:"date-time",example:"2024-12-31T23:59:59Z"},{name:"reduce_only",in:"body",type:"boolean",required:!1,description:"Restrict the order to reducing existing exposure. Supported for INTX perpetuals; US dated futures, spot, and equities may reject it. Not supported for scaled."},{name:"attached_take_profit_price",in:"body",type:"string",required:!1,description:"Positive decimal take-profit limit exit, activated as a market/limit parent fills (including partial fills). May combine with attached_stop_loss_price. Spot: BUY parent only. Futures: BUY/SELL subject to venue eligibility. Not equities. No guaranteed fill.",example:"70000.00"},{name:"attached_stop_loss_price",in:"body",type:"string",required:!1,description:"Positive decimal stop trigger, activated as a market/limit parent fills (including partial fills). Becomes an aggressive limit exit, not a guaranteed fill or loss cap. May combine with attached_take_profit_price. Spot: BUY parent only. Futures: BUY/SELL subject to venue eligibility. Not equities.",example:"58000.00"},{name:"start_time",in:"body",type:"string",required:!1,description:"Requested execution start (RFC 3339). Required for twap. Slice count is automatic.",format:"date-time",example:"2024-12-31T14:00:00Z"},{name:"num_orders",in:"body",type:"integer",required:!1,description:"Number of limit child orders, from 2 to 20. Required for scaled.",example:5},{name:"min_price",in:"body",type:"string",required:!1,description:"Lowest child limit price. Required for scaled. Must be positive and below max_price.",example:"58000.00"},{name:"max_price",in:"body",type:"string",required:!1,description:"Highest child limit price. Required for scaled. Must be positive and above min_price.",example:"62000.00"},{name:"price_distribution",in:"body",type:"string",required:!1,description:"Scaled price spacing. Defaults to FLAT (evenly spaced prices).",enum:["FLAT","LINEAR_INCREASING","LINEAR_DECREASING"],example:"FLAT"},{name:"size_distribution",in:"body",type:"string",required:!1,description:"Scaled size distribution. Defaults to an even split across child orders.",enum:["INCREASING","DECREASING","EVENLY_SPLIT"],example:"EVENLY_SPLIT"},{name:"portfolio_id",in:"body",type:"string",required:!1,description:"The optional UUID of a portfolio containing accounts with which to trade. Defaults to the default portfolio when no portfolio_id is provided."},{name:"equity_trading_session",in:"body",type:"string",required:!1,description:"Equity trading session; ignored for crypto and futures. Defaults to NORMAL (regular trading), not the active session. MULTI_SESSION spans pre-market, regular, and after-hours, excluding overnight. All non-NORMAL sessions require whole-share limit orders.",enum:["NORMAL","PRE_MARKET","AFTER_HOURS","OVERNIGHT","MULTI_SESSION"]},{name:"equity_order_date",in:"body",type:"string",required:!1,description:"Optional equity trade date (YYYY-MM-DD); brokerage populates it when omitted. Ignored for crypto and futures.",format:"date"}],streamable:!1,watchFields:null,watch:null,template:{product_id:"BTC-USDC",side:"BUY",type:"market",quote_size:"100.00",base_size:"0.001",product_type:"SPOT",limit_price:"65000.00",stop_price:"60000.00",stop_direction:"down",post_only:!1,time_in_force:"GTC",end_time:"2024-12-31T23:59:59Z",reduce_only:!1,attached_take_profit_price:"70000.00",attached_stop_loss_price:"58000.00",start_time:"2024-12-31T14:00:00Z",num_orders:5,min_price:"58000.00",max_price:"62000.00",price_distribution:"FLAT",size_distribution:"EVENLY_SPLIT",portfolio_id:"<string>",equity_trading_session:"NORMAL",equity_order_date:"<string>"},responseFields:{fields:["order_total","commission_total","slippage","est_average_filled_price","warning","twap_bucket_metadata","scaled_metadata","base_size","quote_size","best_bid","best_ask","leverage","long_leverage","short_leverage","max_leverage","position_notional_limit","available_buying_power","order_margin_total","current_liquidation_buffer","projected_liquidation_buffer","predicted_liquidation_price","margin_ratio_data"],nested:{twap_bucket_metadata:{fields:["bucket_duration","bucket_size","number_buckets","start_time","end_time"]},scaled_metadata:{fields:["scaled_order_distribution"],nested:{scaled_order_distribution:{fields:["size","price","errs","warning"]}}},margin_ratio_data:{fields:["current_margin_ratio","projected_margin_ratio"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"orders_edit",name:"edit",method:"POST",path:"/orders/{order_id}/edit",summary:"Edit Order",description:"Atomically update an open order's price or size without cancelling. Omit attached fields to keep existing exits. Attach or change exits only on eligible unfilled limit orders: spot BUY or futures BUY/SELL, not equities. Exits activate as the parent fills, including partial fills. Stops become aggressive limit exits; fills and loss limits are not guaranteed. Attached updates replace both legs: send attached_take_profit_price and attached_stop_loss_price to keep both, even when changing one. Read orders_get first: attached_order_configuration.trigger_bracket_gtc.limit_price maps to attached_take_profit_price; stop_trigger_price maps to attached_stop_loss_price. cancel_attached_order removes both legs, but may be rejected after an exit activates.",pathParams:["order_id"],params:[{name:"order_id",in:"path",type:"string",required:!0,description:"Order to edit"},{name:"product_type",in:"body",type:"string",required:!1,description:"Required as GLOBAL_PERP for international perpetual order IDs. Edits support independent limit and stop_limit orders only, with positive decimal base_size (contracts) and/or limit_price of at most 128 characters. Linked orders and attached-exit edits, including cancel_attached_order=false, are rejected. Existing post-only/reduce-only behavior is preserved; post-only price changes reject rather than slide the requested price. No automatic retry after an unknown outcome.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"global_portfolio_id",in:"body",type:"string",required:!1,description:"For GLOBAL_PERP, use your authorized Global Derivatives portfolio UUID or omit to select it automatically. Requires portfolio-read permission. Ignored for other asset classes.",format:"uuid"},{name:"base_size",in:"body",type:"string",required:!1,description:"New base size. GLOBAL_PERP uses total positive decimal contracts including already-filled contracts (at most 128 characters), not remaining quantity. Omitting size preserves the existing total when editing price. Supports independent limit/stop_limit orders only; linked-order and attached-exit edits are rejected. Never automatically retry an unknown write outcome.",example:"0.002"},{name:"limit_price",in:"body",type:"string",required:!1,description:"New limit price",example:"64000.00"},{name:"attached_take_profit_price",in:"body",type:"string",required:!1,description:"Positive take-profit limit price for an eligible unfilled limit order. Send both attached prices to keep both legs. Spot BUY or eligible futures BUY/SELL; not equities.",example:"70000.00"},{name:"attached_stop_loss_price",in:"body",type:"string",required:!1,description:"Positive stop trigger for an eligible unfilled limit order. Send both attached prices to keep both legs. Triggers an aggressive limit exit; fills and loss limits are not guaranteed. Spot BUY or eligible futures BUY/SELL; not equities.",example:"58000.00"},{name:"cancel_attached_order",in:"body",type:"boolean",required:!1,description:"Remove both attached exit legs while keeping the parent order. Cannot be combined with attached_take_profit_price or attached_stop_loss_price. May be rejected after an exit activates."}],streamable:!1,watchFields:null,watch:null,template:{product_type:"SPOT",global_portfolio_id:"<string>",base_size:"0.002",limit_price:"64000.00",attached_take_profit_price:"70000.00",attached_stop_loss_price:"58000.00",cancel_attached_order:!1},responseFields:{fields:["order_id","status"]},annotations:{destructiveHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"orders_edit_preview",name:"edit-preview",method:"POST",path:"/orders/edit-preview",summary:"Preview Order Edit",description:"Estimate the result, fees, fill price, and slippage of changing an open brokerage order's size or limit price without editing it. GLOBAL_PERP edit previews are not available; do not reformat venue order IDs as UUIDs. Hosted OAuth requires mcp:orders:create. CDP API-key callers may use rat#view where supported. Unsupported replacements return errors.",pathParams:[],params:[{name:"order_id",in:"body",type:"string",required:!0,description:"Canonical open brokerage order UUID to preview editing. GLOBAL_PERP venue order IDs are not supported; do not reformat them as UUIDs."},{name:"base_size",in:"body",type:"string",required:!1,description:"Positive decimal replacement base size",example:"0.002"},{name:"limit_price",in:"body",type:"string",required:!1,description:"Positive decimal replacement limit price",example:"64000.00"}],streamable:!1,watchFields:null,watch:null,template:{order_id:"<string>",base_size:"0.002",limit_price:"64000.00"},responseFields:{fields:["slippage","order_total","commission_total","quote_size","base_size","best_bid","best_ask","average_filled_price","order_margin_total","commission_detail_total","pnl_configuration"],nested:{commission_detail_total:{fields:["total_commission","gst_commission","withholding_commission","client_commission","venue_commission","regulatory_commission","clearing_commission"]},pnl_configuration:{fields:["trigger_bracket_pnl"],nested:{trigger_bracket_pnl:{fields:["take_profit_pnl","stop_loss_pnl"]}}}}},anyOf:[["base_size"],["limit_price"]],annotations:{readOnlyHint:!0,destructiveHint:!1},agentApi:"eligible"},{id:"orders_get",name:"get",method:"GET",path:"/orders/{order_id}",summary:"Get Order",description:"Retrieves the status and available fill details of a single order by ID. Use after creating an order to confirm execution, and before orders_edit to see the current attached take-profit/stop-loss (attached_order_id / attached_order_configuration). For EQUITY orders, product_id is TICKER-QUOTE (e.g. AAPL-USD), the same form orders_create expects. For GLOBAL_PERP stop orders, triggered does not mean filled; query triggered_order_id separately for execution status and fills when returned. Do not repeat a placement or cancellation solely because a lookup failed.",pathParams:["order_id"],params:[{name:"order_id",in:"path",type:"string",required:!0,description:"Order ID returned by orders_create or orders_list."},{name:"product_type",in:"query",type:"string",required:!1,description:"Required as GLOBAL_PERP for international perpetual orders; optional for other asset classes.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"portfolio_id",in:"query",type:"string",required:!1,description:"For GLOBAL_PERP, use your authorized Global Derivatives portfolio UUID or omit to select it automatically. Requires portfolio-read permission."},{name:"product_id",in:"query",type:"string",required:!1,description:"GLOBAL_PERP product ID from orders_create or orders_list, e.g. BTC-PERPETUAL. Supply it if the order cannot be found by ID alone. Must match the order's product. Unsupported for other product types.",pattern:"^[^\\s,]{1,128}$"}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["order_id","product_id","side","status","order_configuration","reduce_only","trigger_reference","triggered_order_id","attached_order_id","attached_order_configuration","created_time","last_fill_time","completion_percentage","filled_size","average_filled_price","total_fees","total_value_after_fees","number_of_fills"]},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{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:"product_type",in:"body",type:"string",required:!1,description:"Required as GLOBAL_PERP for every international perpetual order ID in this batch; never inferred from an ID. 1\u2013100 nonempty distinct IDs, with at most 4 calls in flight; per-order failures do not prevent other cancellations. No automatic replay after an unknown outcome.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"global_portfolio_id",in:"body",type:"string",required:!1,description:"For GLOBAL_PERP, use your authorized Global Derivatives portfolio UUID or omit to select it automatically. Requires portfolio-read permission. Ignored for other asset classes.",format:"uuid"},{name:"order_ids",in:"body",type:"array",required:!0,description:"Order IDs to cancel. GLOBAL_PERP requires 1\u2013100 distinct nonempty IDs and at most four concurrent per-ID sequences. Each result is independent; success=false can include an unknown outcome. Reconcile before any new explicit intent; never automatically replay failed IDs."}],streamable:!1,watchFields:null,watch:null,template:{product_type:"SPOT",global_portfolio_id:"<string>",order_ids:[]},responseFields:{fields:["results"],nested:{results:{fields:["success","order_id"]}}},annotations:{destructiveHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{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:!1,description:"Idempotency key for spot, US futures and equities (required). Unsupported for global perpetuals; do not supply it. Never automatically retry an unknown global-perpetual write outcome; check order state and fills first."},{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. GLOBAL_PERP uses positive decimal contracts of at most 128 characters, rejects a size exceeding the current position, and always sends an opposite-side reduce-only order.",example:"0.001"},{name:"product_type",in:"body",type:"string",required:!1,description:"Required as GLOBAL_PERP for international perpetuals. Omit size for a full market close. A positive decimal size is contracts, capped to the current position and submitted as a reduce-only opposite-side market order. Submissions are not deduplicated. Do not resubmit an uncertain partial close: repeating the same size can close additional contracts. Reconcile order state and fills before a new intent.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"global_portfolio_id",in:"body",type:"string",required:!1,description:"For GLOBAL_PERP, use your authorized Global Derivatives portfolio UUID or omit to select it automatically. Requires portfolio-read permission. Ignored for other asset classes.",format:"uuid"}],streamable:!1,watchFields:null,watch:null,template:{client_order_id:"<string>",product_id:"BTC-PERP",size:"0.001",product_type:"SPOT",global_portfolio_id:"<string>"},responseFields:{fields:["success","order_id","product_id"]},annotations:{destructiveHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"orders_fills",name:"fills",method:"GET",path:"/orders/fills",summary:"List Fills",description:"Lists individual trade executions with commissions and maker/taker indicator, filterable by product, order, side, and time range. Use this to reconcile actual fill prices and fees paid. Select portfolio and time range; follow cursor pagination for available history. Report coverage as fills and fees; full performance also requires cost basis, realized P&L, US futures funding/settlements, and cash-flow history. Treat missing values as unknown. Check size_in_quote on each fill before summing size: quote-sized orders (e.g. a dollar-amount buy) report fill size in quote currency, others in base units, shares, or contracts. For EQUITY fills, product_id is TICKER-QUOTE (e.g. AAPL-USD), the same form orders_create expects. GLOBAL_PERP recent and archived sources may repeat a fill; deduplicate by (product_id, trade_id) before aggregating quantities or fees. Within-source page and timestamp-boundary duplicates are suppressed. Follow each cursor until absent, including after empty pages. Do not assume global chronological ordering across products.",pathParams:[],params:[{name:"product_type",in:"query",type:"string",required:!1,description:"Required as GLOBAL_PERP for international perpetual fills; optional for other asset classes. Use the returned product and order IDs. GLOBAL_PERP limit is 1 to 100; at most 100 product or order filters. Pages follow currency or filter order rather than global time order.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"portfolio_id",in:"query",type:"string",required:!1,description:"Scope to a specific portfolio (defaults to all portfolios the caller can access for other asset classes). For GLOBAL_PERP, use your authorized Global Derivatives portfolio UUID or omit to select it automatically. Requires portfolio-read permission."},{name:"product_ids",in:"query",type:"string",required:!1,description:"Filter by product (e.g. BTC-USD)"},{name:"order_ids",in:"query",type:"array",required:!1,description:"Filter by order ID"},{name:"side",in:"query",type:"string",required:!1,description:"Filter by side",enum:["BUY","SELL"],example:"BUY"},{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:"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,watch:null,template:{},responseFields:{fields:["fills","cursor"],nested:{fills:{fields:["trade_id","order_id","trade_time","price","size","size_in_quote","commission","commission_currency","product_id","side","liquidity_indicator"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}}]},{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. Use this to find the portfolio_id needed for orders, transfers, and balance queries. Only if the user asks where to view their portfolios or how to create one themselves, tell them to go to https://www.coinbase.com/advanced-portfolio/spot (Portfolio > Spot), then open the All Portfolios dropdown above the balance; otherwise don't mention it.",pathParams:[],params:[{name:"portfolio_type",in:"query",type:"string",required:!1,description:"Filter by type (DEFAULT, CONSUMER)",enum:["DEFAULT","CONSUMER","INTX"]}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["portfolios"],nested:{portfolios:{fields:["uuid","name","type","deleted"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{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. Only if the user asks where to view their portfolios or how to create one themselves, tell them to go to https://www.coinbase.com/advanced-portfolio/spot (Portfolio > Spot), then open the All Portfolios dropdown above the balance; otherwise don't mention it.",pathParams:[],params:[{name:"name",in:"body",type:"string",required:!0,description:"Portfolio name",example:"agent-1"}],streamable:!1,watchFields:null,watch:null,template:{name:"agent-1"},responseFields:{fields:["uuid","name","type","deleted"]},annotations:{destructiveHint:!1},agentApi:"eligible"},{id:"portfolios_get",name:"get",method:"GET",path:"/portfolios/{portfolio_id}",summary:"Get Portfolio Breakdown",description:"Returns portfolio metadata, total balances, and positions, including staked assets. Use this for portfolio value or total holdings rather than coinbase_balance, which only returns trading-account balances. Staked and liquid holdings can appear separately; sum total_balance_crypto by asset across verified non-overlapping accounts. Keep account_uuid and account_type; show USD rows separately when overlap is unknown. Use portfolio_balances for portfolio totals, since these include their positions. account_type identifies staking positions as ACCOUNT_TYPE_STAKED_FUNDS. Holdings are not necessarily available to trade: use available_to_trade_crypto or available_to_trade_fiat for indicative tradable amounts, and never substitute total holdings when those fields are absent. Spot quantities are approximate; before sizing a spot order, confirm exact available_balance with coinbase_balance for the same portfolio. Eligible callers receive GLOBAL_PERP futures_positions and derivatives_summary only on the corresponding INTX / Global Derivatives portfolio, never DEFAULT. Access to GLOBAL_PERP holdings requires portfolio-read permission and authorization for this Global Derivatives portfolio. For example, list portfolios, select the authorized INTX portfolio UUID, then call portfolios_get with that UUID before sizing a GLOBAL_PERP order on the same portfolio. Derivative sizing uses derivatives_summary.by_currency[].available_collateral, never wallet balance. The collateral summary requires\u2026",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,watch:null,template:{},responseFields:{fields:["portfolio","portfolio_balances","spot_positions","futures_positions","equity_positions","derivatives_summary"],nested:{portfolio:{fields:["uuid","name","type","deleted"]},portfolio_balances:{fields:["total_balance","total_crypto_balance","total_cash_equivalent_balance","total_equities_balance"],nested:{total_balance:{fields:["value","currency"]},total_crypto_balance:{fields:["value","currency"]},total_cash_equivalent_balance:{fields:["value","currency"]},total_equities_balance:{fields:["value","currency"]}}},spot_positions:{fields:["asset","account_uuid","account_type","total_balance_fiat","total_balance_crypto","available_to_trade_fiat","available_to_trade_crypto","allocation","is_cash"]},futures_positions:{fields:["product_id","product_type","contract_size","side","amount","avg_entry_price","current_price","unrealized_pnl","expiry","underlying_asset","product_name","venue","notional_value","leverage","initial_margin","maintenance_margin","settlement_currency"]},equity_positions:{fields:["asset","account_uuid","total_balance_fiat","total_balance_equity","available_to_trade_equity","available_to_trade_fiat","account_type","allocation","cost_basis","average_entry_price","unrealized_pnl"]},derivatives_summary:{fields:["by_currency","equity_usd","initial_margin_usd","maintenance_margin_usd"],nested:{by_currency:{fields:["currency","equity","available_collateral","margin_balance","initial_margin","maintenance_margin","unrealized_pnl"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},{id:"portfolios_edit",name:"edit",method:"PUT",path:"/portfolios/{portfolio_id}",summary:"Edit Portfolio",description:"Renames an existing portfolio. 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,watch:null,template:{name:"<string>"},responseFields:{fields:["uuid","name","type","deleted"]},annotations:{destructiveHint:!1},agentApi:"eligible"},{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,watch:null,template:{},responseFields:null,annotations:{destructiveHint:!0},agentApi:"eligible"}]},{name:"products",actions:[{id:"products_list",name:"list",method:"GET",path:"/products",summary:"List Products",description:"Viewing products, including FUTURE ones, doesn't require any special account approval. Trading them is a separate matter \u2014 see the product_type field description.",pathParams:[],params:[{name:"product_type",in:"query",type:"string",required:!1,description:"Product type filter. GLOBAL_PERP selects international perpetual futures; FUTURE selects US domestic (CFM) futures. Contract expiry is described separately by the product's contract_expiry_type.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"underlying_type",in:"query",type:"string",required:!1,description:"Filter by the asset class of the product's underlying (matches Product.underlying_type). Supported only with product_type=GLOBAL_PERP; rejected otherwise. Products with no underlying_type are excluded when set.",enum:["CRYPTO","EQUITY","COMMODITY","INDEX"]},{name:"product_ids",in:"query",type:"string",required:!1,description:"Comma-separated product IDs. For international perpetuals, use the IDs returned by products_list unchanged (e.g. BTC-PERPETUAL, BTC_USDC-PERPETUAL) and set product_type=GLOBAL_PERP."},{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 products_get (e.g. BTC-USD). Pagination ignored when set.",pattern:"^[A-Za-z0-9]+$"},{name:"limit",in:"query",type:"integer",required:!1,description:"Results per page. For product_type=GLOBAL_PERP it must be 1 to 1000 and defaults to 100; other product types keep their existing bounds."},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor from a previous response. Opaque; pass it back unchanged with the same filters. GLOBAL_PERP results are ordered by product_id."}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["products","cursor","has_next","num_products"],nested:{products:{fields:["product_id","price","price_percentage_change_24h","volume_24h","product_type","underlying_type","open_interest","perp_product_details","valuation","quote_currency_id","base_currency_id","base_increment","quote_increment","base_min_size","base_max_size","quote_min_size","quote_max_size","status","future_product_details","fcm_trading_session_details"],nested:{perp_product_details:{fields:["contract_size","settlement_currency","max_leverage","price_index","state"]},valuation:{fields:["mark_price","index_price","funding_rate","funding_rate_8h","open_interest","market_cap"]},future_product_details:{fields:["contract_expiry_type","contract_size","contract_expiry","time_to_expiry_ms","open_interest","funding_rate","funding_interval","funding_time","intraday_margin_rate","overnight_margin_rate"],nested:{intraday_margin_rate:{fields:["long_margin_rate","short_margin_rate"]},overnight_margin_rate:{fields:["long_margin_rate","short_margin_rate"]}}},fcm_trading_session_details:{fields:["is_session_open","open_time","close_time","session_state"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"],underlying_type:["CRYPTO","EQUITY","COMMODITY","INDEX"]}},{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. Omit product_ids to return pricebooks for all products. Not currently available for equities.",pathParams:[],params:[{name:"product_ids",in:"query",type:"array",required:!1,description:"Product IDs (e.g. BTC-USD and ETH-USD). Omit to return all products. For international perpetuals, use the IDs returned by products_list unchanged (e.g. BTC-PERPETUAL, BTC_USDC-PERPETUAL) and set product_type=GLOBAL_PERP."},{name:"product_type",in:"query",type:"string",required:!1,description:"Product type of every product_ids entry. For international perpetuals, set GLOBAL_PERP and use the product IDs returned by products_list unchanged. Optional for other product types.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["pricebooks"],nested:{pricebooks:{fields:["product_id","bids","asks","time"],nested:{bids:{fields:["price","size"]},asks:{fields:["price","size"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"products_get",name:"get",method:"GET",path:"/products/{product_id}",summary:"Get Product",description:"Viewing a product, including a FUTURE one, doesn't require any special account approval. Trading it is a separate matter \u2014 see the product_type field description.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID (e.g. BTC-USD). For international perpetuals, use the product_id returned by products_list unchanged (e.g. BTC-PERPETUAL, BTC_USDC-PERPETUAL) and set product_type=GLOBAL_PERP."},{name:"product_type",in:"query",type:"string",required:!1,description:"Product type of product_id. For international perpetuals, set GLOBAL_PERP and use the product_id returned by products_list unchanged. Optional for other product types.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"},{name:"include_valuation",in:"query",type:"boolean",required:!1,description:"When true, include the valuation block (mark/index price, funding, open interest) where available. Defaults to false; when false, valuation is omitted."}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["product_id","price","price_percentage_change_24h","volume_24h","product_type","underlying_type","open_interest","perp_product_details","valuation","quote_currency_id","base_currency_id","base_increment","quote_increment","base_min_size","base_max_size","quote_min_size","quote_max_size","status","future_product_details","fcm_trading_session_details"],nested:{perp_product_details:{fields:["contract_size","settlement_currency","max_leverage","price_index","state"]},valuation:{fields:["mark_price","index_price","funding_rate","funding_rate_8h","open_interest","market_cap"]},future_product_details:{fields:["contract_expiry_type","contract_size","contract_expiry","time_to_expiry_ms","open_interest","funding_rate","funding_interval","funding_time","intraday_margin_rate","overnight_margin_rate"],nested:{intraday_margin_rate:{fields:["long_margin_rate","short_margin_rate"]},overnight_margin_rate:{fields:["long_margin_rate","short_margin_rate"]}}},fcm_trading_session_details:{fields:["is_session_open","open_time","close_time","session_state"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"products_ticker",name:"ticker",method:"GET",path:"/products/{product_id}/ticker",summary:"Get Ticker",description:"Returns recent trade prints plus the current best bid/ask for a product. Use for a quick spot-price snapshot before previewing or placing an order. Not currently available for equities.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID (e.g. BTC-USD). For international perpetuals, use the product_id returned by products_list unchanged (e.g. BTC-PERPETUAL, BTC_USDC-PERPETUAL) and set product_type=GLOBAL_PERP."},{name:"limit",in:"query",type:"integer",required:!1,description:"Number of trades. Defaults to 100. For GLOBAL_PERP products it must be 1 to 1000; other product types keep their existing bounds."},{name:"product_type",in:"query",type:"string",required:!1,description:"Product type of product_id. For international perpetuals, set GLOBAL_PERP and use the product_id returned by products_list unchanged. Optional for other product types.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"}],streamable:!0,watchFields:{price:{type:"string",format:"decimal",description:"Last trade price"},bid:{type:"string",format:"decimal",description:"Best bid"},ask:{type:"string",format:"decimal",description:"Best ask"},bid_size:{type:"string",format:"decimal",description:"Size at best bid"},ask_size:{type:"string",format:"decimal",description:"Size at best ask"},volume:{type:"string",format:"decimal",description:"24h volume"},high:{type:"string",format:"decimal",description:"24h high"},low:{type:"string",format:"decimal",description:"24h low"},pct_24h:{type:"string",format:"decimal",description:"24h price change %"},product_id:{type:"string",description:"Trading pair"}},watch:{channel:"ticker",endpoint:"public",requiresAuth:!1,coalesce:!0},template:{},responseFields:{fields:["trades","best_bid","best_ask"],nested:{trades:{fields:["trade_id","product_id","price","size","time","side"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"products_book",name:"book",method:"GET",path:"/products/{product_id}/book",summary:"Get Order Book",description:"Returns the current bid/ask order book for a product. Use to gauge available liquidity and likely slippage before sizing a market order. Not currently available for equities.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID (e.g. BTC-USD). For international perpetuals, use the product_id returned by products_list unchanged (e.g. BTC-PERPETUAL, BTC_USDC-PERPETUAL) and set product_type=GLOBAL_PERP."},{name:"limit",in:"query",type:"integer",required:!1,description:"Number of levels. For GLOBAL_PERP products it must be 1 to 10000 and defaults to 50; other product types keep their existing bounds."},{name:"product_type",in:"query",type:"string",required:!1,description:"Product type of product_id. For international perpetuals, set GLOBAL_PERP and use the product_id returned by products_list unchanged. Optional for other product types.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"}],streamable:!0,watchFields:{spread:{type:"string",format:"decimal",description:"Bid-ask spread"},mid:{type:"string",format:"decimal",description:"Midpoint price"},product_id:{type:"string",description:"Trading pair"}},watch:{channel:"level2",wireName:"l2_data",endpoint:"public",requiresAuth:!1,coalesce:!0},template:{},responseFields:{fields:["pricebook"],nested:{pricebook:{fields:["product_id","bids","asks","time"],nested:{bids:{fields:["price","size"]},asks:{fields:["price","size"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{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. Use for price history and technical analysis. Not currently available for equities.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"Product ID (e.g. BTC-USD). For international perpetuals, use the product_id returned by products_list unchanged (e.g. BTC-PERPETUAL, BTC_USDC-PERPETUAL) and set product_type=GLOBAL_PERP."},{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. GLOBAL_PERP products do not support 4h; a 4h request for a GLOBAL_PERP product is rejected.",enum:["1m","5m","15m","30m","1h","2h","4h","6h","1d"],default:"1h"},{name:"limit",in:"query",type:"integer",required:!1,description:"Max candles. For GLOBAL_PERP products it must be 1 to 350; other product types keep their existing bounds."},{name:"product_type",in:"query",type:"string",required:!1,description:"Product type of product_id. For international perpetuals, set GLOBAL_PERP and use the product_id returned by products_list unchanged. Optional for other product types.",enum:["SPOT","GLOBAL_PERP","FUTURE","EQUITY"],example:"SPOT"}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["candles","truncated"],nested:{candles:{fields:["start","low","high","open","close","volume"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}},{id:"products_funding_history",name:"funding",method:"GET",path:"/products/{product_id}/funding",summary:"Get Funding Rate History",description:"Returns market-wide historical funding rates for a perpetual (GLOBAL_PERP) product with timestamps in the inclusive range [start_time, end_time], at millisecond precision. These are rates, not the user's funding payments. When the response includes cursor, call again with the same product_id, product_type, start_time, and end_time plus that cursor to get the next page; no cursor means the range is complete.",pathParams:["product_id"],params:[{name:"product_id",in:"path",type:"string",required:!0,description:"International perpetual product ID returned by products_list (e.g. BTC-PERPETUAL, BTC_USDC-PERPETUAL). Pass it unchanged."},{name:"product_type",in:"query",type:"string",required:!0,description:"Select GLOBAL_PERP for international perpetual funding history.",enum:["GLOBAL_PERP"]},{name:"start_time",in:"query",type:"string",required:!0,description:"Start of the range, inclusive (RFC 3339 with at most millisecond precision, e.g. 2024-01-01T00:00:00Z). Must be at or after the Unix epoch and at or before end_time.",pattern:"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?(Z|[+-]\\d{2}:\\d{2})$",format:"date-time"},{name:"end_time",in:"query",type:"string",required:!0,description:"End of the range, inclusive (RFC 3339 with at most millisecond precision, e.g. 2024-01-02T00:00:00Z). Must be at or after the Unix epoch and at or after start_time.",pattern:"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?(Z|[+-]\\d{2}:\\d{2})$",format:"date-time"},{name:"cursor",in:"query",type:"string",required:!1,description:"Pagination cursor from a previous response. It is bound to the original product_id, start_time, and end_time; a cursor used with different values is rejected."},{name:"limit",in:"query",type:"integer",required:!1,description:"Funding rates per page, 1 to 100. Defaults to 25.",default:25}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["funding_rates","cursor"],nested:{funding_rates:{fields:["timestamp","funding_rate_1h","funding_rate_8h","index_price"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible",agentApiOnlyWhen:{product_type:["GLOBAL_PERP"]}}]},{name:"x402",actions:[{id:"x402_resources",name:"resources",method:"GET",path:"/x402/resources",summary:"Discover x402 Resources",description:`Discover curated x402 resources: paid on-chain and market metrics, wallet and entity intelligence, and derivatives data. Discovery spends nothing. An optional keyword q filters the catalog; omit it to list all. Each result carries the resource URL, its advisory price, and its input and output schemas. All currently supported x402 purchases through this connector use Base USDC. accepts[].amount and coinbase_x402_fetch's max_amount use USDC's 6-decimal atomic units; for example, "50000" means "0.05 USDC". A result's inputSchema is coinbase_x402_fetch's input verbatim: pass those properties flat; do not build an HTTP envelope. The live 402 challenge sets the exact amount.`,pathParams:[],params:[{name:"q",in:"query",type:"string",required:!1,description:"Optional keyword filter. Matched against each resource's description, provider name, and tags using case-insensitive token search. Omit to return the full catalog."}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["resources"],nested:{resources:{fields:["resource","description","accepts","inputSchema","outputSchema"],nested:{accepts:{fields:["amount"]}}}}},annotations:{readOnlyHint:!0},agentApi:"only"},{id:"x402_pay",name:"pay",method:"POST",path:"/x402/pay",summary:"Pay an x402 Payment Requirement",description:`Turns an x402 PaymentRequirements challenge into a ready-to-send payment header by placing a pre-authorized hold on the caller's Base USDC balance (EIP-3009 exact scheme, v0). All currently supported x402 purchases through this connector use Base USDC, and amount and max_amount use its 6-decimal atomic units; for example, "50000" means "0.05 USDC". Attach the returned header as X-PAYMENT for v1 or PAYMENT-SIGNATURE for v2. This authorizes moving funds up to max_amount \u2014 pass the smallest amount that satisfies the requirement. Funds-touching and gated internal-only behind a default-off feature flag.`,pathParams:[],params:[{name:"scheme",in:"body",type:"string",required:!0,description:'x402 payment scheme. Only "exact" is supported in v0.'},{name:"network",in:"body",type:"string",required:!0,description:'x402 network as a CAIP-2 chain id. Only "eip155:8453" (Base mainnet) is supported in v0.'},{name:"asset",in:"body",type:"string",required:!0,description:"USDC asset contract address on the network (the x402 asset field)."},{name:"pay_to",in:"body",type:"string",required:!0,description:"Recipient address the payment authorizes (the x402 payTo field)."},{name:"amount",in:"body",type:"string",required:!0,description:`The amount the resource requires, in Base USDC's 6-decimal atomic units; for example, "50000" means "0.05 USDC". Decimal string; never truncated.`},{name:"max_amount",in:"body",type:"string",required:!0,description:`Caller-set spend cap in Base USDC's 6-decimal atomic units; for example, "50000" means "0.05 USDC". The hold is rejected if amount exceeds this. Decimal string.`},{name:"max_timeout_seconds",in:"body",type:"integer",required:!0,description:"Validity window for the signed authorization, in seconds (the x402 maxTimeoutSeconds field). Must be between 1 and 300; the server caps how long the authorization stays valid. Pass a value no greater than the resource's advertised maxTimeoutSeconds (a shorter window is valid, and settlement is near-instant); requests above 300 are rejected."},{name:"x402_version",in:"body",type:"integer",required:!1,description:"x402 protocol version from the resource's 402 challenge. Pass the value the resource advertised. Optional; defaults to 1."},{name:"extra",in:"body",type:"object",required:!1,description:"Full extra object from the resource's 402 PaymentRequirements. Required when x402_version is 2; name and version must match the Base USDC EIP-712 domain."},{name:"portfolio_id",in:"body",type:"string",required:!1,description:'Optional UUID of the consumer portfolio to pay from. Omit only when exactly one accessible non-deleted consumer portfolio is available and the caller has portfolio listing permission. If discovery is not authorized, provide portfolio_id explicitly. For OAuth, ask the user to reconnect and select "View your trading portfolios" in Coinbase consent. For an API key, ask the user to edit it, open Advanced Settings, and enable "View (read-only)" for every portfolio the agent needs. If multiple consumer portfolios are available, call coinbase_portfolios_list, select the funding portfolio with the use'},{name:"account_id",in:"body",type:"string",required:!1,description:"Optional UUID of the USDC account to debit, within the chosen portfolio. Omit to use that portfolio's single USDC account; the tool returns an error (it does NOT guess) when the portfolio has zero or multiple USDC accounts."},{name:"idempotency_key",in:"body",type:"string",required:!1,description:"Optional caller-supplied idempotency key; must be a UUID. Omit it on a first attempt \u2014 one is generated and returned to you. Reuse the SAME key when retrying an outcome-unknown payment so a duplicate hold is not placed. If the tool reports a terminal rejection, do not reuse that key; start a new payment attempt with a new key."}],streamable:!1,watchFields:null,watch:null,template:{scheme:"<string>",network:"<string>",asset:"<string>",pay_to:"<string>",amount:"<string>",max_amount:"<string>",max_timeout_seconds:0,x402_version:0,extra:{name:"<string>",version:"<string>"},portfolio_id:"<string>",account_id:"<string>",idempotency_key:"<string>"},responseFields:{fields:["payment_header","payment_id","idempotency_key","expires_at"]},annotations:{destructiveHint:!0},agentApi:"only"},{id:"x402_fetch",name:"fetch",method:"POST",path:"/x402/fetch",summary:"Pay For and Fetch x402 Resource",description:`Fetches a resource returned by x402_resources. On a 402 challenge, pays from the caller's custodial Base USDC via a pre-authorized hold, then retries with PAYMENT-SIGNATURE \u2014 no manual challenge handling. All currently supported x402 purchases through this connector use Base USDC, and max_amount uses its 6-decimal atomic units; for example, "50000" means "0.05 USDC". This tool accepts only resource URLs returned by x402_resources. max_amount is the spend control; when the user has requested the data or stated a budget, proceed in a single call rather than re-confirming. Protocol v2 only; v1 challenges are rejected.`,pathParams:[],params:[{name:"resource",in:"body",type:"string",required:!0,description:"Resource URL returned by coinbase_x402_resources, with any path parameters substituted. Any URL that does not match a catalog resource is rejected."},{name:"input",in:"body",type:"object",required:!1,description:"Request parameters, exactly as described by the resource's inputSchema from coinbase_x402_resources \u2014 pass those properties flat, at the top level. The tool routes them to the query string or the request body per the resource's HTTP method; you do not construct the HTTP envelope. Validated against the returned schema; unknown keys are rejected unless that schema explicitly permits additional properties."},{name:"max_amount",in:"body",type:"string",required:!1,description:`Optional caller-set spend cap in Base USDC's 6-decimal atomic units; for example, "50000" means "0.05 USDC". Defaults to the catalog advisory ceiling for the resource; when supplied the effective cap is min(max_amount, advisory ceiling). Never derived from the live 402 challenge.`},{name:"portfolio_id",in:"body",type:"string",required:!1,description:'Optional UUID of the consumer portfolio to pay from. Omit only when exactly one accessible non-deleted consumer portfolio is available and the caller has portfolio listing permission. If discovery is not authorized, provide portfolio_id explicitly. For OAuth, ask the user to reconnect and select "View your trading portfolios" in Coinbase consent. For an API key, ask the user to edit it, open Advanced Settings, and enable "View (read-only)" for every portfolio the agent needs. If multiple consumer portfolios are available, call coinbase_portfolios_list, select the funding portfolio with the use'},{name:"account_id",in:"body",type:"string",required:!1,description:"Optional UUID of the USDC account to debit, within the chosen portfolio. Omit to use that portfolio's single USDC account; an error (not a guess) is returned when the portfolio has zero or multiple USDC accounts."},{name:"idempotency_key",in:"body",type:"string",required:!1,description:"Optional caller-supplied idempotency key for the payment; must be a UUID. Omit it on a first attempt \u2014 one is generated and returned to you. Reuse the SAME key when retrying an outcome-unknown fetch so a duplicate hold is not placed. If the tool reports a terminal rejection, do not reuse that key; start a new payment attempt with a new key."}],streamable:!1,watchFields:null,watch:null,template:{resource:"<string>",input:{},max_amount:"<string>",portfolio_id:"<string>",account_id:"<string>",idempotency_key:"<string>"},responseFields:{fields:["data","paid","payment_id","idempotency_key","expires_at"]},annotations:{destructiveHint:!0},agentApi:"only"}]}],Q={balance:{id:"balance",name:"balance",method:"GET",path:"/balance",summary:"View Balances",description:"Returns account balances for exactly one portfolio. If portfolio_id is omitted, only the default portfolio is returned. Results are not aggregated across portfolios; use coinbase_portfolios_list and query each portfolio separately. This is a trading-account view, not total holdings: staked assets are excluded. For portfolio value or holdings including staked assets, use coinbase_portfolios_get. The response portfolio_id identifies the effective portfolio queried. Balances show available funds and amounts on hold; available_balance excludes funds held by open orders. Use before trading or transferring to confirm available funds.",pathParams:[],params:[{name:"portfolio_id",in:"query",type:"string",required:!1,description:"UUID of the single portfolio to query. Omit to query only the default 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,watch:null,template:{},responseFields:{fields:["portfolio_id","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"]}}}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},settlements:{id:"settlements_list",name:"settlements",method:"GET",path:"/settlements",summary:"List Perpetual Settlements",description:"Lists customer daily perpetual funding payments and bankruptcy events. Funding is a signed amount in settlement currency, not a market funding rate. Platform-wide profit_loss and session_profit_loss are never customer P&L. Select product_id for one perpetual or currency for a settlement currency. Without either filter, currencies are paged in alphabetical order, newest first within each currency. Empty filtered pages can still have a cursor; follow it until absent. Do not assume global chronological ordering across products. Requires Global Derivatives eligibility and account-read permission.",pathParams:[],params:[{name:"portfolio_id",in:"query",type:"string",required:!1,description:"For GLOBAL_PERP, use your authorized Global Derivatives portfolio UUID or omit to select it automatically. Requires portfolio-read permission.",pattern:"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},{name:"product_type",in:"query",type:"string",required:!1,description:"",enum:["GLOBAL_PERP"],default:"GLOBAL_PERP"},{name:"product_id",in:"query",type:"string",required:!1,description:"Perpetual product identifier from products_list with product_type=GLOBAL_PERP."},{name:"currency",in:"query",type:"string",required:!1,description:"Settlement currency, such as BTC or USDC; must match the product if both filters are set."},{name:"type",in:"query",type:"string",required:!1,description:"",enum:["SETTLEMENT","BANKRUPTCY"]},{name:"start_time",in:"query",type:"string",required:!1,description:"Inclusive earliest event time, at or after the Unix epoch; millisecond precision.",pattern:"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?(Z|[+-]\\d{2}:\\d{2})$",format:"date-time"},{name:"end_time",in:"query",type:"string",required:!1,description:"Inclusive latest event time; millisecond precision.",pattern:"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?(Z|[+-]\\d{2}:\\d{2})$",format:"date-time"},{name:"cursor",in:"query",type:"string",required:!1,description:"Opaque continuation bound to the user, portfolio, and filters."},{name:"limit",in:"query",type:"integer",required:!1,description:"",default:25}],streamable:!1,watchFields:null,watch:null,template:{},responseFields:{fields:["settlements","cursor"],nested:{settlements:{fields:["type","currency","product_id","timestamp","position","mark_price","index_price","funding"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},fees:{id:"fees",name:"fees",method:"GET",path:"/fees",summary:"Fee Tier and Volume",description:"Returns maker/taker fee rates and available 30-day trading volume. For EQUITY, rates cover trading commissions only, not every charge for a specific order. Equity fee and volume history are unavailable; zero totals or missing rates do not establish that a trade has no charges.",pathParams:[],params:[{name:"product_type",in:"query",type:"string",required:!1,description:"Filter by product type.",enum:["SPOT","FUTURE","EQUITY"]}],streamable:!1,watchFields:null,watch: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"]},margin_rate:{fields:["value"]}}},annotations:{readOnlyHint:!0},agentApi:"eligible"},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-8f2c-4a1e-9b30-5c7e1f2a4d61"},{name:"to",in:"body",type:"string",required:!0,description:"Target portfolio UUID",example:"a44ef7a8-3c95-4d18-bf62-90ad7e5c1b04"}],streamable:!1,watchFields:null,watch:null,template:{amount:"100.00",currency:"USD",from:"d17b3486-8f2c-4a1e-9b30-5c7e1f2a4d61",to:"a44ef7a8-3c95-4d18-bf62-90ad7e5c1b04"},responseFields:{fields:["source_portfolio_uuid","target_portfolio_uuid"]},annotations:{destructiveHint:!0},agentApi:"eligible"},feedback:{id:"feedback_submit",name:"feedback",method:"POST",path:"/feedback",summary:"Send Feedback About Coinbase Tools",description:"Submit one feedback observation about Coinbase tools. In about three sentences, describe what you tried, what happened or was missing, and what you expected. The note must be at least 20 characters after trimming. Include a short error code or reproduction detail when useful. Leave out credentials, account details and transcripts. Show agent-drafted feedback to the user and obtain approval before sending it. Do not interrupt the user's task or repeat an offer they declined. Do not retry automatically: an unconfirmed delivery may already have been received.",pathParams:[],params:[{name:"note",in:"body",type:"string",required:!0,description:"The observation: what you tried, what happened or was missing, and what you expected. 20 to 2000 characters after trimming. Never include credentials, account details or transcripts.",example:"coinbase_orders_preview returned invalid_argument for a SOL-USDC limit order with limit_price 150. I expected a fee estimate. The same order previewed fine with base_size."},{name:"tool_name",in:"body",type:"string",required:!1,description:"Optional tool the feedback is about, e.g. coinbase_orders_preview. Omit for cross-cutting feedback or missing capabilities."}],streamable:!1,watchFields:null,watch:null,template:{note:"coinbase_orders_preview returned invalid_argument for a SOL-USDC limit order with limit_price 150. I expected a fee estimate. The same order previewed fine with base_size.",tool_name:"<string>"},responseFields:{fields:["feedback_id","status","additional_feedback"]},closedInput:!0,annotations:{readOnlyHint:!1,destructiveHint:!1},agentApi:"only"}},Xn=new Set(["balance","settlements","fees","transfer","feedback"]),Zn={date:/^\d{4}-\d{2}-\d{2}$/,uuid:/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/,"date-time":/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/};Jn={date:t=>{let e=t.match(/^(\d{4})-(\d{2})-(\d{2})$/);return!!e&&Qn(+e[1],+e[2],+e[3])},"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,o,_]=e;return Qn(+r,+n,+i)&&+s<24&&+o<60&&+_<61}}});function Me(t){return typeof t=="object"&&"endpoint"in t}function G(t,e){return{endpoint:t,...e}}var Lt=C(()=>{"use strict";E();l()});var ti,ei,ri,ni,ii,si,oi,_i,ai,ci,ui,di,Ei,li,gi,Bt=C(()=>{"use strict";E();l();ti={origin:"RetailBrokerageApi_CancelOrders",method:"POST",path:"/api/v3/brokerage/orders/batch_cancel"},ei={origin:"RetailBrokerageApi_ClosePosition",method:"POST",path:"/api/v3/brokerage/orders/close_position"},ri={origin:"RetailBrokerageApi_CommitConvertTrade",method:"POST",path:"/api/v3/brokerage/convert/trade/{trade_id}"},ni={origin:"RetailBrokerageApi_CreatePortfolio",method:"POST",path:"/api/v3/brokerage/portfolios"},ii={origin:"RetailBrokerageApi_DeletePortfolio",method:"DELETE",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},si={origin:"RetailBrokerageApi_EditPortfolio",method:"PUT",path:"/api/v3/brokerage/portfolios/{portfolio_uuid}"},oi={origin:"RetailBrokerageApi_GetBestBidAsk",method:"GET",path:"/api/v3/brokerage/best_bid_ask"},_i={origin:"RetailBrokerageApi_GetConvertTrade",method:"GET",path:"/api/v3/brokerage/convert/trade/{trade_id}"},ai={origin:"RetailBrokerageApi_GetFills",method:"GET",path:"/api/v3/brokerage/orders/historical/fills"},ci={origin:"RetailBrokerageApi_GetHistoricalOrder",method:"GET",path:"/api/v3/brokerage/orders/historical/{order_id}"},ui={origin:"RetailBrokerageApi_GetHistoricalOrders",method:"GET",path:"/api/v3/brokerage/orders/historical/batch"},di={origin:"RetailBrokerageApi_GetPortfolios",method:"GET",path:"/api/v3/brokerage/portfolios"},Ei={origin:"RetailBrokerageApi_GetProduct",method:"GET",path:"/api/v3/brokerage/products/{product_id}"},li={origin:"RetailBrokerageApi_GetPublicProductBook",method:"GET",path:"/api/v3/brokerage/market/product_book"},gi={origin:"RetailBrokerageApi_GetTransactionSummary",method:"GET",path:"/api/v3/brokerage/transaction_summary"}});function v_(t,e){let r={...e},n=t;for(let[i,s]of Object.entries(r)){let o="{"+i+"}";s!=null&&n.includes(o)&&(n=n.replaceAll(o,encodeURIComponent(String(s))),delete r[i])}return{url:n,remaining:r}}async function nt(t,e,r,n){let{url:i,remaining:s}=v_(r,n),o=e==="POST"||e==="PUT"||e==="DELETE"||e==="PATCH",_,a=null;if(o)_=t.baseURL+i,Object.keys(s).length>0&&(a=new TextEncoder().encode(JSON.stringify(s)));else{let g=Object.entries(s).filter(([,p])=>p!=null).flatMap(([p,m])=>(Array.isArray(m)?m:[m]).map(O=>encodeURIComponent(p)+"="+encodeURIComponent(String(O)))).join("&");_=t.baseURL+i+(g?"?"+g:"")}let u=await t.doRequest({method:e,url:_,body:a}),d=new TextDecoder().decode(u.body),c;try{c=JSON.parse(d)}catch{c=d}if(u.status>=400){let g=c,p=g?.error_response?.message??g?.error_response?.error_details??g?.message??g?.error_details??d.slice(0,200);throw new ct(p,u.status,c)}return{status:u.status,data:c}}function pi(t,e){return nt(t,"POST","/api/v3/brokerage/convert/quote",e)}function Ii(t,e){return nt(t,"POST","/api/v3/brokerage/orders/edit",e)}function Ri(t,e){return nt(t,"GET","/api/v3/brokerage/accounts",e)}function Ti(t,e){return nt(t,"GET","/api/v3/brokerage/key_permissions",e)}function mi(t,e){return nt(t,"GET","/api/v3/brokerage/products/{product_id}/candles",e)}function Oi(t,e){return nt(t,"GET","/api/v3/brokerage/products/{product_id}/ticker",e)}function Ai(t,e){return nt(t,"GET","/api/v3/brokerage/portfolios/{portfolio_uuid}",e)}function Dr(t,e){return nt(t,"GET","/api/v3/brokerage/products",e)}function Ni(t,e){return nt(t,"POST","/api/v3/brokerage/portfolios/move_funds",e)}function Si(t,e){return nt(t,"POST","/api/v3/brokerage/orders",e)}function Ci(t,e){return nt(t,"POST","/api/v3/brokerage/orders/edit_preview",e)}function Pi(t,e){return nt(t,"POST","/api/v3/brokerage/orders/preview",e)}var ct,lt=C(()=>{"use strict";E();l();ct=class extends Error{status;data;constructor(e,r,n){super(e),this.status=r,this.data=n}}});function F_(t,e,r){if(!(!t||t===r))return e[t]??t}function G_(t){if(typeof t=="number")return t;if(t&&typeof t=="object"&&"value"in t){let e=Number(t.value);return Number.isFinite(e)?e:void 0}}var M_,k_,V_,w_,fi,yi=C(()=>{"use strict";E();l();Lt();Bt();lt();M_={FUTURES_POSITION_SIDE_LONG:"LONG",FUTURES_POSITION_SIDE_SHORT:"SHORT"},k_="FUTURES_POSITION_SIDE_UNSPECIFIED";V_=["total_balance_fiat","total_balance_equity","available_to_trade_equity","available_to_trade_fiat","cost_basis","average_entry_price","unrealized_pnl"];w_=async(t,e)=>{let n=(await Ai(e,{portfolio_uuid:t.portfolio_id,currency:t.currency})).data.breakdown??{},i=(n.futures_positions??[]).map(o=>({...o,side:F_(o.side,M_,k_)})),s=(n.equity_positions??[]).map(o=>{let _={...o};for(let a of V_)a in _&&(_[a]=G_(_[a]));return _});return{...n,futures_positions:i,equity_positions:s}},fi={portfolios_list:G(di),portfolios_get:w_,portfolios_create:G(ni,{responseUnwrap:"portfolio"}),portfolios_edit:G(si,{requestMap:{portfolio_id:"portfolio_uuid"},responseUnwrap:"portfolio"}),portfolios_delete:G(ii,{requestMap:{portfolio_id:"portfolio_uuid"}})}});var P,Ot=C(()=>{"use strict";E();l();P=class t extends Error{status;correlationId;traceId;code;constructor(e,r,n){super(e),this.status=r,this.correlationId=n?.correlationId,this.traceId=n?.traceId,this.code=n?.code}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,o;try{let a=JSON.parse(i);a.errorType&&a.errorMessage?s=`${a.errorType} \u2014 ${a.errorMessage}`:a.message?s=t.stripGrpcPrefix(a.message):s=i.length>200?i.slice(0,200)+"...":i,o=a.correlationId||a.correlation_id||void 0}catch{s=i.length>200?i.slice(0,200)+"...":i}let _=n?.get("trace-id")??void 0;return new t(s,r,{correlationId:o,traceId:_})}}});function Di(t){return String(t).replace(/^(NEW_ORDER_FAILURE_REASON_|PREVIEW_|EDIT_ORDER_FAILURE_REASON_)/,"").replace(/_/g," ").toLowerCase()}function br(t){if(t?.success===!1){let e=t.error_response,r=t.errors?.[0]?.edit_failure_reason,n=e?.new_order_failure_reason??e?.preview_failure_reason??e?.error,i=n?Di(n):void 0;throw new P(e?.message||e?.error_details||i||(r?Di(r):void 0)||"Operation failed",400)}}var bi=C(()=>{"use strict";E();l();Ot()});var ht,Lr,Ut,Ht,Li=C(()=>{"use strict";E();l();ht={MARKET:"market",LIMIT:"limit",STOP_LIMIT:"stop_limit",BRACKET:"bracket",TWAP:"twap",SCALED:"scaled"},Lr={UP:"up",DOWN:"down"},Ut={GTC:"GTC",IOC:"IOC",FOK:"FOK",GTD:"GTD"},Ht={NORMAL:"NORMAL",PRE_MARKET:"PRE_MARKET",AFTER_HOURS:"AFTER_HOURS",OVERNIGHT:"OVERNIGHT",MULTI_SESSION:"MULTI_SESSION"}});import{randomUUID as x_}from"node:crypto";function hi(t){let e=t.type;if(e===ht.BRACKET||e===ht.TWAP||e===ht.SCALED)throw new P(`Order type "${e}" requires the Agent API.`,400,{code:"AGENT_API_REQUIRED"});if(e===ht.MARKET)return{market_market_ioc:{...t.quote_size&&{quote_size:t.quote_size},...t.base_size&&{base_size:t.base_size}}};if(e===ht.LIMIT){let r=t.time_in_force??Ut.GTC,n={...t.quote_size&&{quote_size:t.quote_size},...t.base_size&&{base_size:t.base_size},limit_price:t.limit_price,...t.post_only&&{post_only:!0}};return r===Ut.IOC?{sor_limit_ioc:n}:r===Ut.FOK?{limit_limit_fok:n}:r===Ut.GTD?{limit_limit_gtd:{...n,...t.end_time&&{end_time:t.end_time}}}:{limit_limit_gtc:n}}else if(e===ht.STOP_LIMIT){let r=t.stop_direction===Lr.UP?"STOP_DIRECTION_STOP_UP":t.stop_direction===Lr.DOWN?"STOP_DIRECTION_STOP_DOWN":(()=>{throw new P("stop_direction is required for stop_limit orders (up or down)",400)})(),n=t.time_in_force??Ut.GTC,i={base_size:t.base_size,limit_price:t.limit_price,stop_price:t.stop_price,stop_direction:r};return n===Ut.GTD?{stop_limit_stop_limit_gtd:{...i,...t.end_time&&{end_time:t.end_time}}}:{stop_limit_stop_limit_gtc:i}}throw new P(`Unknown order type: ${e}. Use market, limit, or stop_limit.`,400)}function Ui(t){if(!t.equity_trading_session&&!t.equity_order_date)return;let e={};if(t.equity_trading_session){let r=W_[t.equity_trading_session];if(!r)throw new P(`Unknown equity_trading_session: ${t.equity_trading_session}`,400);e.equity_trading_session=r}if(t.equity_order_date){let r=t.equity_order_date.match(B_);if(!r)throw new P("equity_order_date must be YYYY-MM-DD",400);e.equity_order_date={year:Number(r[1]),month:Number(r[2]),day:Number(r[3])}}return e}function H_(t){let e={client_order_id:t.client_order_id??x_(),product_id:t.product_id,side:t.side,order_configuration:hi(t)};t.portfolio_id&&(e.retail_portfolio_id=t.portfolio_id),t.reduce_only&&(e.reduce_only=!0);let r=Ui(t);return r&&(e.equity_order_metadata=r),e}function hr(t,e){let r=e.filter(n=>Object.hasOwn(t,n));if(r.length>0)throw new P(`Field(s) ${r.join(", ")} require the Agent API.`,400,{code:"AGENT_API_REQUIRED"})}function $_(t){let e=new Set,r=new Set,n=0,i=!0;for(let s=0;s<t.length;s++){let o=t[s];if(o==='"'){let _=s;for(s++;s<t.length;s++)if(t[s]==="\\")s++;else if(t[s]==='"')break;if(n===1&&i){let a=JSON.parse(t.slice(_,s+1));e.has(a)&&r.add(a),e.add(a),i=!1}}else o==="{"||o==="["?n++:o==="}"||o==="]"?n--:o===","&&n===1&&(i=!0)}return[...r]}function Mi(t){if(!t||typeof t!="object"||Array.isArray(t))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});let e=t;if(e.errors!==void 0&&!Array.isArray(e.errors))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});let r=e.errors;if(r?.some(o=>!o||typeof o!="object"||Array.isArray(o)))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});if(r?.length){let o=r[0],_=o?.edit_failure_reason??o?.preview_failure_reason,a=typeof _=="string"&&/^[A-Z0-9_]+$/.test(_)&&!_.startsWith("UNKNOWN_")?_.slice(_.indexOf("FAILURE_REASON_")>=0?_.indexOf("FAILURE_REASON_")+15:0).replaceAll("_"," ").toLowerCase():"operation failed";throw new P(`Order edit preview rejected: ${a}`,400,{code:"UPSTREAM_REJECTION"})}for(let o of["slippage","order_total","commission_total","quote_size","base_size","best_bid","best_ask","average_filled_price","order_margin_total"])if(e[o]!==void 0&&typeof e[o]!="string")throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});for(let o of["commission_detail_total","pnl_configuration"])if(e[o]!==void 0&&(!e[o]||typeof e[o]!="object"||Array.isArray(e[o])))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});let n=e.commission_detail_total;for(let o of["total_commission","gst_commission","withholding_commission","client_commission","venue_commission","regulatory_commission","clearing_commission"])if(n?.[o]!==void 0&&typeof n[o]!="string")throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});let s=e.pnl_configuration?.trigger_bracket_pnl;if(s!==void 0&&(!s||typeof s!="object"||Array.isArray(s)))throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"});for(let o of["take_profit_pnl","stop_loss_pnl"])if(s&&s[o]!==void 0&&typeof s[o]!="string")throw new P("Malformed order edit preview response",502,{code:"MALFORMED_RESPONSE"})}function ki(t){if(!t||typeof t!="object"||Array.isArray(t))return{error:"ORDER_EDIT_PREVIEW_FAILED",message:"Order edit preview failed"};let e=t,r=s=>String(s).replace(/Bearer\s+\S+/gi,"Bearer [REDACTED]").replace(/-----BEGIN [^-]+-----[\s\S]*?-----END [^-]+-----/g,"[REDACTED PRIVATE KEY]").slice(0,500),n=s=>typeof s=="string"&&/^[A-Z][A-Z0-9_]*$/.test(s)?s:"ORDER_EDIT_PREVIEW_FAILED";if(typeof e.errorType=="string"&&typeof e.errorMessage=="string")return{errorType:n(e.errorType),errorMessage:r(e.errorMessage),...typeof e.correlationId=="string"?{correlationId:e.correlationId}:{}};let i=e.message??e.errorMessage??e.error_response?.message??e.error_response?.error_details??e.error_details??"Order edit preview failed";return{error:n(e.error??e.errorType),...typeof e.code=="number"?{code:e.code}:{},message:r(i),...typeof e.correlationId=="string"?{correlationId:e.correlationId}:{},...typeof e.correlation_id=="string"?{correlation_id:e.correlation_id}:{}}}var W_,B_,vi,K_,q_,Y_,z_,j_,Q_,X_,Fi,Vi=C(()=>{"use strict";E();l();Lt();Ot();bi();Li();Bt();lt();W_={[Ht.NORMAL]:"EQUITY_TRADING_SESSION_NORMAL",[Ht.PRE_MARKET]:"EQUITY_TRADING_SESSION_PRE_MARKET",[Ht.AFTER_HOURS]:"EQUITY_TRADING_SESSION_AFTER_HOURS",[Ht.OVERNIGHT]:"EQUITY_TRADING_SESSION_OVERNIGHT",[Ht.MULTI_SESSION]:"EQUITY_TRADING_SESSION_MULTI_SESSION"},B_=new RegExp("^(\\d{4})-(\\d{2})-(\\d{2})$");vi=["attached_take_profit_price","attached_stop_loss_price","start_time","num_orders","min_price","max_price","price_distribution","size_distribution"],K_=["attached_take_profit_price","attached_stop_loss_price","cancel_attached_order"];q_=async(t,e)=>{hr(t,vi);let r=H_(t),n=await Si(e,r);return br(n.data),n.data.success_response??n.data},Y_=async(t,e)=>{hr(t,[...vi,"reduce_only"]);let r=Ui(t),n=await Pi(e,{product_id:t.product_id,side:t.side,order_configuration:hi(t),...t.portfolio_id&&{retail_portfolio_id:t.portfolio_id},...r&&{equity_order_metadata:r}}),i=n.data;if(i.errs?.length>0)throw new P(i.errs[0].replace(/^PREVIEW_/,"").replace(/_/g," ").toLowerCase(),400);return n.data},z_=async(t,e)=>{if(hr(t,K_),!t.base_size&&!t.limit_price)throw new P("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 Ii(e,r);return br(n.data),{order_id:t.order_id,status:"EDITED"}};j_=({body:t,query:e,path:r,headers:n,rawBody:i,originalParams:s,structured:o})=>{let _=(O,T)=>{throw new P(T,400,{code:O})},a=["order_id","base_size","limit_price"];if(o){for(let O of["body","query","path","headers"]){let T=s[O];T!==void 0&&(!T||typeof T!="object"||Array.isArray(T))&&_(O==="body"?"INVALID_BODY":"INVALID_PARAMETERS",`${O} must be an object.`)}i!==null&&!(i instanceof Uint8Array)&&_("INVALID_BODY","Raw request body must be bytes containing a JSON object.")}let u={};if(i){let O=new TextDecoder().decode(i),T;try{T=JSON.parse(O)}catch{_("INVALID_BODY","Request body must be valid JSON.")}(!T||typeof T!="object"||Array.isArray(T))&&_("INVALID_BODY","Request body must be a JSON object."),u=T;let b=[...new Set([...$_(O),...Object.keys(u).filter(f=>Object.hasOwn(t,f))])];b.length>0&&_("AMBIGUOUS_FIELDS",`Field(s) supplied more than once: ${b.join(", ")}`)}if(o){let O=["body","query","path","headers","rawBody"],T=Object.keys(s).filter(v=>!O.includes(v)),b=T.filter(v=>!a.includes(v));b.length>0&&_("UNKNOWN_FIELDS",`Unknown field(s): ${b.join(", ")}`);let f=T.filter(v=>Object.hasOwn(t,v)||Object.hasOwn(u,v));f.length>0&&_("AMBIGUOUS_FIELDS",`Field(s) supplied more than once: ${f.join(", ")}`),T.length>0&&_("INVALID_PARAMETER_LOCATION",`Body field(s) cannot be supplied outside the body in structured input: ${T.join(", ")}`)}let d=Object.keys(n),c=d.filter(O=>!a.includes(O));c.length>0&&_("UNKNOWN_FIELDS",`Unknown header field(s): ${c.join(", ")}`),d.length>0&&_("INVALID_PARAMETER_LOCATION",`Body field(s) cannot be supplied as headers: ${d.join(", ")}`);let g={...r,...t,...u,...e};(g.order_id===void 0||g.order_id==="")&&_("MISSING_FIELDS","Missing required field(s): order_id");let p=Object.keys(o?g:s).filter(O=>!a.includes(O));p.length>0&&_("UNKNOWN_FIELDS",`Unknown field(s): ${p.join(", ")}`);let m=a.filter(O=>Object.hasOwn(e,O)||Object.hasOwn(r,O));m.length>0&&_("INVALID_PARAMETER_LOCATION",`Body field(s) cannot be supplied as query or path parameters: ${m.join(", ")}`),[g.base_size,g.limit_price].every(O=>O===void 0||O==="")&&_("MISSING_FIELDS","One of base_size, or limit_price is required.");for(let O of a){let T=g[O];if(T===void 0)continue;if(typeof T!="string"&&_("INVALID_VALUE",`Invalid value for ${O}. Expected a string.`),!(O==="order_id"?/^(?!00000000-0000-0000-0000-000000000000$)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/:/^(?=.*[1-9])[0-9]+(?:\.[0-9]+)?$/).test(T)){let f=O==="order_id"?"Open order canonical non-nil UUID to preview editing":`Positive decimal replacement ${O==="base_size"?"base size":"limit price"}; at least one replacement is required`;_("INVALID_VALUE",`Invalid value for ${O}: "${String(T).slice(0,80)}". ${f}.`)}}};Q_=async(t,e)=>{let r={order_id:t.order_id,size:t.base_size??"",price:t.limit_price??""};try{let n=await Ci(e,r);return Mi(n.data),n.data}catch(n){if(n instanceof ct){let i=ki(n.data),s=i.message??i.errorMessage??i.error??"Order edit preview failed";throw new P(String(s),n.status,{code:"UPSTREAM_REQUEST_FAILED"})}throw n}},X_={status:"order_status",side:"order_side",start:"start_date",end:"end_date",portfolio_id:"retail_portfolio_id"},Fi={orders_list:G(ui,{requestMap:X_}),orders_get:G(ci,{responseUnwrap:"order"}),orders_create:q_,orders_preview:Y_,orders_edit_preview:Object.assign(Q_,{validateInput:j_,validateResponse:Mi,sanitizeError:ki}),orders_edit:z_,orders_cancel:G(ti),orders_close_position:G(ei),orders_fills:G(ai,{requestMap:{side:"order_side",start:"start_sequence_timestamp",end:"end_sequence_timestamp",portfolio_id:"retail_portfolio_id"}})}});function Gi(t){return String(Math.floor(new Date(t).getTime()/1e3))}var Z_,J_,ta,ea,ra,na,wi,xi=C(()=>{"use strict";E();l();Lt();Ot();Bt();lt();Z_={"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"},J_={"1m":60,"5m":300,"15m":900,"30m":1800,"1h":3600,"2h":7200,"4h":14400,"6h":21600,"1d":86400},ta=60,ea=async(t,e)=>{let{symbol:r,limit:n,cursor:i,...s}=t;if(r){let _=r.toUpperCase(),d=((await Dr(e,s)).data.products??[]).filter(g=>g.base_currency_id===_||g.quote_currency_id===_),c=n!==void 0&&n>0?d.slice(0,n):d;return{products:c,num_products:c.length}}return(await Dr(e,{...s,limit:n,cursor:i})).data};ra=async(t,e)=>{if(!t.granularity)throw new P("granularity is required (expected execute() to apply its default)",500);let r=t.granularity,n=Z_[r],i=J_[r],s=Math.floor(Date.now()/1e3),o=t.end?Gi(t.end):String(s),_=t.start?Gi(t.start):String(Number(o)-ta*i);return(await mi(e,{...t,granularity:n,start:_,end:o})).data},na=async(t,e)=>{let r=t.limit??100;return(await Oi(e,{...t,limit:r})).data},wi={products_list:ea,products_get:G(Ei),products_ticker:na,products_book:G(li),products_candles:ra,products_best_bid_ask:G(oi)}});var ia,Wi,Bi=C(()=>{"use strict";E();l();Lt();Bt();lt();Ot();ia=async(t,e)=>{let{from:r,to:n,...i}=t,s=await pi(e,{...i,from_account:r,to_account:n});if(!s.data?.trade?.id)throw new P(`Convert quote returned no trade for ${t.from} \u2192 ${t.to}. Verify balance, supported pair, and account eligibility.`,422);return s.data},Wi={convert_quote:ia,convert_execute:G(ri,{requestMap:{quote_id:"trade_id",from:"from_account",to:"to_account"}}),convert_get:G(_i,{requestMap:{quote_id:"trade_id",from:"from_account",to:"to_account"},responseUnwrap:"trade"})}});var sa,Hi,Ki=C(()=>{"use strict";E();l();lt();sa=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 Ri(e,r)).data,s=i.accounts??[],o=t.show_zero?s:s.filter(_=>parseFloat(_.available_balance?.value??"0")!==0||parseFloat(_.hold?.value??"0")!==0);return{accounts:o,has_next:i.has_next,cursor:i.cursor,size:o.length}},Hi={balance:sa}});var oa,qi,Yi=C(()=>{"use strict";E();l();Ot();lt();oa=async(t,e)=>{let r={funds:{value:t.amount,currency:t.currency},source_portfolio_uuid:t.from,target_portfolio_uuid:t.to},i=(await Ni(e,r)).data;if(!i?.source_portfolio_uuid)throw new P("Transfer failed \u2014 check amount, currency, and portfolio UUIDs",400);return i},qi={transfer:oa}});var zi,$i=C(()=>{"use strict";E();l();Lt();Bt();zi={fees:G(gi)}});function ji(t){let e=t&&typeof t=="object"?t:{},r={};return typeof e.can_view=="boolean"&&(r.can_view=e.can_view),typeof e.can_trade=="boolean"&&(r.can_trade=e.can_trade),typeof e.can_transfer=="boolean"&&(r.can_transfer=e.can_transfer),typeof e.portfolio_uuid=="string"&&(r.portfolio_uuid=e.portfolio_uuid),(e.portfolio_type==="UNDEFINED"||e.portfolio_type==="DEFAULT"||e.portfolio_type==="CONSUMER"||e.portfolio_type==="INTX")&&(r.portfolio_type=e.portfolio_type),r}function Qi(t){let e=t===401?"AUTHENTICATION_FAILED":t===403?"PERMISSION_INTROSPECTION_FORBIDDEN":"BROKERAGE_REQUEST_FAILED",r=t===401?"Authentication failed for the current API key. Coinbase Advanced Trade requires an ECDSA key; if this environment uses Ed25519, create an ECDSA key and update the environment credentials.":t===403?"The current API key is not authorized to inspect its permissions.":`Brokerage API permission introspection failed with HTTP ${t}.`;return new ct(r,t,{error:e,code:t,message:r})}var Ur,Xi,Zi=C(()=>{"use strict";E();l();lt();Ur=async(t,e)=>{try{let{data:r}=await Ti(e,{});return ji(r)}catch(r){throw r instanceof ct?Qi(r.status):r}};Ur.normalizeResponse=ji;Ur.errorResponse=t=>Qi(t).data;Xi={api_key_permissions:Ur}});function vr(t){return _a[t]}function Ji(t){return vr(t)!==void 0||aa.has(t)}var _a,aa,Mr=C(()=>{"use strict";E();l();mt();yi();Vi();xi();Bi();Ki();Yi();$i();Zi();_a={...fi,...Fi,...wi,...Wi,...Hi,...qi,...zi,...Xi};aa=new Set([...j.flatMap(t=>t.actions),...Object.values(Q)].filter(t=>t.agentApi).map(t=>t.id))});function kr(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 ts(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 es=C(()=>{"use strict";E();l()});async function rs(t,e,r){if(t.headers.get("content-type")?.split(";")[0].trim()!=="text/event-stream"||!t.body)throw await t.body?.cancel(),new Error("Expected an Agent API event stream.");let n=t.body.getReader(),i=new TextDecoder,s=()=>{n.cancel().catch(()=>{})};r?.addEventListener("abort",s,{once:!0}),r?.aborted&&s();let o="",_="message",a=[],u=!1,d=async c=>{if(!c){if(!a.length)return _="message",!1;let O=JSON.parse(a.join(`
|
|
48
|
+
`));if(!O||typeof O!="object"||Array.isArray(O))throw new Error("Invalid SSE JSON record.");let T={event:_,data:O};if(_="message",a=[],T.event==="error")throw await e(T),new Error(`Agent API stream terminated: ${String(T.data.error_code??"error")}. Start a fresh authenticated request.`);return await e(T)===!0}if(c.startsWith(":"))return!1;let g=c.indexOf(":"),p=g<0?c:c.slice(0,g),m=g<0?"":c.slice(g+1);return m.startsWith(" ")&&(m=m.slice(1)),p==="event"&&(_=m),p==="data"&&a.push(m),!1};try{for(;;){let c=await n.read();if(c.done)throw new Error("Agent API stream disconnected. Start a fresh authenticated request for a new snapshot.");o+=i.decode(c.value,{stream:!0});let g;for(;g=/[\r\n]/.exec(o);){let p=o.slice(0,g.index),m=g[0];if(o=o.slice(g.index+g[0].length),u&&g.index===0&&m===`
|
|
49
|
+
`){u=!1;continue}if(u=m==="\r",await d(p))return}}}finally{r?.removeEventListener("abort",s),await n.cancel().catch(()=>{}),n.releaseLock()}}var ns=C(()=>{"use strict";E();l()});function ke(t){if(t)try{return JSON.parse(new TextDecoder().decode(t))}catch{return}}function Fe(t,...e){return Object.entries(t??{}).some(([r,n])=>e.some(i=>{if(!i||typeof i!="object"||Array.isArray(i))return!1;let s=i[r];return typeof s=="string"&&n.includes(s)}))}function Ve(t,e){if(e!==void 0&&t.enum&&!t.enum.includes(String(e)))return`Invalid value for ${t.name}: "${e}". Expected one of: ${t.enum.join(", ")}`}var Fr=C(()=>{"use strict";E();l()});function ca(t,e){let r={...e},n=t;for(let[i,s]of Object.entries(e)){if(s==null||s==="")continue;let o=`{${i}}`;n.includes(o)&&(n=n.replaceAll(o,encodeURIComponent(String(s))),delete r[i])}return{resolvedPath:n,remainingParams:r}}function ua(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 Ea(t,e){for(let[r,n]of Object.entries(e))for(let i of t){let s=i[r];if(s!=null){if(n==="join-comma"&&Array.isArray(s))i[r]=s.join(",");else if(n==="split-comma"){let o=Array.isArray(s)?s:[s];i[r]=o.flatMap(_=>String(_).split(",").map(a=>a.trim()).filter(Boolean))}}}}function is(t,e){return`${t.replace(/\/+$/,"")}${e}`}function la(t){return t===408||t===429||t>=500}function ga(t){return t instanceof TypeError||t instanceof Error&&(t.name==="AbortError"||t.name==="TimeoutError")}function pa(t,e){if(t&&typeof t=="object"&&!Array.isArray(t)){let r=typeof t.hint=="string"&&t.hint?`${t.hint} `:"";return{...t,hint:`${r}${Vr}`}}return{error:"AGENT_API_REQUEST_FAILED",code:e,message:typeof t=="string"&&t?t:`Agent API request failed with HTTP ${e}.`,hint:Vr}}function ss(t,e){return{status:400,data:{error:"REST_ENDPOINT_UNAVAILABLE",code:400,message:`${e} endpoint is not configured for environment "${t.envName}". Configure the endpoint for this environment before retrying.`}}}function Ia(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 Ra(t){return t&&typeof t=="object"&&("body"in t||"query"in t||"path"in t||"rawBody"in t||"stream"in t)}function ae(t,e){if(t==null||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>ae(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=>ae(s,i)):i&&typeof t[n]=="object"&&t[n]!==null?r[n]=ae(t[n],i):r[n]=t[n]}return r}function Ta(t,e){let r=Gr[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 At(t,e,r){let n=Ra(e),i=n?e.body??{}:{},s=n?e.query??{}:{},o=n?e.path??{}:{},_=n?e.headers??{}:{},a=n?e.rawBody??null:null,u=!1,d=vr(t),c=os.find(I=>I.id===t);if(!d&&!c?.agentApi)return{status:404,data:{error:"UNKNOWN_OPERATION",code:404,message:`No route for ${t}`}};let g=d&&!Me(d)?d:void 0;if(!n)for(let[I,R]of Object.entries(e)){let U=c?.params.find(w=>w.name===I),D=U?.in==="query"?s:U?.in==="path"?o:i;D[I]=R}if(c?.noInput&&([...Object.keys(i),...Object.keys(s),...Object.keys(o),...Object.keys(_)].length>0||(a?.length??0)>0))return{status:400,data:{error:"UNEXPECTED_FIELDS",code:400,message:`${t} does not accept input fields; it always inspects the current credential.`}};if(r.transport==="agent"&&!c?.agentApi)return{status:400,data:{error:"AGENT_API_ROUTE_UNAVAILABLE",code:400,message:`${t} is not available through the Agent API. Set COINBASE_TRANSPORT=brokerage to use direct brokerage.`}};let p=c?.agentApi?Tt(r.env,r.envName):"",m=ke(a),O=Fe(c?.agentApiOnlyWhen,o,i,s,m),T=O||c?.agentApi==="only"||r.transport==="agent"||c?.agentApi==="eligible"&&r.transport!=="brokerage"&&!!p;if(!d&&!T)return{status:400,data:{error:"BROKERAGE_ROUTE_UNAVAILABLE",code:400,message:`${t} is only available through the Agent API. Unset COINBASE_TRANSPORT=brokerage to use it.`}};if(g?.validateInput)try{g.validateInput({body:i,query:s,path:o,headers:_,rawBody:a,originalParams:e,structured:n})}catch(I){if(!(I instanceof P))throw I;return{status:I.status,data:{error:I.code??"INVALID_VALUE",code:I.status,message:I.message}}}if(c?.params){if(a){if(m&&typeof m=="object"&&!Array.isArray(m)){if(c.closedInput){let I=Object.keys(m).filter(R=>Object.hasOwn(i,R));if(I.length>0)return{status:400,data:{error:"AMBIGUOUS_FIELDS",code:400,message:`Field(s) supplied more than once: ${I.join(", ")}`}}}u=!0,Object.assign(i,m)}else if(c.closedInput)return{status:400,data:{error:"INVALID_BODY",code:400,message:m===void 0?"Request body must be valid JSON.":"Request body must be a JSON object."}}}for(let I of c.params){if(I.default===void 0||I.required||o[I.name]!==void 0||i[I.name]!==void 0||s[I.name]!==void 0)continue;let R=I.in==="query"?s:I.in==="path"?o:i;R[I.name]=I.default}{let I=c.params.filter(D=>(D.in==="body"||d!==void 0&&!Me(d)&&D.in==="path")&&D.required),R={...o,...i,...s},U=I.filter(D=>R[D.name]===void 0||R[D.name]==="");if(U.length>0)return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`Missing required field(s): ${U.map(w=>w.name).join(", ")}`}}}{let I={...o,...i,...s},R={},U={};for(let D of c.params)if(D.oneOf&&(U[D.oneOf]||(U[D.oneOf]=[]),U[D.oneOf].push(D.name),I[D.name]!==void 0&&I[D.name]!=="")){if(R[D.oneOf])return{status:400,data:{error:"CONFLICTING_FIELDS",code:400,message:`${R[D.oneOf]} and ${D.name} are mutually exclusive. Provide one, not both.`}};R[D.oneOf]=D.name}for(let[D,w]of Object.entries(U))if(!R[D])return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`One of ${w.join(", ")} is required.`}}}{let I={...o,...i,...s};if(c.closedInput||O){let R=new Set(c.params.map(w=>w.name)),U=Object.keys(I).filter(w=>!R.has(w));if(U.length>0)return{status:400,data:{error:"UNKNOWN_FIELDS",code:400,message:`Unknown field(s): ${U.join(", ")}`}};let D=c.params.filter(w=>w.in==="body"&&(Object.hasOwn(s,w.name)||Object.hasOwn(o,w.name))).map(w=>w.name);if(D.length>0)return{status:400,data:{error:"INVALID_PARAMETER_LOCATION",code:400,message:`Body field(s) cannot be supplied as query or path parameters: ${D.join(", ")}`}}}if(c.anyOf&&!c.anyOf.some(R=>R.every(U=>I[U]!==void 0&&I[U]!=="")))return{status:400,data:{error:"MISSING_FIELDS",code:400,message:`One of ${c.anyOf.map(U=>U.join(" and ")).join(", or ")} is required.`}}}for(let I of c.params)for(let R of[i,s,o]){if(R[I.name]===void 0)continue;if(c.closedInput&&I.type==="string"&&typeof R[I.name]!="string")return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}. Expected a string.`}};if(I.type==="array"&&typeof R[I.name]=="string"?R[I.name]=R[I.name].split(",").map(dt=>dt.trim()).filter(Boolean):I.type==="string"&&Array.isArray(R[I.name])&&(R[I.name]=R[I.name].join(",")),I.type==="boolean"){if(typeof R[I.name]!="boolean"&&(typeof R[I.name]!="string"||R[I.name]!=="true"&&R[I.name]!=="false"))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${R[I.name]}". Expected "true" or "false".`}};typeof R[I.name]=="string"&&(R[I.name]=R[I.name]==="true")}else if((I.type==="integer"||I.type==="number")&&typeof R[I.name]=="string"){let dt=Number(R[I.name]);if(!Number.isFinite(dt))return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${R[I.name]}". Expected a number.`}};R[I.name]=dt}let U=Ve(I,R[I.name]);if(U)return{status:400,data:{error:"INVALID_VALUE",code:400,message:U}};let D=I.pattern?_s.get(I.pattern):void 0,w=I.format?Zn[I.format]:void 0,Cn=D??w;if(Cn&&typeof R[I.name]=="string"){let dt=R[I.name],Pn=I.format?Jn[I.format]:void 0;if(!(Cn.test(dt)&&(!D||!w||w.test(dt))&&(!Pn||Pn(dt)))){let fn=(I.description??"").split(/\.\s/)[0].replace(/\.?\s*$/,""),o_=fn?`. ${fn}.`:".";return{status:400,data:{error:"INVALID_VALUE",code:400,message:`Invalid value for ${I.name}: "${String(dt).slice(0,80)}"${o_}`}}}}}}if(!T&&!r.baseURL)return ss(r,"Brokerage API");let b=da[t];if(!T&&b&&Ea([i,s,o],b),!T&&d&&!Me(d)){let I={...i,...s,...o};try{let R=await d(I,r),U=Gr[t];return U&&(R=ae(R,U)),{status:200,data:R}}catch(R){if(R instanceof ct)return{status:R.status,data:R.data};let U=R instanceof P?R.status:500,D=P.stripGrpcPrefix(R instanceof Error?R.message:String(R));return{status:U,data:{error:R instanceof P&&R.code?R.code:"HANDLER_ERROR",code:U,message:D}}}}let f=d??{},v=T?{origin:"AgentAPI",method:c.method,path:c.path}:f.endpoint,z=T?void 0:f.requestMap,L=T?void 0:f.responseMap,h=T?void 0:f.responseUnwrap,q={...i,...o},Z=kr(q,z),{resolvedPath:tt,remainingParams:it}=ca(v.path,Z);if(tt.includes("{"))return{status:400,data:{error:"MISSING_PATH_PARAMS",code:400,message:`Missing required param(s): ${(tt.match(/\{([^}]+)\}/g)?.map(R=>R.slice(1,-1))??[]).join(", ")}`}};let dr=v.method==="POST"||v.method==="PUT"||v.method==="DELETE"||v.method==="PATCH",yt,S=a??null,y={...T?s:kr(s,z)},k=T?p:v.baseURL??r.baseURL;if(!k)return ss(r,T?"Agent API":"Brokerage API");dr?(yt=is(k,tt),a&&u&&(Object.keys(o).length>0||c?.closedInput||g?.validateInput)?S=new TextEncoder().encode(JSON.stringify(it)):!S&&Object.keys(it).length>0&&(S=new TextEncoder().encode(JSON.stringify(it)))):(Object.assign(y,it),yt=is(k,tt));let et=ua(y);if(et&&(yt+=et),c?.eventStream){let I=n?e.stream:void 0;if(!I||!r.doStream)return{status:400,data:{error:"STREAM_REQUIRED",message:"Use the CLI streaming command; live tools are unavailable over local MCP."}};let R=await r.doStream({method:v.method,url:yt,headers:{..._,Accept:"text/event-stream"},signal:I.signal});if(R.ok)return await rs(R,I.onEvent,I.signal),{status:R.status,data:null,headers:R.headers};let U=await R.text(),D;try{D=JSON.parse(U)}catch{D=U}return{status:R.status,data:D,headers:R.headers}}let $;try{$=await r.doRequest({method:v.method,url:yt,body:S,headers:Object.keys(_).length>0?_:void 0})}catch(I){if(!T||O||c?.agentApi!=="eligible"||!ga(I))throw I;let R=I instanceof Error?I.message:String(I);throw new Error(`${R}
|
|
50
|
+
Hint: ${Vr}`)}let Dt=new TextDecoder().decode($.body),V;try{V=JSON.parse(Dt)}catch{V=Dt}if($.status>=400){let I=f.sanitizeError?f.sanitizeError(V):V,R=g?.errorResponse?.($.status)??(T&&c?.agentApi==="eligible"&&!O&&la($.status)?pa(I,$.status):I);return{status:$.status,data:R,headers:$.headers}}if(f.validateResponse)try{f.validateResponse(V)}catch(I){let R=I instanceof P?I.status:502,U=P.stripGrpcPrefix(I instanceof Error?I.message:String(I));return{status:R,data:{error:R===502?"MALFORMED_RESPONSE":"UPSTREAM_REJECTION",code:R,message:U},headers:$.headers}}h&&(V=Ia(V,h)),L&&(V=ts(V,L)),g?.normalizeResponse&&(V=g.normalizeResponse(V));let re=Ta(t,h);return re&&(V=ae(V,re)),{status:$.status,data:V,headers:$.headers}}var os,Gr,_s,da,Vr,ce=C(()=>{"use strict";E();l();Lt();Mr();es();Ot();lt();mt();_t();ns();Fr();os=[...j.flatMap(t=>t.actions),...Object.values(Q)],Gr={},_s=new Map;for(let t of os){Gr[t.id]=t.responseFields;for(let e of t.params)e.pattern&&_s.set(e.pattern,new RegExp(e.pattern))}da={orders_list:{product_ids:"split-comma"},orders_fills:{product_ids:"split-comma"},products_list:{product_ids:"split-comma"}};Vr="To bypass the Agent API temporarily, retry with COINBASE_TRANSPORT=brokerage."});import{readFileSync as ma,writeFileSync as Oa,mkdirSync as Aa}from"node:fs";import{join as cs}from"node:path";function as(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 Sa(t,e){let r=as(t),n=as(e);return n.major!==r.major?n.major>r.major:n.minor!==r.minor?n.minor>r.minor:n.patch>r.patch}function Pa(t,e){let r=Ae===Ca?"":` --registry ${Ae}`;return`
|
|
49
51
|
Update available: ${t} \u2192 ${e}
|
|
50
|
-
Run: npm i -g ${
|
|
51
|
-
`}function
|
|
52
|
-
`)}var kr,Fr,Va,wr=S(()=>{"use strict";u();d();kr={k:1e3,m:1e6,b:1e9};Fr=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&&ka(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()}};Va=/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/});function ot(t){return Ps[t]??null}var Wa,xa,Ba,Ha,Ps,Ee=S(()=>{"use strict";u();d();ft();Wa="wss://advanced-trade-ws.coinbase.com",xa="wss://advanced-trade-ws-user.coinbase.com",Ba={public:Wa,user:xa},Ha=[...X.flatMap(t=>t.actions),...Object.values(Z)],Ps={};for(let t of Ha)t.watch&&(Ps[t.id]={name:t.watch.channel,...t.watch.wireName?{wireName:t.watch.wireName}:{},endpoint:Ba[t.watch.endpoint],requiresAuth:t.watch.requiresAuth,coalesce:t.watch.coalesce})});var K,Ka,Ya,We,xe=S(()=>{"use strict";u();d();K={CONNECTING:"CONNECTING",CONNECTED:"CONNECTED",SUBSCRIBED:"SUBSCRIBED",RECONNECTING:"RECONNECTING",FAILED:"FAILED"},Ka=3e4,Ya=1e3,We=class{url;opts;ws=null;_state=K.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(K.CONNECTING);try{this.ws=new this.WSClass(this.url)}catch{this.scheduleReconnect();return}this.resetHeartbeat(),this.ws.onopen=()=>{this.lastActivityTime=this.now(),this.setState(K.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(K.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===K.RECONNECTING&&!this.wasReconnecting&&(this.wasReconnecting=!0,this.opts.onDisconnect?.()),e===K.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(K.FAILED);return}this.setState(K.RECONNECTING);let e=Math.min(Ya*Math.pow(2,this.retryCount),Ka),r=500+Math.random()*(e-500);this.retryCount++,this.reconnectTimer=setTimeout(()=>{this.connect()},r)}}});var Be,fs=S(()=>{"use strict";u();d();xe();Be=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===K.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 We(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===K.CONNECTED||this.conn.state===K.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 He(t,e){return br(t,e,"","","")}var Wr=S(()=>{"use strict";u();d();Fe()});var Ke,Ds=S(()=>{"use strict";u();d();Ke=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 xr(t,e,r){if(!r||t===0)return"";let n=t>0?Kt:Yt;return e?`${Ht}${n}`:n}function Ms(t,e,r){if(!r)return"";let n=t==="bid"||t==="BUY"?Kt:Yt;return e?`${Ht}${n}`:n}var z,Ht,Kt,Yt,ys,Y,bs,Ls,hs,Us,qt=S(()=>{"use strict";u();d();z="\x1B[2m",Ht="\x1B[1m",Kt="\x1B[32m",Yt="\x1B[31m",ys="\x1B[33m",Y="\x1B[0m",bs="\x1B[?25l",Ls="\x1B[?25h",hs="\x1B[?1049h",Us="\x1B[?1049l"});var zt,vs=S(()=>{"use strict";u();d();qt();zt=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(hs),this.inAltScreen=!0}exitAltScreen(){this.out.write(Us),this.inAltScreen=!1}hideCursor(){this.out.write(bs),this.cursorHidden=!0}showCursor(){this.out.write(Ls),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(Y),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 ue,ks=S(()=>{"use strict";u();d();ue=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 W(t,e){let r=mt(t);return r>=e?t.slice(0,t.length-(r-e)):t+" ".repeat(e-r)}function k(t,e){let r=mt(t);return r>=e?t.slice(0,t.length-(r-e)):" ".repeat(e-r)+t}function At(t,e){let r="\u2500".repeat(t);return e?`${z}${r}${Y}`:r}function $t(t,e,r){let n=mt(t),i=mt(e);if(n+1+i>r){let o=r-i-1;return o>0?`${t.slice(0,o)} ${e}`:e.slice(0,r)}let _=r-n-i;return _<0?W(`${t} ${e}`,r):`${t}${" ".repeat(_)}${e}`}function jt(t,e){return e?t?`${Ht}\xB7${Y}`:`${z}\xB7${Y}`:""}function J(){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 de=S(()=>{"use strict";u();d();Ge();qt()});function j(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 Qt(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 Fs(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 Vs(t){return`${t>=0?"+":""}${t.toFixed(2)}%`}function Gs(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 Ye=S(()=>{"use strict";u();d()});function xs(t){let e=[],r=0;for(let n of qa){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 Bs(){return{events:[],positions:new Map,openOrders:new Set,totalFees:0,lastClock:J(),netCash:0,fillCount:0,accounted:new Map,prependCount:0,heartbeat:!1,updateCount:0}}function za(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 $a(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 Br(t,e,r="live"){let n=t.events;if(!n)return{inserts:[],updates:[]};let i=[],s=[];for(let _ of n){let o=_.orders;if(o)for(let a of o){let E={order_id:String(a.order_id??""),status:String(a.status??""),product_id:String(a.product_id??""),order_side:String(a.order_side??a.side??""),order_type:a.order_type?String(a.order_type):void 0,average_filled_price:String(a.average_filled_price??a.avg_price??"0"),total_fees:String(a.total_fees??"0"),filled_size:String(a.filled_size??a.cumulative_quantity??"0"),base_size:za(a),creation_time:a.creation_time?String(a.creation_time):a.created_time?String(a.created_time):void 0},g=e.events.findIndex(c=>c.order_id===E.order_id);if(g>=0){let c=e.events[g],l=c.status!==E.status||c.filled_size!==E.filled_size||c.total_fees!==E.total_fees||c.average_filled_price!==E.average_filled_price;c.status=E.status,c.average_filled_price=E.average_filled_price,c.filled_size=E.filled_size,c.total_fees=E.total_fees,l&&(ws(e,E),s.push(c));continue}r==="backfill"?e.events.splice($a(e.events,E),0,E):e.events.unshift(E),e.prependCount++,ws(e,E),i.push(E),e.events.length>1e4&&e.events.pop()}}return{inserts:i,updates:s}}function ws(t,e){t.updateCount++,t.lastClock=J();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,_=i*s,o=t.accounted.get(e.order_id)??{fees:0,size:0,value:0},a=n-o.fees,E=i-o.size,g=_-o.value;(E!==0||a!==0)&&(o.size===0&&i>0&&t.fillCount++,t.totalFees+=a,e.order_side==="BUY"?(t.netCash-=g,t.positions.set(e.product_id,(t.positions.get(e.product_id)??0)+E)):(t.netCash+=g,t.positions.set(e.product_id,(t.positions.get(e.product_id)??0)-E)),t.accounted.set(e.order_id,{fees:n,size:i,value:_}))}function ja(t,e,r,n,i){let s=e.order_side==="BUY"?"BUY":"SELL",_=Ms(s,n,i),o=e.status.toUpperCase(),a=i?Y:"",E=parseFloat(e.average_filled_price??"0"),g=parseFloat(e.filled_size??"0");switch(t){case"time":return W(Gs(e.creation_time??new Date().toISOString()),r);case"status":return`${(o==="OPEN"||o==="PENDING")&&i?ys:""}${W(o,r)}${a}`;case"product":return W(e.product_id,r);case"side":return`${_}${W(s,r)}${a}`;case"size":{let c=g>0?Qt(g):e.base_size??"-";return`${_}${k(c,r)}${a}`}case"price":return`${_}${k(E>0?j(E):"-",r)}${a}`;case"fee":{let c=parseFloat(e.total_fees??"0");return k(c>0?j(c):"-",r)}case"id":return`${i?z:""}${W(e.order_id.slice(0,r),r)}${a}`;default:return W("",r)}}function ge(t,e,r,n=80){return xs(n).map(i=>ja(i.key,t,i.width,e,r)).join(" ")}function Qa(t,e=80){let r=new Set(["size","price","fee"]),i=xs(e).map(s=>r.has(s.key)?k(s.header,s.width):W(s.header,s.width)).join(" ");return t?`${z}${i}${Y}`:i}function Xa(t,e,r){let n=t.netCash>=0?r?Kt:"":r?Yt:"",i=r?Y:"",s=`Fills:${t.fillCount}`,_=`Open:${t.openOrders.size}`,o=`Fees:${j(t.totalFees)}`,a=`Net:${t.netCash>=0?"+":""}${j(t.netCash)}`,E=`${n}${a}${i}`,c=`${jt(t.heartbeat,r)} ${t.lastClock}`,l=`\xB7 ${t.lastClock}`,p=`${s} ${_} ${o} ${a}`,A=`${s} ${_} ${o} ${E}`,T=new Map;for(let[y,h]of t.positions){if(Math.abs(h)<1e-9)continue;let $=(y.match(/-/g)??[]).length===1?y.slice(0,y.indexOf("-")):y;T.set($,(T.get($)??0)+h)}let N=[],f=[];for(let[y,h]of T){if(Math.abs(h)<1e-9)continue;let x=`${y}:${Qt(h)}`;N.push(x),f.push(x)}let M=e-p.length-l.length-6,v="";if(N.length>0&&M>8){let y="",h=0,x=0;for(let $=0;$<N.length;$++){let at=x>0?" ":"";if(h+at.length+f[$].length>M){let ct=N.length-x;ct>0&&(y+=` +${ct}`);break}y+=at+N[$],h+=at.length+f[$].length,x++}v=y}let Q=v?`${A} ${v}`:A;return $t(Q,c,e)}function Hs(t,e,r,n,i){let s=i??e.events,_=t.cols,o=t.rows,a=o,E=o-1,g=o-2;n.inserts.forEach((c,l)=>{r.flashWithOffset(c.order_id,e.prependCount-1-l,1500),t.moveTo(qe,1),t.insertLine(),t.write(ge(c,!0,!0,t.cols)+"\x1B[K")});for(let c of n.updates){let l=s.indexOf(c);if(l>=0){let p=qe+l;p<=g&&(r.flash(c.order_id,1500),t.moveTo(p,1),t.write(ge(c,!0,!0,t.cols)+"\x1B[K"))}}for(let c of r.expired()){let l=s.findIndex(p=>p.order_id===c);if(l>=0){let p=qe+l;p<=g&&(t.moveTo(p,1),t.write(ge(s[l],!1,!0,t.cols)+"\x1B[K"))}}t.moveTo(E,1),t.write(At(_,!0)),t.moveTo(a,1),t.write(Xa(e,_-1,!0)+"\x1B[K")}function Hr(t){t.enterAltScreen(),t.hideCursor();let e=t.rows;t.setScrollRegion(qe,e-2),t.moveTo(1,1),t.write(Qa(!0,t.cols)+"\x1B[K"),t.moveTo(2,1),t.write(At(t.cols,!0))}function Ws(t){return t?.toLowerCase()}function ze(t,e,r){return{_ch:"user",_seq:e,_ts:r,order_id:t.order_id,status:Ws(t.status),product_id:t.product_id,side:Ws(t.order_side),filled_size:t.filled_size??null,price:t.average_filled_price??null,fees:t.total_fees??null}}function Ks(t,e,r){return JSON.stringify(ze(t,e,r))}var qe,qa,Ys=S(()=>{"use strict";u();d();de();qt();Ye();qe=3,qa=[{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 qs(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)),_=Math.round(s*(n-1)),o="";for(let a=0;a<n;a++)o+=a===_?"\u25CF":"\u2500";return o}function zs(t,e,r){if(e<=0||t<=0)return"";let n=Math.max(0,Math.round(t/e*r));return"\u2588".repeat(n)}var Kr=S(()=>{"use strict";u();d()});function Qs(t){let e=[],r=0;for(let n of tc){if(r+n.width+1>t)break;e.push(n),r+=n.width+1}return e}function Xs(){return{products:new Map,prevPrices:new Map,productOrder:[],heartbeat:!1,updateCount:0,lastClock:J()}}function Zs(t,e){let r=t.events;if(!r)return[];let n=[];for(let i of r){let s=i.tickers;if(s)for(let _ of s){let o={product_id:String(_.product_id??""),price:String(_.price??"0"),volume_24_h:String(_.volume_24_h??"0"),price_percent_chg_24_h:String(_.price_percent_chg_24_h??"0"),best_bid:String(_.best_bid??"0"),best_bid_quantity:String(_.best_bid_quantity??"0"),best_ask:String(_.best_ask??"0"),best_ask_quantity:String(_.best_ask_quantity??"0"),high_24_h:String(_.high_24_h??"0"),low_24_h:String(_.low_24_h??"0")},a=e.prevPrices.get(o.product_id),E=parseFloat(o.price),g=0;a!==void 0&&(E>a?g=1:E<a&&(g=-1)),e.prevPrices.set(o.product_id,E),e.products.set(o.product_id,o),e.productOrder.includes(o.product_id)||e.productOrder.push(o.product_id),e.updateCount++,e.lastClock=J(),n.push({ticker:o,direction:g})}}return n}function ec(t,e,r,n,i,s){let _=parseFloat(e.price),o=s?Y:"";switch(t){case"symbol":return W(e.product_id,r);case"price":return`${xr(n,i,s)}${k(j(_),r)}${o}`;case"pct":{let a=parseFloat(e.price_percent_chg_24_h),E=a>0?1:a<0?-1:0;return`${xr(E,!1,s)}${k(Vs(a),r)}${o}`}case"bid":return k(j(parseFloat(e.best_bid)),r);case"ask":return k(j(parseFloat(e.best_ask)),r);case"bidSz":return`${s?z:""}${k(Qt(parseFloat(e.best_bid_quantity)),r)}${o}`;case"askSz":return`${s?z:""}${k(Qt(parseFloat(e.best_ask_quantity)),r)}${o}`;case"low":return`${s?z:""}${k(j(parseFloat(e.low_24_h)),r)}${o}`;case"high":return`${s?z:""}${k(j(parseFloat(e.high_24_h)),r)}${o}`;case"range":return W(qs(_,parseFloat(e.low_24_h),parseFloat(e.high_24_h),r),r);case"vol":return`${s?z:""}${k(Fs(parseFloat(e.volume_24_h)),r)}${o}`;default:return W("",r)}}function js(t,e,r,n,i=80){return Qs(i).map(_=>ec(_.key,t,_.width,e,r,n)).join(" ")}function rc(t,e=80){let n=Qs(e).map(i=>i.key==="symbol"||i.key==="range"?W(i.header,i.width):k(i.header,i.width)).join(" ");return t?`${z}${n}${Y}`:n}function nc(t,e,r){let n=`${t.products.size} product${t.products.size!==1?"s":""}`,s=`${jt(t.heartbeat,r)} ${t.lastClock}`;return $t(n,s,e)}function Yr(t){t.enterAltScreen(),t.hideCursor(),t.moveTo(Za,1),t.write(rc(!0,t.cols)+"\x1B[K"),t.moveTo(Ja,1),t.write(At(t.cols,!0))}function Js(t,e,r,n,i){let s=t.cols,_=t.rows,o=_,a=_-1;for(let{ticker:E,direction:g}of n){let c=e.productOrder.indexOf(E.product_id);if(c<0)continue;let l=$s+c;if(l>=a)continue;let p=i?.has(E.product_id)??!1,A=!p&&r.isFlashing(E.product_id);t.moveTo(l,1);let T=js(E,p?0:g,A,!0,s);t.write((p?z+T+Y:T)+"\x1B[K")}for(let E of r.expired()){let g=e.productOrder.indexOf(E);if(g<0)continue;let c=$s+g;if(c>=a)continue;let l=e.products.get(E);l&&(t.moveTo(c,1),t.write(js(l,0,!1,!0,s)+"\x1B[K"))}t.moveTo(a,1),t.write(At(s,!0)),t.moveTo(o,1),t.write(nc(e,s-1,!0)+"\x1B[K")}function qr(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 t_(t,e,r){return JSON.stringify(qr(t,e,r))}var Za,Ja,$s,tc,e_=S(()=>{"use strict";u();d();de();qt();Ye();Kr();Za=1,Ja=2,$s=3,tc=[{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 r_(t,e){if(!t)return 0n;if(!ic.test(t))throw new Error(`invalid decimal: ${t}`);let r=t.startsWith("-"),[n,i=""]=(r?t.slice(1):t).split(".");if(i.length>e)throw new Error(`too many decimal places (max ${e}): ${t}`);let s=BigInt(n||"0")*10n**BigInt(e)+BigInt(i.padEnd(e,"0")||"0");return r?-s:s}function $e(t,e){let r=t<0n,n=(r?-t:t).toString().padStart(e+1,"0"),i=n.slice(0,n.length-e),s=n.slice(n.length-e).replace(/0+$/,"");return`${r?"-":""}${i}${s?`.${s}`:""}`}var ic,n_=S(()=>{"use strict";u();d();ic=/^-?(?:\d+(?:\.\d*)?|\.\d+)$/});function s_(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:J()}}function __(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 _=s.type,o=s.updates;if(_==="snapshot"&&(e.bids.clear(),e.asks.clear()),!!o){for(let a of o){let E=String(a.side??"").toLowerCase(),g;try{g=r_(String(a.price_level??"0"),je)}catch{continue}let c=parseFloat(String(a.new_quantity??"0"));if(g<=0n)continue;let l=E==="bid"?e.bids:e.asks;c<=0?l.delete(g):l.set(g,c)}e.updateCount++,e.lastClock=J()}}}function Xe(t){let e=[];for(let[r,n]of t.bids)e.push({price:r,size:n});return e.sort((r,n)=>r.price<n.price?1:r.price>n.price?-1:0),e}function Ze(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?-1:r.price>n.price?1:0),e}function Qe(t){return Number($e(t,je))}function o_(t,e){if(t.length===0||e.length===0)return null;let r=t[0].price,n=e[0].price;return{spread:$e(n-r,je),mid:$e(5n*(n+r),je+1)}}function i_(t,e,r,n,i,s,_){let o=_?i==="bid"?Kt:Yt:"",a=_?Y:"",E=zs(r,n,s),g=`${o}${E}${a}`;return[`${o}${k(j(t),Nt[0])}${a}`,k(e.toFixed(4),Nt[1]),k(r.toFixed(4),Nt[2]),g].join(" ")}function oc(t,e,r){let n=o_(Xe(t),Ze(t)),i=r?z:"",s=r?Y:"";if(!n)return`${i}${W(" Waiting for data...",e)}${s}`;let _=Number(n.spread),o=Number(n.mid),a=_/o*100,E=` Spread: ${j(_).padStart(10)} (${a.toFixed(3).padStart(6)}%) Mid: ${j(o).padStart(12)}`;return`${i}${W(E,e)}${s}`}function ac(t,e,r){let n=_c.map((a,E)=>E===3?W(a,Nt[E]):k(a,Nt[E])).join(" "),i=r?z:"",s=r?Ht:"",_=r?Y:"",o=`${s}${t.productId}${_}`;return`${W(o,e)}
|
|
53
|
-
${i}${n}${
|
|
54
|
-
Set up a CDP key: coinbase env <name> --key-file key.json`);if(n.type==="cdp_key"&&n.key_id&&n.key_secret)return
|
|
52
|
+
Run: npm i -g ${Ge}${r}
|
|
53
|
+
`}function Es(){return Rt()}function ya(){try{return JSON.parse(ma(cs(Es(),ds),"utf8"))}catch{return null}}function Da(t){try{let e=Es();Aa(e,{recursive:!0}),Oa(cs(e,ds),JSON.stringify(t))}catch{}}async function ba(){try{let t=new AbortController,e=setTimeout(()=>t.abort(),3e3),r=await fetch(Na,{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 ls(){if(process.env.CI||process.env.COINBASE_NO_UPDATE_CHECK)return"";let t=ya();if(t&&Date.now()-t.checkedAt<fa)return"";let e=await ba();return e?(Da({checkedAt:Date.now(),latestVersion:e}),Sa(gt,e)?Pa(gt,e):""):""}var us,gt,Ge,Na,ds,Ca,fa,we=C(()=>{"use strict";E();l();Ne();_t();us="0.0.11";gt=us,Ge=yn,Na=`${Ae}/${encodeURIComponent(Ge)}`,ds="version-check.json";Ca="https://registry.npmjs.org";fa=1440*60*1e3});import{createSign as La,createPrivateKey as ha,sign as Ua,randomBytes as va}from"node:crypto";function wr(t){return Buffer.from(t).toString("base64url")}function xe(t){return wr(Buffer.from(JSON.stringify(t)))}function Ma(){return va(16).toString("hex")}function ps(t){return t.includes("-----BEGIN EC PRIVATE KEY-----")}function Is(t){let e=Buffer.from(t,"base64");return e.length===32||e.length===64}function xr(t,e,r,n,i){let s=Math.floor(Date.now()/1e3),o=Ma(),_={sub:t,iss:"cdp",nbf:s,iat:s,exp:s+120},a=`${r} ${n}${i}`;if(r&&n&&i&&(_.uris=[a]),ps(e))return Fa(t,e,_,o);if(Is(e))return Va(t,e,_,o);throw new Error("invalid key format - must be either PEM EC key or base64 Ed25519 key")}function ka(t,e,r){let n=`${xe(t)}.${xe(e)}`,i=La("SHA256");i.update(n);let s=i.sign(r);return`${n}.${wr(Ga(s))}`}function Fa(t,e,r,n){return ka({alg:"ES256",typ:"JWT",kid:t,nonce:n},r,e)}function Va(t,e,r,n){let s=`${xe({alg:"EdDSA",typ:"JWT",kid:t,nonce:n})}.${xe(r)}`,o=Buffer.from(e,"base64"),_=ha({key:Buffer.concat([Buffer.from("302e020100300506032b657004220420","hex"),o.subarray(0,32)]),format:"der",type:"pkcs8"}),a=Ua(null,Buffer.from(s),_);return`${s}.${wr(a)}`}function Ga(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=gs(n,32),s=gs(s,32),Buffer.concat([n,s])}function gs(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 wa(t){return ps(t)?"ecdsa":Is(t)?"ed25519":"unknown"}async function Wr(t){let e;if(t.keyId&&t.keySecret){let n=new URL(t.url);e=`Bearer ${xr(t.keyId,t.keySecret,t.method,n.host,n.pathname)}`}else throw new Error("doAuthenticatedRequest: must supply keyId+keySecret");let r={Authorization:e,"Content-Type":"application/json","Correlation-Context":`sdk_version=${encodeURIComponent(gt)},sdk_language=typescript,source=${encodeURIComponent(Ge)}`,...t.headers};return fetch(t.url,{method:t.method,headers:r,body:t.body?Buffer.from(t.body):void 0,signal:t.signal,redirect:t.redirect})}async function We(t){let e=await Wr(t),n={body:new Uint8Array(await e.arrayBuffer()),status:e.status,headers:e.headers};return e.status===401&&t.keySecret&&wa(t.keySecret)==="ed25519"&&(n.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 ...`."),n}var Be=C(()=>{"use strict";E();l();we()});function _c(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 Nt(t){return t.replace(/\x1b\]8;;[^\x07]*\x07/g,"").replace(/\x1b\[[0-9;]*m/g,"").length}var Gs,Ke=C(()=>{"use strict";E();l();Gs=_c(process.env,!!process.stdout.isTTY)});function Kt(t,e){if(!t)return 0n;if(!cc.test(t))throw new Error(`invalid decimal: ${t}`);let r=t.startsWith("-"),[n,i=""]=(r?t.slice(1):t).split(".");if(i.length>e)throw new Error(`too many decimal places (max ${e}): ${t}`);let s=BigInt(n||"0")*10n**BigInt(e)+BigInt(i.padEnd(e,"0")||"0");return r?-s:s}function qt(t,e){let r=t<0n,n=(r?-t:t).toString().padStart(e+1,"0"),i=n.slice(0,n.length-e),s=n.slice(n.length-e).replace(/0+$/,"");return`${r?"-":""}${i}${s?`.${s}`:""}`}var cc,zr=C(()=>{"use strict";E();l();cc=/^-?(?:\d+(?:\.\d*)?|\.\d+)$/});function uc(t,{exactDecimals:e=!1}){let r=[],n=0;for(;n<t.length;){if(t[n]===" "||t[n]===" "){n++;continue}let i=n;if(t[n]==="("){r.push({type:js,value:"(",pos:i}),n++;continue}if(t[n]===")"){r.push({type:Qs,value:")",pos:i}),n++;continue}if(n+1<t.length){let s=t[n]+t[n+1];if(s==="=="){r.push({type:Jr,value:"==",pos:i}),n+=2;continue}if(s==="!="){r.push({type:Bs,value:"!=",pos:i}),n+=2;continue}if(s===">="){r.push({type:qs,value:">=",pos:i}),n+=2;continue}if(s==="<="){r.push({type:tn,value:"<=",pos:i}),n+=2;continue}if(s==="&&"){r.push({type:Ys,value:"&&",pos:i}),n+=2;continue}if(s==="||"){r.push({type:zs,value:"||",pos:i}),n+=2;continue}}if(t[n]===">"){r.push({type:Hs,value:">",pos:i}),n++;continue}if(t[n]==="<"){r.push({type:Ks,value:"<",pos:i}),n++;continue}if(t[n]==='"'){n++;let s="";for(;n<t.length&&t[n]!=='"';)t[n]==="\\"&&n+1<t.length&&n++,s+=t[n],n++;if(n>=t.length)throw new Error(`Unterminated string at position ${i}`);n++,r.push({type:Ws,value:s,pos:i});continue}if(t[n]==="-"||t[n]>="0"&&t[n]<="9"){let s="";if(t[n]==="-")if(n+1<t.length&&t[n+1]>="0"&&t[n+1]<="9")s+=t[n],n++;else throw new Error(`Unexpected character '-' at position ${i}`);for(;n<t.length&&t[n]>="0"&&t[n]<="9";)s+=t[n],n++;if(n<t.length&&t[n]===".")for(s+=".",n++;n<t.length&&t[n]>="0"&&t[n]<="9";)s+=t[n],n++;let o=n<t.length?t[n]:"",_=o.toLowerCase()in $r&&(n+1>=t.length||t[n+1]===" "||t[n+1]===" "||t[n+1]===")"||t[n+1]==="&"||t[n+1]==="|");if(o&&!_&&(o>="a"&&o<="z"||o>="A"&&o<="Z"||o==="-"))n=i;else{let a=e?s:parseFloat(s);if(n<t.length&&t[n].toLowerCase()in $r){let u=$r[t[n].toLowerCase()];if(typeof a=="string"){let d=a.split(".")[1]?.length??0;a=qt(Kt(a,d)*BigInt(u),d)}else a*=u;n++}r.push({type:Qr,value:a,pos:i});continue}}if(t[n]>="a"&&t[n]<="z"||t[n]>="A"&&t[n]<="Z"||t[n]==="_"||t[n]>="0"&&t[n]<="9"){let s="";for(;n<t.length&&(t[n]>="a"&&t[n]<="z"||t[n]>="A"&&t[n]<="Z"||t[n]>="0"&&t[n]<="9"||t[n]==="_"||t[n]==="-");)s+=t[n],n++;r.push({type:jr,value:s,pos:i});continue}throw new Error(`Unexpected character '${t[n]}' at position ${i}`)}return r.push({type:$s,value:"",pos:n}),r}function dc(t){return t>=Jr&&t<=tn}function ge(t,e={}){let r=t.trim();if(r.length===0)throw new Error("Empty predicate");return new Xr(uc(r,e)).parse()}function le(t){switch(t.type){case"comparison":return t.product?[t.product]:[];case"and":case"or":return[...le(t.left),...le(t.right)]}}function Zr(t){return t.format==="decimal"}function Xs(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}let o=Zr(s);!o&&typeof i.value=="number"&&r.push({field:i.field,message:`'${i.field}' is a string field \u2014 use "${i.value}" not ${i.value}`}),o&&typeof i.value=="string"&&r.push({field:i.field,message:`'${i.field}' is a numeric field \u2014 use ${i.value} not "${i.value}"`}),!o&&(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 Ec(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 gc(t,e){if(typeof e=="number"){if(typeof t=="number")return[t,e];if(typeof t=="string"&&lc.test(t))return[parseFloat(t),e]}return null}function pc(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=Ec(n,t.field);if(i==null)return!1;if(t.decimal){let o=typeof i=="number"&&Number.isSafeInteger(i)?String(i):i;if(typeof o!="string"||!/^-?(?:\d+(?:\.\d*)?|\.\d+)$/.test(o))return!1;let _=String(t.value),a=Math.max(o.split(".")[1]?.length??0,_.split(".")[1]?.length??0),u=Kt(o,a),d=Kt(_,a);switch(t.op){case"==":return u===d;case"!=":return u!==d;case">":return u>d;case"<":return u<d;case">=":return u>=d;case"<=":return u<=d}}let s=gc(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 St(t,e,r){switch(t.type){case"comparison":return pc(t,e,r);case"and":return St(t.left,e,r)&&St(t.right,e,r);case"or":return St(t.left,e,r)||St(t.right,e,r)}}function Zs(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,o]of Object.entries(t)){let _=o.enum?o.enum.join("|"):Zr(o)?"number":o.type;e.push(` ${s.padEnd(r)} ${_.padEnd(12)} ${o.description}`)}let n=Object.entries(t).filter(([,s])=>Zr(s)).map(([s])=>s),i=Object.entries(t).filter(([,s])=>s.enum).map(([s,o])=>({k:s,vals:o.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(`
|
|
54
|
+
`)}var jr,Qr,Ws,Jr,Bs,Hs,Ks,qs,tn,Ys,zs,$s,js,Qs,$r,Xr,lc,Ye=C(()=>{"use strict";E();l();zr();jr=0,Qr=1,Ws=2,Jr=3,Bs=4,Hs=5,Ks=6,qs=7,tn=8,Ys=9,zs=10,$s=11,js=12,Qs=13,$r={k:1e3,m:1e6,b:1e9};Xr=class{tokens;pos=0;constructor(e){this.tokens=e}parse(){let e=this.parseOr();if(this.current().type!==$s)throw new Error(`Unexpected token '${this.current().value}' at position ${this.current().pos}`);return e}parseOr(){let e=this.parseAnd();for(;this.current().type===zs;)this.advance(),e={type:"or",left:e,right:this.parseAnd()};return e}parseAnd(){let e=this.parseAtom();for(;this.current().type===Ys;)this.advance(),e={type:"and",left:e,right:this.parseAtom()};return e}parseAtom(){if(this.current().type===js){this.advance();let e=this.parseOr();if(this.current().type!==Qs)throw new Error(`Expected ')' at position ${this.current().pos}`);return this.advance(),e}return this.parseComparison()}parseComparison(){let r=this.expect(jr,"field name").value,n;this.current().type===jr&&this.pos+1<this.tokens.length&&dc(this.tokens[this.pos+1].type)&&(n=this.advance().value);let i=this.parseOp(),s,o=this.current().type===Qr&&typeof this.current().value=="string";if(this.current().type===Qr)s=this.advance().value;else if(this.current().type===Ws)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,...o?{decimal:!0}:{}}}parseOp(){let e=this.current();switch(e.type){case Jr:return this.advance(),"==";case Bs:return this.advance(),"!=";case Hs:return this.advance(),">";case Ks:return this.advance(),"<";case qs:return this.advance(),">=";case tn: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()}};lc=/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/});function ut(t){return Js[t]??null}var Ic,Rc,Tc,mc,Js,pe=C(()=>{"use strict";E();l();mt();Ic="wss://advanced-trade-ws.coinbase.com",Rc="wss://advanced-trade-ws-user.coinbase.com",Tc={public:Ic,user:Rc},mc=[...j.flatMap(t=>t.actions),...Object.values(Q)],Js={};for(let t of mc)t.watch&&(Js[t.id]={name:t.watch.channel,...t.watch.wireName?{wireName:t.watch.wireName}:{},endpoint:Tc[t.watch.endpoint],requiresAuth:t.watch.requiresAuth,coalesce:t.watch.coalesce})});var B,Oc,Ac,ze,$e=C(()=>{"use strict";E();l();B={CONNECTING:"CONNECTING",CONNECTED:"CONNECTED",SUBSCRIBED:"SUBSCRIBED",RECONNECTING:"RECONNECTING",FAILED:"FAILED"},Oc=3e4,Ac=1e3,ze=class{url;opts;ws=null;_state=B.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(B.CONNECTING);try{this.ws=new this.WSClass(this.url)}catch{this.scheduleReconnect();return}this.resetHeartbeat(),this.ws.onopen=()=>{this.lastActivityTime=this.now(),this.setState(B.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(B.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===B.RECONNECTING&&!this.wasReconnecting&&(this.wasReconnecting=!0,this.opts.onDisconnect?.()),e===B.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(B.FAILED);return}this.setState(B.RECONNECTING);let e=Math.min(Ac*Math.pow(2,this.retryCount),Oc),r=500+Math.random()*(e-500);this.retryCount++,this.reconnectTimer=setTimeout(()=>{this.connect()},r)}}});var je,to=C(()=>{"use strict";E();l();$e();je=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===B.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 ze(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===B.CONNECTED||this.conn.state===B.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 Qe(t,e){return xr(t,e,"","","")}var en=C(()=>{"use strict";E();l();Be()});var Xe,eo=C(()=>{"use strict";E();l();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 rn(t,e,r){if(!r||t===0)return"";let n=t>0?zt:$t;return e?`${Yt}${n}`:n}function _o(t,e,r){if(!r)return"";let n=t==="bid"||t==="BUY"?zt:$t;return e?`${Yt}${n}`:n}var Y,Yt,zt,$t,ro,H,no,io,so,oo,jt=C(()=>{"use strict";E();l();Y="\x1B[2m",Yt="\x1B[1m",zt="\x1B[32m",$t="\x1B[31m",ro="\x1B[33m",H="\x1B[0m",no="\x1B[?25l",io="\x1B[?25h",so="\x1B[?1049h",oo="\x1B[?1049l"});var Qt,ao=C(()=>{"use strict";E();l();jt();Qt=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(so),this.inAltScreen=!0}exitAltScreen(){this.out.write(oo),this.inAltScreen=!1}hideCursor(){this.out.write(no),this.cursorHidden=!0}showCursor(){this.out.write(io),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(H),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 Ie,co=C(()=>{"use strict";E();l();Ie=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 W(t,e){let r=Nt(t);return r>=e?t.slice(0,t.length-(r-e)):t+" ".repeat(e-r)}function F(t,e){let r=Nt(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?`${Y}${r}${H}`:r}function Xt(t,e,r){let n=Nt(t),i=Nt(e);if(n+1+i>r){let _=r-i-1;return _>0?`${t.slice(0,_)} ${e}`:e.slice(0,r)}let o=r-n-i;return o<0?W(`${t} ${e}`,r):`${t}${" ".repeat(o)}${e}`}function Zt(t,e){return e?t?`${Yt}\xB7${H}`:`${Y}\xB7${H}`:""}function J(){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 Re=C(()=>{"use strict";E();l();Ke();jt()});function X(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 Jt(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 uo(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 Eo(t){return`${t>=0?"+":""}${t.toFixed(2)}%`}function lo(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 Ze=C(()=>{"use strict";E();l()});function Io(t){let e=[],r=0;for(let n of Nc){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 Ro(){return{events:[],positions:new Map,openOrders:new Set,totalFees:0,lastClock:J(),netCash:0,fillCount:0,accounted:new Map,prependCount:0,heartbeat:!1,updateCount:0}}function Sc(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 Cc(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 nn(t,e,r="live"){let n=t.events;if(!n)return{inserts:[],updates:[]};let i=[],s=[];for(let o of n){let _=o.orders;if(_)for(let a of _){let u={order_id:String(a.order_id??""),status:String(a.status??""),product_id:String(a.product_id??""),order_side:String(a.order_side??a.side??""),order_type:a.order_type?String(a.order_type):void 0,average_filled_price:String(a.average_filled_price??a.avg_price??"0"),total_fees:String(a.total_fees??"0"),filled_size:String(a.filled_size??a.cumulative_quantity??"0"),base_size:Sc(a),creation_time:a.creation_time?String(a.creation_time):a.created_time?String(a.created_time):void 0},d=e.events.findIndex(c=>c.order_id===u.order_id);if(d>=0){let c=e.events[d],g=c.status!==u.status||c.filled_size!==u.filled_size||c.total_fees!==u.total_fees||c.average_filled_price!==u.average_filled_price;c.status=u.status,c.average_filled_price=u.average_filled_price,c.filled_size=u.filled_size,c.total_fees=u.total_fees,g&&(go(e,u),s.push(c));continue}r==="backfill"?e.events.splice(Cc(e.events,u),0,u):e.events.unshift(u),e.prependCount++,go(e,u),i.push(u),e.events.length>1e4&&e.events.pop()}}return{inserts:i,updates:s}}function go(t,e){t.updateCount++,t.lastClock=J();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,o=i*s,_=t.accounted.get(e.order_id)??{fees:0,size:0,value:0},a=n-_.fees,u=i-_.size,d=o-_.value;(u!==0||a!==0)&&(_.size===0&&i>0&&t.fillCount++,t.totalFees+=a,e.order_side==="BUY"?(t.netCash-=d,t.positions.set(e.product_id,(t.positions.get(e.product_id)??0)+u)):(t.netCash+=d,t.positions.set(e.product_id,(t.positions.get(e.product_id)??0)-u)),t.accounted.set(e.order_id,{fees:n,size:i,value:o}))}function Pc(t,e,r,n,i){let s=e.order_side==="BUY"?"BUY":"SELL",o=_o(s,n,i),_=e.status.toUpperCase(),a=i?H:"",u=parseFloat(e.average_filled_price??"0"),d=parseFloat(e.filled_size??"0");switch(t){case"time":return W(lo(e.creation_time??new Date().toISOString()),r);case"status":return`${(_==="OPEN"||_==="PENDING")&&i?ro:""}${W(_,r)}${a}`;case"product":return W(e.product_id,r);case"side":return`${o}${W(s,r)}${a}`;case"size":{let c=d>0?Jt(d):e.base_size??"-";return`${o}${F(c,r)}${a}`}case"price":return`${o}${F(u>0?X(u):"-",r)}${a}`;case"fee":{let c=parseFloat(e.total_fees??"0");return F(c>0?X(c):"-",r)}case"id":return`${i?Y:""}${W(e.order_id.slice(0,r),r)}${a}`;default:return W("",r)}}function Te(t,e,r,n=80){return Io(n).map(i=>Pc(i.key,t,i.width,e,r)).join(" ")}function fc(t,e=80){let r=new Set(["size","price","fee"]),i=Io(e).map(s=>r.has(s.key)?F(s.header,s.width):W(s.header,s.width)).join(" ");return t?`${Y}${i}${H}`:i}function yc(t,e,r){let n=t.netCash>=0?r?zt:"":r?$t:"",i=r?H:"",s=`Fills:${t.fillCount}`,o=`Open:${t.openOrders.size}`,_=`Fees:${X(t.totalFees)}`,a=`Net:${t.netCash>=0?"+":""}${X(t.netCash)}`,u=`${n}${a}${i}`,c=`${Zt(t.heartbeat,r)} ${t.lastClock}`,g=`\xB7 ${t.lastClock}`,p=`${s} ${o} ${_} ${a}`,m=`${s} ${o} ${_} ${u}`,O=new Map;for(let[L,h]of t.positions){if(Math.abs(h)<1e-9)continue;let Z=(L.match(/-/g)??[]).length===1?L.slice(0,L.indexOf("-")):L;O.set(Z,(O.get(Z)??0)+h)}let T=[],b=[];for(let[L,h]of O){if(Math.abs(h)<1e-9)continue;let q=`${L}:${Jt(h)}`;T.push(q),b.push(q)}let f=e-p.length-g.length-6,v="";if(T.length>0&&f>8){let L="",h=0,q=0;for(let Z=0;Z<T.length;Z++){let tt=q>0?" ":"";if(h+tt.length+b[Z].length>f){let it=T.length-q;it>0&&(L+=` +${it}`);break}L+=tt+T[Z],h+=tt.length+b[Z].length,q++}v=L}let z=v?`${m} ${v}`:m;return Xt(z,c,e)}function To(t,e,r,n,i){let s=i??e.events,o=t.cols,_=t.rows,a=_,u=_-1,d=_-2;n.inserts.forEach((c,g)=>{r.flashWithOffset(c.order_id,e.prependCount-1-g,1500),t.moveTo(Je,1),t.insertLine(),t.write(Te(c,!0,!0,t.cols)+"\x1B[K")});for(let c of n.updates){let g=s.indexOf(c);if(g>=0){let p=Je+g;p<=d&&(r.flash(c.order_id,1500),t.moveTo(p,1),t.write(Te(c,!0,!0,t.cols)+"\x1B[K"))}}for(let c of r.expired()){let g=s.findIndex(p=>p.order_id===c);if(g>=0){let p=Je+g;p<=d&&(t.moveTo(p,1),t.write(Te(s[g],!1,!0,t.cols)+"\x1B[K"))}}t.moveTo(u,1),t.write(Ct(o,!0)),t.moveTo(a,1),t.write(yc(e,o-1,!0)+"\x1B[K")}function sn(t){t.enterAltScreen(),t.hideCursor();let e=t.rows;t.setScrollRegion(Je,e-2),t.moveTo(1,1),t.write(fc(!0,t.cols)+"\x1B[K"),t.moveTo(2,1),t.write(Ct(t.cols,!0))}function po(t){return t?.toLowerCase()}function tr(t,e,r){return{_ch:"user",_seq:e,_ts:r,order_id:t.order_id,status:po(t.status),product_id:t.product_id,side:po(t.order_side),filled_size:t.filled_size??null,price:t.average_filled_price??null,fees:t.total_fees??null}}function mo(t,e,r){return JSON.stringify(tr(t,e,r))}var Je,Nc,Oo=C(()=>{"use strict";E();l();Re();jt();Ze();Je=3,Nc=[{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 Ao(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)),o=Math.round(s*(n-1)),_="";for(let a=0;a<n;a++)_+=a===o?"\u25CF":"\u2500";return _}function No(t,e,r){if(e<=0||t<=0)return"";let n=Math.max(0,Math.round(t/e*r));return"\u2588".repeat(n)}var on=C(()=>{"use strict";E();l()});function Po(t){let e=[],r=0;for(let n of Lc){if(r+n.width+1>t)break;e.push(n),r+=n.width+1}return e}function fo(){return{products:new Map,prevPrices:new Map,productOrder:[],heartbeat:!1,updateCount:0,lastClock:J()}}function yo(t,e){let r=t.events;if(!r)return[];let n=[];for(let i of r){let s=i.tickers;if(s)for(let o of s){let _={product_id:String(o.product_id??""),price:String(o.price??"0"),volume_24_h:String(o.volume_24_h??"0"),price_percent_chg_24_h:String(o.price_percent_chg_24_h??"0"),best_bid:String(o.best_bid??"0"),best_bid_quantity:String(o.best_bid_quantity??"0"),best_ask:String(o.best_ask??"0"),best_ask_quantity:String(o.best_ask_quantity??"0"),high_24_h:String(o.high_24_h??"0"),low_24_h:String(o.low_24_h??"0")},a=e.prevPrices.get(_.product_id),u=parseFloat(_.price),d=0;a!==void 0&&(u>a?d=1:u<a&&(d=-1)),e.prevPrices.set(_.product_id,u),e.products.set(_.product_id,_),e.productOrder.includes(_.product_id)||e.productOrder.push(_.product_id),e.updateCount++,e.lastClock=J(),n.push({ticker:_,direction:d})}}return n}function hc(t,e,r,n,i,s){let o=parseFloat(e.price),_=s?H:"";switch(t){case"symbol":return W(e.product_id,r);case"price":return`${rn(n,i,s)}${F(X(o),r)}${_}`;case"pct":{let a=parseFloat(e.price_percent_chg_24_h),u=a>0?1:a<0?-1:0;return`${rn(u,!1,s)}${F(Eo(a),r)}${_}`}case"bid":return F(X(parseFloat(e.best_bid)),r);case"ask":return F(X(parseFloat(e.best_ask)),r);case"bidSz":return`${s?Y:""}${F(Jt(parseFloat(e.best_bid_quantity)),r)}${_}`;case"askSz":return`${s?Y:""}${F(Jt(parseFloat(e.best_ask_quantity)),r)}${_}`;case"low":return`${s?Y:""}${F(X(parseFloat(e.low_24_h)),r)}${_}`;case"high":return`${s?Y:""}${F(X(parseFloat(e.high_24_h)),r)}${_}`;case"range":return W(Ao(o,parseFloat(e.low_24_h),parseFloat(e.high_24_h),r),r);case"vol":return`${s?Y:""}${F(uo(parseFloat(e.volume_24_h)),r)}${_}`;default:return W("",r)}}function Co(t,e,r,n,i=80){return Po(i).map(o=>hc(o.key,t,o.width,e,r,n)).join(" ")}function Uc(t,e=80){let n=Po(e).map(i=>i.key==="symbol"||i.key==="range"?W(i.header,i.width):F(i.header,i.width)).join(" ");return t?`${Y}${n}${H}`:n}function vc(t,e,r){let n=`${t.products.size} product${t.products.size!==1?"s":""}`,s=`${Zt(t.heartbeat,r)} ${t.lastClock}`;return Xt(n,s,e)}function _n(t){t.enterAltScreen(),t.hideCursor(),t.moveTo(Dc,1),t.write(Uc(!0,t.cols)+"\x1B[K"),t.moveTo(bc,1),t.write(Ct(t.cols,!0))}function Do(t,e,r,n,i){let s=t.cols,o=t.rows,_=o,a=o-1;for(let{ticker:u,direction:d}of n){let c=e.productOrder.indexOf(u.product_id);if(c<0)continue;let g=So+c;if(g>=a)continue;let p=i?.has(u.product_id)??!1,m=!p&&r.isFlashing(u.product_id);t.moveTo(g,1);let O=Co(u,p?0:d,m,!0,s);t.write((p?Y+O+H:O)+"\x1B[K")}for(let u of r.expired()){let d=e.productOrder.indexOf(u);if(d<0)continue;let c=So+d;if(c>=a)continue;let g=e.products.get(u);g&&(t.moveTo(c,1),t.write(Co(g,0,!1,!0,s)+"\x1B[K"))}t.moveTo(a,1),t.write(Ct(s,!0)),t.moveTo(_,1),t.write(vc(e,s-1,!0)+"\x1B[K")}function an(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 bo(t,e,r){return JSON.stringify(an(t,e,r))}var Dc,bc,So,Lc,Lo=C(()=>{"use strict";E();l();Re();jt();Ze();on();Dc=1,bc=2,So=3,Lc=[{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 Uo(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:J()}}function vo(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 o=s.type,_=s.updates;if(o==="snapshot"&&(e.bids.clear(),e.asks.clear()),!!_){for(let a of _){let u=String(a.side??"").toLowerCase(),d;try{d=Kt(String(a.price_level??"0"),er)}catch{continue}let c=parseFloat(String(a.new_quantity??"0"));if(d<=0n)continue;let g=u==="bid"?e.bids:e.asks;c<=0?g.delete(d):g.set(d,c)}e.updateCount++,e.lastClock=J()}}}function nr(t){let e=[];for(let[r,n]of t.bids)e.push({price:r,size:n});return e.sort((r,n)=>r.price<n.price?1:r.price>n.price?-1:0),e}function ir(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?-1:r.price>n.price?1:0),e}function rr(t){return Number(qt(t,er))}function Mo(t,e){if(t.length===0||e.length===0)return null;let r=t[0].price,n=e[0].price;return{spread:qt(n-r,er),mid:qt(5n*(n+r),er+1)}}function ho(t,e,r,n,i,s,o){let _=o?i==="bid"?zt:$t:"",a=o?H:"",u=No(r,n,s),d=`${_}${u}${a}`;return[`${_}${F(X(t),Pt[0])}${a}`,F(e.toFixed(4),Pt[1]),F(r.toFixed(4),Pt[2]),d].join(" ")}function Fc(t,e,r){let n=Mo(nr(t),ir(t)),i=r?Y:"",s=r?H:"";if(!n)return`${i}${W(" Waiting for data...",e)}${s}`;let o=Number(n.spread),_=Number(n.mid),a=o/_*100,u=` Spread: ${X(o).padStart(10)} (${a.toFixed(3).padStart(6)}%) Mid: ${X(_).padStart(12)}`;return`${i}${W(u,e)}${s}`}function Vc(t,e,r){let n=kc.map((a,u)=>u===3?W(a,Pt[u]):F(a,Pt[u])).join(" "),i=r?Y:"",s=r?Yt:"",o=r?H:"",_=`${s}${t.productId}${o}`;return`${W(_,e)}
|
|
55
|
+
${i}${n}${o}`}function Gc(t,e,r){let n=nr(t).reduce((d,c)=>d+c.size,0),i=ir(t).reduce((d,c)=>d+c.size,0),s=i>0?(n/i).toFixed(2):"-",_=`${t.depth?`Depth:${t.depth} `:""}B/A:${s} Rate:${t.msgRate}/s`,u=`${Zt(t.heartbeat,r)} ${t.lastClock}`;return Xt(_,u,e)}function cn(t,e){t.enterAltScreen(),t.hideCursor(),un(t,e)}function un(t,e){let r=t.cols,n=t.rows;if(n<4)return;let i=Pt[0]+Pt[1]+Pt[2]+3,s=Math.max(4,r-i),o=ir(e),_=nr(e),a=n-1,u=n,d=Math.max(0,n-4),c=Math.floor(d/2),g=d>c*2||c>0,p=e.depth?Math.min(c,e.depth):c,m=o.slice(0,p),O=_.slice(0,p),T=0,b=[];for(let h of m)T+=h.size,b.push(T);let f=0,v=[];for(let h of O)f+=h.size,v.push(f);let z=Math.max(T,f),L=1;t.moveTo(L,1),t.write(Vc(e,r,!0)+"\x1B[K"),L=Mc;for(let h=0;h<p&&L<a;h++,L++)if(t.moveTo(L,1),h<m.length){let q=m.length-1-h;t.write(ho(rr(m[q].price),m[q].size,b[q],z,"ask",s,!0)+"\x1B[K")}else t.clearLine();g&&L<a&&(t.moveTo(L,1),t.write(Fc(e,r,!0)+"\x1B[K"),L++);for(let h=0;h<p&&L<a;h++,L++)t.moveTo(L,1),h<O.length?t.write(ho(rr(O[h].price),O[h].size,v[h],z,"bid",s,!0)+"\x1B[K"):t.clearLine();for(;L<a;)t.moveTo(L,1),t.clearLine(),L++;t.moveTo(a,1),t.write(Ct(r,!0)),t.moveTo(u,1),t.write(Gc(e,r-1,!0)+"\x1B[K")}function dn(t,e,r){let n=nr(t),i=ir(t),s=Mo(n,i);return{_ch:"level2",_seq:e,_ts:r,product_id:t.productId,spread:s?s.spread:null,mid:s?s.mid:null,bids:n.map(o=>({price:rr(o.price),size:o.size})),asks:i.map(o=>({price:rr(o.price),size:o.size}))}}function ko(t,e,r){return JSON.stringify(dn(t,e,r))}var Mc,Pt,kc,er,Fo=C(()=>{"use strict";E();l();Re();jt();Ze();on();zr();Mc=3,Pt=[14,12,12,16],kc=["PRICE","SIZE","TOTAL","DEPTH"],er=12});function Vo(t,e,r,n,i){return new En(t,e,r,n,i)}function Go(t,e,r){return new ln(t,e,r)}function wo(t,e,r,n){return new gn(t,e,r,n)}var En,ln,gn,xo=C(()=>{"use strict";E();l();$e();en();ao();co();Re();Oo();Lo();Fo();ce();En=class{productIds=[];screen;refreshJWT;state=Ro();flash=new Ie;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 Qt(e.out),sn(this.screen),this.screen.onResize(()=>{sn(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?Qe(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(),To(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(a=>a.order_id):void 0,s=nn(e,this.state);this.liveness=!this.liveness;let o={inserts:s.inserts.filter(a=>this.matchesFilter(a)),updates:s.updates.filter(a=>this.matchesFilter(a))};if(i){let a=this.visibleEvents().map(d=>d.order_id);a.length!==i.length||a.some((d,c)=>d!==i[c])?this.repaintFrame():this.render(o)}else this.render(o);return[...o.inserts,...o.updates].map(a=>({obj:tr(a,r,n),line:mo(a,r,n)}))}onHeartbeat(){this.liveness=!this.liveness,this.state.lastClock=J(),this.render({inserts:[],updates:[]})}onConnState(e){this.connected=e===B.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 At("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=nn({events:[{orders:[n]}]},this.state,"backfill");if(this.until.active)for(let o of[...s.inserts,...s.updates]){let _=String(n.created_time??new Date().toISOString());if(this.until.check(tr(o,0,_)))return}}}}catch{}this.repaintFrame()}};ln=class{productIds;screen;state=fo();flash=new Ie;until;liveness=!1;connected=!1;constructor(e,r,n){this.until=n,this.productIds=r,e.isTTY&&!e.untilActive&&(this.screen=new Qt(e.out),_n(this.screen),this.screen.onResize(()=>{_n(this.screen),this.repaintFrame()}))}syncHeartbeat(){this.state.heartbeat=this.connected&&this.liveness}render(e){this.screen&&(this.syncHeartbeat(),Do(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=yo(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:an(s,r,n),line:bo(s,r,n)}))}onHeartbeat(){this.liveness=!this.liveness,this.state.lastClock=J(),this.render([])}onConnState(e){this.connected=e===B.SUBSCRIBED,this.render([])}onGap(){}onReconnected(){}async setup(){}cleanup(){this.screen?.cleanup()}};gn=class{productIds;screen;state;productId;liveness=!1;connected=!1;constructor(e,r,n,i){this.productId=r,this.productIds=[r],this.state=Uo(r,e.flags.depth??0),e.isTTY&&!e.untilActive&&(this.screen=new Qt(e.out),cn(this.screen,this.state),this.screen.onResize(()=>{cn(this.screen,this.state),this.render()}))}syncHeartbeat(){this.state.heartbeat=this.connected&&this.liveness}render(){this.screen&&(this.syncHeartbeat(),un(this.screen,this.state))}onData(e,r,n){return vo(e,this.state),this.liveness=!this.liveness,this.render(),[{obj:dn(this.state,r,n),line:ko(this.state,r,n)}]}onHeartbeat(){this.liveness=!this.liveness,this.state.lastClock=J(),this.render()}onConnState(e){this.connected=e===B.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 Wo={};Mt(Wo,{applyJQ:()=>pn});import{execFileSync as wc}from"node:child_process";function pn(t,e){try{return wc("jq",["-r",e],{input:t,encoding:"utf8",maxBuffer:10*1024*1024,env:Sr()}).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 In=C(()=>{"use strict";E();l();_t()});var Rn={};Mt(Rn,{UntilController:()=>te,__test:()=>qc,startWatch:()=>Kc,surfaceForChannel:()=>ft});function Wc(t){return xc.find(e=>e.id===t)}function ft(t){switch(t.name){case"user":return"blotter";case"ticker":return"watchlist";case"level2":return"ladder";default:return null}}async function Hc(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).
|
|
56
|
+
Set up a CDP key: coinbase env <name> --key-file key.json`);if(n.type==="cdp_key"&&n.key_id&&n.key_secret)return Qe(n.key_id,n.key_secret);throw new Error("Unsupported auth type for WebSocket")}async function Kc(t,e,r,n){let i=ut(t);if(!i)throw new Error(`--watch is not supported for "${t.replace(/_/g," ")}"`);let s=ft(i);if(!s)throw new Error(`--watch is not yet implemented for channel "${i.name}"`);if(n.until){let a;try{a=ge(n.until)}catch(c){throw new Error(`Invalid --until predicate: ${c.message}`)}let u=Wc(t);if(u?.watchFields){let c=Xs(a,u.watchFields);if(c.length>0){let g=Object.keys(u.watchFields).join(", ");throw new Error(c.map(p=>p.message).join(`
|
|
55
57
|
`)+`
|
|
56
|
-
Available fields: ${
|
|
57
|
-
Watching: ${e.join(", ")}`)}}let
|
|
58
|
-
`),onStateChange:
|
|
58
|
+
Available fields: ${g}`)}}let d=le(a);if(d.length>0&&e.length>0){let c=d.filter(g=>!e.includes(g));if(c.length>0)throw new Error(`Predicate references product${c.length>1?"s":""} not in watch: ${c.join(", ")}
|
|
59
|
+
Watching: ${e.join(", ")}`)}}let o=await Hc(r,i),_=!!process.stdout.isTTY;await zc(n),s==="blotter"?await Ho(i,o,r,n,_):s==="watchlist"?await Ko(i,e,o,n,_):s==="ladder"&&await qo(i,e,o,n,_)}async function or(t,e,r,n,i,s){let o=n.start();await i.setup();let _=0,a;a=new je({channel:t,WebSocketClass:s,onEvent:d=>{let c=d;_=c.sequence_num??_;let g=String(c.timestamp??new Date().toISOString()),p=i.onData(c,_,g);if(p.length!==0){if(!i.screen&&!n.active)for(let m of p)zo(m.line,r);if(n.active){for(let m of p)if(n.check(m.obj))return}}},onHeartbeat:()=>i.onHeartbeat(),onSequenceGap:()=>{let d=i.onGap();d&&(a.unsubscribe(d.resubscribe),a.subscribe(d.resubscribe,i.refreshJWT?i.refreshJWT():e))},onError:i.screen?void 0:d=>process.stderr.write(`ws error: ${d}
|
|
60
|
+
`),onStateChange:d=>{d===B.FAILED&&n.onFailed(),i.onConnState(d)},onDisconnect:()=>n.onDisconnect(),onReconnect:()=>n.onReconnect(),onReconnected:()=>i.onReconnected(),refreshJWT:i.refreshJWT}),a.connect(),a.subscribe(i.productIds,e);let u=await Yc(o,i.screen);a.close(),Yo(u,i,r,n),u===null&&process.exit(process.exitCode??0)}async function Ho(t,e,r,n,i,s,o){let _=new te(n),a=Vo({isTTY:i,untilActive:_.active,flags:n,out:s?.out},r,e,t,_);await or(t,e,n,_,a,o)}async function Ko(t,e,r,n,i,s,o){if(e.length===0)throw new Error("--watch requires at least one product_id (e.g. BTC-USD)");let _=new te(n),a=Go({isTTY:i,untilActive:_.active,flags:n,out:s?.out},e,_);await or(t,r,n,_,a,o)}async function qo(t,e,r,n,i,s,o){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 _=e[0],a=new te(n),u=wo({isTTY:i,untilActive:a.active,flags:n,out:s?.out},_,r,a);await or(t,r,n,a,u,o)}function Yc(t,e){return new Promise(r=>{let n=()=>{},i=s=>{n(),r(s)};if(e)e.installSignalHandlers(()=>i(null));else{let s=()=>i(null),o=()=>i(null);n=()=>{process.off("SIGINT",s),process.off("SIGTERM",o)},process.on("SIGINT",s),process.on("SIGTERM",o)}t.then(i)})}function Yo(t,e,r,n){if(e.cleanup(),n?.cleanup(),!!t)switch(t.type){case"matched":zo(JSON.stringify(t.event),r??{}),process.exitCode=0;break;case"timeout":process.stderr.write(`error: --until timed out
|
|
59
61
|
`),process.exitCode=124;break;case"failed":process.stderr.write(`error: WebSocket connection failed permanently
|
|
60
62
|
`),process.exitCode=2;break;case"disconnect_budget_exceeded":process.stderr.write(`error: cumulative disconnection exceeded ${Math.round(t.totalMs/1e3)}s
|
|
61
|
-
`),process.exitCode=2;break}}function
|
|
63
|
+
`),process.exitCode=2;break}}function zo(t,e){if(e.jq)try{let{applyJQ:r}=sr,n=r(new TextEncoder().encode(t),e.jq);process.stdout.write(n+`
|
|
62
64
|
`)}catch(r){process.stderr.write(`jq error: ${r.message??r}
|
|
63
65
|
`)}else process.stdout.write(t+`
|
|
64
|
-
`)}async function
|
|
65
|
-
`));for(let n of this.requiredProducts)if(this.signals.hasSeen(n)&&this.signals.isStale(n,
|
|
66
|
-
`)),!1;return
|
|
66
|
+
`)}async function zc(t){if(t.jq&&!sr){sr=await Promise.resolve().then(()=>(In(),Wo));try{let{applyJQ:e}=sr;e(new TextEncoder().encode("{}"),t.jq)}catch(e){throw new Error(`Invalid --jq expression: ${e.message??e}`)}}}var xc,Bc,Bo,te,qc,sr,me=C(()=>{"use strict";E();l();pe();to();$e();en();eo();Ye();mt();xo();xc=[...j.flatMap(t=>t.actions),...Object.values(Q)];Bc=300*1e3,Bo=3e4,te=class{predicate;timeoutMs;timeoutTimer=null;disconnectStart=null;cumulativeDisconnectMs=0;resolve=null;settled=!1;signals;requiredProducts;reportedStale=new Set;constructor(e,r){this.predicate=e.until?ge(e.until):null,this.timeoutMs=e.untilTimeout?e.untilTimeout*1e3:null,this.requiredProducts=this.predicate?[...new Set(le(this.predicate))]:[],this.signals=r??new Xe}get active(){return this.predicate!==null}get stale(){return this.signals.staleProducts(this.requiredProducts,Bo)}start(){return new Promise(e=>{this.resolve=e,this.active&&this.timeoutMs!==null&&(this.timeoutTimer=setTimeout(()=>{this.settle({type:"timeout"})},this.timeoutMs))})}check(e){if(!this.predicate||this.settled)return!1;let r=e.product_id;r&&(this.signals.update(r,e),this.reportedStale.delete(r)&&process.stderr.write(`notice: ${r} recovered
|
|
67
|
+
`));for(let n of this.requiredProducts)if(this.signals.hasSeen(n)&&this.signals.isStale(n,Bo))return this.reportedStale.has(n)||(this.reportedStale.add(n),process.stderr.write(`warning: ${n} stale (no update for ${Math.round(this.signals.age(n)/1e3)}s)
|
|
68
|
+
`)),!1;return St(this.predicate,e,this.signals.all())?(this.settle({type:"matched",event:e}),!0):!1}onDisconnect(){!this.active||this.settled||(this.disconnectStart=Date.now())}onReconnect(){!this.active||this.settled||(this.disconnectStart!==null&&(this.cumulativeDisconnectMs+=Date.now()-this.disconnectStart,this.disconnectStart=null),this.cumulativeDisconnectMs>Bc&&this.settle({type:"disconnect_budget_exceeded",totalMs:this.cumulativeDisconnectMs}))}onFailed(){this.settled||this.settle({type:"failed"})}cleanup(){this.timeoutTimer&&(clearTimeout(this.timeoutTimer),this.timeoutTimer=null)}settle(e){this.settled||(this.settled=!0,this.cleanup(),this.resolve?.(e))}};qc={runSurface:or,runBlotter:Ho,runWatchlist:Ko,runLadder:qo,handleResult:Yo};sr=null});var _r={};Mt(_r,{bodyBytes:()=>Zc,hasBody:()=>Xc,isFieldArg:()=>tu,parseFields:()=>jc,setNested:()=>On});import{readFileSync as Zo}from"node:fs";function jc(t,e=$c){let r={body:{},query:new URLSearchParams,headers:{},rawBody:null};for(let n of t)if(n==="-")r.rawBody=e.readStdin();else if(n.startsWith("@"))r.rawBody=e.readFile(n.slice(1));else if(Qc(n)){let i=n.indexOf(":");r.headers[n.slice(0,i)]=n.slice(i+1).trim()}else{let i=n.indexOf("=");if(i<=0)throw new Error(`unrecognized argument: ${n} (use key=value, key:=json, key==query, or Header:value)`);if(n[i-1]===":"){let s=n.slice(0,i-1);try{On(r.body,s,JSON.parse(n.slice(i+1)))}catch(o){throw new Error(`invalid JSON in ${s}: ${o.message}`)}}else n[i+1]==="="?r.query.append(n.slice(0,i),n.slice(i+2)):On(r.body,n.slice(0,i),n.slice(i+1))}return r}function Qc(t){let e=t.indexOf(":");return e<=0||t.slice(0,e).includes("=")?!1:t[0]>="A"&&t[0]<="Z"}function Xc(t){return Object.keys(t.body).length>0||t.rawBody!==null}function Zc(t){return t.rawBody?t.rawBody:Object.keys(t.body).length===0?null:new TextEncoder().encode(JSON.stringify(t.body))}function tu(t){return!!(t.includes("=")||t.startsWith("@")||t.startsWith("-")||t.indexOf(":")>0&&t[0]>="A"&&t[0]<="Z")}function On(t,e,r){let n=e.split("."),i=t;for(let s=0;s<n.length;s++){let o=n[s];if(Jc.has(o))throw new Error(`invalid field name: ${o}`);if(s===n.length-1){Object.defineProperty(i,o,{value:r,writable:!0,enumerable:!0,configurable:!0});return}(!Object.hasOwn(i,o)||typeof i[o]!="object"||i[o]===null)&&Object.defineProperty(i,o,{value:{},writable:!0,enumerable:!0,configurable:!0}),i=i[o]}}var $c,Jc,ar=C(()=>{"use strict";E();l();$c={readFile(t){try{return Zo(t)}catch(e){throw new Error(`reading file ${t}: ${e.message}`)}},readStdin(){try{return Zo(0)}catch(t){throw new Error(`reading stdin: ${t.message}`)}}};Jc=new Set(["__proto__","constructor","prototype"])});var Jo={};Mt(Jo,{outputResult:()=>cr});function cr(t,e){let r=JSON.stringify(t.data),n=t.status>=400;if(e)try{process.stdout.write(pn(new TextEncoder().encode(r),e)+`
|
|
67
69
|
`)}catch(i){process.stdout.write(r+`
|
|
68
70
|
`),process.stderr.write(`jq error: ${i.message}
|
|
69
71
|
`)}else n&&process.stdout.isTTY||(process.stdout.isTTY?process.stdout.write(JSON.stringify(t.data,null,2)+`
|
|
70
72
|
`):process.stdout.write(r+`
|
|
71
|
-
`));if(n){let i=t.data?.message||t.data?.errorMessage||r.slice(0,200),s=t.data?.hint,
|
|
72
|
-
Hint: ${s}`:""}`)}}var
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
`);
|
|
76
|
-
`)
|
|
77
|
-
`)
|
|
78
|
-
`)
|
|
79
|
-
`)
|
|
80
|
-
`);return}if(
|
|
81
|
-
`);return}if(
|
|
73
|
+
`));if(n){let i=t.data?.message||t.data?.errorMessage||r.slice(0,200),s=t.data?.hint,o=t.data?.correlationId,_=t.headers?.get("trace-id"),a=[_?`trace ${_}`:"",o?`correlation ${o}`:""].filter(Boolean).join(", ");throw new Error(`${i} (HTTP ${t.status})${a?` [${a}]`:""}${s?`
|
|
74
|
+
Hint: ${s}`:""}`)}}var An=C(()=>{"use strict";E();l();In()});var t_={};Mt(t_,{matchesSnapshot:()=>ur,runEventStream:()=>eu});function ur(t,e){if(!e||typeof e!="object")return!1;if(Array.isArray(e))return e.some(n=>ur(t,n));let r=e;return St(t,r)||Object.values(r).some(n=>ur(t,n))}async function eu(t,e,r,n,i=s=>cr({status:200,data:s},n.jq)){if(n.paginate||n.depth)throw new Error("--paginate and --depth are unavailable for snapshot streams. Use the corresponding read command for paging or depth.");let s=n.until?ge(n.until,{exactDecimals:!0}):void 0,o=n["until-timeout"]===void 0?void 0:Number(n["until-timeout"]);if(o!==void 0&&(!s||!Number.isFinite(o)||o<=0||o*1e3>2147483647))throw new Error("--until-timeout requires --until and a positive timeout of at most 2147483.647 seconds.");let _=new AbortController,a=!1,u,d=()=>{u=130,_.abort()},c=()=>{u=143,_.abort()};process.on("SIGINT",d),process.on("SIGTERM",c);let g=o===void 0?void 0:setTimeout(()=>{a=!0,_.abort()},o*1e3);try{let p=await At(t,{...e,stream:{signal:_.signal,onEvent:m=>{if(!(m.event!=="snapshot"&&m.event!=="reset"&&m.event!=="error")){if(s&&m.event!=="error")return ur(s,m.data.data)?(i(m),!0):void 0;i(m)}}}},r);p.status>=400&&cr(p,n.jq)}catch(p){if(!_.signal.aborted)throw p}finally{g&&clearTimeout(g),_.abort(),process.off("SIGINT",d),process.off("SIGTERM",c)}a?(process.stderr.write(`error: --until timed out
|
|
75
|
+
`),process.exitCode=124):u&&(process.exitCode=u)}var e_=C(()=>{"use strict";E();l();ce();An();Ye()});E();l();E();l();_t();pr();import{createInterface as yr}from"node:readline/promises";import{readFileSync as y_}from"node:fs";function Wt(t,e={}){Ar(()=>{let r=rt();t(r),Et(r,{allowPlaintext:e.allowPlaintext})})}function D_(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 fr(t,e){if(!e&&!wn())throw new Error(`OS keychain unavailable; refusing to persist secrets for "${t}".
|
|
76
|
+
Re-run with --allow-plaintext-secrets to write secrets to ${at()} (file is mode 0600), or install/unlock your OS keychain (macOS Keychain, libsecret on Linux, Windows Credential Manager).`)}async function jn(t,e){D_(e);let r=rt();if(t.length===0){let c=[...new Set([...Object.keys(r.environments),...Object.keys(st)])].sort();if(c.length===0){process.stderr.write(`No environments configured. Run: coinbase env <name>
|
|
77
|
+
`);return}let g=Math.max(14,...c.map(O=>O.length)),p=45,m=O=>(O.length>p?O.slice(0,p-3)+"...":O).padEnd(p);process.stdout.write(`${"Environment".padEnd(g)} ${"Brokerage API".padEnd(p)} ${"Agent API".padEnd(p)} Key
|
|
78
|
+
`);for(let O of c){let T=r.environments[O]??{},b=ot(T,O),f=Tt(T,O),v=ie(T),z=v?.type==="cdp_key"?v.key_id:"(no key)",L=z.length>60?z.slice(0,57)+"...":z;process.stdout.write(`${O===r.env?"* ":" "}${O.padEnd(g)} ${m(b||"\u2014")} ${m(f||"\u2014")} ${L}
|
|
79
|
+
`)}return}let n=t[0];if(e.remove){Wt(c=>{delete c.environments[n],c.env===n&&(c.env="")}),Or(n),process.stderr.write(`Removed ${n}.
|
|
80
|
+
`);return}let i=r.environments[n]??{};if(e.status){h_(n,i);return}let s=(c,g)=>{i.auth={type:"cdp_key",key_id:c,key_secret:g}},o=()=>{e.url&&(i.url=e.url,Ue(e.url)||process.stderr.write(`warning: custom brokerage URL does not match a known endpoint
|
|
81
|
+
`)),e.brokerageApiUrl&&(i.endpoints={...i.endpoints,brokerageApi:e.brokerageApiUrl}),e.agentApiUrl&&(i.endpoints={...i.endpoints,agentApi:e.agentApiUrl})};if(e.keyFile){fr(n,!!e.allowPlaintextSecrets);let c=U_(e.keyFile);s(c.keyId,c.keySecret),o(),Wt(g=>{g.environments[n]=i,g.env=n},{allowPlaintext:e.allowPlaintextSecrets}),process.stderr.write(`Loaded key from ${e.keyFile}. Switched to ${n}.
|
|
82
|
+
`);return}if(e.keyId||e.keySecret||e.url||e.brokerageApiUrl||e.agentApiUrl){let c=ie(i),g=c?.type==="cdp_key"?c.key_id:"",p=c?.type==="cdp_key"?c.key_secret:"";(e.keyId||e.keySecret)&&(fr(n,!!e.allowPlaintextSecrets),s(e.keyId??g,e.keySecret??p)),o(),Wt(m=>{m.environments[n]=i,m.env=n},{allowPlaintext:e.allowPlaintextSecrets}),process.stderr.write(`Saved and switched to ${n}.
|
|
83
|
+
`);return}if(ie(i)){Wt(c=>{c.env=n}),process.stderr.write(`Switched to ${n}.
|
|
84
|
+
`);return}if(r.environments[n]){Wt(c=>{c.env=n}),process.stderr.write(`Switched to ${n} (no credentials yet).
|
|
82
85
|
`),process.stderr.write(` CDP key: coinbase env ${n} --key-file path/to/key.json
|
|
83
|
-
`);return}if(!process.stdout.isTTY)throw new Error(`environment "${n}" needs API keys. Run: coinbase env ${n} --key-id=... --key-secret=...`);
|
|
84
|
-
`)}function
|
|
86
|
+
`);return}if(!process.stdout.isTTY)throw new Error(`environment "${n}" needs API keys. Run: coinbase env ${n} --key-id=... --key-secret=...`);fr(n,!!e.allowPlaintextSecrets);let a="",u="",d=yr({input:process.stdin,output:process.stderr});try{if(!a){let c=await d.question("API Key ID: ");if(!c.trim())throw new Error("API Key ID is required");a=c.trim()}if(!u){d.close();let c=await b_("API Key Secret: ");if(!c.trim())throw new Error("API Key Secret is required");u=c.trim(),d=yr({input:process.stdin,output:process.stderr})}if(s(a,u),!ot(i,n)){let c=await d.question("Brokerage API URL (optional): ");c.trim()&&(i.endpoints={...i.endpoints,brokerageApi:c.trim()})}if(!Tt(i,n)){let c=await d.question("Agent API URL (optional): ");c.trim()&&(i.endpoints={...i.endpoints,agentApi:c.trim()})}}finally{d.close()}Wt(c=>{c.environments[n]=i,c.env=n},{allowPlaintext:e.allowPlaintextSecrets}),process.stderr.write(`Saved. Switched to ${n}.
|
|
87
|
+
`)}function b_(t){return process.stderr.write(t),process.stdin.isTTY?new Promise(e=>{let r=process.stdin;r.setRawMode(!0),r.resume(),r.setEncoding("utf8");let n="",i=s=>{s===`
|
|
85
88
|
`||s==="\r"||s===""?(r.setRawMode(!1),r.pause(),r.removeListener("data",i),process.stderr.write(`
|
|
86
|
-
`),e(n)):s==="\x7F"||s==="\b"?n=n.slice(0,-1):s===""?process.exit(1):n+=s};r.on("data",i)}):new Promise(e=>{let r=
|
|
89
|
+
`),e(n)):s==="\x7F"||s==="\b"?n=n.slice(0,-1):s===""?process.exit(1):n+=s};r.on("data",i)}):new Promise(e=>{let r=yr({input:process.stdin});r.once("line",n=>{r.close(),e(n)})})}function L_(t){return t?t.length<=12?"***":t.slice(0,8)+"\u2026"+t.slice(-4):"(none)"}function h_(t,e){(!e.auth||e.auth.type!=="cdp_key")&&(process.stderr.write(`Environment "${t}" has no stored credentials.
|
|
87
90
|
`),process.exit(1)),process.stdout.write(`env: ${t}
|
|
88
|
-
`),process.stdout.write(`brokerage_api: ${
|
|
89
|
-
`),process.stdout.write(`agent_api: ${
|
|
91
|
+
`),process.stdout.write(`brokerage_api: ${ot(e,t)||"(unset)"}
|
|
92
|
+
`),process.stdout.write(`agent_api: ${Tt(e,t)||"(unset)"}
|
|
90
93
|
`),process.stdout.write(`auth: cdp_key
|
|
91
|
-
`),process.stdout.write(`key_id: ${
|
|
92
|
-
`)}function
|
|
93
|
-
Run: coinbase env <name> --key-id=... --key-secret=... to configure.`),
|
|
94
|
-
`))}function
|
|
95
|
-
`))}function
|
|
94
|
+
`),process.stdout.write(`key_id: ${L_(e.auth.key_id)}
|
|
95
|
+
`)}function U_(t){let e;try{e=y_(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}}E();l();mt();ce();Mr();_t();Be();import{createInterface as Ba}from"node:readline";E();l();function He(){let t=process.env.COINBASE_TRANSPORT;if(!t||t==="auto")return"auto";if(t==="brokerage")return"brokerage";if(t==="agent")return"agent";throw new Error(`invalid COINBASE_TRANSPORT value "${t}"; expected "auto", "agent", or "brokerage"`)}we();E();l();_t();Ot();function x(t,e=!1){return{content:[{type:"text",text:t}],isError:e}}function ue(t,e){return t===e?`coinbase_${t.replace(/-/g,"_")}`:`coinbase_${t.replace(/-/g,"_")}_${e.replace(/[-\s]/g,"_")}`}function Rs(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){if("eventStream"in n&&n.eventStream)continue;let i={},s=[];for(let p of n.params){let m={type:p.type,description:p.description};p.enum&&(m.enum=p.enum),p.pattern&&(m.pattern=p.pattern),p.format&&(m.format=p.format),p.example!==void 0&&(m.example=p.example),p.default!==void 0&&(m.default=p.default),i[p.name]=m,p.required&&s.push(p.name)}let o=n.params.filter(p=>p.in==="body").length,_=n.params.filter(p=>p.in==="body"&&p.required).length,a=o>0?_>0?` (${o} fields, ${_} required)`:` (${o} fields)`:"",d=[...new Set(n.params.map(p=>p.oneOf).filter(p=>!!p))].map(p=>` (one of: ${p.split("|").join(", ")})`).join(""),c=(n.anyOf??[]).length>0?` (one of: ${n.anyOf.map(p=>p.join(" and ")).join(", ")})`:"",g=n.description||n.summary;e.push({name:ue(r.name,n.name),description:`${n.method} ${n.path}${g?" \u2014 "+g:""}${a}${d}${c}`,inputSchema:{type:"object",properties:i,required:s.length>0?s:void 0,additionalProperties:n.closedInput||n.noInput?!1:void 0},...n.annotations?{annotations:n.annotations}:{}})}return e}function Ts(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 x(`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?P.stripGrpcPrefix(t.data.message):t.data.error;return x(`Error: ${e}`,!0)}return x(JSON.stringify(t.data,null,2))}function Br(t){let e=xt(t,""),r=Object.keys(t.environments??{}),n=[`Active: ${e||"(none)"}`,`Configured: ${r.length>0?r.join(", "):"(none)"}`];return e||n.push(`
|
|
96
|
+
Run: coinbase env <name> --key-id=... --key-secret=... to configure.`),x(n.join(`
|
|
97
|
+
`))}function ms(t,e){if(!e)return x("Environment name is required.",!0);let r=Object.keys(t.environments??{});return r.length===0?x("No environments configured. Run: coinbase env <name> --key-id=... --key-secret=... to configure.",!0):t.environments[e]?{cfg:{...t,env:e}}:x(`Unknown environment: "${e}". Available environments: ${r.join(", ")}`,!0)}function Os(t){return Br(t)}function xa(t,e){let r=t.params??[],n=[];n.push(`${t.summary||t.name}`),n.push(`${t.method} ${t.path}`);let i=t.pathParams.map(_=>`${_}="..."`).join(", ");n.push("",`Usage: ${e}(${i})`);let s=r.filter(_=>_.in==="body");if(s.length>0){n.push("","Fields:");for(let _ of s){let a=_.required?" (required)":"",u=_.description?` \u2014 ${_.description}`:"";n.push(` ${_.name} (${_.type})${a}${u}`)}}let o=r.filter(_=>_.in==="query");if(o.length>0){n.push("","Query parameters:");for(let _ of o){let a=_.description?` \u2014 ${_.description}`:"";n.push(` ${_.name} (${_.type})${a}`)}}return x(n.join(`
|
|
98
|
+
`))}function As(t,e,r,n){if(n&&Object.hasOwn(n,e)&&(!t||t===e))return{act:n[e],toolName:`coinbase_${e}`};if(t){let o=r.find(_=>_.name===t);if(o){let _=o.actions.find(a=>a.name===e);return _?{act:_,toolName:ue(o.name,_.name)}:x(`Unknown action: ${e}. Available for ${t}: ${o.actions.map(a=>a.name).join(", ")}`,!0)}}let i=r.map(o=>o.name),s=n?Object.keys(n):[];return x(`Not found. Resources: ${i.join(", ")}. Top-level actions: ${s.join(", ")}`,!0)}function Ns(t,e,r,n){if(!e)return x("action is required",!0);let i=As(t,e,r,n);return"isError"in i?i:xa(i.act,i.toolName)}function Wa(t){let e=(t.params??[]).filter(i=>i.in==="body");if(e.length===0)return x("This action has no request body.");let r=t.template??{},n=[];for(let i of e){let s=i.required?" (required)":"",o=i.description?` \u2014 ${i.description}`:"";n.push(`${i.name} (${i.type})${s}${o}`)}return x(`Template:
|
|
96
99
|
${JSON.stringify(r,null,2)}
|
|
97
100
|
|
|
98
101
|
Fields:
|
|
99
102
|
${n.join(`
|
|
100
|
-
`)}`)}function
|
|
101
|
-
`)}function
|
|
103
|
+
`)}`)}function Ss(t,e,r,n){if(!e)return x("action is required",!0);let i=As(t,e,r,n);return"isError"in i?i:Wa(i.act)}var Ha=(()=>{let t={},e=(r,n)=>{let i=t[r];if(i!==void 0&&i!==n)throw new Error(`operationIdForTool collision: tool "${r}" maps to both "${i}" and "${n}"`);t[r]=n};for(let r of Object.values(Q))e(ue(r.name,r.name),r.id);for(let r of j)for(let n of r.actions)e(ue(r.name,n.name),n.id);return t})();function Ps(t){process.stdout.write(JSON.stringify({jsonrpc:"2.0",...t})+`
|
|
104
|
+
`)}function de(t,e){Ps({id:t,result:e})}function Ee(t,e,r){Ps({id:t,error:{code:e,message:r}})}function Ka(){return j}async function qa(t,e){let r=Ka();if(t==="coinbase_env")return Br(rt());if(t==="coinbase_set_env"){let n=rt(),i=ms(n,e.name);return"isError"in i?i:(Et(i.cfg),Nr(),Os(i.cfg))}return t==="coinbase_help"?Ns(String(e.resource??""),String(e.action??""),r,Q):t==="coinbase_template"?Ss(String(e.resource??""),String(e.action??""),r,Q):Ya(t,e)}async function Ya(t,e){let r=Ha[t];if(!r||!Ji(r))return x(`Unknown tool: ${t}`,!0);let n=rt(),i;try{i=oe(n,"")}catch(_){return x(`Environment error: ${_.message}
|
|
102
105
|
|
|
103
|
-
Run: coinbase env <name> --key-id=... --key-secret=...`,!0)}let{name:s,env:
|
|
104
|
-
`),n.id!=null&&
|
|
105
|
-
`)}
|
|
106
|
-
`);return}throw new Error("usage: coinbase history [clear [env.action]]")}function
|
|
106
|
+
Run: coinbase env <name> --key-id=... --key-secret=...`,!0)}let{name:s,env:o}=i;try{let _=await se(s,o),a={envName:s,env:o,baseURL:ot(o,s),doRequest:d=>We({...d,..._}),transport:He()},u=await At(r,e,a);return Ts(u)}catch(_){return x(`Request failed: ${_.message}`,!0)}}var za={name:"coinbase",version:gt},$a={tools:{}},Hr=null;function Cs(){if(!Hr){let t=[...j];for(let[e,r]of Object.entries(Q))t.push({name:e,actions:[r]});Hr=Rs(t)}return Hr}async function ja(t){let{id:e,method:r,params:n}=t;switch(r){case"initialize":de(e,{protocolVersion:"2024-11-05",serverInfo:za,capabilities:$a});break;case"notifications/initialized":break;case"tools/list":de(e,{tools:Cs()});break;case"tools/call":{let{name:i,arguments:s}=n??{};if(!i){Ee(e,-32602,"Missing tool name");return}if(!Cs().find(_=>_.name===i)){Ee(e,-32602,`Unknown tool: ${i}`);return}try{let _=await qa(i,s??{});de(e,_)}catch(_){de(e,x(`Internal error: ${_.message}`,!0))}break}case"ping":de(e,{});break;default:e!=null&&Ee(e,-32601,`Method not found: ${r}`);break}}function fs(){let t=Ba({input:process.stdin,terminal:!1}),e=new Set;t.on("line",r=>{if(r.trim())try{let n=JSON.parse(r),i=ja(n).catch(s=>{process.stderr.write(`MCP error: ${s.message}
|
|
107
|
+
`),n.id!=null&&Ee(n.id,-32603,s.message)}).finally(()=>e.delete(i));e.add(i)}catch{Ee(null,-32700,"Parse error")}}),t.on("close",async()=>{await Promise.all(e),process.exit(0)}),process.stderr.write(`coinbase MCP server v${gt} ready
|
|
108
|
+
`)}E();l();_t();function ys(t){let e=rt();if(t.length===0)return Qa(e);if(t[0]==="clear"){let r=t[1],n;if(r&&r.includes(".")){let i=r.indexOf(".");n=_e(e,r.slice(0,i),r.slice(i+1))}else r?n=_e(e,r):n=_e(e);Et(e),process.stderr.write(`Cleared ${n} history ${n===1?"entry":"entries"}.
|
|
109
|
+
`);return}throw new Error("usage: coinbase history [clear [env.action]]")}function Qa(t){let e=[];for(let[i,s]of Object.entries(t.history))for(let[o,_]of Object.entries(s))e.push({env:i,action:o,lastUsed:_.last_used,fields:Object.keys(_.values)});if(e.length===0){process.stderr.write(`No saved history.
|
|
107
110
|
`);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(", ")}
|
|
108
|
-
`)}}
|
|
109
|
-
`,{mode:384})}function
|
|
111
|
+
`)}}E();l();_t();import{readFileSync as Us,writeFileSync as Xa,mkdirSync as vs,readdirSync as Ms,existsSync as vt,cpSync as Za,rmSync as Ja}from"node:fs";import Ds,{join as pt,resolve as bs}from"node:path";import{fileURLToPath as tc}from"node:url";import{homedir as Ls}from"node:os";import{createInterface as hs}from"node:readline";function qr(){try{return JSON.parse(Us(at(),"utf8"))}catch{return{}}}function Kr(t){let e=Rt();vs(e,{recursive:!0,mode:448}),Xa(at(),JSON.stringify(t,null,2)+`
|
|
112
|
+
`,{mode:384})}function ks(){let t=Ds.dirname(tc(import.meta.url));return Ds.join(t,"..","skills")}function ec(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 Fs(t){let e=t??ks();if(!vt(e))return[];let r=[];for(let n of Ms(e,{withFileTypes:!0})){if(!n.isDirectory())continue;let i=pt(e,n.name,"SKILL.md");if(!vt(i))continue;let s=Us(i,"utf8"),o=ec(s);r.push({name:o.name||n.name,description:o.description,dir:pt(e,n.name)})}return r.sort((n,i)=>n.name.localeCompare(i.name))}function rc(t,e){if(!vt(t))return 0;vs(e,{recursive:!0});let r=0;for(let n of Ms(t,{withFileTypes:!0})){if(!n.isDirectory())continue;let i=pt(t,n.name,"SKILL.md");if(!vt(i))continue;let s=pt(e,n.name);Za(pt(t,n.name),s,{recursive:!0,force:!0}),r++}return r}async function nc(){let t=process.platform==="win32"?pt(process.env.USERPROFILE??Ls(),".claude","skills"):pt(Ls(),".claude","skills");process.stderr.write(`Where should skills be installed?
|
|
110
113
|
`),process.stderr.write(`Tip: Not sure where your agent looks for skills? Ask your agent.
|
|
111
114
|
|
|
112
115
|
`),process.stderr.write(` 1) ${t} User \u2014 available across all projects (Recommended)
|
|
113
116
|
`),process.stderr.write(` 2) Other Specify a custom path
|
|
114
117
|
|
|
115
|
-
`);let e=
|
|
116
|
-
`),t)}return
|
|
118
|
+
`);let e=hs({input:process.stdin,output:process.stderr}),r=await new Promise(n=>{e.question("? Skills directory [1]: ",i=>{e.close(),n(i.trim())})});if(!r||r==="1")return t;if(r==="2"){let n=hs({input:process.stdin,output:process.stderr}),i=await new Promise(s=>{n.question("? Path: ",o=>{n.close(),s(o.trim())})});return i?bs(i):(process.stderr.write(`No path provided, using default.
|
|
119
|
+
`),t)}return bs(r)}async function ic(t){let e=qr(),r=t||e.settings?.skillsDir,n=!1;r||(process.stdin.isTTY||(process.stderr.write(`error: no skills directory configured.
|
|
117
120
|
Run: coinbase skills add --dir <path>
|
|
118
|
-
`),process.exit(1)),r=await
|
|
121
|
+
`),process.exit(1)),r=await nc(),n=!0),(!e.settings?.skillsDir||t&&e.settings.skillsDir!==r)&&(e.settings||(e.settings={}),e.settings.skillsDir=r,Kr(e));let i=ks(),s=rc(i,r);process.stderr.write(`Installed ${s} skills to ${r}.
|
|
119
122
|
`),n&&process.stderr.write(`Skills will auto-update on future installs.
|
|
120
|
-
`)}function
|
|
123
|
+
`)}function sc(){let e=qr().settings?.skillsDir,r=Fs();if(r.length===0){process.stderr.write(`No bundled skills found.
|
|
121
124
|
`);return}let n=Math.max(...r.map(i=>i.name.length),4);process.stderr.write(`${"Name".padEnd(n+2)}${"Installed".padEnd(12)}Description
|
|
122
125
|
`),process.stderr.write(`${"\u2500".repeat(n+2)}${"\u2500".repeat(12)}${"\u2500".repeat(40)}
|
|
123
|
-
`);for(let i of r){let
|
|
126
|
+
`);for(let i of r){let o=e&&vt(pt(e,i.name,"SKILL.md"))?"yes":"no";process.stderr.write(`${i.name.padEnd(n+2)}${o.padEnd(12)}${i.description}
|
|
124
127
|
`)}process.stderr.write(`
|
|
125
128
|
${r.length} skills available.`),e?process.stderr.write(` Installed to: ${e}`):process.stderr.write(" Run: coinbase skills add"),process.stderr.write(`
|
|
126
|
-
`)}function
|
|
127
|
-
`);return}if(!
|
|
128
|
-
`),t.settings&&delete t.settings.skillsDir,
|
|
129
|
-
`);return}let r=
|
|
129
|
+
`)}function oc(){let t=qr(),e=t.settings?.skillsDir;if(!e){process.stderr.write(`No skills directory configured. Nothing to remove.
|
|
130
|
+
`);return}if(!vt(e)){process.stderr.write(`Skills directory not found: ${e}
|
|
131
|
+
`),t.settings&&delete t.settings.skillsDir,Kr(t),process.stderr.write(`Cleared skillsDir from config.
|
|
132
|
+
`);return}let r=Fs(),n=0;for(let i of r){let s=pt(e,i.name);vt(s)&&(Ja(s,{recursive:!0,force:!0}),n++)}t.settings&&delete t.settings.skillsDir,Kr(t),process.stderr.write(`Removed ${n} skills from ${e}.
|
|
130
133
|
`),process.stderr.write(`Cleared skillsDir from config.
|
|
131
|
-
`)}async function
|
|
134
|
+
`)}async function Vs(t){let e=t[0];if(!e||e==="-h"||e==="--help"){process.stderr.write(`Manage CDP agent skills
|
|
132
135
|
|
|
133
136
|
Usage:
|
|
134
137
|
coinbase skills add Install/update skills to your skills directory
|
|
@@ -136,90 +139,95 @@ Usage:
|
|
|
136
139
|
coinbase skills list List available skills from this package
|
|
137
140
|
coinbase skills remove Remove installed skills and clear config
|
|
138
141
|
|
|
139
|
-
`);return}let r,n=t.slice(1);for(let i=0;i<n.length;i++)if(n[i]==="--dir"&&n[i+1]){r=n[++i];break}else if(n[i].startsWith("--dir=")){r=n[i].slice(6);break}switch(e){case"add":await
|
|
142
|
+
`);return}let r,n=t.slice(1);for(let i=0;i<n.length;i++)if(n[i]==="--dir"&&n[i+1]){r=n[++i];break}else if(n[i].startsWith("--dir=")){r=n[i].slice(6);break}switch(e){case"add":await ic(r);break;case"list":sc();break;case"remove":oc();break;default:process.stderr.write(`error: unknown skills subcommand: ${e}
|
|
140
143
|
Run: coinbase skills --help
|
|
141
|
-
`),process.exit(1)}}
|
|
144
|
+
`),process.exit(1)}}E();l();mt();E();l();Ke();function ac(t,e,r){return r?`\x1B]8;;${e}\x07\x1B[4m${t}\x1B[24m\x1B]8;;\x07`:`${t} (${e})`}function ws(t,e=Gs){return t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(r,n,i)=>ac(n,i,e))}function Yr(t){return t.replace(/\*\*(.+?)\*\*/g,"$1").replace(/__(.+?)__/g,"$1").replace(/\*(.+?)\*/g,"$1").replace(/_(.+?)_/g,"$1").replace(/\[([^\]]+)\]\([^)]+\)/g,"$1").replace(/^#{1,6}\s+/gm,"")}function xs(t,e){let r=e??process.stdout.columns??100;return t.replace(/\r\n/g,`
|
|
142
145
|
`).trim().split(`
|
|
143
|
-
`).flatMap(n=>{n=
|
|
146
|
+
`).flatMap(n=>{n=Yr(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(`
|
|
144
147
|
`)+`
|
|
145
|
-
`}
|
|
146
|
-
`),o="",a=!
|
|
147
|
-
`)
|
|
148
|
-
`)
|
|
148
|
+
`}E();l();Ke();function qe(t,e,r,n){if(!r&&e.trim()){t.write(e.trimEnd()+`
|
|
149
|
+
`);return}let i=n??e.length,s=Math.max(20,(process.stdout.columns||80)-i),o=r.split(" "),_="",a=!0;for(let u of o){let d=Nt(u),c=Nt(_),g=u.includes("\x1B]8;;");(c+d+1>s||g&&c>0&&c+d+1>s*.6)&&_.length>0&&(t.write((a?e:" ".repeat(i))+_.trimEnd()+`
|
|
150
|
+
`),_="",a=!1),_+=(_?" ":"")+u}_&&t.write((a?e:" ".repeat(i))+_.trimEnd()+`
|
|
151
|
+
`)}Ye();pe();me();function Tn(){return j}function $o(t){return Xn.has(t)}function jo(t,e,r){for(let n of e.fields){let i=e.nested?.[n];t.write(`${r}${n}
|
|
152
|
+
`),i&&jo(t,i,r+" ")}}function mn(t,e){let r=process.stderr,n=ut(e.id),i=n?ft(n):null;r.write(`${e.summary||e.name}
|
|
149
153
|
`),e.description&&r.write(`
|
|
150
|
-
`+
|
|
154
|
+
`+xs(e.description));let s=t===e.name?`coinbase ${e.name}`:`coinbase ${t} ${e.name}`;for(let c of e.pathParams)s+=` <${c}>`;let o=e.params??[];r.write(`
|
|
151
155
|
Usage:
|
|
152
156
|
${s}${e.noInput?"":" [fields...]"}
|
|
153
|
-
`);let o
|
|
157
|
+
`);let _=o.filter(c=>c.in==="path");if(_.length>0){r.write(`
|
|
154
158
|
Arguments:
|
|
155
|
-
`);let c=Math.max(...
|
|
159
|
+
`);let c=Math.max(..._.map(g=>g.name.length));for(let g of _){let p=` <${g.name}>${" ".repeat(Math.max(1,c-g.name.length+2))}${g.type}${g.required?" required":""} `,m=/[.!?]$/.test(g.description)?g.description:`${g.description}.`,O=i==="watchlist"?`${m} With --watch, accepts multiple comma-separated pairs (e.g. BTC-USD,ETH-USD).`:g.description;qe(r,p,O)}}let a=o.filter(c=>c.in==="body");if(a.length>0){r.write(`
|
|
156
160
|
Fields:
|
|
157
|
-
`);let c=Math.max(...a.map(
|
|
161
|
+
`);let c=Math.max(...a.map(g=>g.name.length));for(let g of a){let p=g.required?"required":"",m=" ".repeat(Math.max(1,c-g.name.length+2)),O=" ".repeat(Math.max(1,8-g.type.length)),T=p?" ":" ",b=g.type==="array"||g.type==="object"?" (use :=json)":"",f=ws(Yr(g.description)),v=` ${g.name}${m}${g.type}${O}${p}${T}`;qe(r,v,f+b)}}let u=o.filter(c=>c.in==="query");if(u.length>0){r.write(`
|
|
158
162
|
Query params (use == syntax):
|
|
159
|
-
`);let c=Math.max(...
|
|
163
|
+
`);let c=Math.max(...u.map(g=>g.name.length));for(let g of u){let p=g.description;g.enum?.length&&(p+=(p?" ":"")+`[${g.enum.join(", ")}]`);let m=` ${g.name}${" ".repeat(Math.max(1,c-g.name.length+2))}${g.type} `;qe(r,m,p)}}e.responseFields&&(r.write(`
|
|
160
164
|
Response:
|
|
161
|
-
`),
|
|
165
|
+
`),jo(r,e.responseFields," "));let d=a.length>0;if(r.write(`
|
|
162
166
|
Flags:
|
|
163
|
-
`),
|
|
167
|
+
`),d&&r.write(` --template Show request body template from spec
|
|
164
168
|
`),r.write(` --dry-run Preview request without sending
|
|
165
|
-
`),
|
|
169
|
+
`),d&&r.write(` --edit Open request body in $EDITOR
|
|
166
170
|
`),r.write(` --jq <expr> Filter response with jq
|
|
167
171
|
`),e.streamable&&r.write(` --paginate Auto-paginate using nextPageToken
|
|
168
|
-
`),
|
|
172
|
+
`),e.eventStream&&(r.write(` --watch Stream Agent API snapshots (also the default for this command)
|
|
173
|
+
`),r.write(` --until <predicate> Exit on a matching snapshot field or row; use native response field names and enum values
|
|
174
|
+
`),r.write(` --until-timeout <s> Exit 124 if no match within N seconds
|
|
175
|
+
`),r.write(` Reset events replace prior snapshots. Errors and disconnects terminate; rerun for fresh authentication.
|
|
176
|
+
`)),i!==null&&(r.write(` --watch Live stream via WebSocket
|
|
169
177
|
`),e.watchFields&&(r.write(`
|
|
170
|
-
`+
|
|
178
|
+
`+Zs(e.watchFields)+`
|
|
171
179
|
`),r.write(` --until-timeout <s> Exit 124 if predicate not matched within N seconds
|
|
172
|
-
`))),
|
|
180
|
+
`))),d||u.length>0){r.write(`
|
|
173
181
|
Example:
|
|
174
|
-
`+s);for(let c of a)c.example!==void 0&&r.write(` ${c.name}=${c.example}`);for(let c of
|
|
175
|
-
`)}}function
|
|
182
|
+
`+s);for(let c of a)c.example!==void 0&&r.write(` ${c.name}=${c.example}`);for(let c of u)c.example!==void 0&&r.write(` ${c.name}==${c.example}`);r.write(`
|
|
183
|
+
`)}}function Qo(t){let e=j.find(i=>i.name===t);e||(process.stderr.write(`error: unknown resource: ${t}
|
|
176
184
|
Run: coinbase --help
|
|
177
185
|
`),process.exit(1)),process.stderr.write(`Manage ${e.name}
|
|
178
186
|
|
|
179
187
|
Available actions:
|
|
180
|
-
`);let r=e.actions.some(i=>{let s=
|
|
188
|
+
`);let r=e.actions.some(i=>{let s=ut(i.id);return i.eventStream||s&&ft(s)!==null});for(let i of e.actions){let s=ut(i.id),o=s?ft(s):null,_=i.eventStream||o!==null?" [--watch]":"",a=i.pathParams.map(u=>` <${u}>`).join("");process.stderr.write(` coinbase ${e.name} ${i.name}${a}${_} ${i.summary}
|
|
181
189
|
`)}let n=e.actions.every(i=>i.noInput);process.stderr.write(`
|
|
182
190
|
Flags:
|
|
183
191
|
`),n||process.stderr.write(` --template Show request body template from spec
|
|
184
192
|
`),process.stderr.write(` --dry-run Show assembled request without sending
|
|
185
193
|
`),n||process.stderr.write(` --edit Open request body in $EDITOR
|
|
186
194
|
`),process.stderr.write(` --jq <expr> jq filter expression for response
|
|
187
|
-
`),r&&process.stderr.write(` --watch Live stream watchable actions
|
|
188
|
-
`)}
|
|
195
|
+
`),r&&process.stderr.write(` --watch Live stream watchable actions (add --until <predicate> to exit on a condition)
|
|
196
|
+
`)}pe();me();E();l();ce();E();l();var Xo=t=>t?.has_next===!1?null:t?.cursor||null;Fr();_t();Be();pe();function ru(t,e,r,n){for(let i of e){let s=r[i];if(typeof s=="string"&&s.includes(",")){let o=t.replace(/_/g," ");return`'${s}' looks like multiple values, but \`coinbase ${o}\` takes a single ${i}.`+(n?`
|
|
189
197
|
To stream several live, add --watch:
|
|
190
|
-
coinbase ${
|
|
191
|
-
`);return}let
|
|
198
|
+
coinbase ${o} ${s} --watch`:"")}}return null}var nu=new Set(["x402_pay","x402_fetch"]);function r_(t){return!nu.has(t)}async function Nn(t,e,r,n,i=t.replace(/_/g," ")){if(e.noInput&&(r.args.length>0||r.flags.template||r.flags.edit))throw new Error(`${i} does not accept input fields; it always inspects the current credential.`);if(r.flags.template){let S=e.template??{};process.stdout.write(JSON.stringify(S,null,2)+`
|
|
199
|
+
`);return}let s=[],o=[],{isFieldArg:_}=await Promise.resolve().then(()=>(ar(),_r));for(let S of r.args)s.length<e.pathParams.length&&!_(S)?s.push(S):o.push(S);if(s.length<e.pathParams.length){let S=e.pathParams.slice(s.length);throw new Error(`Missing argument(s): ${S.map(M=>`<${M}>`).join(" ")}
|
|
192
200
|
|
|
193
|
-
Usage: coinbase ${
|
|
194
|
-
`),{...
|
|
195
|
-
`),r.flags.edit=!0;else{let
|
|
201
|
+
Usage: coinbase ${i} ${e.pathParams.map(M=>`<${M}>`).join(" ")} [fields...]`)}let{parseFields:a}=await Promise.resolve().then(()=>(ar(),_r)),u=a(o),d=!1,c={},g=rt(),p=xt(g,n);if(r_(t)&&p&&ve(g)){let S=Pr(g,p,t);if(S){let{setNested:M}=await Promise.resolve().then(()=>(ar(),_r));for(let[y,k]of Object.entries(S.values))try{M(c,y,JSON.parse(k))}catch{M(c,y,k)}d=!0}}let m=e.params??[];for(let S of Object.keys(u.body)){let M=m.find(y=>y.name===S);if(M?.oneOf)for(let y of m)y.oneOf===M.oneOf&&y.name!==S&&delete c[y.name]}let T=Object.keys(u.body).length>0?{...c,...u.body}:d?(process.stderr.write(`Using saved values from last ${i} call. Pass fields to override.
|
|
202
|
+
`),{...c}):{...u.body},b={};for(let[S,M]of u.query.entries())b[S]=M;let f={};for(let S=0;S<s.length;S++)f[e.pathParams[S]]=s[S];if(!r.flags.watch&&!r.flags.until){let M=e.pathParams.some(y=>typeof f[y]=="string"&&f[y].includes(","))?ut(t):null;if(M){let{surfaceForChannel:y}=await Promise.resolve().then(()=>(me(),Rn)),k=ru(t,e.pathParams,f,y(M)==="watchlist");if(k)throw new Error(k)}}let v=m.filter(S=>S.in==="body"&&S.required&&S.type!=="object"&&S.type!=="array"),z=v.map(S=>S.name);if(z.length>0&&Object.keys(T).length===0&&!r.flags.edit&&!u.rawBody)if(process.stdin.isTTY)if(v.length<=3){let{createInterface:S}=await import("node:readline"),M=S({input:process.stdin,output:process.stderr});for(let y of v){let k=y.enum?` [${y.enum.join(", ")}]`:"",et=y.example?` (e.g. ${y.example})`:"",$=await new Promise(Dt=>{M.question(`${y.name}${k}${et}: `,Dt)});$&&(T[y.name]=$)}M.close()}else process.stderr.write(`This action requires ${z.length} fields. Opening editor.
|
|
203
|
+
`),r.flags.edit=!0;else{let S=z.join(", ");throw new Error(`Missing required field(s): ${S}
|
|
196
204
|
|
|
197
205
|
Provide fields inline:
|
|
198
|
-
coinbase ${
|
|
206
|
+
coinbase ${i} ${z.map(M=>`${M}=<value>`).join(" ")}
|
|
199
207
|
|
|
200
208
|
Or use --template to see the full body:
|
|
201
|
-
coinbase ${
|
|
202
|
-
`)}if(r.flags.edit){let
|
|
203
|
-
`);let
|
|
204
|
-
`);return}let
|
|
205
|
-
`);break}}while(!0)}function
|
|
209
|
+
coinbase ${i} --template
|
|
210
|
+
`)}if(r.flags.edit){let M={...e.template??{},...T},y=await ou(JSON.stringify(M,null,2));for(let k of Object.keys(T))delete T[k];Object.assign(T,y)}if((r.flags.watch||r.flags.until)&&!e.eventStream){let S=ke(u.rawBody);if(u.rawBody&&S===void 0)throw new Error("Request body must be valid JSON.");for(let y of m)for(let k of[f,T,b,S]){if(!k||typeof k!="object"||Array.isArray(k))continue;let et=Ve(y,k[y.name]);if(et)throw new Error(et)}if(Fe(e.agentApiOnlyWhen,f,T,b,S))throw new Error("Run this REST read command without --watch/--until. Use coinbase derivatives updates product_type=GLOBAL_PERP channel=ticker (or channel=book) for public market streaming.")}if(r.flags["dry-run"]){process.stderr.write(`would execute ${t}
|
|
211
|
+
`);let S={...f,...T,...Object.keys(b).length>0?{_query:b}:{}};process.stdout.write(JSON.stringify(S,null,2)+`
|
|
212
|
+
`);return}let L=He(),{name:h,env:q}=oe(g,n),Z=await se(h,q),tt={envName:h,env:q,baseURL:ot(q,h),doRequest:S=>We({...S,...Z}),doStream:S=>Wr({...S,...Z,redirect:"error"}),transport:!e.eventStream&&(r.flags.watch||r.flags.until)?"brokerage":L};if(e.eventStream){let{runEventStream:S}=await Promise.resolve().then(()=>(e_(),t_));await S(t,{body:T,query:b,path:f,headers:u.headers,rawBody:u.rawBody},tt,r.flags);return}if(r.flags.watch||r.flags.until){let{startWatch:S}=await Promise.resolve().then(()=>(me(),Rn)),M=s.length>0?s.flatMap(et=>et.split(",")).filter(Boolean):[],y=r.flags.depth?Number(r.flags.depth):void 0,k=r.flags["until-timeout"]?Number(r.flags["until-timeout"]):void 0;if(y!==void 0&&(!Number.isFinite(y)||y<1))throw new Error(`Invalid --depth value: ${r.flags.depth}`);if(k!==void 0&&(!Number.isFinite(k)||k<1))throw new Error(`Invalid --until-timeout value: ${r.flags["until-timeout"]}`);await S(t,M,tt,{jq:r.flags.jq,depth:y,until:r.flags.until,untilTimeout:k,query:Object.keys(b).length>0?b:void 0});return}let it={body:T,query:{...b},path:f,headers:u.headers,rawBody:u.rawBody??void 0},{outputResult:dr}=await Promise.resolve().then(()=>(An(),Jo)),yt=0;do{let S=await At(t,it,tt);if(dr(S,r.flags.jq),r_(t)&&S.status<400&&Object.keys(T).length>0)try{if(p&&ve(g)){let y={};(function k(et,$){for(let[Dt,V]of Object.entries($)){let re=et?`${et}.${Dt}`:Dt;typeof V=="object"&&V&&!Array.isArray(V)?k(re,V):y[re]=JSON.stringify(V)}})("",T),Cr(g,p,t,y),Et(g)}}catch{}if(!r.flags.paginate)break;let M=Xo(S.data);if(!M||M===it.query.cursor)break;if(it.query.cursor=M,++yt>=100){process.stderr.write(`Pagination limit reached (100 pages)
|
|
213
|
+
`);break}}while(!0)}function iu(){if(process.platform!=="win32")return"vi";try{let{execSync:t}=a_("node:child_process");return t("where code",{stdio:"pipe"}),"code --wait"}catch{}return"notepad"}function su(t){return t.split(`
|
|
206
214
|
`).filter(e=>!e.trimStart().startsWith("//")).join(`
|
|
207
|
-
`)}async function
|
|
215
|
+
`)}async function ou(t){let{writeFileSync:e,readFileSync:r,unlinkSync:n,mkdtempSync:i}=await import("node:fs"),{tmpdir:s}=await import("node:os"),{join:o}=await import("node:path"),{execFileSync:_}=await import("node:child_process"),{scrubbedEnv:a}=await Promise.resolve().then(()=>(_t(),$n));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 u=process.env.VISUAL??process.env.EDITOR??iu();(u.trim()==="code"||u.trim().endsWith("/code"))&&(u+=" --wait");let d=o(i(o(s(),"coinbase-")),"request.json");e(d,t);try{let[c,...g]=u.split(/\s+/);_(c,[...g,d],{stdio:"inherit",env:a()});let p=su(r(d,"utf8"));return JSON.parse(p)}catch(c){throw new Error(c.message?.includes("Unexpected")?`Edited file is not valid JSON: ${c.message}`:`Editor: ${c.message}`)}finally{try{n(d)}catch{}}}mt();E();l();var Oe=class extends Error{constructor(e){super(e),this.name="HelpExit"}};function n_(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 i_(t,e,r){let n=t,i,s=0,o=[],_=[];for(let c=0;c<e.length;c++){let g=e[c],p=n.children.get(g);if(p){_.push(g),o=[...n.children.keys()],n=p,n.action&&(i=n.action,s=_.length);continue}if(g.includes("=")){let m=g.split("=")[0],O=n.children.get(m);if(O?.action){let T=O.action.pathParams.map(f=>` <${f}>`).join(""),b=_.length>0?`coinbase ${r} ${_.join(" ")}`:`coinbase ${r}`;throw new Error(`Did you mean: ${b} ${O.action.name.split(" ").pop()}${T}`)}}break}if(i)return{action:i,remaining:e.slice(s),siblingNames:o};let a=e[_.length],u=_.length>0?`coinbase ${r} ${_.join(" ")}`:`coinbase ${r}`,d=_u(n,r);throw a&&a!=="--help"&&a!=="-h"?new Error(`unknown subcommand "${a}" for ${u}
|
|
208
216
|
|
|
209
217
|
Available actions:
|
|
210
|
-
${
|
|
218
|
+
${d}`):new Oe(`${u}
|
|
211
219
|
|
|
212
220
|
Available actions:
|
|
213
|
-
${
|
|
214
|
-
`)}
|
|
215
|
-
`),process.exit(1));function
|
|
221
|
+
${d}`)}function _u(t,e){let r=[];function n(i){if(i.action){let s=i.action.pathParams.map(o=>` <${o}>`).join("");r.push(` coinbase ${e} ${i.action.name}${s}`)}for(let s of i.children.values())n(s)}return n(t),r.join(`
|
|
222
|
+
`)}we();Ne();E();l();function ee(t,e){let r={},n=[],i=!1,s=new Map;for(let[o,_,a]of e)s.set("--"+o,[o,a]),_&&s.set("-"+_,[o,a]);for(let o=0;o<t.length;o++){let _=t[o];if(_==="-h"||_==="--help"){i=!0;continue}let a=_.indexOf("=");if(a>0&&_.startsWith("--")){let d=s.get(_.slice(0,a));if(d){r[d[0]]=_.slice(a+1);continue}}let u=s.get(_);if(u){r[u[0]]=u[1]?t[++o]??"":!0;continue}if(_.length>2&&_[0]==="-"&&_[1]!=="-"){let d=s.get(_.slice(0,2));if(d?.[1]){r[d[0]]=_.slice(2);continue}}n.push(_)}return{flags:r,args:n,help:i}}process.stdout.on("error",t=>{throw t.code==="EPIPE"&&process.exit(0),t});process.stderr.on("error",t=>{throw t.code==="EPIPE"&&process.exit(0),t});var[au]=process.versions.node.split(".").map(Number);au<22&&(process.stderr.write(`coinbase requires Node.js ${22}+. You have: ${process.versions.node}
|
|
223
|
+
`),process.exit(1));function cu(){return`Coinbase CLI
|
|
216
224
|
|
|
217
225
|
Usage:
|
|
218
226
|
coinbase <resource> <action> [fields...]
|
|
219
227
|
coinbase <action> [fields...]
|
|
220
228
|
|
|
221
229
|
Resources:
|
|
222
|
-
${
|
|
230
|
+
${Tn().map(r=>` ${r.name.padEnd(20)}${r.actions.map(n=>{let i=ut(n.id);return n.eventStream||i&&ft(i)!==null?`${n.name} [--watch]`:n.name}).join(", ")}`).join(`
|
|
223
231
|
`)}
|
|
224
232
|
|
|
225
233
|
Actions:
|
|
@@ -239,8 +247,8 @@ Flags:
|
|
|
239
247
|
-e, --env <name> Environment override
|
|
240
248
|
-V, --version Show version
|
|
241
249
|
-h, --help Show help
|
|
242
|
-
`}async function
|
|
243
|
-
`);return}if(
|
|
250
|
+
`}async function uu(){let t=process.argv.slice(2),e="",r=[];for(let s=0;s<t.length;s++){let o=t[s];o==="-e"||o==="--env"?e=t[++s]??"":o.startsWith("--env=")?e=o.slice(6):o.startsWith("-e")&&o.length>2?e=o.slice(2):r.push(o)}if(r[0]==="--version"||r[0]==="-V"){process.stdout.write(`coinbase ${gt}
|
|
251
|
+
`);return}if(Sn=ls(),r.length===0||r[0]==="-h"||r[0]==="--help"||r[0]==="help"){process.stderr.write(cu());return}let[n,...i]=r;if(n==="env"){let s=ee(i,[["key-id",null,!0],["key-secret",null,!0],["key-file","k",!0],["status",null,!1],["url",null,!0],["brokerage-api-url",null,!0],["agent-api-url",null,!0],["remove",null,!1],["allow-plaintext-secrets",null,!1]]);if(s.help){process.stderr.write(`Manage environments and credentials
|
|
244
252
|
|
|
245
253
|
Usage:
|
|
246
254
|
coinbase env List all environments
|
|
@@ -261,14 +269,14 @@ Flags:
|
|
|
261
269
|
--agent-api-url <url> First-party Agent API URL (includes /api)
|
|
262
270
|
--remove Remove an environment
|
|
263
271
|
--allow-plaintext-secrets Persist secrets to ~/.config/coinbase/config.json (mode 0600) when no OS keychain is available. Default: refuse and error.
|
|
264
|
-
`);return}await
|
|
272
|
+
`);return}await jn(s.args,{keyId:s.flags["key-id"],keySecret:s.flags["key-secret"],keyFile:s.flags["key-file"],status:!!s.flags.status,url:s.flags.url,brokerageApiUrl:s.flags["brokerage-api-url"],agentApiUrl:s.flags["agent-api-url"],remove:!!s.flags.remove,allowPlaintextSecrets:!!s.flags["allow-plaintext-secrets"],envFlag:e})}else if(n==="history"){let s=ee(i,[]);if(s.help){process.stderr.write(`View or clear saved request history
|
|
265
273
|
|
|
266
274
|
Usage:
|
|
267
275
|
coinbase history Show all saved history
|
|
268
276
|
coinbase history clear Clear all history
|
|
269
277
|
coinbase history clear <env> Clear history for an environment
|
|
270
278
|
coinbase history clear <env>.<action> Clear a specific entry
|
|
271
|
-
`);return}
|
|
279
|
+
`);return}ys(s.args)}else if(n==="skills")await Vs(i);else if(n==="mcp"){if(ee(i,[]).help){process.stderr.write(`MCP server for AI agent integration
|
|
272
280
|
|
|
273
281
|
Usage:
|
|
274
282
|
coinbase mcp Start MCP server over stdio
|
|
@@ -276,9 +284,9 @@ Usage:
|
|
|
276
284
|
The MCP server implements the Model Context Protocol (JSON-RPC over
|
|
277
285
|
stdin/stdout) and exposes brokerage and x402 API resources as tools. It is
|
|
278
286
|
typically invoked automatically by AI agents, not run directly.
|
|
279
|
-
`);return}
|
|
280
|
-
`),process.exit(1));let
|
|
287
|
+
`);return}fs()}else if($o(n)){let s=Q[n];s||(process.stderr.write(`error: "${n}" is not available
|
|
288
|
+
`),process.exit(1));let o=ee(i,[["template",null,!1],["dry-run",null,!1],["edit",null,!1],["jq",null,!0],["paginate",null,!1],["watch",null,!1],["depth",null,!0],["until",null,!0],["until-timeout",null,!0]]);if(o.help){mn(n,s);return}await Nn(s.id,s,o,e,n)}else{let s=Tn().find(d=>d.name===n);if(s||(process.stderr.write(`error: unknown command "${n}"
|
|
281
289
|
Run: coinbase --help
|
|
282
|
-
`),process.exit(1)),i.length===0||i[0]==="-h"||i[0]==="--help"){
|
|
290
|
+
`),process.exit(1)),i.length===0||i[0]==="-h"||i[0]==="--help"){Qo(n);return}let o=n_(s.actions),_=i_(o,i,n),a=ee(_.remaining,[["template",null,!1],["dry-run",null,!1],["edit",null,!1],["jq",null,!0],["paginate",null,!1],["watch",null,!1],["depth",null,!0],["until",null,!0],["until-timeout",null,!0]]);if(a.help){mn(n,_.action);return}let u=_.action.id??`${n}_${_.action.name.replace(/[-\s]/g,"_")}`;await Nn(u,_.action,a,e)}}var Sn;uu().catch(t=>{t instanceof Oe&&(process.stderr.write(t.message+`
|
|
283
291
|
`),process.exit(0)),process.stderr.write(`error: ${t.message}
|
|
284
|
-
`),process.exit(1)}).finally(async()=>{if(!
|
|
292
|
+
`),process.exit(1)}).finally(async()=>{if(!Sn||!process.stderr.isTTY)return;let t=await Sn.catch(()=>"");t&&process.stderr.write(t)});
|