@oracle-agent/oracle 0.35.19 → 0.35.21

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.
Files changed (31) hide show
  1. package/dist/assets/skills/oracle-desk-product/SKILL.md +23 -17
  2. package/dist/assets/skills/oracle-mcp-install/SKILL.md +17 -22
  3. package/dist/assets/skills/protocol-api-key-integration/SKILL.md +14 -11
  4. package/dist/assets/skills/self-custodial-onchain-execution/SKILL.md +14 -13
  5. package/dist/assets/skills/trade-loop-circuit-breaker/SKILL.md +1 -1
  6. package/dist/bin/desk-server.mjs +30 -30
  7. package/dist/bin/oracle-data-mcp.mjs +17 -17
  8. package/dist/bin/oracle-gateway.mjs +3 -3
  9. package/dist/bin/oracle-public-server.mjs +5 -5
  10. package/dist/bin/oracle-telegram-mcp.mjs +5 -5
  11. package/dist/cli/commands/chat.mjs +200 -200
  12. package/dist/cli/commands/doctor.mjs +7 -7
  13. package/dist/cli/commands/eval.mjs +113 -113
  14. package/dist/cli/commands/extension-policy.mjs +1 -1
  15. package/dist/cli/commands/governance-prepare.mjs +5 -0
  16. package/dist/cli/commands/model.mjs +204 -204
  17. package/dist/cli/commands/portfolio-risk.mjs +4 -0
  18. package/dist/cli/commands/position-health.mjs +4 -0
  19. package/dist/cli/commands/safety-intelligence.mjs +4 -0
  20. package/dist/cli/commands/swap.mjs +12 -12
  21. package/dist/cli/commands/tax-lots.mjs +4 -0
  22. package/dist/cli/commands/telegram.mjs +6 -6
  23. package/dist/data/desk-data.mjs +26 -26
  24. package/dist/index.mjs +40 -40
  25. package/package.json +1 -1
  26. package/public/eval-report.json +22 -8
  27. package/public/oracle-splash/index.html +44 -23
  28. package/server.json +2 -2
  29. package/dist/assets/skills/oracle-best-execution.md +0 -27
  30. package/dist/assets/skills/oracle-desk.md +0 -27
  31. package/dist/assets/skills/oracle-receipts.md +0 -29
@@ -0,0 +1,4 @@
1
+ import{wordlists as Ie}from"ethers";var we=new Set(["privatekey","privkey","secretkey","seedphrase","seed","mnemonic","passphrase","password","keystore","keymaterial","wif","xprv","xpriv","bearer","authorization","signature","apikey","credential"]),_e=[/\b[5KL][1-9A-HJ-NP-Za-km-z]{50,51}\b/,/\bxprv[0-9A-Za-z]{50,}\b/],Se=new Set([12,15,18,21,24]);function Ae(e){let t=String(e).trim().toLowerCase().split(/\s+/).filter(Boolean);return Se.has(t.length)&&t.every(n=>Ie.en.getWordIndex(n)>=0)}var ke=/^\s*(?:0x)?[0-9a-fA-F]{64}\s*$/,qe=/(hash|digest|root|salt|nonce|proof|commitment|sig|id)(?:e?s)?$/i,Me=new Set(["calldata","data","publickey","pubkey","message","payload","input","extradata"]);function ve(e){let t=re(e);return Me.has(t)||qe.test(t)}var j=class extends Error{constructor(t){super(`action receipt refused: secret-bearing field at ${t}`),this.name="ActionReceiptSecretError",this.code="ACTION_RECEIPT_SECRET"}};function re(e){return String(e).replace(/[^a-z0-9]/gi,"").toLowerCase()}function $e(e){let t=re(e);return[...we].some(n=>t.includes(n))}function Oe(e,t,n){if(typeof t=="string"){if(_e.some(o=>o.test(t))||Ae(t))throw new j(n);if(ke.test(t)&&!ve(e))throw new j(n)}}function P(e,t="$",n=""){if(e==null||typeof e=="boolean")return e;if(typeof e=="string")return Oe(n,e,t),e;if(typeof e=="number"){if(!Number.isFinite(e))throw new TypeError(`action receipt: non-finite number at ${t}`);return e}if(typeof e=="bigint")return e.toString();if(Array.isArray(e))return e.map((i,a)=>P(i,`${t}[${a}]`,n));if(typeof e!="object"||Object.getPrototypeOf(e)!==Object.prototype)throw new TypeError(`action receipt: JSON-like value required at ${t}`);let o={};for(let i of Object.keys(e).sort()){let a=`${t}.${i}`;if($e(i))throw new j(a);e[i]!==void 0&&(o[i]=P(e[i],a,i))}return o}function N(e){return P(e)}function G(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(G).join(",")}]`:`{${Object.keys(e).map(t=>`${JSON.stringify(t)}:${G(e[t])}`).join(",")}}`}function K(e){return G(P(e))}var Ee=1,xe=Object.freeze(["fifo","lifo","hifo","specific"]),Be="Accounting records only; not tax advice.",Te=new Set(["acquisition","disposal","transfer"]),Re=new Set(["complete","incomplete","unknown"]),Le=/[\u0000-\u001f\u007f]/,W=class extends Error{constructor(t,n="COST_BASIS_INVALID"){super(`cost basis: ${t}`),this.name="CostBasisValidationError",this.code=n}};function f(e,t){throw new W(e,t)}function M(e,t){return e<t?-1:e>t?1:0}function g(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){for(let t of Object.values(e))g(t);Object.freeze(e)}return e}function v(e,t){return(!e||typeof e!="object"||Array.isArray(e)||Object.getPrototypeOf(e)!==Object.prototype)&&f(`${t} must be a plain object`),e}function b(e,t,{optional:n=!1,lower:o=!1}={}){if(e==null&&n)return null;typeof e!="string"&&f(`${t} must be a string`);let i=e.trim();return i||f(`${t} is required`),Le.test(i)&&f(`${t} contains control characters`),i.length>512&&f(`${t} is too long`),o?i.toLowerCase():i}function k(e,t,{optional:n=!1,positive:o=!1}={}){if(e==null&&n)return null;typeof e=="number"&&f(`${t} must be an exact decimal string or BigInt; Number coercion is refused`,"COST_BASIS_UNSAFE_NUMBER");let i;typeof e=="bigint"?i=e.toString():typeof e=="string"?i=e:f(`${t} must be an exact decimal string or BigInt`),/^\d+$/.test(i)||f(`${t} must be a non-negative base-10 integer string`);let a=BigInt(i);return o&&a===0n&&f(`${t} must be positive`),a.toString()}function L(e){return e==null?null:e.toString()}function F(e,t){let n=v(e,t);return g({chain:b(n.chain??n.chainId,`${t}.chain`,{lower:!0}),account:b(n.account??n.address??n.owner,`${t}.account`)})}function E(e,t){return`${e.length}:${e}|${t.chain.length}:${t.chain}|${t.account.length}:${t.account}`}function ue(e,t="evidence"){if(e==null)return g({status:"unknown",references:[]});let n=v(e,t),o=b(n.status??"unknown",`${t}.status`,{lower:!0});Re.has(o)||f(`${t}.status must be complete, incomplete, or unknown`),n.references!=null&&!Array.isArray(n.references)&&f(`${t}.references must be an array`);let i=(n.references||[]).map((s,c)=>{let u=v(s,`${t}.references[${c}]`);return{kind:b(u.kind??u.type,`${t}.references[${c}].kind`,{lower:!0}),id:b(u.id??u.receiptId??u.txHash,`${t}.references[${c}].id`)}}).sort((s,c)=>M(s.kind,c.kind)||M(s.id,c.id)),a=[];for(let s of i)a.some(c=>c.kind===s.kind&&c.id===s.id)||a.push(s);return g({status:o,references:a})}function se(e,t){if(e==null)return[];(!Array.isArray(e)||e.length===0)&&f(`${t} must be a non-empty array`);let n=new Set;return e.map((o,i)=>{let a=v(o,`${t}[${i}]`),s=b(a.lotId,`${t}[${i}].lotId`);return n.has(s)&&f(`${t} repeats lotId ${JSON.stringify(s)}`),n.add(s),g({lotId:s,quantity:k(a.quantity,`${t}[${i}].quantity`,{positive:!0})})})}function Ce(e){N(e);let t=v(e,"event"),n=b(t.type,"event.type",{lower:!0});Te.has(n)||f("event.type must be acquisition, disposal, or transfer");let o=b(t.id??t.eventId,"event.id"),i=k(t.occurredAt??t.timestamp,"event.occurredAt"),a=b(t.asset??t.symbol??t.coin,"event.asset"),s=k(t.quantity??t.amount??t.size,"event.quantity",{positive:!0}),c=k(t.feeMinor??t.feeUsdMinor??"0","event.feeMinor"),u=ue(t.evidence),p=t.source==null?null:b(t.source,"event.source"),d={id:o,type:n,occurredAt:i,asset:a,quantity:s,feeMinor:c,source:p,evidence:u};if(n==="acquisition"){let I={...d,location:F(t.location??{chain:t.chain??t.chainId,account:t.account??t.address??t.owner},"event.location"),grossAmountMinor:k(t.grossAmountMinor??t.costMinor??t.basisBeforeFeesMinor,"event.grossAmountMinor",{optional:!0}),lotId:b(t.lotId??o,"event.lotId"),specificLots:[]};return g(I)}return g(n==="disposal"?{...d,location:F(t.location??{chain:t.chain??t.chainId,account:t.account??t.address??t.owner},"event.location"),grossAmountMinor:k(t.grossAmountMinor??t.proceedsMinor??t.proceedsBeforeFeesMinor,"event.grossAmountMinor",{optional:!0}),specificLots:se(t.specificLots??t.lotSelections,"event.specificLots")}:{...d,from:F(t.from,"event.from"),to:F(t.to,"event.to"),grossAmountMinor:null,specificLots:se(t.specificLots??t.lotSelections,"event.specificLots")})}function ze(e,t){let n=BigInt(e.occurredAt)-BigInt(t.occurredAt);return n<0n?-1:n>0n?1:M(e.id,t.id)}function je(e=[]){Array.isArray(e)||f("events must be an array");let t=new Map,n=0;for(let o of e){let i=Ce(o),a=K(i),s=t.get(i.id);if(s){s.canonical!==a&&f(`conflicting duplicate event id ${JSON.stringify(i.id)}`,"COST_BASIS_DUPLICATE_CONFLICT"),n+=1;continue}t.set(i.id,{event:i,canonical:a})}return g({events:[...t.values()].map(({event:o})=>o).sort(ze),duplicatesIgnored:n})}function Ne(e){let t=b(e??"fifo","method",{lower:!0});return xe.includes(t)||f("method must be fifo, lifo, hifo, or specific"),t}var ae=Object.freeze({acquisitionFees:new Set(["include-in-basis","exclude","unresolved"]),disposalFees:new Set(["reduce-proceeds","exclude","unresolved"]),transferFees:new Set(["include-in-basis","exclude","unresolved"])});function Fe(e){e!=null&&v(e,"treatment");let t=e||{},n={};for(let o of Object.keys(ae))n[o]=b(t[o]??"unresolved",`treatment.${o}`,{lower:!0}),ae[o].has(n[o])||f(`treatment.${o} has an unsupported value`);return g(n)}function Ve(e,t){N(e);let n=v(e,`marketValues[${t}]`);return g({id:b(n.id??n.valuationId,`marketValues[${t}].id`),asset:b(n.asset??n.symbol??n.coin,`marketValues[${t}].asset`),location:F(n.location??{chain:n.chain??n.chainId,account:n.account??n.address??n.owner},`marketValues[${t}].location`),quantity:k(n.quantity,`marketValues[${t}].quantity`),valueMinor:k(n.valueMinor??n.marketValueMinor,`marketValues[${t}].valueMinor`),asOf:k(n.asOf,`marketValues[${t}].asOf`),evidence:ue(n.evidence,`marketValues[${t}].evidence`)})}function le(e,t){return t==null||BigInt(e)<=BigInt(t)}function Pe(e=[],t=null){Array.isArray(e)||f("marketValues must be an array");let n=new Map,o=0;e.forEach((s,c)=>{let u=Ve(s,c),p=K(u),d=n.get(u.id);d?(d.canonical!==p&&f(`conflicting duplicate market value id ${JSON.stringify(u.id)}`,"COST_BASIS_DUPLICATE_CONFLICT"),o+=1):n.set(u.id,{row:u,canonical:p})});let i=[...n.values()].map(({row:s})=>s).filter(s=>le(s.asOf,t)),a=new Map;for(let s of i){let c=E(s.asset,s.location),u=a.get(c);(!u||BigInt(s.asOf)>BigInt(u.asOf)||s.asOf===u.asOf&&M(s.id,u.id)<0)&&a.set(c,s)}return{values:i.sort((s,c)=>M(s.id,c.id)),byHolding:a,duplicatesIgnored:o}}function h(e,t,n,o){e.push(g({code:t,eventId:n??null,detail:o}))}function He(e,t,n){if(e.grossAmountMinor==null)return h(n,"missing-acquisition-basis",e.id,"gross acquisition amount is unknown; lot basis remains unknown"),null;let o=BigInt(e.grossAmountMinor),i=BigInt(e.feeMinor);return i===0n?o:t.acquisitionFees==="include-in-basis"?o+i:t.acquisitionFees==="exclude"?o:(h(n,"unresolved-acquisition-fee-treatment",e.id,"fee treatment was not supplied; lot basis remains unknown"),null)}function Je(e,t,n){if(e.grossAmountMinor==null)return h(n,"missing-disposal-proceeds",e.id,"gross disposal proceeds are unknown"),null;let o=BigInt(e.grossAmountMinor),i=BigInt(e.feeMinor);return i===0n?o:t.disposalFees==="reduce-proceeds"?o-i:t.disposalFees==="exclude"?o:(h(n,"unresolved-disposal-fee-treatment",e.id,"fee treatment was not supplied; recognized proceeds remain unknown"),null)}function De(e,t){let n=(o,i)=>{let a=BigInt(o.acquiredAt)-BigInt(i.acquiredAt);return a<0n?-1:a>0n?1:M(o.lotId,i.lotId)};return e==="fifo"?[...t].sort(n):e==="lifo"?[...t].sort((o,i)=>-n(o,i)):e==="hifo"?[...t].sort((o,i)=>{let a=o.basisRemaining*i.quantityRemaining,s=i.basisRemaining*o.quantityRemaining;return a>s?-1:a<s?1:n(o,i)}):[...t]}function ce(e,t){let n=e.quantityRemaining,o=e.basisRemaining,i=null;return o!=null&&(i=t===n?o:o*t/n,e.basisRemaining-=i),e.quantityRemaining-=t,{lot:e,quantity:t,basis:i}}function Ue(e,t,n){let o=E(t,n);return e.filter(i=>i.key===o&&i.quantityRemaining>0n)}function Ge({event:e,lots:t,method:n,issues:o,tainted:i}){let a=e.type==="transfer"?e.from:e.location,s=E(e.asset,a),c=BigInt(e.quantity);if(i.has(s))return h(o,"inventory-state-incomplete",e.id,"an earlier unmatched record makes this holding indeterminate"),{matches:[],missing:c,key:s,indeterminate:!0};let u=Ue(t,e.asset,a);if(n==="hifo"&&u.some(I=>I.basisRemaining==null))return h(o,"hifo-basis-unknown",e.id,"HIFO cannot rank a lot whose basis is unknown"),i.add(s),{matches:[],missing:c,key:s,indeterminate:!0};let p=[],d=c;if(n==="specific"){if(e.specificLots.length===0)return h(o,"specific-lots-required",e.id,"specific-lot method requires explicit lot selections"),i.add(s),{matches:p,missing:d,key:s,indeterminate:!0};if(e.specificLots.reduce((_,S)=>_+BigInt(S.quantity),0n)!==c)return h(o,"specific-lot-quantity-mismatch",e.id,"specific-lot quantities do not equal the event quantity"),i.add(s),{matches:p,missing:d,key:s,indeterminate:!0};for(let _ of e.specificLots){let S=u.find(T=>T.lotId===_.lotId),z=BigInt(_.quantity);if(!S||S.quantityRemaining<z){h(o,"specific-lot-unavailable",e.id,`requested lot ${JSON.stringify(_.lotId)} is absent or too small`);continue}p.push(ce(S,z)),d-=z}}else{e.specificLots.length&&f(`event ${JSON.stringify(e.id)} supplies specificLots but method is ${n}`);for(let I of De(n,u)){if(d===0n)break;let _=d<I.quantityRemaining?d:I.quantityRemaining;p.push(ce(I,_)),d-=_}}return d>0n&&(h(o,"insufficient-inventory",e.id,"recorded lots do not cover the event quantity; no replacement basis was invented"),i.add(s)),{matches:p,missing:d,key:s,indeterminate:d>0n}}function Y(e,t,n){if(e==null)return t.map(()=>null);let o=e,i=n;return t.map(a=>{if(i===0n)return 0n;let s=a===i?o:o*a/i;return o-=s,i-=a,s})}function Ke(e,t){let n=[...e.map(o=>o.evidence.status),...t.map(o=>o.evidence.status)];return n.length===0||n.every(o=>o==="complete")?"complete":n.some(o=>o==="incomplete")?"incomplete":"unknown"}function C(e,t){let n=e.map(i=>i[t]),o=n.filter(i=>i!=null).reduce((i,a)=>i+BigInt(a),0n);return{value:n.every(i=>i!=null)?o.toString():null,known:o.toString()}}function Ye(e,t){return{lotId:e.lotId,originLotId:e.lotId,acquisitionEventId:e.id,asset:e.asset,location:e.location,key:E(e.asset,e.location),acquiredAt:e.occurredAt,quantityRemaining:BigInt(e.quantity),basisRemaining:t,evidenceStatus:e.evidence.status}}function de(e={},t={}){N(e),N(t),v(e,"input"),v(t,"options");let n=k(t.asOf??e.asOf,"asOf",{optional:!0}),o=je(e.events||[]),i=n==null?o.events:o.events.filter(r=>le(r.occurredAt,n)),a=Ne(t.method??e.method),s=Fe(t.treatment??e.treatment),c=Pe(e.marketValues||[],n),u=[],p=[],d=new Set,I=[],_=[],S=new Set;for(let r of i){if(r.type==="acquisition"){if(d.has(r.lotId)){h(u,"duplicate-lot-id",r.id,`lotId ${JSON.stringify(r.lotId)} is already in use`),S.add(E(r.asset,r.location));continue}d.add(r.lotId),p.push(Ye(r,He(r,s,u)));continue}let m=Ge({event:r,lots:p,method:a,issues:u,tainted:S});if(r.type==="disposal"){let l=Je(r,s,u),O=Y(l,m.matches.map(y=>y.quantity),BigInt(r.quantity)),w=m.matches.map((y,D)=>{let U=O[D];return g({lotId:y.lot.lotId,originLotId:y.lot.originLotId,quantity:y.quantity.toString(),basisMinor:L(y.basis),proceedsMinor:L(U),gainMinor:y.basis==null||U==null?null:(U-y.basis).toString(),acquiredAt:y.lot.acquiredAt,evidenceStatus:y.lot.evidenceStatus})}),A=w.filter(y=>y.basisMinor!=null).reduce((y,D)=>y+BigInt(D.basisMinor),0n),H=m.missing===0n&&w.every(y=>y.basisMinor!=null),J=m.missing===0n&&l!=null;I.push(g({eventId:r.id,asset:r.asset,location:r.location,occurredAt:r.occurredAt,quantity:r.quantity,grossProceedsMinor:r.grossAmountMinor,feeMinor:r.feeMinor,recognizedProceedsMinor:J?l.toString():null,basisMinor:H?A.toString():null,gainMinor:H&&J?(l-A).toString():null,unknownQuantity:m.missing.toString(),status:H&&J?"complete":"incomplete",evidenceStatus:r.evidence.status,matches:w}));continue}let $=BigInt(r.feeMinor),q=$>0n&&s.transferFees==="include-in-basis",x=$>0n&&s.transferFees==="unresolved";x&&h(u,"unresolved-transfer-fee-treatment",r.id,"fee treatment was not supplied; transferred lot basis remains unknown");let B=Y(q?$:0n,m.matches.map(l=>l.quantity),BigInt(r.quantity)),V=m.matches.map((l,O)=>{let w=l.basis;x?w=null:w!=null&&q&&(w+=B[O]);let A=`${r.id}:${O+1}`;return d.has(A)?(h(u,"duplicate-lot-id",r.id,`derived transfer lotId ${JSON.stringify(A)} is already in use`),S.add(E(r.asset,r.to)),null):(d.add(A),p.push({lotId:A,originLotId:l.lot.originLotId,acquisitionEventId:l.lot.acquisitionEventId,asset:r.asset,location:r.to,key:E(r.asset,r.to),acquiredAt:l.lot.acquiredAt,quantityRemaining:l.quantity,basisRemaining:w,evidenceStatus:r.evidence.status==="complete"&&l.lot.evidenceStatus==="complete"?"complete":"unknown"}),g({fromLotId:l.lot.lotId,toLotId:A,originLotId:l.lot.originLotId,quantity:l.quantity.toString(),basisMinor:L(w)}))}).filter(Boolean);m.indeterminate&&S.add(E(r.asset,r.to)),_.push(g({eventId:r.id,asset:r.asset,from:r.from,to:r.to,occurredAt:r.occurredAt,quantity:r.quantity,feeMinor:r.feeMinor,unknownQuantity:m.missing.toString(),status:m.indeterminate||V.some(l=>l.basisMinor==null)?"incomplete":"complete",moved:V}))}let z=p.filter(r=>r.quantityRemaining>0n).sort((r,m)=>M(r.key,m.key)||M(r.lotId,m.lotId)),T=new Map;for(let r of z)T.has(r.key)||T.set(r.key,[]),T.get(r.key).push(r);let R=[];for(let[r,m]of[...T].sort(([$],[q])=>M($,q))){let $=m.reduce((l,O)=>l+O.quantityRemaining,0n),q=c.byHolding.get(r)||null,x=S.has(r),B=q;q?BigInt(q.quantity)!==$&&(h(u,"market-value-quantity-mismatch",null,`market value ${JSON.stringify(q.id)} does not cover the recorded holding quantity`),B=null):h(u,"missing-market-value",null,`no market value was supplied for holding ${r}`),x&&(B=null);let V=Y(B?BigInt(B.valueMinor):null,m.map(l=>l.quantityRemaining),$);m.forEach((l,O)=>{let w=V[O],A=w==null||l.basisRemaining==null?null:w-l.basisRemaining;R.push(g({lotId:l.lotId,originLotId:l.originLotId,acquisitionEventId:l.acquisitionEventId,asset:l.asset,location:l.location,acquiredAt:l.acquiredAt,quantity:l.quantityRemaining.toString(),basisMinor:x?null:L(l.basisRemaining),marketValueMinor:L(w),unrealizedGainMinor:x?null:L(A),valuationId:B?.id??null,status:x||l.basisRemaining==null||w==null?"incomplete":"complete",evidenceStatus:l.evidenceStatus}))})}let X=C(I,"basisMinor"),Z=C(I,"recognizedProceedsMinor"),ee=C(I,"gainMinor"),te=C(R,"basisMinor"),ne=C(R,"marketValueMinor"),oe=C(R,"unrealizedGainMinor"),ie=i.every(r=>BigInt(r.feeMinor)>0n?r.type==="acquisition"?s.acquisitionFees!=="unresolved":r.type==="disposal"?s.disposalFees!=="unresolved":s.transferFees!=="unresolved":!0),be={recordVersion:Ee,recordType:"cost-basis-records",label:Be,asOf:n,method:a,units:{quantity:"exact asset minor units as base-10 integer strings",usd:"USD minor units as base-10 integer strings"},accountingFacts:{events:i,marketValues:c.values,duplicatesIgnored:o.duplicatesIgnored+c.duplicatesIgnored},jurisdictionalTreatment:{suppliedByCaller:s,status:ie?"specified":"unresolved",note:"Fee and lot-selection treatment can vary by jurisdiction. These caller-selected recordkeeping rules are not tax advice."},realized:{disposals:I,totals:{proceedsMinor:Z.value,basisMinor:X.value,gainMinor:ee.value,knownProceedsSubtotalMinor:Z.known,knownBasisSubtotalMinor:X.known,knownGainSubtotalMinor:ee.known}},transfers:_,holdings:R,unrealized:{totals:{marketValueMinor:ne.value,basisMinor:te.value,gainMinor:oe.value,knownMarketValueSubtotalMinor:ne.known,knownBasisSubtotalMinor:te.known,knownGainSubtotalMinor:oe.known}},completeness:{accounting:u.some(r=>r.code!=="missing-market-value")?"incomplete":"complete",valuation:R.every(r=>r.marketValueMinor!=null)?"complete":"incomplete",evidence:Ke(i,c.values),treatment:ie?"specified":"unresolved"},issues:u};return g(be)}import fe from"node:fs";var pe=1024*1024;function me(e=[],t={}){let n=[],o={};for(let i=0;i<e.length;i+=1){let a=e[i];if(!a.startsWith("--")){n.push(a);continue}let s=a.indexOf("="),c=a.slice(2,s===-1?void 0:s),u=t[c];if(!u)throw new TypeError(`unknown option --${c}`);if(Object.hasOwn(o,c))throw new TypeError(`duplicate option --${c}`);if(u==="boolean"){if(s!==-1)throw new TypeError(`option --${c} does not take a value`);o[c]=!0;continue}let p=s===-1?e[++i]:a.slice(s+1);if(p==null||p===""||p.startsWith("--"))throw new TypeError(`option --${c} requires a value`);o[c]=p}return{positionals:n,options:o}}function ge(e,t="input"){if(!e)throw new TypeError(`${t} JSON path or - is required`);let n=e==="-"?fe.readFileSync(0):fe.readFileSync(e);if(n.length>pe)throw new RangeError(`${t} exceeds ${pe} bytes`);let o;try{o=JSON.parse(n.toString("utf8"))}catch(i){throw new TypeError(`${t} must be valid JSON: ${i.message}`)}if(!o||typeof o!="object"||Array.isArray(o)||Object.getPrototypeOf(o)!==Object.prototype)throw new TypeError(`${t} must be a JSON object`);return o}function ye(e,t=process.stdout){t.write(`${JSON.stringify(e,null,2)}
2
+ `)}function he(e,t=process.stderr){return t.write(`oracle: ${e instanceof Error?e.message:String(e)}
3
+ `),2}var Q="oracle tax-lots <input.json|-> [--method fifo|lifo|hifo|specific] [--as-of <integer>]",rt={name:"tax-lots",summary:"build exact cost-basis records from supplied events",group:"read",usage:Q,async run(e){let t=e.argv??[];if(t.length===0||t.includes("--help")||t.includes("-h"))return process.stdout.write(`${Q}
4
+ `),0;try{let{positionals:n,options:o}=me(t,{method:"value","as-of":"value"});if(n.length!==1)throw new TypeError(Q);let i=ge(n[0]);return ye(de(i,{method:o.method,asOf:o["as-of"]})),0}catch(n){return he(n)}}};export{rt as default};
@@ -1,6 +1,6 @@
1
- import{createHash as we,randomBytes as $e}from"node:crypto";import{mkdirSync as Se,readFileSync as Ce,writeFileSync as Re}from"node:fs";import{homedir as Ae}from"node:os";import{dirname as Ne,join as j}from"node:path";var re=/^[A-Z0-9][A-Z0-9._-]{0,11}$/;function ne(t){let e=String(t||"").trim();if(!e||e.includes("ts.net")||!/^https:\/\//i.test(e))return null;try{return new URL(e)}catch{return null}}function U(t,{coin:e,side:r,sizeUsd:o,leverage:s,venue:a,confirm:i,user:u}={}){let l=ne(t);if(!l)return null;if(e&&re.test(String(e).toUpperCase())&&l.searchParams.set("coin",String(e).toUpperCase()),(r==="long"||r==="short")&&l.searchParams.set("side",r),Number.isFinite(Number(o))&&Number(o)>=1&&l.searchParams.set("size",String(Math.min(1e5,Math.round(Number(o))))),Number.isInteger(Number(s))&&Number(s)>=1&&l.searchParams.set("lev",String(Math.min(50,Number(s)))),a){let b=String(a).toLowerCase()==="hl"?"hyperliquid":String(a).toLowerCase();l.searchParams.set("venue",b)}else l.searchParams.get("venue")||l.searchParams.set("venue","hyperliquid");return l.searchParams.set("view","perps"),l.searchParams.set("build","1"),i&&/^[0-9a-f]{32}$/i.test(String(i))&&l.searchParams.set("confirm",String(i).toLowerCase()),u&&/^0x[0-9a-fA-F]{40}$/.test(String(u))&&l.searchParams.set("user",String(u).toLowerCase()),l.toString()}var ie={robinhood:{chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC"],evm:!0},ethereum:{chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],evm:!0},polygon:{chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],evm:!0},arbitrum:{chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],evm:!0},base:{chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],evm:!0},hyperevm:{chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],evm:!0},bsc:{chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],evm:!0},avalanche:{chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],evm:!0},optimism:{chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],evm:!0},abstract:{chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],evm:!0},stable:{chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],evm:!0}},oe=new Map(Object.values(ie).map(t=>[t.chainId,t]));function H(t){return oe.get(Number(t))||null}var Ue=Object.freeze([100,50,25]),He=Object.freeze([100,50,25,10]);var c="UNKNOWN",ze=Object.freeze(["token","launch","hip3","hip4","polymarket","twap","bridge","swap","approve"]),ae=/[_*[\]`]/g;function n(t){return d(t)?String(t).replace(ae,e=>`\\${e}`):c}function d(t){return t==null?!1:typeof t=="number"?Number.isFinite(t):typeof t=="string"?t.trim()!=="":!0}function f(t){if(!d(t))return c;let e=String(t).replace(/`/g,"");return e===""?c:`\`${e}\``}function w(t,{decimals:e=2}={}){if(!d(t))return c;let r=Number(t);return Number.isFinite(r)?r.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:e}):c}function p(t,{decimals:e=2}={}){let r=w(t,{decimals:e});return r===c?c:`${r} USD`}function I(t,{decimals:e=2}={}){let r=w(t,{decimals:e});return r===c?c:`${r}%`}function N(t){let e=w(t,{decimals:0});return e===c?c:`${e} bps`}function $(t,e){if(!d(t))return c;let r=Number(e);if(!Number.isInteger(r)||r<0||r>77)return c;let o;try{o=BigInt(typeof t=="string"?t.trim():t)}catch{return c}let s=o<0n,a=s?-o:o,i=10n**BigInt(r),u=(a/i).toString(),l=(a%i).toString().padStart(r,"0").replace(/0+$/,"");return`${s?"-":""}${u}${l?`.${l}`:""}`}function E(t){if(typeof t=="number"&&Number.isFinite(t))return t<0||t>1?c:t>=.75?"HIGH":t>=.4?"MEDIUM":"LOW";if(typeof t=="string"){let e=t.trim().toUpperCase();if(e==="HIGH"||e==="MEDIUM"||e==="LOW")return e}return c}function k(t={}){let e=t.chainId;if(!d(e)||!Number.isFinite(Number(e)))return d(t.chain)?n(t.chain):c;let o=H(e)?.name||(d(t.chain)?String(t.chain):c);return`${n(o)} (chainId ${Number(e)})`}function D(t={}){return n(t.venue??t.dex??t.pool?.venue)}function se(t){return t==null?"NONE (text card only)":typeof t=="string"?t.trim()?f(t):"NONE (text card only)":t.error||t.ok===!1||t.available===!1?`UNAVAILABLE${d(t.error)?` \u2014 ${n(t.error)}`:""} (text card stands)`:d(t.url)?f(t.url):"NONE (text card only)"}function R(t={},{now:e=Date.now()}={}){let r=t.grant??t.session??null;if(!r||typeof r!="object")return{allowed:!1,reason:"no local grant/session",actions:[]};if(r.local===!1)return{allowed:!1,reason:"grant is not local",actions:[]};if(r.revoked===!0)return{allowed:!1,reason:"grant revoked",actions:[]};let o=r.expiresAt??r.expiry;if(d(o)){let a=typeof o=="number"?o:Date.parse(o);if(!Number.isFinite(a))return{allowed:!1,reason:"grant expiry unreadable",actions:[]};if(a<=e)return{allowed:!1,reason:"grant expired",actions:[]}}return{allowed:!0,reason:"valid local grant",actions:Array.isArray(r.actions)&&r.actions.length?r.actions.slice():["BUY","SELL"]}}function ce(t){let e=R(t);return e.allowed?`${e.actions.map(r=>n(r)).join(" / ")} (${n(e.reason)})`:`prepare-only \u2014 ${n(e.reason)}`}function h(t,e,r={}){let o=[`*${t}*`];for(let[s,a]of e)o.push(`${s}: ${a==null||a===""?c:a}`);return o.push(`Chart: ${se(r.chart)}`),o.push(`Actions: ${ce(r)}`),Array.isArray(r.warnings)&&r.warnings.length&&o.push(`Warnings: ${r.warnings.map(s=>n(s)).join("; ")}`),(d(r.source)||d(r.fetchedAt))&&o.push(`Source: ${n(r.source)} at ${n(r.fetchedAt)}`),o.join(`
2
- `)}function g(t){return["Confidence",E(t.confidence)]}function le(t){let e=t.quote;if(!e||typeof e!="object")return[];let r=d(e.decimals)?$(e.amountOutRaw??e.out??e.raw,e.decimals):c;return[["Quote out (raw)",f(e.amountOutRaw??e.out??e.raw)],["Quote out",r===c?c:`${n(r)} ${n(e.symbol??"")}`.trim()]]}function F(t){let e=t.autoSlippage;if(!e||typeof e!="object")return["Auto-slippage",c];let r=N(e.selectedBps),o=N(e.capBps);return["Auto-slippage",r===c&&o===c?c:`${r} selected, cap ${o}`]}function ue(t={}){let e=t||{};return h(`ORACLE TOKEN \u2014 ${n(e.symbol??e.token??e.name)}`,[["Chain",k(e)],["Venue",D(e)],["Name",n(e.name)],["Address",f(e.address??e.mint??e.contract)],["Price",p(e.priceUsd,{decimals:8})],["Market cap",p(e.marketCapUsd)],["Liquidity",p(e.liquidityUsd)],["Volume 24h",p(e.volume24hUsd)],["Change 24h",I(e.priceChange24h)],["Fee tier",d(e.feeTier)?`${N(Number(e.feeTier)/100)} (${w(e.feeTier,{decimals:0})})`:c],["Age",n(e.age)],...le(e),F(e),g(e)],e)}function de(t={}){let e=t||{};return h(`ORACLE LAUNCH \u2014 ${n(e.symbol??e.token??e.name)}`,[["Chain",k(e)],["Venue",D(e)],["Address",f(e.address??e.mint??e.contract)],["Pool",f(e.pool?.address??e.poolAddress??e.pool)],["Liquidity",p(e.liquidityUsd)],["Route ready",n(e.routeReady)],["Sellable",n(e.sellable)],["Sell sim",n(e.sellSimulation??e.sellSim)],["Smart wallets",n(e.smartWalletOverlap)],["Risk",n(e.risk??e.riskStatus)],["Prepared ticket",n(e.preparedTicket??e.ticketStatus)],F(e),g(e)],e)}function pe(t={}){let e=t||{};return h(`ORACLE HIP-3 \u2014 ${n(e.market??e.coin??e.name)}`,[["Venue",`Hyperliquid builder-dex ${n(e.dex)}`],["Market",n(e.market??e.coin)],["Mark",p(e.markPx,{decimals:6})],["Oracle",p(e.oraclePx,{decimals:6})],["Funding",I(e.funding,{decimals:6})],["Open interest",p(e.openInterestUsd)],["Depth",n(e.depth)],["Liquidation notes",n(e.liquidationNotes??e.riskNotes)],["Account context",n(e.accountContext)],g(e)],e)}function me(t={}){let e=t||{};return h(`ORACLE HIP-4 \u2014 ${n(e.event??e.market??e.name)}`,[["Venue",`Hyperliquid HIP-4 ${n(e.dex??"outcome")}`],["Event",n(e.event)],["Outcome",n(e.outcome)],["Market id",f(e.marketId??e.market)],["Bid",p(e.bid,{decimals:6})],["Ask",p(e.ask,{decimals:6})],["Depth",n(e.depth)],["Edge",I(e.edge)],["Position",n(e.position)],g(e)],e)}function fe(t={}){let e=t||{};return h(`ORACLE POLYMARKET \u2014 ${n(e.event??e.market??e.name)}`,[["Venue","Polymarket CLOB"],["Event",n(e.event)],["Market",n(e.market)],["Market id",f(e.marketId??e.conditionId??e.tokenId)],["Yes",p(e.yesPrice,{decimals:4})],["No",p(e.noPrice,{decimals:4})],["Best bid / ask",`${p(e.bestBid,{decimals:4})} / ${p(e.bestAsk,{decimals:4})}`],["Volume",p(e.volumeUsd)],["Resolution risk",n(e.resolutionRisk)],["Order intent",n(e.orderIntent)],g(e)],e)}function he(t={}){let e=t||{},r=d(e.completedSplits)&&d(e.totalSplits)?`${w(e.completedSplits,{decimals:0})} / ${w(e.totalSplits,{decimals:0})}`:c;return h(`ORACLE TWAP \u2014 ${n(e.pair??e.symbol??e.name)}`,[["Chain",k(e)],["Side",n(e.side??e.direction)],["Amount",`${n($(e.amountTotal??e.amount,e.decimals??18))} ${n(e.symbol??"")}`.trim()],["Splits",`${w(e.totalSplits,{decimals:0})} over ${n(e.window)}`],["Progress",r],["Avg price",p(e.averagePrice,{decimals:6})],["Next split",n(e.nextSplitAt)],["Slippage cap",N(e.slippageBps)],["Status",n(e.status)],g(e)],e)}function ge(t={}){let e=t||{},r=e.approval??e.revokeCheck??{},o=r.needsRevoke&&r.spender?`revoke.cash \u2014 ${n(r.spender)}`:r.needsRevoke===!1?"revoke.cash \u2014 clean":"revoke.cash \u2014 unchecked";return h(`ORACLE BRIDGE \u2014 ${n(e.pair??e.fromSymbol)} \u2192 ${n(e.toSymbol??"")}`.replace(/→ $/,""),[["Bridging","deBridge \xB7 LI.FI \u2014 best route wins"],["From chain",k({chainId:e.fromChainId,chain:e.fromChain})],["To chain",k({chainId:e.toChainId,chain:e.toChain})],["Amount",`${n($(e.amount,e.fromDecimals??18))} ${n(e.fromSymbol??"")}`.trim()],["Best route",n(e.bestRoute??e.winner)],["Est. received",`${n($(e.amountOut,e.toDecimals??18))} ${n(e.toSymbol??"")}`.trim()],["Fee",p(e.feeUsd)],["Est. time",n(e.estimatedTime)],["Revoke check",o],["All providers",n(e.providers?.join(", "))],["Preparable",n(e.preparable)],g(e)],e)}function be(t){let r=(Array.isArray(t)?t:[]).slice(1,4).map(o=>{let s=n(o.source??o.venue??o.name),a=o.improvementBps==null&&o.deltaBps==null?null:Number(o.improvementBps??o.deltaBps),i=Number.isFinite(a)?`${Math.abs(a).toFixed(0)} bps behind`:"spread UNKNOWN";return`${s} (${i})`});return r.length?r.join("; "):c}function ke(t){let e=t.rankedOn??t.swap?.rankedOn??t.best?.rankedOn;return d(e)?n(e):c}function ye(t={}){let e=t||{},r=e.swap&&typeof e.swap=="object"?e.swap:e,o=e.bridge&&typeof e.bridge=="object"?e.bridge:null,s=r.best??r.winner??{},a=`${n(e.tokenInSymbol??e.fromSymbol??"IN")} \u2192 ${n(e.tokenOutSymbol??e.toSymbol??"OUT")}`,i=[["Intent",n(e.intent??"swap")],["Chain",k({chainId:e.chainId??r.chainId,chain:e.chain??r.chain})],["Pair",a],["Amount in",`${n($(e.amountIn??r.amountIn,e.decimalsIn??18))} ${n(e.tokenInSymbol??"")}`.trim()],["Best swap",n(s.source??s.venue??r.bestRoute??e.bestRoute)],["Net out",`${n($(s.netOut??s.amountOut??r.amountOut,e.decimalsOut??18))} ${n(e.tokenOutSymbol??"")}`.trim()],["Ranked on",ke(r)],["Gas accounted",n(s.costAccounted===!0?"yes":s.costAccounted===!1?"no \u2014 gross ranking may flatter this route":null)],["Spread vs next",d(r.improvementBps)?`${n(r.improvementBps)} bps`:c],["Runners-up",be(r.routes??e.routes)]];if(o){let u=o.best??o.winner??{};i.push(["Best bridge",n(u.source??o.bestRoute??e.bestBridge)],["Bridge out",`${n($(u.netOut??u.amountOut??o.amountOut,e.bridgeDecimalsOut??e.decimalsOut??18))} ${n(e.bridgeOutSymbol??e.tokenOutSymbol??"")}`.trim()],["Bridge to",k({chainId:o.toChainId??e.toChainId,chain:o.toChain??e.toChain})],["Est. time",n(o.estimatedTime??u.meta?.durationSeconds)])}else i.push(["Best bridge","same-chain \u2014 use Best swap"]);return i.push(["Preparable",n(e.preparable??s.executionReady)],g(e)),h(`ORACLE SWAP \u2014 ${a}`,i,e)}function xe(t={}){let e=t||{};return h("ORACLE APPROVE \u2014 local signer",[["Pending id",f(e.id??(typeof e.digest=="string"?e.digest.slice(0,8):null))],["Surface",n(e.surface)],["Action",n(e.action)],["Chain",k({chainId:e.chain??e.chainId,chain:e.chainName})],["To",f(e.to??e.destination)],["Value",d(e.value)?n(e.value):c],["Signer",n(e.armed===!0?"running + armed":e.armed===!1?"running, disarmed":"not running")],g({confidence:e.confidence??(e.armed===!0?"high":"low")})],e)}var We=Object.freeze({token:ue,launch:de,hip3:pe,hip4:me,polymarket:fe,twap:he,bridge:ge,swap:ye,approve:xe});var _e=Object.freeze(["deepen","refresh","prepare","ta","fa","long","short","allow","deny"]),Oe=new Set(_e),v=/^[a-z0-9-]{4,40}$/i,q=/^[0-9a-f]{32}$/,z=/^\d+$/;function P(t=process.env){return j(t.ORACLE_CONFIG_DIR||j(Ae(),".config","oracle"),"telegram-cards.json")}function S(){return{links:{},artifacts:{},threads:{}}}var A=S();function T(){return A}function W(t,{readFile:e=Ce}={}){try{let r=JSON.parse(String(e(t)));A={links:r.links&&typeof r.links=="object"?r.links:{},artifacts:r.artifacts&&typeof r.artifacts=="object"?r.artifacts:{},threads:r.threads&&typeof r.threads=="object"?r.threads:{}}}catch{A=S()}return A}function V(t,e=A,{writeFile:r=Re,mkdir:o=Se}={}){o(Ne(t),{recursive:!0,mode:448}),r(t,JSON.stringify(e),{mode:384})}function y(t){return t==null?!1:typeof t=="string"?t.trim()!=="":!0}function K(t){return we("sha256").update(String(t)).digest("hex")}function L(t){if(Array.isArray(t))return t.map(L);if(!t||typeof t!="object")return t;let e={};for(let[r,o]of Object.entries(t))/(secret|token|key|seed|private|password|mnemonic|auth)/i.test(r)||(e[r]=L(o));return e}function Ie(t){let r=String(t||"").trim().match(/^oracle:card:(deepen|refresh|prepare|ta|fa|long|short|allow|deny):([a-z0-9-]{4,40})$/i);return r?{action:r[1].toLowerCase(),artifactId:r[2].toLowerCase()}:null}function Y({platform:t="telegram",artifactId:e,openUrl:r,hasGrant:o=!1}={}){let s=String(e||"").trim().toLowerCase();if(!v.test(s))return{kind:"text_menu",text:"no artifact to continue",cancelHint:""};let a=[],i=[{text:"TA",callback_data:`oracle:card:ta:${s}`},{text:"FA",callback_data:`oracle:card:fa:${s}`}],u=O=>U(r,{side:O}),l=u("long"),b=u("short"),x=l&&b?[{text:"LONG",url:l},{text:"SHORT",url:b}]:[{text:"LONG",callback_data:`oracle:card:long:${s}`},{text:"SHORT",callback_data:`oracle:card:short:${s}`}];return y(r)?(a.push([{text:"Open",url:String(r)},i[0]]),a.push(x),a.push(o?[i[1],{text:"Prep",callback_data:`oracle:card:prepare:${s}`}]:[i[1]])):(a.push(i),a.push(x),o&&a.push([{text:"Prep",callback_data:`oracle:card:prepare:${s}`}])),String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:a.filter(O=>O.length>0)},cancelHint:"LONG/SHORT open the graph. CONFIRM there. Telegram never sends."}:{kind:"text_menu",text:"TA / FA / LONG / SHORT",cancelHint:""}}function G(t={}){let r=[`*${y(t.title)?n(t.title):"Oracle artifact"}*`,`Kind: ${y(t.kind)?n(t.kind):c}`,`Id: ${y(t.id)?`\`${String(t.id).replace(/`/g,"")}\``:c}`,`Summary: ${y(t.summary)?n(t.summary):c}`,`Confidence: ${E(t.confidence)}`];(y(t.source)||y(t.fetchedAt))&&r.push(`Source: ${n(t.source)} at ${n(t.fetchedAt)}`),Array.isArray(t.warnings)&&t.warnings.length&&r.push(`Warnings: ${t.warnings.map(s=>n(s)).join("; ")}`);let o=R(t);return r.push(o.allowed?"Actions: TA / FA / LONG / SHORT open the graph. Execute on CONFIRM there.":`Actions: TA / FA / LONG / SHORT \u2014 ${n(o.reason)}`),r.join(`
3
- `)}function Ee(t,e={},{now:r=Date.now()}={}){let o=t||S(),s=String(e.id||"").trim().toLowerCase();if(!v.test(s))throw new TypeError("artifact id required");let a={id:s,kind:String(e.kind||"thesis"),title:String(e.title||"Oracle artifact"),summary:String(e.summary||""),openUrl:y(e.openUrl)?String(e.openUrl):null,confidence:e.confidence,source:e.source||"oracle",fetchedAt:e.fetchedAt||new Date(r).toISOString(),warnings:Array.isArray(e.warnings)?e.warnings.map(String):[],payload:L(e.payload||{}),createdAt:new Date(r).toISOString()};return o.artifacts[s]=a,a}function B(t,{chatId:e,artifactId:r,now:o=Date.now()}={}){let s=t||S(),a=String(e||"").trim(),i=String(r||"").trim().toLowerCase();if(!a)throw new TypeError("chat id required");if(!v.test(i))throw new TypeError("artifact id required");return s.threads[a]={artifactId:i,updatedAt:o},s.threads[a]}function J(t,{chatId:e,text:r}={}){let o=String(e||"").trim(),s=String(r||"").trim();if(!o||!s||/^\//.test(s))return null;let a=t?.threads?.[o];if(!a?.artifactId)return null;let i=t.artifacts?.[a.artifactId];return i?`Continue artifact ${i.id} (${i.kind}). Prior: ${i.summary||i.title}. User: ${s}`:null}function Q(t,{ownerId:e,botUsername:r,now:o=Date.now(),ttlMs:s=600*1e3,token:a,randomBytes:i=$e}={}){let u=t||S(),l=String(e||"").trim(),b=String(r||"").replace(/^@/,"").trim();if(!z.test(l))throw new TypeError("owner Telegram id required");if(!/^[A-Za-z0-9_]{5,32}$/.test(b))throw new TypeError("bot username required");let x=a||i(16).toString("hex");if(!q.test(x))throw new TypeError("link token must be 32 hex chars");return u.links[K(x)]={ownerId:l,expiresAt:o+Number(s)},{token:x,url:`https://t.me/${b}?start=${x}`,expiresAt:o+Number(s)}}function Z(t,{token:e,telegramUserId:r,now:o=Date.now()}={}){let s=t||S(),a=String(e||"").trim(),i=String(r||"").trim();if(!q.test(a))return{ok:!1,error:"invalid start token"};if(!z.test(i))return{ok:!1,error:"invalid telegram user"};let u=K(a),l=s.links[u];return l?(delete s.links[u],Number(l.expiresAt)<=o?{ok:!1,error:"start token expired"}:String(l.ownerId)!==i?{ok:!1,error:"start token is bound to a different owner"}:{ok:!0,ownerId:i}):{ok:!1,error:"unknown or already used start token"}}function X(t,{data:e,chatId:r,grant:o=null,now:s=Date.now()}={}){let a=Ie(e);if(!a)return null;if(!Oe.has(a.action))return{text:"That card action is not available.",buttons:null};let i=t?.artifacts?.[a.artifactId];if(!i)return{text:"That artifact is gone. Ask again and I will issue a new card.",buttons:null};r&&B(t,{chatId:r,artifactId:i.id,now:s});let u=R({grant:o},{now:s}),l=Y({artifactId:i.id,openUrl:i.openUrl,hasGrant:u.allowed});return a.action==="refresh"?{text:G(i),buttons:l,prompt:null}:a.action==="deepen"?{text:null,buttons:null,prompt:`Deepen artifact ${i.id} (${i.kind}). Prior: ${i.summary||i.title}. Be terse. Do not sign or broadcast.`}:a.action==="ta"?{text:null,buttons:null,prompt:`TA artifact ${i.id}. Prior: ${i.summary||i.title}. Run deterministic TA on the coin/venue in the artifact (RSI divergence, S/R, candle patterns). Reply in this Telegram chat with the verdict rows and say what was drawn. Do not sign or broadcast.`}:a.action==="fa"?{text:null,buttons:null,prompt:`FA artifact ${i.id}. Prior: ${i.summary||i.title}. Run per-coin FA (funding, OI, book, premium) plus the separate MACRO thesis (M1/M2/Fed BS/net liquidity) if relevant. Cite receipts. Stay in this Telegram chat. Do not sign or broadcast.`}:a.action==="allow"?{text:"Allow is the graph. Open the ticket there and CONFIRM. Telegram did not send.",buttons:null,prompt:null}:a.action==="deny"?{text:`Denied ${i.id}. Ticket cancelled. Nothing signed.`,buttons:null,prompt:null}:a.action==="long"||a.action==="short"?{text:null,buttons:null,prompt:`Open the live graph ticket for a ${a.action} on artifact ${i.id}. Prior: ${i.summary||i.title}. Size from the connected HL account. Execute only on CONFIRM on the graph. Never sign from Telegram.`}:u.allowed?{text:`Queued unsigned prepare for ${i.id}. Nothing signed. Allow/Deny still required.`,buttons:l,prompt:null,prepare:{artifactId:i.id,unsigned:!0,broadcast:!1}}:{text:`Prepare blocked \u2014 ${u.reason}. Deepen and Refresh still work.`,buttons:l,prompt:null}}function ee(t={},{grant:e=null,now:r=Date.now(),state:o}={}){let s=o||T(),a=String(t.id||`art-${Math.abs(Number(r)).toString(36)}`).toLowerCase().slice(0,40),i=Ee(s,{...t,id:a},{now:r}),u=R({grant:e},{now:r});return{text:G({...i,grant:e}),replyMarkup:Y({artifactId:i.id,openUrl:i.openUrl,hasGrant:u.allowed}).replyMarkup,artifact:i,state:s}}var M=`oracle telegram \u2014 TrueNorth-style interactive cards (native, no Hermes)
1
+ import{createHash as xe,randomBytes as $e}from"node:crypto";import{mkdirSync as Se,readFileSync as Ce,writeFileSync as Re}from"node:fs";import{homedir as Ae}from"node:os";import{dirname as Ne,join as j}from"node:path";var re=/^[A-Z0-9][A-Z0-9._-]{0,11}$/;function ne(t){let e=String(t||"").trim();if(!e||e.includes("ts.net")||!/^https:\/\//i.test(e))return null;try{return new URL(e)}catch{return null}}function U(t,{coin:e,side:r,sizeUsd:o,leverage:s,venue:a,confirm:n,user:u}={}){let l=ne(t);if(!l)return null;if(e&&re.test(String(e).toUpperCase())&&l.searchParams.set("coin",String(e).toUpperCase()),(r==="long"||r==="short")&&l.searchParams.set("side",r),Number.isFinite(Number(o))&&Number(o)>=1&&l.searchParams.set("size",String(Math.min(1e5,Math.round(Number(o))))),Number.isInteger(Number(s))&&Number(s)>=1&&l.searchParams.set("lev",String(Math.min(50,Number(s)))),a){let b=String(a).toLowerCase()==="hl"?"hyperliquid":String(a).toLowerCase();l.searchParams.set("venue",b)}else l.searchParams.get("venue")||l.searchParams.set("venue","hyperliquid");return l.searchParams.set("view","perps"),l.searchParams.set("build","1"),n&&/^[0-9a-f]{32}$/i.test(String(n))&&l.searchParams.set("confirm",String(n).toLowerCase()),u&&/^0x[0-9a-fA-F]{40}$/.test(String(u))&&l.searchParams.set("user",String(u).toLowerCase()),l.toString()}var ie={robinhood:{chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC"],evm:!0},ethereum:{chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],evm:!0},polygon:{chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],evm:!0},arbitrum:{chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],evm:!0},base:{chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],evm:!0},hyperevm:{chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],evm:!0},bsc:{chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],evm:!0},avalanche:{chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],evm:!0},optimism:{chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],evm:!0},abstract:{chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],evm:!0},stable:{chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],evm:!0}},oe=new Map(Object.values(ie).map(t=>[t.chainId,t]));function H(t){return oe.get(Number(t))||null}var Ue=Object.freeze([100,50,25]),He=Object.freeze([100,50,25,10]);var c="UNKNOWN",ze=Object.freeze(["token","launch","hip3","hip4","polymarket","twap","bridge","swap","approve"]),ae=/[_*[\]`]/g;function i(t){return d(t)?String(t).replace(ae,e=>`\\${e}`):c}function d(t){return t==null?!1:typeof t=="number"?Number.isFinite(t):typeof t=="string"?t.trim()!=="":!0}function f(t){if(!d(t))return c;let e=String(t).replace(/`/g,"");return e===""?c:`\`${e}\``}function x(t,{decimals:e=2}={}){if(!d(t))return c;let r=Number(t);return Number.isFinite(r)?r.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:e}):c}function p(t,{decimals:e=2}={}){let r=x(t,{decimals:e});return r===c?c:`${r} USD`}function I(t,{decimals:e=2}={}){let r=x(t,{decimals:e});return r===c?c:`${r}%`}function N(t){let e=x(t,{decimals:0});return e===c?c:`${e} bps`}function $(t,e){if(!d(t))return c;let r=Number(e);if(!Number.isInteger(r)||r<0||r>77)return c;let o;try{o=BigInt(typeof t=="string"?t.trim():t)}catch{return c}let s=o<0n,a=s?-o:o,n=10n**BigInt(r),u=(a/n).toString(),l=(a%n).toString().padStart(r,"0").replace(/0+$/,"");return`${s?"-":""}${u}${l?`.${l}`:""}`}function E(t){if(typeof t=="number"&&Number.isFinite(t))return t<0||t>1?c:t>=.75?"HIGH":t>=.4?"MEDIUM":"LOW";if(typeof t=="string"){let e=t.trim().toUpperCase();if(e==="HIGH"||e==="MEDIUM"||e==="LOW")return e}return c}function k(t={}){let e=t.chainId;if(!d(e)||!Number.isFinite(Number(e)))return d(t.chain)?i(t.chain):c;let o=H(e)?.name||(d(t.chain)?String(t.chain):c);return`${i(o)} (chainId ${Number(e)})`}function D(t={}){return i(t.venue??t.dex??t.pool?.venue)}function se(t){return t==null?"NONE (text card only)":typeof t=="string"?t.trim()?f(t):"NONE (text card only)":t.error||t.ok===!1||t.available===!1?`UNAVAILABLE${d(t.error)?` \u2014 ${i(t.error)}`:""} (text card stands)`:d(t.url)?f(t.url):"NONE (text card only)"}function R(t={},{now:e=Date.now()}={}){let r=t.grant??t.session??null;if(!r||typeof r!="object")return{allowed:!1,reason:"no local grant/session",actions:[]};if(r.local===!1)return{allowed:!1,reason:"grant is not local",actions:[]};if(r.revoked===!0)return{allowed:!1,reason:"grant revoked",actions:[]};let o=r.expiresAt??r.expiry;if(d(o)){let a=typeof o=="number"?o:Date.parse(o);if(!Number.isFinite(a))return{allowed:!1,reason:"grant expiry unreadable",actions:[]};if(a<=e)return{allowed:!1,reason:"grant expired",actions:[]}}return{allowed:!0,reason:"valid local grant",actions:Array.isArray(r.actions)&&r.actions.length?r.actions.slice():["BUY","SELL"]}}function ce(t){let e=R(t);return e.allowed?`${e.actions.map(r=>i(r)).join(" / ")} (${i(e.reason)})`:`prepare-only \u2014 ${i(e.reason)}`}function h(t,e,r={}){let o=[`*${t}*`];for(let s of e){if(!s)continue;let[a,n]=s;o.push(`${a}: ${n==null||n===""?c:n}`)}return o.push(`Chart: ${se(r.chart)}`),o.push(`Actions: ${ce(r)}`),Array.isArray(r.warnings)&&r.warnings.length&&o.push(`Warnings: ${r.warnings.map(s=>i(s)).join("; ")}`),(d(r.source)||d(r.fetchedAt))&&o.push(`Source: ${i(r.source)} at ${i(r.fetchedAt)}`),o.join(`
2
+ `)}function g(t){let e=E(t.confidence);return e===c?null:["Confidence",e]}function le(t){let e=t.quote;if(!e||typeof e!="object")return[];let r=d(e.decimals)?$(e.amountOutRaw??e.out??e.raw,e.decimals):c;return[["Quote out (raw)",f(e.amountOutRaw??e.out??e.raw)],["Quote out",r===c?c:`${i(r)} ${i(e.symbol??"")}`.trim()]]}function F(t){let e=t.autoSlippage;if(!e||typeof e!="object")return["Auto-slippage",c];let r=N(e.selectedBps),o=N(e.capBps);return["Auto-slippage",r===c&&o===c?c:`${r} selected, cap ${o}`]}function ue(t={}){let e=t||{};return h(`ORACLE TOKEN \u2014 ${i(e.symbol??e.token??e.name)}`,[["Chain",k(e)],["Venue",D(e)],["Name",i(e.name)],["Address",f(e.address??e.mint??e.contract)],["Price",p(e.priceUsd,{decimals:8})],["Market cap",p(e.marketCapUsd)],["Liquidity",p(e.liquidityUsd)],["Volume 24h",p(e.volume24hUsd)],["Change 24h",I(e.priceChange24h)],["Fee tier",d(e.feeTier)?`${N(Number(e.feeTier)/100)} (${x(e.feeTier,{decimals:0})})`:c],["Age",i(e.age)],...le(e),F(e),g(e)],e)}function de(t={}){let e=t||{};return h(`ORACLE LAUNCH \u2014 ${i(e.symbol??e.token??e.name)}`,[["Chain",k(e)],["Venue",D(e)],["Address",f(e.address??e.mint??e.contract)],["Pool",f(e.pool?.address??e.poolAddress??e.pool)],["Liquidity",p(e.liquidityUsd)],["Route ready",i(e.routeReady)],["Sellable",i(e.sellable)],["Sell sim",i(e.sellSimulation??e.sellSim)],["Smart wallets",i(e.smartWalletOverlap)],["Risk",i(e.risk??e.riskStatus)],["Prepared ticket",i(e.preparedTicket??e.ticketStatus)],F(e),g(e)],e)}function pe(t={}){let e=t||{};return h(`ORACLE HIP-3 \u2014 ${i(e.market??e.coin??e.name)}`,[["Venue",`Hyperliquid builder-dex ${i(e.dex)}`],["Market",i(e.market??e.coin)],["Mark",p(e.markPx,{decimals:6})],["Oracle",p(e.oraclePx,{decimals:6})],["Funding",I(e.funding,{decimals:6})],["Open interest",p(e.openInterestUsd)],["Depth",i(e.depth)],["Liquidation notes",i(e.liquidationNotes??e.riskNotes)],["Account context",i(e.accountContext)],g(e)],e)}function me(t={}){let e=t||{};return h(`ORACLE HIP-4 \u2014 ${i(e.event??e.market??e.name)}`,[["Venue",`Hyperliquid HIP-4 ${i(e.dex??"outcome")}`],["Event",i(e.event)],["Outcome",i(e.outcome)],["Market id",f(e.marketId??e.market)],["Bid",p(e.bid,{decimals:6})],["Ask",p(e.ask,{decimals:6})],["Depth",i(e.depth)],["Edge",I(e.edge)],["Position",i(e.position)],g(e)],e)}function fe(t={}){let e=t||{};return h(`ORACLE POLYMARKET \u2014 ${i(e.event??e.market??e.name)}`,[["Venue","Polymarket CLOB"],["Event",i(e.event)],["Market",i(e.market)],["Market id",f(e.marketId??e.conditionId??e.tokenId)],["Yes",p(e.yesPrice,{decimals:4})],["No",p(e.noPrice,{decimals:4})],["Best bid / ask",`${p(e.bestBid,{decimals:4})} / ${p(e.bestAsk,{decimals:4})}`],["Volume",p(e.volumeUsd)],["Resolution risk",i(e.resolutionRisk)],["Order intent",i(e.orderIntent)],g(e)],e)}function he(t={}){let e=t||{},r=d(e.completedSplits)&&d(e.totalSplits)?`${x(e.completedSplits,{decimals:0})} / ${x(e.totalSplits,{decimals:0})}`:c;return h(`ORACLE TWAP \u2014 ${i(e.pair??e.symbol??e.name)}`,[["Chain",k(e)],["Side",i(e.side??e.direction)],["Amount",`${i($(e.amountTotal??e.amount,e.decimals??18))} ${i(e.symbol??"")}`.trim()],["Splits",`${x(e.totalSplits,{decimals:0})} over ${i(e.window)}`],["Progress",r],["Avg price",p(e.averagePrice,{decimals:6})],["Next split",i(e.nextSplitAt)],["Slippage cap",N(e.slippageBps)],["Status",i(e.status)],g(e)],e)}function ge(t={}){let e=t||{},r=e.approval??e.revokeCheck??{},o=r.needsRevoke&&r.spender?`revoke.cash \u2014 ${i(r.spender)}`:r.needsRevoke===!1?"revoke.cash \u2014 clean":"revoke.cash \u2014 unchecked";return h(`ORACLE BRIDGE \u2014 ${i(e.pair??e.fromSymbol)} \u2192 ${i(e.toSymbol??"")}`.replace(/→ $/,""),[["Bridging","deBridge \xB7 LI.FI \u2014 best route wins"],["From chain",k({chainId:e.fromChainId,chain:e.fromChain})],["To chain",k({chainId:e.toChainId,chain:e.toChain})],["Amount",`${i($(e.amount,e.fromDecimals??18))} ${i(e.fromSymbol??"")}`.trim()],["Best route",i(e.bestRoute??e.winner)],["Est. received",`${i($(e.amountOut,e.toDecimals??18))} ${i(e.toSymbol??"")}`.trim()],["Fee",p(e.feeUsd)],["Est. time",i(e.estimatedTime)],["Revoke check",o],["All providers",i(e.providers?.join(", "))],["Preparable",i(e.preparable)],g(e)],e)}function be(t){let r=(Array.isArray(t)?t:[]).slice(1,4).map(o=>{let s=i(o.source??o.venue??o.name),a=o.improvementBps==null&&o.deltaBps==null?null:Number(o.improvementBps??o.deltaBps),n=Number.isFinite(a)?`${Math.abs(a).toFixed(0)} bps behind`:"spread UNKNOWN";return`${s} (${n})`});return r.length?r.join("; "):c}function ke(t){let e=t.rankedOn??t.swap?.rankedOn??t.best?.rankedOn;return d(e)?i(e):c}function ye(t={}){let e=t||{},r=e.swap&&typeof e.swap=="object"?e.swap:e,o=e.bridge&&typeof e.bridge=="object"?e.bridge:null,s=r.best??r.winner??{},a=`${i(e.tokenInSymbol??e.fromSymbol??"IN")} \u2192 ${i(e.tokenOutSymbol??e.toSymbol??"OUT")}`,n=[["Intent",i(e.intent??"swap")],["Chain",k({chainId:e.chainId??r.chainId,chain:e.chain??r.chain})],["Pair",a],["Amount in",`${i($(e.amountIn??r.amountIn,e.decimalsIn??18))} ${i(e.tokenInSymbol??"")}`.trim()],["Best swap",i(s.source??s.venue??r.bestRoute??e.bestRoute)],["Net out",`${i($(s.netOut??s.amountOut??r.amountOut,e.decimalsOut??18))} ${i(e.tokenOutSymbol??"")}`.trim()],["Ranked on",ke(r)],["Gas accounted",i(s.costAccounted===!0?"yes":s.costAccounted===!1?"no \u2014 gross ranking may flatter this route":null)],["Spread vs next",d(r.improvementBps)?`${i(r.improvementBps)} bps`:c],["Runners-up",be(r.routes??e.routes)]];if(o){let u=o.best??o.winner??{};n.push(["Best bridge",i(u.source??o.bestRoute??e.bestBridge)],["Bridge out",`${i($(u.netOut??u.amountOut??o.amountOut,e.bridgeDecimalsOut??e.decimalsOut??18))} ${i(e.bridgeOutSymbol??e.tokenOutSymbol??"")}`.trim()],["Bridge to",k({chainId:o.toChainId??e.toChainId,chain:o.toChain??e.toChain})],["Est. time",i(o.estimatedTime??u.meta?.durationSeconds)])}else n.push(["Best bridge","same-chain \u2014 use Best swap"]);return n.push(["Preparable",i(e.preparable??s.executionReady)],g(e)),h(`ORACLE SWAP \u2014 ${a}`,n,e)}function we(t={}){let e=t||{};return h("ORACLE APPROVE \u2014 local signer",[["Pending id",f(e.id??(typeof e.digest=="string"?e.digest.slice(0,8):null))],["Surface",i(e.surface)],["Action",i(e.action)],["Chain",k({chainId:e.chain??e.chainId,chain:e.chainName})],["To",f(e.to??e.destination)],["Value",d(e.value)?i(e.value):c],["Signer",i(e.armed===!0?"running + armed":e.armed===!1?"running, disarmed":"not running")],g({confidence:e.confidence??(e.armed===!0?"high":"low")})],e)}var We=Object.freeze({token:ue,launch:de,hip3:pe,hip4:me,polymarket:fe,twap:he,bridge:ge,swap:ye,approve:we});var _e=Object.freeze(["deepen","refresh","prepare","ta","fa","long","short","allow","deny"]),Oe=new Set(_e),v=/^[a-z0-9-]{4,40}$/i,q=/^[0-9a-f]{32}$/,z=/^\d+$/;function P(t=process.env){return j(t.ORACLE_CONFIG_DIR||j(Ae(),".config","oracle"),"telegram-cards.json")}function S(){return{links:{},artifacts:{},threads:{}}}var A=S();function T(){return A}function W(t,{readFile:e=Ce}={}){try{let r=JSON.parse(String(e(t)));A={links:r.links&&typeof r.links=="object"?r.links:{},artifacts:r.artifacts&&typeof r.artifacts=="object"?r.artifacts:{},threads:r.threads&&typeof r.threads=="object"?r.threads:{}}}catch{A=S()}return A}function V(t,e=A,{writeFile:r=Re,mkdir:o=Se}={}){o(Ne(t),{recursive:!0,mode:448}),r(t,JSON.stringify(e),{mode:384})}function y(t){return t==null?!1:typeof t=="string"?t.trim()!=="":!0}function K(t){return xe("sha256").update(String(t)).digest("hex")}function L(t){if(Array.isArray(t))return t.map(L);if(!t||typeof t!="object")return t;let e={};for(let[r,o]of Object.entries(t))/(secret|token|key|seed|private|password|mnemonic|auth)/i.test(r)||(e[r]=L(o));return e}function Ie(t){let r=String(t||"").trim().match(/^oracle:card:(deepen|refresh|prepare|ta|fa|long|short|allow|deny):([a-z0-9-]{4,40})$/i);return r?{action:r[1].toLowerCase(),artifactId:r[2].toLowerCase()}:null}function Y({platform:t="telegram",artifactId:e,openUrl:r,hasGrant:o=!1}={}){let s=String(e||"").trim().toLowerCase();if(!v.test(s))return{kind:"text_menu",text:"no artifact to continue",cancelHint:""};let a=[],n=[{text:"TA",callback_data:`oracle:card:ta:${s}`},{text:"FA",callback_data:`oracle:card:fa:${s}`}],u=O=>U(r,{side:O}),l=u("long"),b=u("short"),w=l&&b?[{text:"LONG",url:l},{text:"SHORT",url:b}]:[{text:"LONG",callback_data:`oracle:card:long:${s}`},{text:"SHORT",callback_data:`oracle:card:short:${s}`}];return y(r)?(a.push([{text:"Open",url:String(r)},n[0]]),a.push(w),a.push(o?[n[1],{text:"Prep",callback_data:`oracle:card:prepare:${s}`}]:[n[1]])):(a.push(n),a.push(w),o&&a.push([{text:"Prep",callback_data:`oracle:card:prepare:${s}`}])),String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:a.filter(O=>O.length>0)},cancelHint:"LONG/SHORT open the graph. CONFIRM there. Telegram never sends."}:{kind:"text_menu",text:"TA / FA / LONG / SHORT",cancelHint:""}}function G(t={}){let r=[`*${y(t.title)?i(t.title):"Oracle artifact"}*`,`Kind: ${y(t.kind)?i(t.kind):c}`,`Id: ${y(t.id)?`\`${String(t.id).replace(/`/g,"")}\``:c}`,`Summary: ${y(t.summary)?i(t.summary):c}`],o=E(t.confidence);o!==c&&r.push(`Confidence: ${o}`),(y(t.source)||y(t.fetchedAt))&&r.push(`Source: ${i(t.source)} at ${i(t.fetchedAt)}`),Array.isArray(t.warnings)&&t.warnings.length&&r.push(`Warnings: ${t.warnings.map(a=>i(a)).join("; ")}`);let s=R(t);return r.push(s.allowed?"Actions: TA / FA / LONG / SHORT open the graph. Execute on CONFIRM there.":`Actions: TA / FA / LONG / SHORT \u2014 ${i(s.reason)}`),r.join(`
3
+ `)}function Ee(t,e={},{now:r=Date.now()}={}){let o=t||S(),s=String(e.id||"").trim().toLowerCase();if(!v.test(s))throw new TypeError("artifact id required");let a={id:s,kind:String(e.kind||"thesis"),title:String(e.title||"Oracle artifact"),summary:String(e.summary||""),openUrl:y(e.openUrl)?String(e.openUrl):null,confidence:e.confidence,source:e.source||"oracle",fetchedAt:e.fetchedAt||new Date(r).toISOString(),warnings:Array.isArray(e.warnings)?e.warnings.map(String):[],payload:L(e.payload||{}),createdAt:new Date(r).toISOString()};return o.artifacts[s]=a,a}function B(t,{chatId:e,artifactId:r,now:o=Date.now()}={}){let s=t||S(),a=String(e||"").trim(),n=String(r||"").trim().toLowerCase();if(!a)throw new TypeError("chat id required");if(!v.test(n))throw new TypeError("artifact id required");return s.threads[a]={artifactId:n,updatedAt:o},s.threads[a]}function J(t,{chatId:e,text:r}={}){let o=String(e||"").trim(),s=String(r||"").trim();if(!o||!s||/^\//.test(s))return null;let a=t?.threads?.[o];if(!a?.artifactId)return null;let n=t.artifacts?.[a.artifactId];return n?`Continue artifact ${n.id} (${n.kind}). Prior: ${n.summary||n.title}. User: ${s}`:null}function Q(t,{ownerId:e,botUsername:r,now:o=Date.now(),ttlMs:s=600*1e3,token:a,randomBytes:n=$e}={}){let u=t||S(),l=String(e||"").trim(),b=String(r||"").replace(/^@/,"").trim();if(!z.test(l))throw new TypeError("owner Telegram id required");if(!/^[A-Za-z0-9_]{5,32}$/.test(b))throw new TypeError("bot username required");let w=a||n(16).toString("hex");if(!q.test(w))throw new TypeError("link token must be 32 hex chars");return u.links[K(w)]={ownerId:l,expiresAt:o+Number(s)},{token:w,url:`https://t.me/${b}?start=${w}`,expiresAt:o+Number(s)}}function Z(t,{token:e,telegramUserId:r,now:o=Date.now()}={}){let s=t||S(),a=String(e||"").trim(),n=String(r||"").trim();if(!q.test(a))return{ok:!1,error:"invalid start token"};if(!z.test(n))return{ok:!1,error:"invalid telegram user"};let u=K(a),l=s.links[u];return l?(delete s.links[u],Number(l.expiresAt)<=o?{ok:!1,error:"start token expired"}:String(l.ownerId)!==n?{ok:!1,error:"start token is bound to a different owner"}:{ok:!0,ownerId:n}):{ok:!1,error:"unknown or already used start token"}}function X(t,{data:e,chatId:r,grant:o=null,now:s=Date.now()}={}){let a=Ie(e);if(!a)return null;if(!Oe.has(a.action))return{text:"That card action is not available.",buttons:null};let n=t?.artifacts?.[a.artifactId];if(!n)return{text:"That artifact is gone. Ask again and I will issue a new card.",buttons:null};r&&B(t,{chatId:r,artifactId:n.id,now:s});let u=R({grant:o},{now:s}),l=Y({artifactId:n.id,openUrl:n.openUrl,hasGrant:u.allowed});return a.action==="refresh"?{text:G(n),buttons:l,prompt:null}:a.action==="deepen"?{text:null,buttons:null,prompt:`Deepen artifact ${n.id} (${n.kind}). Prior: ${n.summary||n.title}. Be terse. Do not sign or broadcast.`}:a.action==="ta"?{text:null,buttons:null,prompt:`TA artifact ${n.id}. Prior: ${n.summary||n.title}. Run deterministic TA on the coin/venue in the artifact (RSI divergence, S/R, candle patterns). Reply in this Telegram chat with the verdict rows and say what was drawn. Do not sign or broadcast.`}:a.action==="fa"?{text:null,buttons:null,prompt:`FA artifact ${n.id}. Prior: ${n.summary||n.title}. Run per-coin FA (funding, OI, book, premium) plus the separate MACRO thesis (M1/M2/Fed BS/net liquidity) if relevant. Cite receipts. Stay in this Telegram chat. Do not sign or broadcast.`}:a.action==="allow"?{text:"Allow is the graph. Open the ticket there and CONFIRM. Telegram did not send.",buttons:null,prompt:null}:a.action==="deny"?{text:`Denied ${n.id}. Ticket cancelled. Nothing signed.`,buttons:null,prompt:null}:a.action==="long"||a.action==="short"?{text:null,buttons:null,prompt:`Open the live graph ticket for a ${a.action} on artifact ${n.id}. Prior: ${n.summary||n.title}. Size from the connected HL account. Execute only on CONFIRM on the graph. Never sign from Telegram.`}:u.allowed?{text:`Queued unsigned prepare for ${n.id}. Nothing signed. Allow/Deny still required.`,buttons:l,prompt:null,prepare:{artifactId:n.id,unsigned:!0,broadcast:!1}}:{text:`Prepare blocked \u2014 ${u.reason}. Deepen and Refresh still work.`,buttons:l,prompt:null}}function ee(t={},{grant:e=null,now:r=Date.now(),state:o}={}){let s=o||T(),a=String(t.id||`art-${Math.abs(Number(r)).toString(36)}`).toLowerCase().slice(0,40),n=Ee(s,{...t,id:a},{now:r}),u=R({grant:e},{now:r});return{text:G({...n,grant:e}),replyMarkup:Y({artifactId:n.id,openUrl:n.openUrl,hasGrant:u.allowed}).replyMarkup,artifact:n,state:s}}var M=`oracle telegram \u2014 TrueNorth-style interactive cards (native, no Hermes)
4
4
 
5
5
  oracle telegram link --owner <tg-id> --bot <username>
6
6
  oracle telegram redeem --token <32hex> --user <tg-id>
@@ -12,8 +12,8 @@ Native oracle-gateway uses the same module. Hermes is an optional adapter that
12
12
  must call this CLI instead of owning card state. Prepare is unsigned. Execute
13
13
  stays on Allow/Deny.`;function m(t,e){let r=t.indexOf(e);return r<0||r+1>=t.length?null:t[r+1]}function te(t,e){return t.includes(e)}function Le(){return W(P()),T()}function _(t){V(P(),t)}function C(t,e){t.write(JSON.stringify(e)+`
14
14
  `)}async function ve(t=[],e={}){let r=e.out??process.stdout,o=e.err??process.stderr,s=t[0];if(!s||s==="--help"||s==="-h"||s==="help")return r.write(M+`
15
- `),0;let a=Le();if(s==="link")try{let i=Q(a,{ownerId:m(t,"--owner"),botUsername:m(t,"--bot")});return _(a),C(r,{ok:!0,...i}),0}catch(i){return o.write(String(i.message||i)+`
16
- `),1}if(s==="redeem"){let i=Z(a,{token:m(t,"--token"),telegramUserId:m(t,"--user")});return _(a),C(r,i),i.ok?0:1}if(s==="wrap")try{let i=ee({id:m(t,"--id"),kind:m(t,"--kind")||"thesis",title:m(t,"--title")||"Oracle artifact",summary:m(t,"--summary")||"",openUrl:m(t,"--url"),source:"oracle-telegram"},{grant:te(t,"--grant")?{local:!0}:null,state:a}),u=m(t,"--chat");return u&&B(a,{chatId:u,artifactId:i.artifact.id}),_(a),C(r,{ok:!0,text:i.text,replyMarkup:i.replyMarkup||null,artifactId:i.artifact.id,fallback:`Reply: deepen ${i.artifact.id} | refresh ${i.artifact.id}`}),0}catch(i){return o.write(String(i.message||i)+`
17
- `),1}if(s==="callback"){let i=X(a,{data:m(t,"--data"),chatId:m(t,"--chat"),grant:te(t,"--grant")?{local:!0}:null});return _(a),i?(C(r,{ok:!0,...i}),0):(C(r,{ok:!1,error:"not an interactive card callback"}),1)}if(s==="continue"){let i=J(a,{chatId:m(t,"--chat"),text:m(t,"--text")});return C(r,{ok:!0,prompt:i}),0}return o.write(`unknown telegram verb '${s}'
15
+ `),0;let a=Le();if(s==="link")try{let n=Q(a,{ownerId:m(t,"--owner"),botUsername:m(t,"--bot")});return _(a),C(r,{ok:!0,...n}),0}catch(n){return o.write(String(n.message||n)+`
16
+ `),1}if(s==="redeem"){let n=Z(a,{token:m(t,"--token"),telegramUserId:m(t,"--user")});return _(a),C(r,n),n.ok?0:1}if(s==="wrap")try{let n=ee({id:m(t,"--id"),kind:m(t,"--kind")||"thesis",title:m(t,"--title")||"Oracle artifact",summary:m(t,"--summary")||"",openUrl:m(t,"--url"),source:"oracle-telegram"},{grant:te(t,"--grant")?{local:!0}:null,state:a}),u=m(t,"--chat");return u&&B(a,{chatId:u,artifactId:n.artifact.id}),_(a),C(r,{ok:!0,text:n.text,replyMarkup:n.replyMarkup||null,artifactId:n.artifact.id,fallback:`Reply: deepen ${n.artifact.id} | refresh ${n.artifact.id}`}),0}catch(n){return o.write(String(n.message||n)+`
17
+ `),1}if(s==="callback"){let n=X(a,{data:m(t,"--data"),chatId:m(t,"--chat"),grant:te(t,"--grant")?{local:!0}:null});return _(a),n?(C(r,{ok:!0,...n}),0):(C(r,{ok:!1,error:"not an interactive card callback"}),1)}if(s==="continue"){let n=J(a,{chatId:m(t,"--chat"),text:m(t,"--text")});return C(r,{ok:!0,prompt:n}),0}return o.write(`unknown telegram verb '${s}'
18
18
  ${M}
19
19
  `),1}var tt={name:"telegram",summary:"native interactive Telegram cards (TrueNorth-style, no Hermes)",group:"system",usage:M,run:t=>ve(t.argv||[])};export{tt as default,ve as run};